From d2a487e6408b50890cbf21f55b72b6645ed8308a Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Mon, 25 Jan 2021 09:07:53 +0100 Subject: [PATCH 001/108] Revert "stream: fix .end() error propagation" This reverts commit 4c819d65f91f32290188f87031a95410bbd66e64. PR-URL: https://github.com/nodejs/node/pull/37060 Reviewed-By: Luigi Pinca Reviewed-By: Robert Nagy Reviewed-By: Beth Griggs Reviewed-By: Rich Trott Reviewed-By: Danielle Adams --- lib/internal/streams/writable.js | 40 ++++++------------- .../test-stream-writable-end-cb-error.js | 35 ---------------- 2 files changed, 13 insertions(+), 62 deletions(-) diff --git a/lib/internal/streams/writable.js b/lib/internal/streams/writable.js index 2510398d999fe1..97fe1d28ef1f3a 100644 --- a/lib/internal/streams/writable.js +++ b/lib/internal/streams/writable.js @@ -27,7 +27,6 @@ const { FunctionPrototype, - Error, ObjectDefineProperty, ObjectDefineProperties, ObjectSetPrototypeOf, @@ -291,8 +290,8 @@ Writable.prototype.pipe = function() { errorOrDestroy(this, new ERR_STREAM_CANNOT_PIPE()); }; -function _write(stream, chunk, encoding, cb) { - const state = stream._writableState; +Writable.prototype.write = function(chunk, encoding, cb) { + const state = this._writableState; if (typeof encoding === 'function') { cb = encoding; @@ -334,15 +333,11 @@ function _write(stream, chunk, encoding, cb) { if (err) { process.nextTick(cb, err); - errorOrDestroy(stream, err, true); - return err; + errorOrDestroy(this, err, true); + return false; } state.pendingcb++; - return writeOrBuffer(stream, state, chunk, encoding, cb); -} - -Writable.prototype.write = function(chunk, encoding, cb) { - return _write(this, chunk, encoding, cb) === true; + return writeOrBuffer(this, state, chunk, encoding, cb); }; Writable.prototype.cork = function() { @@ -612,14 +607,8 @@ Writable.prototype.end = function(chunk, encoding, cb) { encoding = null; } - let err; - - if (chunk !== null && chunk !== undefined) { - const ret = _write(this, chunk, encoding); - if (ret instanceof Error) { - err = ret; - } - } + if (chunk !== null && chunk !== undefined) + this.write(chunk, encoding); // .end() fully uncorks. if (state.corked) { @@ -627,15 +616,12 @@ Writable.prototype.end = function(chunk, encoding, cb) { this.uncork(); } - if (err) { - // Do nothing... - } else if (!state.errored && !state.ending) { - // This is forgiving in terms of unnecessary calls to end() and can hide - // logic errors. However, usually such errors are harmless and causing a - // hard error can be disproportionately destructive. It is not always - // trivial for the user to determine whether end() needs to be called - // or not. - + // This is forgiving in terms of unnecessary calls to end() and can hide + // logic errors. However, usually such errors are harmless and causing a + // hard error can be disproportionately destructive. It is not always + // trivial for the user to determine whether end() needs to be called or not. + let err; + if (!state.errored && !state.ending) { state.ending = true; finishMaybe(this, state, true); state.ended = true; diff --git a/test/parallel/test-stream-writable-end-cb-error.js b/test/parallel/test-stream-writable-end-cb-error.js index 20428f1777fd17..8f6d209954436f 100644 --- a/test/parallel/test-stream-writable-end-cb-error.js +++ b/test/parallel/test-stream-writable-end-cb-error.js @@ -46,38 +46,3 @@ const stream = require('stream'); writable.emit('error', new Error('kaboom')); })); } - -{ - const w = new stream.Writable({ - write(chunk, encoding, callback) { - setImmediate(callback); - }, - finish(callback) { - setImmediate(callback); - } - }); - w.end('testing ended state', common.mustCall((err) => { - // This errors since .destroy(err), which is invoked by errors - // in same tick below, will error all pending callbacks. - // Does this make sense? Not sure. - assert.strictEqual(err.code, 'ERR_STREAM_DESTROYED'); - })); - assert.strictEqual(w.destroyed, false); - assert.strictEqual(w.writableEnded, true); - w.end(common.mustCall((err) => { - // This errors since .destroy(err), which is invoked by errors - // in same tick below, will error all pending callbacks. - // Does this make sense? Not sure. - assert.strictEqual(err.code, 'ERR_STREAM_DESTROYED'); - })); - assert.strictEqual(w.destroyed, false); - assert.strictEqual(w.writableEnded, true); - w.end('end', common.mustCall((err) => { - assert.strictEqual(err.code, 'ERR_STREAM_WRITE_AFTER_END'); - })); - assert.strictEqual(w.destroyed, true); - w.on('error', common.mustCall((err) => { - assert.strictEqual(err.code, 'ERR_STREAM_WRITE_AFTER_END'); - })); - w.on('finish', common.mustNotCall()); -} From 67c9a8e176571c08cb06fe924910deafd6dd87c6 Mon Sep 17 00:00:00 2001 From: Benjamin Gruenbaum Date: Tue, 2 Feb 2021 11:06:50 +0200 Subject: [PATCH 002/108] doc: improve promise terminology PR-URL: https://github.com/nodejs/node/pull/37181 Reviewed-By: Antoine du Hamel Reviewed-By: Zijian Liu Reviewed-By: Darshan Sen --- doc/api/fs.md | 109 +++++++++++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 54 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index 2f9dea37f3fd7f..04735faff41bee 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -56,7 +56,7 @@ fs.unlink('/tmp/hello', (err) => { ## Promise example -Promise-based operations return a `Promise` that is resolved when the +Promise-based operations return a `Promise` that is fulfilled when the asynchronous operation is complete. ```js @@ -335,7 +335,7 @@ added: v12.12.0 Asynchronously close the directory's underlying resource handle. Subsequent reads will result in errors. -A `Promise` is returned that will be resolved after the resource has been +A `Promise` is returned that will be fulfilled after the resource has been closed. ### `dir.close(callback)` @@ -379,8 +379,9 @@ added: v12.12.0 Asynchronously read the next directory entry via readdir(3) as an [`fs.Dirent`][]. -After the read is completed, a `Promise` is returned that will be resolved with -an [`fs.Dirent`][], or `null` if there are no more directory entries to read. +After the read is completed, a `Promise` is returned that will be fulfilled +with an [`fs.Dirent`][], or `null` if there are no more directory entries to +read. Directory entries returned by this function are in no particular order as provided by the operating system's underlying directory mechanisms. @@ -4740,8 +4741,8 @@ Instances of the `FileHandle` object are created internally by the Unlike the callback-based API (`fs.fstat()`, `fs.fchown()`, `fs.fchmod()`, and so on), a numeric file descriptor is not used by the promise-based API. Instead, the promise-based API uses the `FileHandle` class in order to help avoid -accidental leaking of unclosed file descriptors after a `Promise` is resolved or -rejected. +accidental leaking of unclosed file descriptors after a `Promise` is fulfilled +or rejected. #### Event: `'close'` -* Returns: {Promise} A `Promise` that will be resolved once the underlying +* Returns: {Promise} A `Promise` that will be fulfilled once the underlying file descriptor is closed, or will be rejected if an error occurs while closing. @@ -4822,7 +4823,7 @@ added: v10.0.0 * Returns: {Promise} -Asynchronous fdatasync(2). The `Promise` is resolved with no arguments upon +Asynchronous fdatasync(2). The `Promise` is fulfilled with no arguments upon success. #### `filehandle.fd` @@ -4856,7 +4857,7 @@ If `position` is `null`, data will be read from the current file position, and the file position will be updated. If `position` is an integer, the file position will remain unchanged. -Following successful read, the `Promise` is resolved with an object with a +Following successful read, the `Promise` is fulfilled with an object with a `bytesRead` property specifying the number of bytes read, and a `buffer` property that is a reference to the passed in `buffer` argument. @@ -4888,7 +4889,7 @@ added: v10.0.0 Asynchronously reads the entire contents of a file. -The `Promise` is resolved with the contents of the file. If no encoding is +The `Promise` is fulfilled with the contents of the file. If no encoding is specified (using `options.encoding`), the data is returned as a `Buffer` object. Otherwise, the data will be a string. @@ -4914,7 +4915,7 @@ added: Read from a file and write to an array of `ArrayBufferView`s -The `Promise` is resolved with an object containing a `bytesRead` property +The `Promise` is fulfilled with an object containing a `bytesRead` property identifying the number of bytes read, and a `buffers` property containing a reference to the `buffers` input. @@ -4946,7 +4947,7 @@ added: v10.0.0 * Returns: {Promise} -Asynchronous fsync(2). The `Promise` is resolved with no arguments upon +Asynchronous fsync(2). The `Promise` is fulflled with no arguments upon success. #### `filehandle.truncate(len)` @@ -4957,7 +4958,7 @@ added: v10.0.0 * `len` {integer} **Default:** `0` * Returns: {Promise} -Truncates the file then resolves the `Promise` with no arguments upon success. +Truncates the file then fulfills the `Promise` with no arguments upon success. If the file was larger than `len` bytes, only the first `len` bytes will be retained in the file. @@ -5028,9 +5029,9 @@ added: v10.0.0 * Returns: {Promise} Change the file system timestamps of the object referenced by the `FileHandle` -then resolves the `Promise` with no arguments upon success. +then fulfills the `Promise` with no arguments upon success. -This function does not work on AIX versions before 7.1, it will resolve the +This function does not work on AIX versions before 7.1, it will reject the `Promise` with an error using code `UV_ENOSYS`. #### `filehandle.write(buffer[, offset[, length[, position]]])` @@ -5055,7 +5056,7 @@ changes: Write `buffer` to the file. -The `Promise` is resolved with an object containing a `bytesWritten` property +The `Promise` is fulfilled with an object containing a `bytesWritten` property identifying the number of bytes written, and a `buffer` property containing a reference to the `buffer` written. @@ -5067,7 +5068,7 @@ should be written. If `typeof position !== 'number'`, the data will be written at the current position. See pwrite(2). It is unsafe to use `filehandle.write()` multiple times on the same file -without waiting for the `Promise` to be resolved (or rejected). For this +without waiting for the `Promise` to be fulfilled (or rejected). For this scenario, use [`fs.createWriteStream()`][]. On Linux, positional writes do not work when the file is opened in append mode. @@ -5096,7 +5097,7 @@ changes: Write `string` to the file. If `string` is not a string, or an object with an own `toString` function property, then an exception is thrown. -The `Promise` is resolved with an object containing a `bytesWritten` property +The `Promise` is fulfilled with an object containing a `bytesWritten` property identifying the number of bytes written, and a `buffer` property containing a reference to the `string` written. @@ -5107,7 +5108,7 @@ will be written at the current position. See pwrite(2). `encoding` is the expected string encoding. It is unsafe to use `filehandle.write()` multiple times on the same file -without waiting for the `Promise` to be resolved (or rejected). For this +without waiting for the `Promise` to be fulfilled (or rejected). For this scenario, use [`fs.createWriteStream()`][]. On Linux, positional writes do not work when the file is opened in append mode. @@ -5135,7 +5136,7 @@ changes: Asynchronously writes data to a file, replacing the file if it already exists. `data` can be a string, a buffer, or an object with an own `toString` function -property. The `Promise` is resolved with no arguments upon success. +property. The `Promise` is fulfilled with no arguments upon success. The `encoding` option is ignored if `data` is a buffer. @@ -5144,7 +5145,7 @@ If `options` is a string, then it specifies the encoding. The `FileHandle` has to support writing. It is unsafe to use `filehandle.writeFile()` multiple times on the same file -without waiting for the `Promise` to be resolved (or rejected). +without waiting for the `Promise` to be fulfilled (or rejected). If one or more `filehandle.write()` calls are made on a file handle and then a `filehandle.writeFile()` call is made, the data will be written from the @@ -5162,7 +5163,7 @@ added: v12.9.0 Write an array of `ArrayBufferView`s to the file. -The `Promise` is resolved with an object containing a `bytesWritten` property +The `Promise` is fulfilled with an object containing a `bytesWritten` property identifying the number of bytes written, and a `buffers` property containing a reference to the `buffers` input. @@ -5192,7 +5193,7 @@ checks to be performed. Check [File access constants][] for possible values of `mode`. It is possible to create a mask consisting of the bitwise OR of two or more values (e.g. `fs.constants.W_OK | fs.constants.R_OK`). -If the accessibility check is successful, the `Promise` is resolved with no +If the accessibility check is successful, the `Promise` is fulfilled with no value. If any of the accessibility checks fail, the `Promise` is rejected with an `Error` object. The following example checks if the file `/etc/passwd` can be read and written by the current process. @@ -5227,7 +5228,7 @@ added: v10.0.0 Asynchronously append data to a file, creating the file if it does not yet exist. `data` can be a string or a [`Buffer`][]. The `Promise` will be -resolved with no arguments upon success. +fulfilled with no arguments upon success. If `options` is a string, then it specifies the encoding. @@ -5243,7 +5244,7 @@ added: v10.0.0 * `mode` {string|integer} * Returns: {Promise} -Changes the permissions of a file then resolves the `Promise` with no +Changes the permissions of a file then fulfills the `Promise` with no arguments upon succces. ### `fsPromises.chown(path, uid, gid)` @@ -5256,7 +5257,7 @@ added: v10.0.0 * `gid` {integer} * Returns: {Promise} -Changes the ownership of a file then resolves the `Promise` with no arguments +Changes the ownership of a file then fulfills the `Promise` with no arguments upon success. ### `fsPromises.copyFile(src, dest[, mode])` @@ -5275,7 +5276,7 @@ changes: * Returns: {Promise} Asynchronously copies `src` to `dest`. By default, `dest` is overwritten if it -already exists. The `Promise` will be resolved with no arguments upon success. +already exists. The `Promise` will be fulfilled with no arguments upon success. Node.js makes no guarantees about the atomicity of the copy operation. If an error occurs after the destination file has been opened for writing, Node.js @@ -5323,7 +5324,7 @@ deprecated: v10.0.0 * `mode` {integer} * Returns: {Promise} -Changes the permissions on a symbolic link then resolves the `Promise` with +Changes the permissions on a symbolic link then fulfills the `Promise` with no arguments upon success. This method is only implemented on macOS. ### `fsPromises.lchown(path, uid, gid)` @@ -5340,7 +5341,7 @@ changes: * `gid` {integer} * Returns: {Promise} -Changes the ownership on a symbolic link then resolves the `Promise` with +Changes the ownership on a symbolic link then fulfills the `Promise` with no arguments upon success. ### `fsPromises.lutimes(path, atime, mtime)` @@ -5360,7 +5361,7 @@ Changes the access and modification times of a file in the same way as symbolic link, then the link is not dereferenced: instead, the timestamps of the symbolic link itself are changed. -Upon success, the `Promise` is resolved without arguments. +Upon success, the `Promise` is fulfilled without arguments. ### `fsPromises.link(existingPath, newPath)` + +* Type: {X509Certificate} + +The issuer certificate or `undefined` if the issuer certificate is not +available. + ### `x509.keyUsage` + +* `length` {number} number of bytes to retrieve from keying material +* `label` {string} an application specific label, typically this will be a + value from the + [IANA Exporter Label Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). +* `context` {Buffer} Optionally provide a context. + +* Returns: {Buffer} requested bytes of the keying material + +Keying material is used for validations to prevent different kind of attacks in +network protocols, for example in the specifications of IEEE 802.1X. + +Example + +```js +const keyingMaterial = tlsSocket.exportKeyingMaterial( + 128, + 'client finished'); + +/** + Example return value of keyingMaterial: + +*/ +``` +See the OpenSSL [`SSL_export_keying_material`][] documentation for more +information. + ### `tlsSocket.getCertificate()` + +* Returns: {X509Certificate} + +Returns the peer certificate as an {X509Certificate} object. + +If there is no peer certificate, or the socket has been destroyed, +`undefined` will be returned. + ### `tlsSocket.getProtocol()` - -* `length` {number} number of bytes to retrieve from keying material -* `label` {string} an application specific label, typically this will be a - value from the - [IANA Exporter Label Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). -* `context` {Buffer} Optionally provide a context. - -* Returns: {Buffer} requested bytes of the keying material - -Keying material is used for validations to prevent different kind of attacks in -network protocols, for example in the specifications of IEEE 802.1X. - -Example - -```js -const keyingMaterial = tlsSocket.exportKeyingMaterial( - 128, - 'client finished'); - -/** - Example return value of keyingMaterial: - -*/ -``` -See the OpenSSL [`SSL_export_keying_material`][] documentation for more -information. - ### `tlsSocket.getTLSTicket()` + +* Returns: {X509Certificate} + +Returns the local certificate as an {X509Certificate} object. + +If there is no local certificate, or the socket has been destroyed, +`undefined` will be returned. + ### `tlsSocket.isSessionReused()` * `options`: {Object} -* Returns: {string | Buffer} +* Returns: {string | Buffer | Object} -For symmetric keys, this function allocates a `Buffer` containing the key -material and ignores any options. +For symmetric keys, the following encoding options can be used: -For asymmetric keys, the `options` parameter is used to determine the export -format. +* `format`: {string} Must be `'buffer'` (default) or `'jwk'`. For public keys, the following encoding options can be used: * `type`: {string} Must be one of `'pkcs1'` (RSA only) or `'spki'`. -* `format`: {string} Must be `'pem'` or `'der'`. +* `format`: {string} Must be `'pem'`, `'der'`, or `'jwk'`. For private keys, the following encoding options can be used: * `type`: {string} Must be one of `'pkcs1'` (RSA only), `'pkcs8'` or `'sec1'` (EC only). -* `format`: {string} Must be `'pem'` or `'der'`. +* `format`: {string} Must be `'pem'`, `'der'`, or `'jwk'`. * `cipher`: {string} If specified, the private key will be encrypted with the given `cipher` and `passphrase` using PKCS#5 v2.0 password based encryption. * `passphrase`: {string | Buffer} The passphrase to use for encryption, see `cipher`. -When PEM encoding was selected, the result will be a string, otherwise it will -be a buffer containing the data encoded as DER. +The result type depends on the selected encoding format, when PEM the +result is a string, when DER it will be a buffer containing the data +encoded as DER, when [JWK][] it will be an object. + +When [JWK][] encoding format was selected, all other encoding options are +ignored. PKCS#1, SEC1, and PKCS#8 type keys can be encrypted by using a combination of the `cipher` and `format` options. The PKCS#8 `type` can be used with any @@ -4355,6 +4361,7 @@ See the [list of SSL OP Flags][] for details. [Crypto constants]: #crypto_crypto_constants_1 [HTML 5.2]: https://www.w3.org/TR/html52/changes.html#features-removed [HTML5's `keygen` element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/keygen +[JWK]: https://tools.ietf.org/html/rfc7517 [NIST SP 800-131A]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf [NIST SP 800-132]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf [NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf diff --git a/doc/api/errors.md b/doc/api/errors.md index 896a403188cbc2..411e2a4221004e 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -919,6 +919,18 @@ added: v15.0.0 Initialization of an asynchronous crypto operation failed. + +### `ERR_CRYPTO_JWK_UNSUPPORTED_CURVE` + +Key's Elliptic Curve is not registered for use in the +[JSON Web Key Elliptic Curve Registry][]. + + +### `ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE` + +Key's Asymmetric Key Type is not registered for use in the +[JSON Web Key Types Registry][]. + ### `ERR_CRYPTO_OPERATION_FAILED` + + ## The `Module` object From 3f815d93bfeb320344ae3617cab99f69b3189b1f Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Wed, 3 Feb 2021 14:26:07 +0100 Subject: [PATCH 010/108] doc: fix pr-url for DEP0148 PR-URL: https://github.com/nodejs/node/pull/37205 Reviewed-By: Beth Griggs Reviewed-By: Richard Lau Reviewed-By: Pooja D P Reviewed-By: Darshan Sen Reviewed-By: Zijian Liu Reviewed-By: James M Snell --- doc/api/deprecations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index c66e27895bcd61..c61d2ad9366af3 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -2681,7 +2681,7 @@ Use `fs.rm(path, { recursive: true, force: true })` instead.

Platinum Sponsors

Automattic

Gold Sponsors

-

Chrome's Web Framework & Tools Performance Fund Shopify Salesforce Airbnb Microsoft FOSS Fund Sponsorships

Silver Sponsors

-

Liftoff AMP Project

Bronze Sponsors

+

Chrome's Web Framework & Tools Performance Fund Shopify Salesforce Airbnb Microsoft FOSS Fund Sponsorships

Silver Sponsors

+

Retool Liftoff AMP Project

Bronze Sponsors

Streamat The Standard Daily Writers Per Hour February 2021 calendar Buy.Fineproxy.Org Anagram Solver Bugsnag Stability Monitoring Mixpanel VPS Server Icons8: free icons, photos, illustrations, and music Discord ThemeIsle Fire Stick Tricks

diff --git a/tools/node_modules/eslint/lib/rules/indent.js b/tools/node_modules/eslint/lib/rules/indent.js index 1c0dccc5c9891f..8f4079d31f91d9 100644 --- a/tools/node_modules/eslint/lib/rules/indent.js +++ b/tools/node_modules/eslint/lib/rules/indent.js @@ -1178,6 +1178,7 @@ module.exports = { offsets.setDesiredOffset(colonToken, firstToken, 1); offsets.setDesiredOffset(firstConsequentToken, firstToken, + firstConsequentToken.type === "Punctuator" && options.offsetTernaryExpressions ? 2 : 1); /* diff --git a/tools/node_modules/eslint/lib/rules/no-extra-parens.js b/tools/node_modules/eslint/lib/rules/no-extra-parens.js index 19c6fced79d4ff..307e340c958d88 100644 --- a/tools/node_modules/eslint/lib/rules/no-extra-parens.js +++ b/tools/node_modules/eslint/lib/rules/no-extra-parens.js @@ -844,45 +844,49 @@ module.exports = { ExportDefaultDeclaration: node => checkExpressionOrExportStatement(node.declaration), ExpressionStatement: node => checkExpressionOrExportStatement(node.expression), - "ForInStatement, ForOfStatement"(node) { - if (node.left.type !== "VariableDeclarator") { + ForInStatement(node) { + if (node.left.type !== "VariableDeclaration") { const firstLeftToken = sourceCode.getFirstToken(node.left, astUtils.isNotOpeningParenToken); if ( - firstLeftToken.value === "let" && ( - - /* - * If `let` is the only thing on the left side of the loop, it's the loop variable: `for ((let) of foo);` - * Removing it will cause a syntax error, because it will be parsed as the start of a VariableDeclarator. - */ - (firstLeftToken.range[1] === node.left.range[1] || /* - * If `let` is followed by a `[` token, it's a property access on the `let` value: `for ((let[foo]) of bar);` - * Removing it will cause the property access to be parsed as a destructuring declaration of `foo` instead. - */ - astUtils.isOpeningBracketToken( - sourceCode.getTokenAfter(firstLeftToken, astUtils.isNotClosingParenToken) - )) + firstLeftToken.value === "let" && + astUtils.isOpeningBracketToken( + sourceCode.getTokenAfter(firstLeftToken, astUtils.isNotClosingParenToken) ) ) { + + // ForInStatement#left expression cannot start with `let[`. tokensToIgnore.add(firstLeftToken); } } - if (node.type === "ForOfStatement") { - const hasExtraParens = node.right.type === "SequenceExpression" - ? hasDoubleExcessParens(node.right) - : hasExcessParens(node.right); + if (hasExcessParens(node.left)) { + report(node.left); + } - if (hasExtraParens) { - report(node.right); - } - } else if (hasExcessParens(node.right)) { + if (hasExcessParens(node.right)) { report(node.right); } + }, + + ForOfStatement(node) { + if (node.left.type !== "VariableDeclaration") { + const firstLeftToken = sourceCode.getFirstToken(node.left, astUtils.isNotOpeningParenToken); + + if (firstLeftToken.value === "let") { + + // ForOfStatement#left expression cannot start with `let`. + tokensToIgnore.add(firstLeftToken); + } + } if (hasExcessParens(node.left)) { report(node.left); } + + if (hasExcessParensWithPrecedence(node.right, PRECEDENCE_OF_ASSIGNMENT_EXPR)) { + report(node.right); + } }, ForStatement(node) { diff --git a/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js b/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js index 6136ebb9e0be11..94ad5ba6d5c23d 100644 --- a/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js +++ b/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js @@ -69,6 +69,28 @@ module.exports = { return node && node.type === "Literal" && typeof node.value === "string"; } + /** + * Gets flags of a regular expression created by the given `RegExp()` or `new RegExp()` call + * Examples: + * new RegExp(".") // => "" + * new RegExp(".", "gu") // => "gu" + * new RegExp(".", flags) // => null + * @param {ASTNode} node `CallExpression` or `NewExpression` node + * @returns {string|null} flags if they can be determined, `null` otherwise + * @private + */ + function getFlags(node) { + if (node.arguments.length < 2) { + return ""; + } + + if (isString(node.arguments[1])) { + return node.arguments[1].value; + } + + return null; + } + /** * Check syntax error in a given pattern. * @param {string} pattern The RegExp pattern to validate. @@ -104,18 +126,23 @@ module.exports = { return; } const pattern = node.arguments[0].value; - let flags = isString(node.arguments[1]) ? node.arguments[1].value : ""; + let flags = getFlags(node); - if (allowedFlags) { + if (flags && allowedFlags) { flags = flags.replace(allowedFlags, ""); } - // If flags are unknown, check both are errored or not. - const message = validateRegExpFlags(flags) || ( - flags - ? validateRegExpPattern(pattern, flags.indexOf("u") !== -1) - : validateRegExpPattern(pattern, true) && validateRegExpPattern(pattern, false) - ); + const message = + ( + flags && validateRegExpFlags(flags) + ) || + ( + + // If flags are unknown, report the regex only if its pattern is invalid both with and without the "u" flag + flags === null + ? validateRegExpPattern(pattern, true) && validateRegExpPattern(pattern, false) + : validateRegExpPattern(pattern, flags.includes("u")) + ); if (message) { context.report({ diff --git a/tools/node_modules/eslint/lib/rules/no-shadow.js b/tools/node_modules/eslint/lib/rules/no-shadow.js index 1be8590e47abcb..a0b1db50c0b5f2 100644 --- a/tools/node_modules/eslint/lib/rules/no-shadow.js +++ b/tools/node_modules/eslint/lib/rules/no-shadow.js @@ -44,7 +44,8 @@ module.exports = { ], messages: { - noShadow: "'{{name}}' is already declared in the upper scope." + noShadow: "'{{name}}' is already declared in the upper scope on line {{shadowedLine}} column {{shadowedColumn}}.", + noShadowGlobal: "'{{name}}' is already a global variable." } }, @@ -117,6 +118,29 @@ module.exports = { return def && def.name.range; } + /** + * Get declared line and column of a variable. + * @param {eslint-scope.Variable} variable The variable to get. + * @returns {Object} The declared line and column of the variable. + */ + function getDeclaredLocation(variable) { + const identifier = variable.identifiers[0]; + let obj; + + if (identifier) { + obj = { + global: false, + line: identifier.loc.start.line, + column: identifier.loc.start.column + 1 + }; + } else { + obj = { + global: true + }; + } + return obj; + } + /** * Checks if a variable is in TDZ of scopeVar. * @param {Object} variable The variable to check. @@ -165,10 +189,18 @@ module.exports = { !isOnInitializer(variable, shadowed) && !(options.hoist !== "all" && isInTdz(variable, shadowed)) ) { + const location = getDeclaredLocation(shadowed); + const messageId = location.global ? "noShadowGlobal" : "noShadow"; + const data = { name: variable.name }; + + if (!location.global) { + data.shadowedLine = location.line; + data.shadowedColumn = location.column; + } context.report({ node: variable.identifiers[0], - messageId: "noShadow", - data: variable + messageId, + data }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-useless-rename.js b/tools/node_modules/eslint/lib/rules/no-useless-rename.js index fa88f37f50b79c..a7cec025da7e70 100644 --- a/tools/node_modules/eslint/lib/rules/no-useless-rename.js +++ b/tools/node_modules/eslint/lib/rules/no-useless-rename.js @@ -5,6 +5,12 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("./utils/ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -54,11 +60,10 @@ module.exports = { * Reports error for unnecessarily renamed assignments * @param {ASTNode} node node to report * @param {ASTNode} initial node with initial name value - * @param {ASTNode} result node with new name value * @param {string} type the type of the offending node * @returns {void} */ - function reportError(node, initial, result, type) { + function reportError(node, initial, type) { const name = initial.type === "Identifier" ? initial.name : initial.value; return context.report({ @@ -69,18 +74,21 @@ module.exports = { type }, fix(fixer) { - if (sourceCode.commentsExistBetween(initial, result)) { + const replacementNode = node.type === "Property" ? node.value : node.local; + + if (sourceCode.getCommentsInside(node).length > sourceCode.getCommentsInside(replacementNode).length) { return null; } - const replacementText = result.type === "AssignmentPattern" - ? sourceCode.getText(result) - : name; + // Don't autofix code such as `({foo: (foo) = a} = obj);`, parens are not allowed in shorthand properties. + if ( + replacementNode.type === "AssignmentPattern" && + astUtils.isParenthesised(sourceCode, replacementNode.left) + ) { + return null; + } - return fixer.replaceTextRange([ - initial.range[0], - result.range[1] - ], replacementText); + return fixer.replaceText(node, sourceCode.getText(replacementNode)); } }); } @@ -97,19 +105,11 @@ module.exports = { for (const property of node.properties) { - /* - * TODO: Remove after babel-eslint removes ExperimentalRestProperty - * https://github.com/eslint/eslint/issues/12335 - */ - if (property.type === "ExperimentalRestProperty") { - continue; - } - /** * Properties using shorthand syntax and rest elements can not be renamed. * If the property is computed, we have no idea if a rename is useless or not. */ - if (property.shorthand || property.type === "RestElement" || property.computed) { + if (property.type !== "Property" || property.shorthand || property.computed) { continue; } @@ -117,7 +117,7 @@ module.exports = { const renamedKey = property.value.type === "AssignmentPattern" ? property.value.left.name : property.value.name; if (key === renamedKey) { - reportError(property, property.key, property.value, "Destructuring assignment"); + reportError(property, property.key, "Destructuring assignment"); } } } @@ -134,7 +134,7 @@ module.exports = { if (node.imported.name === node.local.name && node.imported.range[0] !== node.local.range[0]) { - reportError(node, node.imported, node.local, "Import"); + reportError(node, node.imported, "Import"); } } @@ -150,7 +150,7 @@ module.exports = { if (node.local.name === node.exported.name && node.local.range[0] !== node.exported.range[0]) { - reportError(node, node.local, node.exported, "Export"); + reportError(node, node.local, "Export"); } } diff --git a/tools/node_modules/eslint/lib/rules/prefer-const.js b/tools/node_modules/eslint/lib/rules/prefer-const.js index 439a4db3c963f6..f6e79e71c3e975 100644 --- a/tools/node_modules/eslint/lib/rules/prefer-const.js +++ b/tools/node_modules/eslint/lib/rules/prefer-const.js @@ -5,6 +5,11 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const FixTracker = require("./utils/fix-tracker"); const astUtils = require("./utils/ast-utils"); //------------------------------------------------------------------------------ @@ -451,10 +456,18 @@ module.exports = { messageId: "useConst", data: node, fix: shouldFix - ? fixer => fixer.replaceText( - sourceCode.getFirstToken(varDeclParent, t => t.value === varDeclParent.kind), - "const" - ) + ? fixer => { + const letKeywordToken = sourceCode.getFirstToken(varDeclParent, t => t.value === varDeclParent.kind); + + /** + * Extend the replacement range to the whole declaration, + * in order to prevent other fixes in the same pass + * https://github.com/eslint/eslint/issues/13899 + */ + return new FixTracker(fixer, sourceCode) + .retainRange(varDeclParent.range) + .replaceTextRange(letKeywordToken.range, "const"); + } : null }); }); diff --git a/tools/node_modules/eslint/lib/rules/space-infix-ops.js b/tools/node_modules/eslint/lib/rules/space-infix-ops.js index 471c22210eb613..3c550984fc6252 100644 --- a/tools/node_modules/eslint/lib/rules/space-infix-ops.js +++ b/tools/node_modules/eslint/lib/rules/space-infix-ops.js @@ -132,7 +132,9 @@ module.exports = { if (nonSpacedConsequentNode) { report(node, nonSpacedConsequentNode); - } else if (nonSpacedAlternateNode) { + } + + if (nonSpacedAlternateNode) { report(node, nonSpacedAlternateNode); } } diff --git a/tools/node_modules/eslint/node_modules/esprima/package.json b/tools/node_modules/eslint/node_modules/esprima/package.json index 03d154ee722a3c..4dfb4a142e7aa5 100644 --- a/tools/node_modules/eslint/node_modules/esprima/package.json +++ b/tools/node_modules/eslint/node_modules/esprima/package.json @@ -4,8 +4,8 @@ "email": "ariya.hidayat@gmail.com" }, "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "esparse": "./bin/esparse.js", + "esvalidate": "./bin/esvalidate.js" }, "bugs": { "url": "https://github.com/jquery/esprima/issues" diff --git a/tools/node_modules/eslint/node_modules/flatted/package.json b/tools/node_modules/eslint/node_modules/flatted/package.json index 1834f209fa8a22..41a5b5defc6d20 100644 --- a/tools/node_modules/eslint/node_modules/flatted/package.json +++ b/tools/node_modules/eslint/node_modules/flatted/package.json @@ -57,5 +57,5 @@ "type": "module", "types": "types.d.ts", "unpkg": "min.js", - "version": "3.1.0" + "version": "3.1.1" } \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/which/package.json b/tools/node_modules/eslint/node_modules/which/package.json index 32eaa57575d680..9620a99a29e14c 100644 --- a/tools/node_modules/eslint/node_modules/which/package.json +++ b/tools/node_modules/eslint/node_modules/which/package.json @@ -5,7 +5,7 @@ "url": "http://blog.izs.me" }, "bin": { - "node-which": "bin/node-which" + "node-which": "./bin/node-which" }, "bugs": { "url": "https://github.com/isaacs/node-which/issues" diff --git a/tools/node_modules/eslint/package.json b/tools/node_modules/eslint/package.json index dda9992ee81177..24c8bc57f61b9f 100644 --- a/tools/node_modules/eslint/package.json +++ b/tools/node_modules/eslint/package.json @@ -154,5 +154,5 @@ "test:cli": "mocha", "webpack": "node Makefile.js webpack" }, - "version": "7.18.0" + "version": "7.19.0" } \ No newline at end of file From bfe0b46d929c81b842ba54258c6a94d2bf22d0c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Mon, 1 Feb 2021 14:42:01 +0100 Subject: [PATCH 012/108] src: simplify calls to BN_bin2bn in prime gen PR-URL: https://github.com/nodejs/node/pull/37169 Reviewed-By: James M Snell Reviewed-By: Rich Trott --- src/crypto/crypto_random.cc | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/crypto/crypto_random.cc b/src/crypto/crypto_random.cc index e5722169486e3e..ceac834cb94d6f 100644 --- a/src/crypto/crypto_random.cc +++ b/src/crypto/crypto_random.cc @@ -104,29 +104,21 @@ Maybe RandomPrimeTraits::AdditionalConfig( bool safe = args[offset + 1]->IsTrue(); if (!args[offset + 2]->IsUndefined()) { - params->add.reset(BN_secure_new()); + ArrayBufferOrViewContents add(args[offset + 2]); + params->add.reset(BN_bin2bn(add.data(), add.size(), nullptr)); if (!params->add) { THROW_ERR_CRYPTO_OPERATION_FAILED(env, "could not generate prime"); return Nothing(); } - ArrayBufferOrViewContents add(args[offset + 2]); - if (BN_bin2bn(add.data(), add.size(), params->add.get()) == nullptr) { - THROW_ERR_INVALID_ARG_VALUE(env, "invalid options.add"); - return Nothing(); - } } if (!args[offset + 3]->IsUndefined()) { - params->rem.reset(BN_secure_new()); + ArrayBufferOrViewContents rem(args[offset + 3]); + params->rem.reset(BN_bin2bn(rem.data(), rem.size(), nullptr)); if (!params->rem) { THROW_ERR_CRYPTO_OPERATION_FAILED(env, "could not generate prime"); return Nothing(); } - ArrayBufferOrViewContents rem(args[offset + 3]); - if (BN_bin2bn(rem.data(), rem.size(), params->rem.get()) == nullptr) { - THROW_ERR_INVALID_ARG_VALUE(env, "invalid options.rem"); - return Nothing(); - } } int bits = static_cast(size); From 4ebe38b212bfd648cb6229b59e5dbf92326f5cf6 Mon Sep 17 00:00:00 2001 From: linkgoron Date: Sun, 31 Jan 2021 01:16:18 +0200 Subject: [PATCH 013/108] timers: introduce setInterval async iterator Added setInterval async generator to timers\promises. Utilises async generators to provide an iterator compatible with `for await`. Co-Authored-By: Fabian Cook fix message PR-URL: https://github.com/nodejs/node/pull/37153 Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell --- doc/api/timers.md | 32 +++ lib/timers/promises.js | 58 +++++- test/parallel/test-timers-promisified.js | 250 +++++++++++++++++++++-- 3 files changed, 327 insertions(+), 13 deletions(-) diff --git a/doc/api/timers.md b/doc/api/timers.md index 108c102db51383..fe8f70f5572a93 100644 --- a/doc/api/timers.md +++ b/doc/api/timers.md @@ -363,6 +363,38 @@ added: v15.0.0 * `signal` {AbortSignal} An optional `AbortSignal` that can be used to cancel the scheduled `Immediate`. +### `timersPromises.setInterval([delay[, value[, options]]])` + + +Returns an async iterator that generates values in an interval of `delay` ms. + +* `delay` {number} The number of milliseconds to wait between iterations. + **Default**: `1`. +* `value` {any} A value with which the iterator returns. +* `options` {Object} + * `ref` {boolean} Set to `false` to indicate that the scheduled `Timeout` + between iterations should not require the Node.js event loop to + remain active. + **Default**: `true`. + * `signal` {AbortSignal} An optional `AbortSignal` that can be used to + cancel the scheduled `Timeout` between operations. + +```js +(async function() { + const { setInterval } = require('timers/promises'); + const interval = 100; + for await (const startTime of setInterval(interval, Date.now())) { + const now = Date.now(); + console.log(now); + if ((now - startTime) > 1000) + break; + } + console.log(Date.now()); +})(); +``` + [Event Loop]: https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#setimmediate-vs-settimeout [`AbortController`]: globals.md#globals_class_abortcontroller [`TypeError`]: errors.md#errors_class_typeerror diff --git a/lib/timers/promises.js b/lib/timers/promises.js index c46b98f798ccaf..cc2d264d987e20 100644 --- a/lib/timers/promises.js +++ b/lib/timers/promises.js @@ -18,7 +18,11 @@ const { codes: { ERR_INVALID_ARG_TYPE } } = require('internal/errors'); -const { validateAbortSignal } = require('internal/validators'); +const { + validateAbortSignal, + validateBoolean, + validateObject, +} = require('internal/validators'); function cancelListenerHandler(clear, reject) { if (!this._destroyed) { @@ -111,7 +115,59 @@ function setImmediate(value, options = {}) { () => signal.removeEventListener('abort', oncancel)) : ret; } +async function* setInterval(after, value, options = {}) { + validateObject(options, 'options'); + const { signal, ref = true } = options; + validateAbortSignal(signal, 'options.signal'); + validateBoolean(ref, 'options.ref'); + + if (signal?.aborted) + throw new AbortError(); + + let onCancel; + let interval; + try { + let notYielded = 0; + let callback; + interval = new Timeout(() => { + notYielded++; + if (callback) { + callback(); + callback = undefined; + } + }, after, undefined, true, true); + if (!ref) interval.unref(); + insert(interval, interval._idleTimeout); + if (signal) { + onCancel = () => { + // eslint-disable-next-line no-undef + clearInterval(interval); + if (callback) { + callback(PromiseReject(new AbortError())); + callback = undefined; + } + }; + signal.addEventListener('abort', onCancel, { once: true }); + } + + while (!signal?.aborted) { + if (notYielded === 0) { + await new Promise((resolve) => callback = resolve); + } + for (; notYielded > 0; notYielded--) { + yield value; + } + } + throw new AbortError(); + } finally { + // eslint-disable-next-line no-undef + clearInterval(interval); + signal?.removeEventListener('abort', onCancel); + } +} + module.exports = { setTimeout, setImmediate, + setInterval, }; diff --git a/test/parallel/test-timers-promisified.js b/test/parallel/test-timers-promisified.js index be73984b4fa602..e59fda58ceea49 100644 --- a/test/parallel/test-timers-promisified.js +++ b/test/parallel/test-timers-promisified.js @@ -19,6 +19,7 @@ const exec = promisify(child_process.exec); assert.strictEqual(setTimeout, timerPromises.setTimeout); assert.strictEqual(setImmediate, timerPromises.setImmediate); +const { setInterval } = timerPromises; process.on('multipleResolves', common.mustNotCall()); @@ -50,10 +51,51 @@ process.on('multipleResolves', common.mustNotCall()); })); } +{ + const iterable = setInterval(1, undefined); + const iterator = iterable[Symbol.asyncIterator](); + const promise = iterator.next(); + promise.then(common.mustCall((result) => { + assert.ok(!result.done, 'iterator was wrongly marked as done'); + assert.strictEqual(result.value, undefined); + return iterator.return(); + })).then(common.mustCall()); +} + +{ + const iterable = setInterval(1, 'foobar'); + const iterator = iterable[Symbol.asyncIterator](); + const promise = iterator.next(); + promise.then(common.mustCall((result) => { + assert.ok(!result.done, 'iterator was wronly marked as done'); + assert.strictEqual(result.value, 'foobar'); + return iterator.return(); + })).then(common.mustCall()); +} + +{ + const iterable = setInterval(1, 'foobar'); + const iterator = iterable[Symbol.asyncIterator](); + const promise = iterator.next(); + promise + .then(common.mustCall((result) => { + assert.ok(!result.done, 'iterator was wronly marked as done'); + assert.strictEqual(result.value, 'foobar'); + return iterator.next(); + })) + .then(common.mustCall((result) => { + assert.ok(!result.done, 'iterator was wrongly marked as done'); + assert.strictEqual(result.value, 'foobar'); + return iterator.return(); + })) + .then(common.mustCall()); +} + { const ac = new AbortController(); const signal = ac.signal; - assert.rejects(setTimeout(10, undefined, { signal }), /AbortError/); + assert.rejects(setTimeout(10, undefined, { signal }), /AbortError/) + .then(common.mustCall()); ac.abort(); } @@ -61,13 +103,15 @@ process.on('multipleResolves', common.mustNotCall()); const ac = new AbortController(); const signal = ac.signal; ac.abort(); // Abort in advance - assert.rejects(setTimeout(10, undefined, { signal }), /AbortError/); + assert.rejects(setTimeout(10, undefined, { signal }), /AbortError/) + .then(common.mustCall()); } { const ac = new AbortController(); const signal = ac.signal; - assert.rejects(setImmediate(10, { signal }), /AbortError/); + assert.rejects(setImmediate(10, { signal }), /AbortError/) + .then(common.mustCall()); ac.abort(); } @@ -75,23 +119,85 @@ process.on('multipleResolves', common.mustNotCall()); const ac = new AbortController(); const signal = ac.signal; ac.abort(); // Abort in advance - assert.rejects(setImmediate(10, { signal }), /AbortError/); + assert.rejects(setImmediate(10, { signal }), /AbortError/) + .then(common.mustCall()); +} + +{ + const ac = new AbortController(); + const { signal } = ac; + ac.abort(); // Abort in advance + + const iterable = setInterval(1, undefined, { signal }); + const iterator = iterable[Symbol.asyncIterator](); + assert.rejects(iterator.next(), /AbortError/).then(common.mustCall()); +} + +{ + const ac = new AbortController(); + const { signal } = ac; + + const iterable = setInterval(100, undefined, { signal }); + const iterator = iterable[Symbol.asyncIterator](); + + // This promise should take 100 seconds to resolve, so now aborting it should + // mean we abort early + const promise = iterator.next(); + + ac.abort(); // Abort in after we have a next promise + + assert.rejects(promise, /AbortError/).then(common.mustCall()); +} + +{ + // Check aborting after getting a value. + const ac = new AbortController(); + const { signal } = ac; + + const iterable = setInterval(100, undefined, { signal }); + const iterator = iterable[Symbol.asyncIterator](); + + const promise = iterator.next(); + const abortPromise = promise.then(common.mustCall(() => ac.abort())) + .then(() => iterator.next()); + assert.rejects(abortPromise, /AbortError/).then(common.mustCall()); } { // Check that aborting after resolve will not reject. const ac = new AbortController(); const signal = ac.signal; - setTimeout(10, undefined, { signal }).then(() => { - ac.abort(); - }); + assert.doesNotReject(setTimeout(10, undefined, { signal }) + .then(common.mustCall(() => { + ac.abort(); + }))).then(common.mustCall()); } { // Check that aborting after resolve will not reject. const ac = new AbortController(); const signal = ac.signal; - setImmediate(10, { signal }).then(() => { + assert.doesNotReject(setImmediate(10, { signal }).then(common.mustCall(() => { ac.abort(); + }))).then(common.mustCall()); +} + +{ + [1, '', Infinity, null, {}].forEach((ref) => { + const iterable = setInterval(10, undefined, { ref }); + assert.rejects(() => iterable[Symbol.asyncIterator]().next(), /ERR_INVALID_ARG_TYPE/) + .then(common.mustCall()); + }); + + [1, '', Infinity, null, {}].forEach((signal) => { + const iterable = setInterval(10, undefined, { signal }); + assert.rejects(() => iterable[Symbol.asyncIterator]().next(), /ERR_INVALID_ARG_TYPE/) + .then(common.mustCall()); + }); + + [1, '', Infinity, null, true, false].forEach((options) => { + const iterable = setInterval(10, undefined, options); + assert.rejects(() => iterable[Symbol.asyncIterator]().next(), /ERR_INVALID_ARG_TYPE/) + .then(common.mustCall()); }); } @@ -113,6 +219,43 @@ process.on('multipleResolves', common.mustNotCall()); })); } +{ + // Check that timer adding signals does not leak handlers + const signal = new NodeEventTarget(); + signal.aborted = false; + const iterator = setInterval(1, undefined, { signal }); + iterator.next().then(common.mustCall(() => { + assert.strictEqual(signal.listenerCount('abort'), 1); + iterator.return(); + })).finally(common.mustCall(() => { + assert.strictEqual(signal.listenerCount('abort'), 0); + })); +} + +{ + // Check that break removes the signal listener + const signal = new NodeEventTarget(); + signal.aborted = false; + async function tryBreak() { + const iterator = setInterval(10, undefined, { signal }); + let i = 0; + // eslint-disable-next-line no-unused-vars + for await (const _ of iterator) { + if (i === 0) { + assert.strictEqual(signal.listenerCount('abort'), 1); + } + i++; + if (i === 2) { + break; + } + } + assert.strictEqual(i, 2); + assert.strictEqual(signal.listenerCount('abort'), 0); + } + + tryBreak().then(common.mustCall()); +} + { Promise.all( [1, '', false, Infinity].map((i) => assert.rejects(setImmediate(10, i)), { @@ -152,16 +295,99 @@ process.on('multipleResolves', common.mustNotCall()); { exec(`${process.execPath} -pe "const assert = require('assert');` + - 'require(\'timers/promises\').setTimeout(1000, null, { ref: false }).' + - 'then(assert.fail)"').then(common.mustCall(({ stderr }) => { + 'require(\'timers/promises\').setTimeout(1000, null, { ref: false }).' + + 'then(assert.fail)"').then(common.mustCall(({ stderr }) => { + assert.strictEqual(stderr, ''); + })); +} + +{ + exec(`${process.execPath} -pe "const assert = require('assert');` + + 'require(\'timers/promises\').setImmediate(null, { ref: false }).' + + 'then(assert.fail)"').then(common.mustCall(({ stderr }) => { assert.strictEqual(stderr, ''); })); } { exec(`${process.execPath} -pe "const assert = require('assert');` + - 'require(\'timers/promises\').setImmediate(null, { ref: false }).' + - 'then(assert.fail)"').then(common.mustCall(({ stderr }) => { + 'const interval = require(\'timers/promises\')' + + '.setInterval(1000, null, { ref: false });' + + 'interval[Symbol.asyncIterator]().next()' + + '.then(assert.fail)"').then(common.mustCall(({ stderr }) => { assert.strictEqual(stderr, ''); })); } + +{ + async function runInterval(fn, intervalTime, signal) { + const input = 'foobar'; + const interval = setInterval(intervalTime, input, { signal }); + let iteration = 0; + for await (const value of interval) { + assert.strictEqual(value, input); + iteration++; + await fn(iteration); + } + } + + { + // Check that we call the correct amount of times. + const controller = new AbortController(); + const { signal } = controller; + + let loopCount = 0; + const delay = 20; + const timeoutLoop = runInterval(() => { + loopCount++; + if (loopCount === 5) controller.abort(); + if (loopCount > 5) throw new Error('ran too many times'); + }, delay, signal); + + assert.rejects(timeoutLoop, /AbortError/).then(common.mustCall(() => { + assert.strictEqual(loopCount, 5); + })); + } + + { + // Check that if we abort when we have some callbacks left, + // we actually call them. + const controller = new AbortController(); + const { signal } = controller; + const delay = 10; + let totalIterations = 0; + const timeoutLoop = runInterval(async (iterationNumber) => { + if (iterationNumber === 2) { + await setTimeout(delay * 2); + controller.abort(); + } + if (iterationNumber > totalIterations) { + totalIterations = iterationNumber; + } + }, delay, signal); + + timeoutLoop.catch(common.mustCall(() => { + assert.ok(totalIterations >= 3, `iterations was ${totalIterations} < 3`); + })); + } +} + +{ + // Check that the timing is correct + let pre = false; + let post = false; + setTimeout(1).then(() => pre = true); + const iterable = setInterval(2); + const iterator = iterable[Symbol.asyncIterator](); + + iterator.next().then(common.mustCall(() => { + assert.ok(pre, 'interval ran too early'); + assert.ok(!post, 'interval ran too late'); + return iterator.next(); + })).then(common.mustCall(() => { + assert.ok(post, 'second interval ran too early'); + return iterator.return(); + })); + + setTimeout(3).then(() => post = true); +} From 51575252f5a6e31d2532a28bfc71b153ac1a480f Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sat, 30 Jan 2021 20:54:28 -0800 Subject: [PATCH 014/108] test: remove flaky designation for test-http2-large-file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This seems to have stopped happening, possibly because it only ever happened on win2008 and that went eol last year. Closes: https://github.com/nodejs/node/issues/22327 PR-URL: https://github.com/nodejs/node/pull/37156 Fixes: https://github.com/nodejs/node/issues/22327 Reviewed-By: Colin Ihrig Reviewed-By: Stephen Belanger Reviewed-By: Michaël Zasso Reviewed-By: Richard Lau Reviewed-By: Gireesh Punathil Reviewed-By: James M Snell --- test/sequential/sequential.status | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/sequential/sequential.status b/test/sequential/sequential.status index fce8bd959f0326..e7f8640d621c08 100644 --- a/test/sequential/sequential.status +++ b/test/sequential/sequential.status @@ -9,8 +9,6 @@ prefix sequential test-cpu-prof-dir-worker: PASS, FLAKY [$system==win32] -# https://github.com/nodejs/node/issues/22327 -test-http2-large-file: PASS, FLAKY # https://github.com/nodejs/node/issues/26401 test-worker-prof: PASS, FLAKY From b87c0d6c1682fd81f93131d38c0b9f2da909dea4 Mon Sep 17 00:00:00 2001 From: Kalvin Vasconcellos Date: Wed, 3 Feb 2021 14:39:16 -0300 Subject: [PATCH 015/108] doc: fix typo in cli.md PR-URL: https://github.com/nodejs/node/pull/37214 Reviewed-By: Antoine du Hamel Reviewed-By: Richard Lau Reviewed-By: Luigi Pinca --- doc/api/cli.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/cli.md b/doc/api/cli.md index 5373f97fca07a9..044e8caf5882a2 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -357,7 +357,7 @@ Generating V8 snapshots takes time and memory (both memory managed by the V8 heap and native memory outside the V8 heap). The bigger the heap is, the more resources it needs. Node.js will adjust the V8 heap to accommondate the additional V8 heap memory overhead, and try its best to avoid using up -all the memory avialable to the process. When the process uses +all the memory available to the process. When the process uses more memory than the system deems appropriate, the process may be terminated abruptly by the system, depending on the system configuration. From 4cdc5ea823458e5d4fe0b7767529785d41fcbd3e Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Sat, 16 Jan 2021 18:17:57 +0100 Subject: [PATCH 016/108] http: fix ClientRequest unhandled errors ClientRequest could someone cause an unhandled error from socket. Fixes: https://github.com/nodejs/node/issues/36931 PR-URL: https://github.com/nodejs/node/pull/36970 Reviewed-By: Luigi Pinca Reviewed-By: Matteo Collina Reviewed-By: Benjamin Gruenbaum --- lib/_http_client.js | 16 ++++++------ test/parallel/test-http-client-abort3.js | 32 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 test/parallel/test-http-client-abort3.js diff --git a/lib/_http_client.js b/lib/_http_client.js index fbaebacc1559ed..70c8a26f3fc17f 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -818,13 +818,15 @@ function onSocketNT(req, socket, err) { req.emit('close'); } - if (!err && req.agent) { - socket?.emit('free'); - } else if (socket) { - finished(socket.destroy(err || req[kError]), (er) => { - _destroy(req, er || err); - }); - return; + if (socket) { + if (!err && req.agent && !socket.destroyed) { + socket.emit('free'); + } else { + finished(socket.destroy(err || req[kError]), (er) => { + _destroy(req, er || err); + }); + return; + } } _destroy(req, err || req[kError]); diff --git a/test/parallel/test-http-client-abort3.js b/test/parallel/test-http-client-abort3.js new file mode 100644 index 00000000000000..4fb7d0fdba8d6b --- /dev/null +++ b/test/parallel/test-http-client-abort3.js @@ -0,0 +1,32 @@ +'use strict'; + +const common = require('../common'); +const http = require('http'); +const net = require('net'); + +function createConnection() { + const socket = new net.Socket(); + + process.nextTick(function() { + socket.destroy(new Error('Oops')); + }); + + return socket; +} + +{ + const req = http.get({ createConnection }); + + req.on('error', common.expectsError({ name: 'Error', message: 'Oops' })); + req.abort(); +} + +{ + class CustomAgent extends http.Agent {} + CustomAgent.prototype.createConnection = createConnection; + + const req = http.get({ agent: new CustomAgent() }); + + req.on('error', common.expectsError({ name: 'Error', message: 'Oops' })); + req.abort(); +} From 48ce1eb364ef29839167b97667e14d61ab4f7f2c Mon Sep 17 00:00:00 2001 From: Darshan Sen Date: Sat, 30 Jan 2021 20:07:48 +0530 Subject: [PATCH 017/108] src: fix warning in string_search.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/nodejs/node/issues/37145 PR-URL: https://github.com/nodejs/node/pull/37146 Reviewed-By: Anna Henningsen Reviewed-By: Rich Trott Reviewed-By: James M Snell Reviewed-By: Juan José Arboleda Reviewed-By: Tobias Nießen --- src/string_search.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string_search.h b/src/string_search.h index 3d06f32058f673..3648bc015ab229 100644 --- a/src/string_search.h +++ b/src/string_search.h @@ -458,7 +458,7 @@ size_t StringSearch::BoyerMooreHorspoolSearch( const size_t subject_length = subject.length(); const size_t pattern_length = pattern_.length(); int* char_occurrences = bad_char_shift_table_; - int64_t badness = -pattern_length; + int64_t badness = -static_cast(pattern_length); // How bad we are doing without a good-suffix table. Char last_char = pattern_[pattern_length - 1]; From eb08afdf24fda4ca0e65d93ee82eb3019f4ff8fd Mon Sep 17 00:00:00 2001 From: Darshan Sen Date: Thu, 4 Feb 2021 19:24:51 +0530 Subject: [PATCH 018/108] doc: fix typo in globals.md PR-URL: https://github.com/nodejs/node/pull/37228 Reviewed-By: Richard Lau Reviewed-By: Antoine du Hamel Reviewed-By: Zijian Liu Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- doc/api/globals.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/globals.md b/doc/api/globals.md index 11b7ffa6388eb2..6144c662a22821 100644 --- a/doc/api/globals.md +++ b/doc/api/globals.md @@ -74,7 +74,7 @@ added: v15.0.0 The `'abort'` event is emitted when the `abortController.abort()` method is called. The callback is invoked with a single object argument with a -single `type` propety set to `'abort'`: +single `type` property set to `'abort'`: ```js const ac = new AbortController(); From eb7ec1b257d14e058c247d25e6434dfdce35561c Mon Sep 17 00:00:00 2001 From: Nitzan Uziely Date: Thu, 4 Feb 2021 15:34:47 +0200 Subject: [PATCH 019/108] timers: remove flaky setInterval test PR-URL: https://github.com/nodejs/node/pull/37227 Reviewed-By: Benjamin Gruenbaum Reviewed-By: Antoine du Hamel --- test/parallel/test-timers-promisified.js | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/test/parallel/test-timers-promisified.js b/test/parallel/test-timers-promisified.js index e59fda58ceea49..348f6c2ae0476d 100644 --- a/test/parallel/test-timers-promisified.js +++ b/test/parallel/test-timers-promisified.js @@ -348,28 +348,6 @@ process.on('multipleResolves', common.mustNotCall()); assert.strictEqual(loopCount, 5); })); } - - { - // Check that if we abort when we have some callbacks left, - // we actually call them. - const controller = new AbortController(); - const { signal } = controller; - const delay = 10; - let totalIterations = 0; - const timeoutLoop = runInterval(async (iterationNumber) => { - if (iterationNumber === 2) { - await setTimeout(delay * 2); - controller.abort(); - } - if (iterationNumber > totalIterations) { - totalIterations = iterationNumber; - } - }, delay, signal); - - timeoutLoop.catch(common.mustCall(() => { - assert.ok(totalIterations >= 3, `iterations was ${totalIterations} < 3`); - })); - } } { From c3778343aa4c16bb9e70fea701ce03e1074f993a Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Tue, 2 Feb 2021 15:22:04 +0100 Subject: [PATCH 020/108] repl: refactor to avoid unsafe array iteration PR-URL: https://github.com/nodejs/node/pull/37188 Reviewed-By: Zijian Liu Reviewed-By: Rich Trott Reviewed-By: Darshan Sen --- lib/readline.js | 2 +- lib/repl.js | 22 +-- test/parallel/test-repl-autocomplete.js | 215 ++++++++++++++++++++++++ 3 files changed, 227 insertions(+), 12 deletions(-) create mode 100644 test/parallel/test-repl-autocomplete.js diff --git a/lib/readline.js b/lib/readline.js index 38ddebaa4917ca..b5d841aa37a2fa 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -607,7 +607,7 @@ Interface.prototype._tabComplete = function(lastKeypressWasTab) { } // Result and the text that was completed. - const [completions, completeOn] = value; + const { 0: completions, 1: completeOn } = value; if (!completions || completions.length === 0) { return; diff --git a/lib/repl.js b/lib/repl.js index 09494c3f2fcf15..d5d9371de34428 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -54,6 +54,7 @@ const { ArrayPrototypePush, ArrayPrototypeReverse, ArrayPrototypeShift, + ArrayPrototypeSome, ArrayPrototypeSort, ArrayPrototypeSplice, ArrayPrototypeUnshift, @@ -1155,7 +1156,7 @@ REPLServer.prototype.complete = function() { function gracefulReaddir(...args) { try { - return fs.readdirSync(...args); + return ReflectApply(fs.readdirSync, null, args); } catch {} } @@ -1236,11 +1237,11 @@ function complete(line, callback) { ArrayPrototypeForEach(paths, (dir) => { dir = path.resolve(dir, subdir); const dirents = gracefulReaddir(dir, { withFileTypes: true }) || []; - for (const dirent of dirents) { + ArrayPrototypeForEach(dirents, (dirent) => { if (RegExpPrototypeTest(versionedFileNamesRe, dirent.name) || dirent.name === '.npm') { // Exclude versioned names that 'npm' installs. - continue; + return; } const extension = path.extname(dirent.name); const base = StringPrototypeSlice(dirent.name, 0, -extension.length); @@ -1249,18 +1250,17 @@ function complete(line, callback) { (!subdir || base !== 'index')) { ArrayPrototypePush(group, `${subdir}${base}`); } - continue; + return; } ArrayPrototypePush(group, `${subdir}${dirent.name}/`); const absolute = path.resolve(dir, dirent.name); - const subfiles = gracefulReaddir(absolute) || []; - for (const subfile of subfiles) { - if (ArrayPrototypeIncludes(indexes, subfile)) { - ArrayPrototypePush(group, `${subdir}${dirent.name}`); - break; - } + if (ArrayPrototypeSome( + gracefulReaddir(absolute) || [], + (subfile) => ArrayPrototypeIncludes(indexes, subfile) + )) { + ArrayPrototypePush(group, `${subdir}${dirent.name}`); } - } + }); }); if (group.length) { ArrayPrototypePush(completionGroups, group); diff --git a/test/parallel/test-repl-autocomplete.js b/test/parallel/test-repl-autocomplete.js new file mode 100644 index 00000000000000..e1d2189fdb17cb --- /dev/null +++ b/test/parallel/test-repl-autocomplete.js @@ -0,0 +1,215 @@ +'use strict'; + +// Flags: --expose-internals + +const common = require('../common'); +const stream = require('stream'); +const REPL = require('internal/repl'); +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); +const { inspect } = require('util'); + +common.skipIfDumbTerminal(); + +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); + +process.throwDeprecation = true; + +const defaultHistoryPath = path.join(tmpdir.path, '.node_repl_history'); + +// Create an input stream specialized for testing an array of actions +class ActionStream extends stream.Stream { + run(data) { + const _iter = data[Symbol.iterator](); + const doAction = () => { + const next = _iter.next(); + if (next.done) { + // Close the repl. Note that it must have a clean prompt to do so. + this.emit('keypress', '', { ctrl: true, name: 'd' }); + return; + } + const action = next.value; + + if (typeof action === 'object') { + this.emit('keypress', '', action); + } else { + this.emit('data', `${action}`); + } + setImmediate(doAction); + }; + doAction(); + } + resume() {} + pause() {} +} +ActionStream.prototype.readable = true; + +// Mock keys +const ENTER = { name: 'enter' }; +const UP = { name: 'up' }; +const DOWN = { name: 'down' }; +const LEFT = { name: 'left' }; +const RIGHT = { name: 'right' }; +const BACKSPACE = { name: 'backspace' }; +const TABULATION = { name: 'tab' }; +const WORD_LEFT = { name: 'left', ctrl: true }; +const WORD_RIGHT = { name: 'right', ctrl: true }; +const GO_TO_END = { name: 'end' }; +const SIGINT = { name: 'c', ctrl: true }; +const ESCAPE = { name: 'escape', meta: true }; + +const prompt = '> '; + +const tests = [ + { + env: { NODE_REPL_HISTORY: defaultHistoryPath }, + test: (function*() { + // Deleting Array iterator should not break history feature. + // + // Using a generator function instead of an object to allow the test to + // keep iterating even when Array.prototype[Symbol.iterator] has been + // deleted. + yield 'const ArrayIteratorPrototype ='; + yield ' Object.getPrototypeOf(Array.prototype[Symbol.iterator]());'; + yield ENTER; + yield 'const {next} = ArrayIteratorPrototype;'; + yield ENTER; + yield 'const realArrayIterator = Array.prototype[Symbol.iterator];'; + yield ENTER; + yield 'delete Array.prototype[Symbol.iterator];'; + yield ENTER; + yield 'delete ArrayIteratorPrototype.next;'; + yield ENTER; + yield UP; + yield UP; + yield DOWN; + yield DOWN; + yield 'fu'; + yield 'n'; + yield RIGHT; + yield BACKSPACE; + yield LEFT; + yield LEFT; + yield 'A'; + yield BACKSPACE; + yield GO_TO_END; + yield BACKSPACE; + yield WORD_LEFT; + yield WORD_RIGHT; + yield ESCAPE; + yield ENTER; + yield 'require("./'; + yield TABULATION; + yield SIGINT; + yield 'Array.proto'; + yield RIGHT; + yield '.pu'; + yield ENTER; + yield 'ArrayIteratorPrototype.next = next;'; + yield ENTER; + yield 'Array.prototype[Symbol.iterator] = realArrayIterator;'; + yield ENTER; + })(), + expected: [], + clean: false + }, +]; +const numtests = tests.length; + +const runTestWrap = common.mustCall(runTest, numtests); + +function cleanupTmpFile() { + try { + // Write over the file, clearing any history + fs.writeFileSync(defaultHistoryPath, ''); + } catch (err) { + if (err.code === 'ENOENT') return true; + throw err; + } + return true; +} + +function runTest() { + const opts = tests.shift(); + if (!opts) return; // All done + + const { expected, skip } = opts; + + // Test unsupported on platform. + if (skip) { + setImmediate(runTestWrap, true); + return; + } + const lastChunks = []; + let i = 0; + + REPL.createInternalRepl(opts.env, { + input: new ActionStream(), + output: new stream.Writable({ + write(chunk, _, next) { + const output = chunk.toString(); + + if (!opts.showEscapeCodes && + (output[0] === '\x1B' || /^[\r\n]+$/.test(output))) { + return next(); + } + + lastChunks.push(output); + + if (expected.length && !opts.checkTotal) { + try { + assert.strictEqual(output, expected[i]); + } catch (e) { + console.error(`Failed test # ${numtests - tests.length}`); + console.error('Last outputs: ' + inspect(lastChunks, { + breakLength: 5, colors: true + })); + throw e; + } + // TODO(BridgeAR): Auto close on last chunk! + i++; + } + + next(); + } + }), + allowBlockingCompletions: true, + completer: opts.completer, + prompt, + useColors: false, + preview: opts.preview, + terminal: true + }, function(err, repl) { + if (err) { + console.error(`Failed test # ${numtests - tests.length}`); + throw err; + } + + repl.once('close', () => { + if (opts.clean) + cleanupTmpFile(); + + if (opts.checkTotal) { + assert.deepStrictEqual(lastChunks, expected); + } else if (expected.length !== i) { + console.error(tests[numtests - tests.length - 1]); + throw new Error(`Failed test # ${numtests - tests.length}`); + } + + setImmediate(runTestWrap, true); + }); + + if (opts.columns) { + Object.defineProperty(repl, 'columns', { + value: opts.columns, + enumerable: true + }); + } + repl.input.run(opts.test); + }); +} + +// run the tests +runTest(); From 52c40c7a4854e108ae76a736c8179e790d0a2a74 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Fri, 5 Feb 2021 00:07:13 +0100 Subject: [PATCH 021/108] doc: fix CHANGELOG_ARCHIVE table of contents PR-URL: https://github.com/nodejs/node/pull/37232 Refs: https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_ARCHIVE.md#0.8.0 Reviewed-By: Richard Lau Reviewed-By: Beth Griggs --- doc/changelogs/CHANGELOG_ARCHIVE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/changelogs/CHANGELOG_ARCHIVE.md b/doc/changelogs/CHANGELOG_ARCHIVE.md index 650d4c6c69cddd..4914d45b955754 100644 --- a/doc/changelogs/CHANGELOG_ARCHIVE.md +++ b/doc/changelogs/CHANGELOG_ARCHIVE.md @@ -73,6 +73,7 @@ 0.8.3
0.8.2
0.8.1
+0.8.0
0.7.12
From 5906e85ce29ddd1065d23bd67ba2a4b9634f4c1c Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Fri, 5 Feb 2021 00:04:26 +0100 Subject: [PATCH 022/108] doc: fix version number for DEP006 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/37231 Reviewed-By: Juan José Arboleda Reviewed-By: Rich Trott Reviewed-By: Pooja D P Reviewed-By: Trivikram Kamat --- doc/api/deprecations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index c61d2ad9366af3..bb8cbe63725a19 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -173,7 +173,7 @@ changes: description: A deprecation code has been assigned. - version: v0.11.14 description: Runtime deprecation. - - version: v0.5.11 + - version: v0.5.10 description: Documentation-only deprecation. --> From acd087dffbb221530da900ac4fe1bc6ee4b2fe2b Mon Sep 17 00:00:00 2001 From: Benjamin Gruenbaum Date: Tue, 2 Feb 2021 19:30:43 +0200 Subject: [PATCH 023/108] fs: add AbortSignal support to watch PR-URL: https://github.com/nodejs/node/pull/37190 Refs: https://github.com/nodejs/node/pull/37179 Reviewed-By: James M Snell Reviewed-By: Antoine du Hamel Reviewed-By: Darshan Sen --- doc/api/fs.md | 7 +++++ lib/fs.js | 11 +++++++ test/parallel/test-fs-watch-abort-signal.js | 32 +++++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 test/parallel/test-fs-watch-abort-signal.js diff --git a/doc/api/fs.md b/doc/api/fs.md index 04735faff41bee..4a2182b86fc40d 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4123,6 +4123,9 @@ this API: [`fs.utimes()`][]. diff --git a/lib/fs.js b/lib/fs.js index d01e99c21b0178..368ddfae188fa7 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -1579,6 +1579,17 @@ function watch(filename, options, listener) { if (listener) { watcher.addListener('change', listener); } + if (options.signal) { + if (options.signal.aborted) { + process.nextTick(() => watcher.close()); + } else { + const listener = () => watcher.close(); + options.signal.addEventListener('abort', listener); + watcher.once('close', () => { + options.signal.removeEventListener('abort', listener); + }); + } + } return watcher; } diff --git a/test/parallel/test-fs-watch-abort-signal.js b/test/parallel/test-fs-watch-abort-signal.js new file mode 100644 index 00000000000000..cbe9a1457dc9ae --- /dev/null +++ b/test/parallel/test-fs-watch-abort-signal.js @@ -0,0 +1,32 @@ +// Flags: --expose-internals +'use strict'; + +// Verify that AbortSignal integration works for fs.watch + +const common = require('../common'); + +if (common.isIBMi) + common.skip('IBMi does not support `fs.watch()`'); + +const fs = require('fs'); +const fixtures = require('../common/fixtures'); + + +{ + // Signal aborted after creating the watcher + const file = fixtures.path('empty.js'); + const ac = new AbortController(); + const { signal } = ac; + const watcher = fs.watch(file, { signal }); + watcher.once('close', common.mustCall()); + setImmediate(() => ac.abort()); +} +{ + // Signal aborted before creating the watcher + const file = fixtures.path('empty.js'); + const ac = new AbortController(); + const { signal } = ac; + ac.abort(); + const watcher = fs.watch(file, { signal }); + watcher.once('close', common.mustCall()); +} From 2a5f67b3812a531f2bfed3330d827da165283163 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 28 Jan 2021 22:00:03 +0800 Subject: [PATCH 024/108] src: refactor bookkeeping of bootstrap status This patch 1. Refactors the bootstrap routine of the main instance so that when --no-node-snapshot is used, Environment::InitializeMainContext() will only be called once (previously it would be called twice, which was harmless for now but not ideal). 2. Mark the number of BaseObjects in RunBootstrapping() when creating the Environment from scratch and in InitializeMainContext() when the Environment is deserialized. Previously the marking was done in the Environment constructor and InitializeMainContext() respectively for the cctest which was incorrect because the cctest never uses an Environment that's not bootstrapped. Also renames the mark to base_object_created_after_bootstrap to reflect what it's intended for. PR-URL: https://github.com/nodejs/node/pull/37113 Refs: https://github.com/nodejs/node/pull/36943 Reviewed-By: James M Snell --- src/env-inl.h | 14 ++++++++--- src/env.cc | 9 ------- src/env.h | 5 ++-- src/node.cc | 2 +- src/node_main_instance.cc | 24 +++++++++--------- test/cctest/test_base_object_ptr.cc | 38 ++++++++++++----------------- 6 files changed, 43 insertions(+), 49 deletions(-) diff --git a/src/env-inl.h b/src/env-inl.h index 98badcd0362627..95b818373b9a0a 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -784,8 +784,12 @@ inline bool Environment::has_run_bootstrapping_code() const { return has_run_bootstrapping_code_; } -inline void Environment::set_has_run_bootstrapping_code(bool value) { - has_run_bootstrapping_code_ = value; +inline void Environment::DoneBootstrapping() { + has_run_bootstrapping_code_ = true; + // This adjusts the return value of base_object_created_after_bootstrap() so + // that tests that check the count do not have to account for internally + // created BaseObjects. + base_object_created_by_bootstrap_ = base_object_count_; } inline bool Environment::has_serialized_options() const { @@ -1089,8 +1093,12 @@ void Environment::modify_base_object_count(int64_t delta) { base_object_count_ += delta; } +int64_t Environment::base_object_created_after_bootstrap() const { + return base_object_count_ - base_object_created_by_bootstrap_; +} + int64_t Environment::base_object_count() const { - return base_object_count_ - initial_base_object_count_; + return base_object_count_; } void Environment::set_main_utf16(std::unique_ptr str) { diff --git a/src/env.cc b/src/env.cc index 69d5a33a945d9f..16c6fcc3db4749 100644 --- a/src/env.cc +++ b/src/env.cc @@ -422,10 +422,6 @@ Environment::Environment(IsolateData* isolate_data, "args", std::move(traced_value)); } - - // This adjusts the return value of base_object_count() so that tests that - // check the count do not have to account for internally created BaseObjects. - initial_base_object_count_ = base_object_count(); } Environment::Environment(IsolateData* isolate_data, @@ -468,10 +464,6 @@ void Environment::InitializeMainContext(Local context, per_process::node_start_time); performance_state_->Mark(performance::NODE_PERFORMANCE_MILESTONE_V8_START, performance::performance_v8_start); - - // This adjusts the return value of base_object_count() so that tests that - // check the count do not have to account for internally created BaseObjects. - initial_base_object_count_ = base_object_count(); } Environment::~Environment() { @@ -662,7 +654,6 @@ void Environment::RunCleanup() { TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment), "RunCleanup", this); bindings_.clear(); - initial_base_object_count_ = 0; CleanupHandles(); while (!cleanup_hooks_.empty() || diff --git a/src/env.h b/src/env.h index 38c087b650e3ac..f2fc681f56ed69 100644 --- a/src/env.h +++ b/src/env.h @@ -1132,7 +1132,7 @@ class Environment : public MemoryRetainer { inline void add_refs(int64_t diff); inline bool has_run_bootstrapping_code() const; - inline void set_has_run_bootstrapping_code(bool has_run_bootstrapping_code); + inline void DoneBootstrapping(); inline bool has_serialized_options() const; inline void set_has_serialized_options(bool has_serialized_options); @@ -1318,6 +1318,7 @@ class Environment : public MemoryRetainer { // no memory leaks caused by BaseObjects staying alive longer than expected // (in particular, no circular BaseObjectPtr references). inline void modify_base_object_count(int64_t delta); + inline int64_t base_object_created_after_bootstrap() const; inline int64_t base_object_count() const; inline int32_t stack_trace_limit() const { return 10; } @@ -1511,7 +1512,7 @@ class Environment : public MemoryRetainer { bool started_cleanup_ = false; int64_t base_object_count_ = 0; - int64_t initial_base_object_count_ = 0; + int64_t base_object_created_by_bootstrap_ = 0; std::atomic_bool is_stopping_ { false }; std::unordered_set unmanaged_fds_; diff --git a/src/node.cc b/src/node.cc index efb4876002f774..decaa755e39f12 100644 --- a/src/node.cc +++ b/src/node.cc @@ -415,7 +415,7 @@ MaybeLocal Environment::RunBootstrapping() { CHECK(req_wrap_queue()->IsEmpty()); CHECK(handle_wrap_queue()->IsEmpty()); - set_has_run_bootstrapping_code(true); + DoneBootstrapping(); return scope.Escape(result); } diff --git a/src/node_main_instance.cc b/src/node_main_instance.cc index 84d39831dcd1f7..37d9dbb9b75525 100644 --- a/src/node_main_instance.cc +++ b/src/node_main_instance.cc @@ -209,10 +209,18 @@ NodeMainInstance::CreateMainEnvironment(int* exit_code, {DeserializeNodeInternalFields, env.get()}) .ToLocalChecked(); + CHECK(!context.IsEmpty()); + Context::Scope context_scope(context); InitializeContextRuntime(context); SetIsolateErrorHandlers(isolate_, {}); + env->InitializeMainContext(context, env_info); +#if HAVE_INSPECTOR + env->InitializeInspector({}); +#endif + env->DoneBootstrapping(); } else { context = NewContext(isolate_); + CHECK(!context.IsEmpty()); Context::Scope context_scope(context); env.reset(new Environment(isolate_data_.get(), context, @@ -221,24 +229,16 @@ NodeMainInstance::CreateMainEnvironment(int* exit_code, nullptr, EnvironmentFlags::kDefaultFlags, {})); - } - - CHECK(!context.IsEmpty()); - Context::Scope context_scope(context); - - env->InitializeMainContext(context, env_info); - #if HAVE_INSPECTOR - env->InitializeInspector({}); + env->InitializeInspector({}); #endif - - if (!deserialize_mode_ && env->RunBootstrapping().IsEmpty()) { - return nullptr; + if (env->RunBootstrapping().IsEmpty()) { + return nullptr; + } } CHECK(env->req_wrap_queue()->IsEmpty()); CHECK(env->handle_wrap_queue()->IsEmpty()); - env->set_has_run_bootstrapping_code(true); return env; } diff --git a/test/cctest/test_base_object_ptr.cc b/test/cctest/test_base_object_ptr.cc index a3a8df98a9efc7..52a1e2aff79dde 100644 --- a/test/cctest/test_base_object_ptr.cc +++ b/test/cctest/test_base_object_ptr.cc @@ -14,10 +14,6 @@ using v8::Isolate; using v8::Local; using v8::Object; -// Environments may come with existing BaseObject instances. -// This variable offsets the expected BaseObject counts. -static const int BASE_OBJECT_COUNT = 0; - class BaseObjectPtrTest : public EnvironmentTestFixture {}; class DummyBaseObject : public BaseObject { @@ -51,12 +47,12 @@ TEST_F(BaseObjectPtrTest, ScopedDetached) { Env env_{handle_scope, argv}; Environment* env = *env_; - EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT); + EXPECT_EQ(env->base_object_created_after_bootstrap(), 0); { BaseObjectPtr ptr = DummyBaseObject::NewDetached(env); - EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1); + EXPECT_EQ(env->base_object_created_after_bootstrap(), 1); } - EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT); + EXPECT_EQ(env->base_object_created_after_bootstrap(), 0); } TEST_F(BaseObjectPtrTest, ScopedDetachedWithWeak) { @@ -67,14 +63,14 @@ TEST_F(BaseObjectPtrTest, ScopedDetachedWithWeak) { BaseObjectWeakPtr weak_ptr; - EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT); + EXPECT_EQ(env->base_object_created_after_bootstrap(), 0); { BaseObjectPtr ptr = DummyBaseObject::NewDetached(env); weak_ptr = ptr; - EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1); + EXPECT_EQ(env->base_object_created_after_bootstrap(), 1); } EXPECT_EQ(weak_ptr.get(), nullptr); - EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT); + EXPECT_EQ(env->base_object_created_after_bootstrap(), 0); } TEST_F(BaseObjectPtrTest, Undetached) { @@ -86,13 +82,12 @@ TEST_F(BaseObjectPtrTest, Undetached) { node::AddEnvironmentCleanupHook( isolate_, [](void* arg) { - EXPECT_EQ(static_cast(arg)->base_object_count(), - BASE_OBJECT_COUNT); + EXPECT_EQ(static_cast(arg)->base_object_count(), 0); }, env); BaseObjectPtr ptr = DummyBaseObject::New(env); - EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1); + EXPECT_EQ(env->base_object_created_after_bootstrap(), 1); } TEST_F(BaseObjectPtrTest, GCWeak) { @@ -109,21 +104,21 @@ TEST_F(BaseObjectPtrTest, GCWeak) { weak_ptr = ptr; ptr->MakeWeak(); - EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1); + EXPECT_EQ(env->base_object_created_after_bootstrap(), 1); EXPECT_EQ(weak_ptr.get(), ptr.get()); EXPECT_EQ(weak_ptr->persistent().IsWeak(), false); ptr.reset(); } - EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1); + EXPECT_EQ(env->base_object_created_after_bootstrap(), 1); EXPECT_NE(weak_ptr.get(), nullptr); EXPECT_EQ(weak_ptr->persistent().IsWeak(), true); v8::V8::SetFlagsFromString("--expose-gc"); isolate_->RequestGarbageCollectionForTesting(Isolate::kFullGarbageCollection); - EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT); + EXPECT_EQ(env->base_object_created_after_bootstrap(), 0); EXPECT_EQ(weak_ptr.get(), nullptr); } @@ -134,7 +129,7 @@ TEST_F(BaseObjectPtrTest, Moveable) { Environment* env = *env_; BaseObjectPtr ptr = DummyBaseObject::NewDetached(env); - EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1); + EXPECT_EQ(env->base_object_created_after_bootstrap(), 1); BaseObjectWeakPtr weak_ptr { ptr }; EXPECT_EQ(weak_ptr.get(), ptr.get()); @@ -145,12 +140,12 @@ TEST_F(BaseObjectPtrTest, Moveable) { BaseObjectWeakPtr weak_ptr2 = std::move(weak_ptr); EXPECT_EQ(weak_ptr2.get(), ptr2.get()); EXPECT_EQ(weak_ptr.get(), nullptr); - EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1); + EXPECT_EQ(env->base_object_created_after_bootstrap(), 1); ptr2.reset(); EXPECT_EQ(weak_ptr2.get(), nullptr); - EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT); + EXPECT_EQ(env->base_object_created_after_bootstrap(), 0); } TEST_F(BaseObjectPtrTest, NestedClasses) { @@ -174,8 +169,7 @@ TEST_F(BaseObjectPtrTest, NestedClasses) { node::AddEnvironmentCleanupHook( isolate_, [](void* arg) { - EXPECT_EQ(static_cast(arg)->base_object_count(), - BASE_OBJECT_COUNT); + EXPECT_EQ(static_cast(arg)->base_object_count(), 0); }, env); @@ -184,5 +178,5 @@ TEST_F(BaseObjectPtrTest, NestedClasses) { obj->ptr1 = DummyBaseObject::NewDetached(env); obj->ptr2 = DummyBaseObject::New(env); - EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 3); + EXPECT_EQ(env->base_object_created_after_bootstrap(), 3); } From 337b4e754042f8ea68eb236d6572361ccfb4aa47 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 29 Jan 2021 00:04:22 +0800 Subject: [PATCH 025/108] src: put (de)serialization code into node_snapshotable.h/cc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So that it's easier to find the corresponding code. PR-URL: https://github.com/nodejs/node/pull/37114 Refs: https://github.com/nodejs/node/pull/36943 Reviewed-By: Juan José Arboleda --- node.gyp | 2 ++ src/node_main_instance.cc | 14 +---------- src/node_snapshotable.cc | 39 ++++++++++++++++++++++++++++++ src/node_snapshotable.h | 21 ++++++++++++++++ tools/snapshot/snapshot_builder.cc | 18 +------------- 5 files changed, 64 insertions(+), 30 deletions(-) create mode 100644 src/node_snapshotable.cc create mode 100644 src/node_snapshotable.h diff --git a/node.gyp b/node.gyp index 131461de63d503..03868ab2ef1507 100644 --- a/node.gyp +++ b/node.gyp @@ -636,6 +636,7 @@ 'src/node_report_module.cc', 'src/node_report_utils.cc', 'src/node_serdes.cc', + 'src/node_snapshotable.cc', 'src/node_sockaddr.cc', 'src/node_stat_watcher.cc', 'src/node_symbols.cc', @@ -738,6 +739,7 @@ 'src/node_report.h', 'src/node_revert.h', 'src/node_root_certs.h', + 'src/node_snapshotable.h', 'src/node_sockaddr.h', 'src/node_sockaddr-inl.h', 'src/node_stat_watcher.h', diff --git a/src/node_main_instance.cc b/src/node_main_instance.cc index 37d9dbb9b75525..b1c9444fcad039 100644 --- a/src/node_main_instance.cc +++ b/src/node_main_instance.cc @@ -5,6 +5,7 @@ #include "node_external_reference.h" #include "node_internals.h" #include "node_options-inl.h" +#include "node_snapshotable.h" #include "node_v8_platform-inl.h" #include "util-inl.h" #if defined(LEAK_SANITIZER) @@ -22,7 +23,6 @@ using v8::HandleScope; using v8::Isolate; using v8::Local; using v8::Locker; -using v8::Object; std::unique_ptr NodeMainInstance::registry_ = nullptr; @@ -167,18 +167,6 @@ int NodeMainInstance::Run(const EnvSerializeInfo* env_info) { return exit_code; } -void DeserializeNodeInternalFields(Local holder, - int index, - v8::StartupData payload, - void* env) { - if (payload.raw_size == 0) { - holder->SetAlignedPointerInInternalField(index, nullptr); - return; - } - // No embedder object in the builtin snapshot yet. - UNREACHABLE(); -} - DeleteFnPtr NodeMainInstance::CreateMainEnvironment(int* exit_code, const EnvSerializeInfo* env_info) { diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc new file mode 100644 index 00000000000000..21de10868564d3 --- /dev/null +++ b/src/node_snapshotable.cc @@ -0,0 +1,39 @@ + +#include "node_snapshotable.h" +#include "base_object-inl.h" + +namespace node { + +using v8::Local; +using v8::Object; +using v8::StartupData; + +void DeserializeNodeInternalFields(Local holder, + int index, + v8::StartupData payload, + void* env) { + if (payload.raw_size == 0) { + holder->SetAlignedPointerInInternalField(index, nullptr); + return; + } + // No embedder object in the builtin snapshot yet. + UNREACHABLE(); +} + +StartupData SerializeNodeContextInternalFields(Local holder, + int index, + void* env) { + void* ptr = holder->GetAlignedPointerFromInternalField(index); + if (ptr == nullptr || ptr == env) { + return StartupData{nullptr, 0}; + } + if (ptr == env && index == ContextEmbedderIndex::kEnvironment) { + return StartupData{nullptr, 0}; + } + + // No embedder objects in the builtin snapshot yet. + UNREACHABLE(); + return StartupData{nullptr, 0}; +} + +} // namespace node diff --git a/src/node_snapshotable.h b/src/node_snapshotable.h new file mode 100644 index 00000000000000..c45c1381b5554f --- /dev/null +++ b/src/node_snapshotable.h @@ -0,0 +1,21 @@ + +#ifndef SRC_NODE_SNAPSHOTABLE_H_ +#define SRC_NODE_SNAPSHOTABLE_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "v8.h" +namespace node { + +v8::StartupData SerializeNodeContextInternalFields(v8::Local holder, + int index, + void* env); +void DeserializeNodeInternalFields(v8::Local holder, + int index, + v8::StartupData payload, + void* env); +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_NODE_SNAPSHOTABLE_H_ diff --git a/tools/snapshot/snapshot_builder.cc b/tools/snapshot/snapshot_builder.cc index eb755b7d29ed7c..f97c646dfa17c4 100644 --- a/tools/snapshot/snapshot_builder.cc +++ b/tools/snapshot/snapshot_builder.cc @@ -6,6 +6,7 @@ #include "node_external_reference.h" #include "node_internals.h" #include "node_main_instance.h" +#include "node_snapshotable.h" #include "node_v8_platform-inl.h" namespace node { @@ -14,7 +15,6 @@ using v8::Context; using v8::HandleScope; using v8::Isolate; using v8::Local; -using v8::Object; using v8::SnapshotCreator; using v8::StartupData; @@ -75,22 +75,6 @@ const EnvSerializeInfo* NodeMainInstance::GetEnvSerializeInfo() { return ss.str(); } -static StartupData SerializeNodeContextInternalFields(Local holder, - int index, - void* env) { - void* ptr = holder->GetAlignedPointerFromInternalField(index); - if (ptr == nullptr || ptr == env) { - return StartupData{nullptr, 0}; - } - if (ptr == env && index == ContextEmbedderIndex::kEnvironment) { - return StartupData{nullptr, 0}; - } - - // No embedder objects in the builtin snapshot yet. - UNREACHABLE(); - return StartupData{nullptr, 0}; -} - std::string SnapshotBuilder::Generate( const std::vector args, const std::vector exec_args) { From 8a254058f581b868309585bd6aafbf4fc6b6f1cc Mon Sep 17 00:00:00 2001 From: cjihrig Date: Thu, 4 Feb 2021 12:07:27 -0500 Subject: [PATCH 026/108] doc: fix accommodate typos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/37229 Reviewed-By: Antoine du Hamel Reviewed-By: Richard Lau Reviewed-By: Michael Dawson Reviewed-By: Juan José Arboleda Reviewed-By: Pooja D P Reviewed-By: Trivikram Kamat Reviewed-By: Darshan Sen --- doc/api/cli.md | 2 +- doc/changelogs/CHANGELOG_V15.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/cli.md b/doc/api/cli.md index 044e8caf5882a2..70cb69cd54a451 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -355,7 +355,7 @@ Node.js instance runs out of memory when `max_count` is greater than `0`. Generating V8 snapshots takes time and memory (both memory managed by the V8 heap and native memory outside the V8 heap). The bigger the heap is, -the more resources it needs. Node.js will adjust the V8 heap to accommondate +the more resources it needs. Node.js will adjust the V8 heap to accommodate the additional V8 heap memory overhead, and try its best to avoid using up all the memory available to the process. When the process uses more memory than the system deems appropriate, the process may be terminated diff --git a/doc/changelogs/CHANGELOG_V15.md b/doc/changelogs/CHANGELOG_V15.md index f8bd62ce317045..5ddb5d7544a3b5 100644 --- a/doc/changelogs/CHANGELOG_V15.md +++ b/doc/changelogs/CHANGELOG_V15.md @@ -1097,7 +1097,7 @@ With the new `--heapsnapshot-near-heap-limit=max_count` experimental command lin When generating snapshots, garbage collection may be triggered and bring the heap usage down, therefore multiple snapshots may be written to disk before the Node.js instance finally runs out of memory. These heap snapshots can be compared to determine what objects are being allocated during the time consecutive snapshots are taken. -Generating V8 snapshots takes time and memory (both memory managed by the V8 heap and native memory outside the V8 heap). The bigger the heap is, the more resources it needs. Node.js will adjust the V8 heap to accommondate the additional V8 heap memory overhead, and try its best to avoid using up all the memory avialable to the process. +Generating V8 snapshots takes time and memory (both memory managed by the V8 heap and native memory outside the V8 heap). The bigger the heap is, the more resources it needs. Node.js will adjust the V8 heap to accommodate the additional V8 heap memory overhead, and try its best to avoid using up all the memory avialable to the process. ```console $ node --max-old-space-size=100 --heapsnapshot-near-heap-limit=3 index.js From 66a14d3992b6006e1d82e5556475fedcdbb857af Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Fri, 25 Sep 2020 15:22:52 -0500 Subject: [PATCH 027/108] vm: add importModuleDynamically option to compileFunction This reverts commit 2d5d77306f6dff9110c1f77fefab25f973415770. See: https://github.com/nodejs/node/pull/32985 See: https://github.com/nodejs/node/pull/33364 See: https://github.com/nodejs/node/issues/33166 Fixes: https://github.com/nodejs/node/issues/31860 PR-URL: https://github.com/nodejs/node/pull/35431 Reviewed-By: Matteo Collina Reviewed-By: Antoine du Hamel Reviewed-By: Ujjwal Sharma --- doc/api/vm.md | 13 +++++++++ lib/internal/modules/cjs/loader.js | 40 ++++++++------------------- lib/vm.js | 17 ++++++++++++ test/parallel/test-vm-module-basic.js | 19 ++++++++++++- 4 files changed, 60 insertions(+), 29 deletions(-) diff --git a/doc/api/vm.md b/doc/api/vm.md index 1bd9303fc4ef0d..cb97cda7d791c0 100644 --- a/doc/api/vm.md +++ b/doc/api/vm.md @@ -813,6 +813,9 @@ const vm = require('vm'); * `format`: {string} Must be one of `'raw'`, `'pkcs8'`, `'spki'`, `'jwk'`, or - `node.keyObject`. + `'node.keyObject'`. * `key`: {CryptoKey} * Returns: {Promise} containing {ArrayBuffer}, or, if `format` is - `node.keyObject`, a {KeyObject}. + `'node.keyObject'`, a {KeyObject}. Exports the given key into the specified format, if supported. @@ -695,7 +695,7 @@ added: v15.0.0 --> * `format`: {string} Must be one of `'raw'`, `'pkcs8'`, `'spki'`, `'jwk'`, or - `node.keyObject`. + `'node.keyObject'`. * `keyData`: {ArrayBuffer|TypedArray|DataView|Buffer|KeyObject} * `algorithm`: {RsaHashedImportParams|EcKeyImportParams|HmacImportParams|AesImportParams|Pbkdf2ImportParams|NodeDsaImportParams|NodeDhImportParams|NodeScryptImportParams|NodeEdKeyImportParams} @@ -1465,7 +1465,7 @@ added: v15.0.0 The Node.js Web Crypto API extends various aspects of the Web Crypto API. These extensions are consistently identified by prepending names with the -`node.` prefix. For instance, the `node.keyObject` key format can be +`node.` prefix. For instance, the `'node.keyObject'` key format can be used with the `subtle.exportKey()` and `subtle.importKey()` methods to convert between a WebCrypto {CryptoKey} object and a Node.js {KeyObject}. From 760f126adb010e1e82489dc94fd7eb87613fbe9a Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Wed, 3 Feb 2021 11:08:23 +0100 Subject: [PATCH 032/108] doc: mark Certificate methods as static, add missing KeyObject.from MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/37198 Reviewed-By: James M Snell Reviewed-By: Tobias Nießen --- doc/api/crypto.md | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 9088b78babdadb..dfe49afa497781 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -53,7 +53,7 @@ The `crypto` module provides the `Certificate` class for working with SPKAC data. The most common usage is handling output generated by the HTML5 `` element. Node.js uses [OpenSSL's SPKAC implementation][] internally. -### `Certificate.exportChallenge(spkac[, encoding])` +### Static method: `Certificate.exportChallenge(spkac[, encoding])` + +* `key` {CryptoKey} +* Returns: {KeyObject} + +Example: Converting a `CryptoKey` instance to a `KeyObject`: + +```js +const { webcrypto: { subtle }, KeyObject } = require('crypto'); + +(async function() { + const key = await subtle.generateKey({ + name: 'HMAC', + hash: 'SHA-256', + length: 256 + }, true, ['sign', 'verify']); + + const keyObject = KeyObject.from(key); + console.log(keyObject.symmetricKeySize); + // Prints: 32 (symmetric key size in bytes) +})(); +``` + ### `keyObject.asymmetricKeyDetails` * `format`: {string} Must be one of `'raw'`, `'pkcs8'`, `'spki'`, `'jwk'`, or @@ -642,7 +646,7 @@ extension that allows converting a {CryptoKey} into a Node.js {KeyObject}. | `'RSA-OAEP'` | ✔ | ✔ | ✔ | | | `'RSA-PSS'` | ✔ | ✔ | ✔ | | | `'RSASSA-PKCS1-v1_5'` | ✔ | ✔ | ✔ | | -| `'NODE-DSA'` 1 | ✔ | ✔ | ✔ | | +| `'NODE-DSA'` 1 | ✔ | ✔ | | | | `'NODE-DH'` 1 | ✔ | ✔ | | | | `'NODE-SCRYPT'` 1 | | | | | | `'NODE-ED25519'` 1 | ✔ | ✔ | ✔ | ✔ | @@ -692,6 +696,10 @@ The {CryptoKey} (secret key) generating algorithms supported include: ### `subtle.importKey(format, keyData, algorithm, extractable, keyUsages)` * `format`: {string} Must be one of `'raw'`, `'pkcs8'`, `'spki'`, `'jwk'`, or @@ -730,7 +738,7 @@ The algorithms currently supported include: | `'RSA-OAEP'` | ✔ | ✔ | ✔ | | | `'RSA-PSS'` | ✔ | ✔ | ✔ | | | `'RSASSA-PKCS1-v1_5'` | ✔ | ✔ | ✔ | | -| `'NODE-DSA'` 1 | ✔ | ✔ | ✔ | | +| `'NODE-DSA'` 1 | ✔ | ✔ | | | | `'NODE-DH'` 1 | ✔ | ✔ | | | | `'NODE-SCRYPT'` 1 | | | | ✔ | | `'NODE-ED25519'` 1 | ✔ | ✔ | ✔ | ✔ | diff --git a/src/crypto/crypto_dsa.cc b/src/crypto/crypto_dsa.cc index 8a80904d9c1afb..970ab5cf5f048b 100644 --- a/src/crypto/crypto_dsa.cc +++ b/src/crypto/crypto_dsa.cc @@ -22,7 +22,6 @@ using v8::Maybe; using v8::Nothing; using v8::Number; using v8::Object; -using v8::String; using v8::Uint32; using v8::Value; @@ -127,107 +126,6 @@ WebCryptoKeyExportStatus DSAKeyExportTraits::DoExport( } } -Maybe ExportJWKDsaKey( - Environment* env, - std::shared_ptr key, - Local target) { - ManagedEVPPKey pkey = key->GetAsymmetricKey(); - CHECK_EQ(EVP_PKEY_id(pkey.get()), EVP_PKEY_DSA); - - DSA* dsa = EVP_PKEY_get0_DSA(pkey.get()); - CHECK_NOT_NULL(dsa); - - const BIGNUM* y; - const BIGNUM* x; - const BIGNUM* p; - const BIGNUM* q; - const BIGNUM* g; - - DSA_get0_key(dsa, &y, &x); - DSA_get0_pqg(dsa, &p, &q, &g); - - if (target->Set( - env->context(), - env->jwk_kty_string(), - env->jwk_dsa_string()).IsNothing()) { - return Nothing(); - } - - if (SetEncodedValue(env, target, env->jwk_y_string(), y).IsNothing() || - SetEncodedValue(env, target, env->jwk_p_string(), p).IsNothing() || - SetEncodedValue(env, target, env->jwk_q_string(), q).IsNothing() || - SetEncodedValue(env, target, env->jwk_g_string(), g).IsNothing()) { - return Nothing(); - } - - if (key->GetKeyType() == kKeyTypePrivate && - SetEncodedValue(env, target, env->jwk_x_string(), x).IsNothing()) { - return Nothing(); - } - - return Just(true); -} - -std::shared_ptr ImportJWKDsaKey( - Environment* env, - Local jwk, - const FunctionCallbackInfo& args, - unsigned int offset) { - Local y_value; - Local p_value; - Local q_value; - Local g_value; - Local x_value; - - if (!jwk->Get(env->context(), env->jwk_y_string()).ToLocal(&y_value) || - !jwk->Get(env->context(), env->jwk_p_string()).ToLocal(&p_value) || - !jwk->Get(env->context(), env->jwk_q_string()).ToLocal(&q_value) || - !jwk->Get(env->context(), env->jwk_g_string()).ToLocal(&g_value) || - !jwk->Get(env->context(), env->jwk_x_string()).ToLocal(&x_value)) { - return std::shared_ptr(); - } - - if (!y_value->IsString() || - !p_value->IsString() || - !q_value->IsString() || - !q_value->IsString() || - (!x_value->IsUndefined() && !x_value->IsString())) { - THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK DSA key"); - return std::shared_ptr(); - } - - KeyType type = x_value->IsString() ? kKeyTypePrivate : kKeyTypePublic; - - DsaPointer dsa(DSA_new()); - - ByteSource y = ByteSource::FromEncodedString(env, y_value.As()); - ByteSource p = ByteSource::FromEncodedString(env, p_value.As()); - ByteSource q = ByteSource::FromEncodedString(env, q_value.As()); - ByteSource g = ByteSource::FromEncodedString(env, g_value.As()); - - if (!DSA_set0_key(dsa.get(), y.ToBN().release(), nullptr) || - !DSA_set0_pqg(dsa.get(), - p.ToBN().release(), - q.ToBN().release(), - g.ToBN().release())) { - THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK DSA key"); - return std::shared_ptr(); - } - - if (type == kKeyTypePrivate) { - ByteSource x = ByteSource::FromEncodedString(env, x_value.As()); - if (!DSA_set0_key(dsa.get(), nullptr, x.ToBN().release())) { - THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK DSA key"); - return std::shared_ptr(); - } - } - - EVPKeyPointer pkey(EVP_PKEY_new()); - CHECK_EQ(EVP_PKEY_set1_DSA(pkey.get(), dsa.get()), 1); - - return KeyObjectData::CreateAsymmetric(type, ManagedEVPPKey(std::move(pkey))); -} - Maybe GetDsaKeyDetail( Environment* env, std::shared_ptr key, @@ -269,4 +167,3 @@ void Initialize(Environment* env, Local target) { } // namespace DSAAlg } // namespace crypto } // namespace node - diff --git a/src/crypto/crypto_dsa.h b/src/crypto/crypto_dsa.h index b685d6a88f9412..3f241b33ba06cf 100644 --- a/src/crypto/crypto_dsa.h +++ b/src/crypto/crypto_dsa.h @@ -61,17 +61,6 @@ struct DSAKeyExportTraits final { using DSAKeyExportJob = KeyExportJob; -v8::Maybe ExportJWKDsaKey( - Environment* env, - std::shared_ptr key, - v8::Local target); - -std::shared_ptr ImportJWKDsaKey( - Environment* env, - v8::Local jwk, - const v8::FunctionCallbackInfo& args, - unsigned int offset); - v8::Maybe GetDsaKeyDetail( Environment* env, std::shared_ptr key, diff --git a/src/crypto/crypto_keys.cc b/src/crypto/crypto_keys.cc index 9c9fc4a9fcaf59..891e65dcbc2933 100644 --- a/src/crypto/crypto_keys.cc +++ b/src/crypto/crypto_keys.cc @@ -490,7 +490,6 @@ Maybe ExportJWKAsymmetricKey( case EVP_PKEY_RSA: // Fall through case EVP_PKEY_RSA_PSS: return ExportJWKRsaKey(env, key, target); - case EVP_PKEY_DSA: return ExportJWKDsaKey(env, key, target); case EVP_PKEY_EC: return ExportJWKEcKey(env, key, target); case EVP_PKEY_ED25519: // Fall through @@ -512,14 +511,12 @@ std::shared_ptr ImportJWKAsymmetricKey( unsigned int offset) { if (strcmp(kty, "RSA") == 0) { return ImportJWKRsaKey(env, jwk, args, offset); - } else if (strcmp(kty, "DSA") == 0) { - return ImportJWKDsaKey(env, jwk, args, offset); } else if (strcmp(kty, "EC") == 0) { return ImportJWKEcKey(env, jwk, args, offset); } char msg[1024]; - snprintf(msg, sizeof(msg), "%s is not a support JWK key type", kty); + snprintf(msg, sizeof(msg), "%s is not a supported JWK key type", kty); THROW_ERR_CRYPTO_INVALID_JWK(env, msg); return std::shared_ptr(); } diff --git a/test/parallel/test-webcrypto-export-import-dsa.js b/test/parallel/test-webcrypto-export-import-dsa.js index f73e6513dddaff..e6bcdebc5bbdc7 100644 --- a/test/parallel/test-webcrypto-export-import-dsa.js +++ b/test/parallel/test-webcrypto-export-import-dsa.js @@ -46,20 +46,6 @@ const keyData = { 'f26fe27c533587b765e57948439084e76fd6a4fd004f5c78d972cf7f100ec9494a902' + '645baca4b4c6f3993041e021c600daa0a9c4cc674c98bb07956374c84ac1c33af8816' + '3ea7e2587876', 'hex'), - jwk: { - kty: 'DSA', - y: 'mo32ny_jIYaeIJTjh7wdwrXzv_Ki4jz7pR08EZ-6a0wVpJSF-oEbaVXZHSjJ4uBEWn' + - 'ndxUJrL-ROAKbJJUx3bxP9ENvJNCYgd7HfcsFryEiBfGH7amB6vmDH0RUoq5vfVd5F' + - 'SVczoEe9daSLgWbxqj3qtoGiV0pPNRBvDXi2Qdc', - p: '1fNapXMOJhZv0-qB-PDusFvRJQ4WS3x2sYC22ulQltE97mlW4Vqa6nzxig33xdwybM' + - '7xy_l2NtIvhwt28mB_moZ9snVq7PZVBapI_epfXuVPUIoF2drna_JitMo2YswXa3xi' + - 'jHvuIHbfB_mmTgQCYw3-5j6vDtZNSLRp_hyaxKE', - q: 'sUITImz8-1njoDeeVZx0_4pzg-tMQc7Lbzcytw', - g: 'oIZbf4lU565YfI5qieOR6CZXxY8FzNlN5hdI6J4hfvqz2bX6hC68YlJZZpFq0revQi' + - 'qbJAeBels4K2WBQ0_RoWnHWtTQ44YqP0hOn58qgW-UOo5gYPJv4nxTNYe3ZeV5SEOQ' + - 'hOdv1qT9AE9ceNlyz38QDslJSpAmRbrKS0xvOZM', - x: 'YA2qCpxMxnTJi7B5VjdMhKwcM6-IFj6n4lh4dg', - } }, }; @@ -123,81 +109,6 @@ async function testImportPkcs8( } } -async function testImportJwk( - { name, publicUsages, privateUsages }, - size, - hash, - extractable) { - - const jwk = keyData[size].jwk; - - const [ - publicKey, - privateKey, - ] = await Promise.all([ - subtle.importKey( - 'jwk', - { - kty: jwk.kty, - y: jwk.y, - p: jwk.p, - q: jwk.q, - g: jwk.g, - alg: `NODE-DSA-${hash}` - }, - { name, hash }, - extractable, - publicUsages), - subtle.importKey( - 'jwk', - { ...jwk, alg: `NODE-DSA-${hash}` }, - { name, hash }, - extractable, - privateUsages) - ]); - - assert.strictEqual(publicKey.type, 'public'); - assert.strictEqual(privateKey.type, 'private'); - assert.strictEqual(publicKey.extractable, extractable); - assert.strictEqual(privateKey.extractable, extractable); - assert.strictEqual(publicKey.algorithm.name, name); - assert.strictEqual(privateKey.algorithm.name, name); - assert.strictEqual(publicKey.algorithm.modulusLength, size); - assert.strictEqual(privateKey.algorithm.modulusLength, size); - - if (extractable) { - const [ - pubJwk, - pvtJwk - ] = await Promise.all([ - subtle.exportKey('jwk', publicKey), - subtle.exportKey('jwk', privateKey) - ]); - - assert.strictEqual(pubJwk.kty, 'DSA'); - assert.strictEqual(pvtJwk.kty, 'DSA'); - assert.strictEqual(pubJwk.y, jwk.y); - assert.strictEqual(pvtJwk.y, jwk.y); - assert.strictEqual(pubJwk.p, jwk.p); - assert.strictEqual(pvtJwk.p, jwk.p); - assert.strictEqual(pubJwk.q, jwk.q); - assert.strictEqual(pvtJwk.q, jwk.q); - assert.strictEqual(pubJwk.g, jwk.g); - assert.strictEqual(pvtJwk.g, jwk.g); - assert.strictEqual(pvtJwk.x, jwk.x); - assert.strictEqual(pubJwk.x, undefined); - } else { - await assert.rejects( - subtle.exportKey('jwk', publicKey), { - message: /key is not extractable/ - }); - await assert.rejects( - subtle.exportKey('jwk', privateKey), { - message: /key is not extractable/ - }); - } -} - // combinations to test const testVectors = [ { @@ -215,7 +126,6 @@ const testVectors = [ testVectors.forEach((vector) => { variations.push(testImportSpki(vector, size, hash, extractable)); variations.push(testImportPkcs8(vector, size, hash, extractable)); - variations.push(testImportJwk(vector, size, hash, extractable)); }); }); }); From 48a634e514718e4d94785e5873d1d365d9dccade Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Wed, 3 Feb 2021 12:01:28 -0800 Subject: [PATCH 034/108] test: rename n-api to node-api This renames the macros used in the tests from `NAPI_*` to `NODE_API_*`. PR-URL: https://github.com/nodejs/node/pull/37217 Reviewed-By: Michael Dawson Reviewed-By: Beth Griggs Reviewed-By: Rich Trott --- .../2_function_arguments/binding.c | 20 +- test/js-native-api/3_callbacks/binding.c | 28 +- test/js-native-api/4_object_factory/binding.c | 8 +- .../5_function_factory/binding.c | 6 +- test/js-native-api/6_object_wrap/myobject.cc | 62 ++-- test/js-native-api/7_factory_wrap/binding.cc | 13 +- test/js-native-api/7_factory_wrap/myobject.cc | 26 +- .../8_passing_wrapped/binding.cc | 26 +- .../8_passing_wrapped/myobject.cc | 15 +- test/js-native-api/common.c | 37 +-- test/js-native-api/common.h | 26 +- test/js-native-api/test_array/test_array.c | 104 +++---- test/js-native-api/test_bigint/test_bigint.c | 66 ++-- .../test_constructor/test_constructor.c | 34 +- .../test_conversions/test_conversions.c | 74 ++--- .../test_conversions/test_null.c | 34 +- .../test_dataview/test_dataview.c | 48 +-- test/js-native-api/test_date/test_date.c | 34 +- test/js-native-api/test_error/test_error.c | 106 +++---- .../test_exception/test_exception.c | 38 +-- .../test_function/test_function.c | 117 +++---- .../js-native-api/test_general/test_general.c | 150 +++++---- .../test_handle_scope/test_handle_scope.c | 44 +-- .../test_instance_data/test_instance_data.c | 45 ++- test/js-native-api/test_new_target/binding.c | 46 +-- test/js-native-api/test_number/test_number.c | 58 ++-- test/js-native-api/test_object/test_null.c | 90 +++--- test/js-native-api/test_object/test_object.c | 292 +++++++++--------- .../js-native-api/test_promise/test_promise.c | 24 +- .../test_properties/test_properties.c | 49 ++- .../test_reference/test_reference.c | 89 +++--- test/js-native-api/test_string/test_string.c | 149 ++++----- test/js-native-api/test_symbol/test_symbol.c | 12 +- .../test_typedarray/test_typedarray.c | 111 +++---- test/node-api/1_hello_world/binding.c | 6 +- test/node-api/test_async/test_async.c | 100 +++--- test/node-api/test_async_context/binding.c | 52 ++-- test/node-api/test_buffer/test_buffer.c | 101 +++--- test/node-api/test_callback_scope/binding.c | 77 +++-- test/node-api/test_exception/test_exception.c | 8 +- test/node-api/test_fatal/test_fatal.c | 6 +- .../test_fatal_exception.c | 8 +- test/node-api/test_general/test_general.c | 29 +- .../test_instance_data/test_instance_data.c | 147 ++++----- test/node-api/test_make_callback/binding.c | 20 +- .../test_make_callback_recurse/binding.c | 10 +- test/node-api/test_policy/binding.c | 6 +- .../test_threadsafe_function/binding.c | 104 ++++--- test/node-api/test_uv_loop/test_uv_loop.cc | 28 +- .../test_worker_buffer_callback.c | 10 +- .../test_worker_terminate.c | 12 +- .../test_worker_terminate_finalization.c | 20 +- 52 files changed, 1374 insertions(+), 1451 deletions(-) diff --git a/test/js-native-api/2_function_arguments/binding.c b/test/js-native-api/2_function_arguments/binding.c index c9f2d03c7d2117..2f7a196f65c0b3 100644 --- a/test/js-native-api/2_function_arguments/binding.c +++ b/test/js-native-api/2_function_arguments/binding.c @@ -4,35 +4,35 @@ static napi_value Add(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 2, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); napi_valuetype valuetype1; - NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1)); - NAPI_ASSERT(env, valuetype0 == napi_number && valuetype1 == napi_number, + NODE_API_ASSERT(env, valuetype0 == napi_number && valuetype1 == napi_number, "Wrong argument type. Numbers expected."); double value0; - NAPI_CALL(env, napi_get_value_double(env, args[0], &value0)); + NODE_API_CALL(env, napi_get_value_double(env, args[0], &value0)); double value1; - NAPI_CALL(env, napi_get_value_double(env, args[1], &value1)); + NODE_API_CALL(env, napi_get_value_double(env, args[1], &value1)); napi_value sum; - NAPI_CALL(env, napi_create_double(env, value0 + value1, &sum)); + NODE_API_CALL(env, napi_create_double(env, value0 + value1, &sum)); return sum; } EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { - napi_property_descriptor desc = DECLARE_NAPI_PROPERTY("add", Add); - NAPI_CALL(env, napi_define_properties(env, exports, 1, &desc)); + napi_property_descriptor desc = DECLARE_NODE_API_PROPERTY("add", Add); + NODE_API_CALL(env, napi_define_properties(env, exports, 1, &desc)); return exports; } EXTERN_C_END diff --git a/test/js-native-api/3_callbacks/binding.c b/test/js-native-api/3_callbacks/binding.c index 5384fb1fc569b0..3be18daff1d7a6 100644 --- a/test/js-native-api/3_callbacks/binding.c +++ b/test/js-native-api/3_callbacks/binding.c @@ -5,31 +5,31 @@ static napi_value RunCallback(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 1, + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments. Expects a single argument."); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_function, + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_ASSERT(env, valuetype0 == napi_function, "Wrong type of arguments. Expects a function as first argument."); napi_valuetype valuetype1; - NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); - NAPI_ASSERT(env, valuetype1 == napi_undefined, + NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1)); + NODE_API_ASSERT(env, valuetype1 == napi_undefined, "Additional arguments should be undefined."); napi_value argv[1]; const char* str = "hello world"; size_t str_len = strlen(str); - NAPI_CALL(env, napi_create_string_utf8(env, str, str_len, argv)); + NODE_API_CALL(env, napi_create_string_utf8(env, str, str_len, argv)); napi_value global; - NAPI_CALL(env, napi_get_global(env, &global)); + NODE_API_CALL(env, napi_get_global(env, &global)); napi_value cb = args[0]; - NAPI_CALL(env, napi_call_function(env, global, cb, 1, argv, NULL)); + NODE_API_CALL(env, napi_call_function(env, global, cb, 1, argv, NULL)); return NULL; } @@ -37,21 +37,21 @@ static napi_value RunCallback(napi_env env, napi_callback_info info) { static napi_value RunCallbackWithRecv(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_value cb = args[0]; napi_value recv = args[1]; - NAPI_CALL(env, napi_call_function(env, recv, cb, 0, NULL, NULL)); + NODE_API_CALL(env, napi_call_function(env, recv, cb, 0, NULL, NULL)); return NULL; } EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor desc[2] = { - DECLARE_NAPI_PROPERTY("RunCallback", RunCallback), - DECLARE_NAPI_PROPERTY("RunCallbackWithRecv", RunCallbackWithRecv), + DECLARE_NODE_API_PROPERTY("RunCallback", RunCallback), + DECLARE_NODE_API_PROPERTY("RunCallbackWithRecv", RunCallbackWithRecv), }; - NAPI_CALL(env, napi_define_properties(env, exports, 2, desc)); + NODE_API_CALL(env, napi_define_properties(env, exports, 2, desc)); return exports; } EXTERN_C_END diff --git a/test/js-native-api/4_object_factory/binding.c b/test/js-native-api/4_object_factory/binding.c index 5e1403a892143a..5b06517744dd3e 100644 --- a/test/js-native-api/4_object_factory/binding.c +++ b/test/js-native-api/4_object_factory/binding.c @@ -4,19 +4,19 @@ static napi_value CreateObject(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_value obj; - NAPI_CALL(env, napi_create_object(env, &obj)); + NODE_API_CALL(env, napi_create_object(env, &obj)); - NAPI_CALL(env, napi_set_named_property(env, obj, "msg", args[0])); + NODE_API_CALL(env, napi_set_named_property(env, obj, "msg", args[0])); return obj; } EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_function(env, "exports", -1, CreateObject, NULL, &exports)); return exports; } diff --git a/test/js-native-api/5_function_factory/binding.c b/test/js-native-api/5_function_factory/binding.c index 73c6890253d580..679f09fee9e49e 100644 --- a/test/js-native-api/5_function_factory/binding.c +++ b/test/js-native-api/5_function_factory/binding.c @@ -3,20 +3,20 @@ static napi_value MyFunction(napi_env env, napi_callback_info info) { napi_value str; - NAPI_CALL(env, napi_create_string_utf8(env, "hello world", -1, &str)); + NODE_API_CALL(env, napi_create_string_utf8(env, "hello world", -1, &str)); return str; } static napi_value CreateFunction(napi_env env, napi_callback_info info) { napi_value fn; - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_function(env, "theFunction", -1, MyFunction, NULL, &fn)); return fn; } EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_function(env, "exports", -1, CreateFunction, NULL, &exports)); return exports; } diff --git a/test/js-native-api/6_object_wrap/myobject.cc b/test/js-native-api/6_object_wrap/myobject.cc index 30e6b66dcbe4b7..7f8fdd341673e6 100644 --- a/test/js-native-api/6_object_wrap/myobject.cc +++ b/test/js-native-api/6_object_wrap/myobject.cc @@ -19,52 +19,50 @@ void MyObject::Init(napi_env env, napi_value exports) { { "value", nullptr, nullptr, GetValue, SetValue, 0, napi_default, 0 }, { "valueReadonly", nullptr, nullptr, GetValue, nullptr, 0, napi_default, 0 }, - DECLARE_NAPI_PROPERTY("plusOne", PlusOne), - DECLARE_NAPI_PROPERTY("multiply", Multiply), + DECLARE_NODE_API_PROPERTY("plusOne", PlusOne), + DECLARE_NODE_API_PROPERTY("multiply", Multiply), }; napi_value cons; - NAPI_CALL_RETURN_VOID(env, napi_define_class( + NODE_API_CALL_RETURN_VOID(env, napi_define_class( env, "MyObject", -1, New, nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &cons)); - NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, cons, 1, &constructor)); + NODE_API_CALL_RETURN_VOID(env, + napi_create_reference(env, cons, 1, &constructor)); - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_set_named_property(env, exports, "MyObject", cons)); } napi_value MyObject::New(napi_env env, napi_callback_info info) { napi_value new_target; - NAPI_CALL(env, napi_get_new_target(env, info, &new_target)); + NODE_API_CALL(env, napi_get_new_target(env, info, &new_target)); bool is_constructor = (new_target != nullptr); size_t argc = 1; napi_value args[1]; napi_value _this; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr)); if (is_constructor) { // Invoked as constructor: `new MyObject(...)` double value = 0; napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); if (valuetype != napi_undefined) { - NAPI_CALL(env, napi_get_value_double(env, args[0], &value)); + NODE_API_CALL(env, napi_get_value_double(env, args[0], &value)); } MyObject* obj = new MyObject(value); obj->env_ = env; - NAPI_CALL(env, napi_wrap(env, - _this, - obj, - MyObject::Destructor, - nullptr, // finalize_hint - &obj->wrapper_)); + NODE_API_CALL(env, + napi_wrap(env, _this, obj, MyObject::Destructor, + nullptr /* finalize_hint */, &obj->wrapper_)); return _this; } @@ -74,24 +72,24 @@ napi_value MyObject::New(napi_env env, napi_callback_info info) { napi_value argv[1] = {args[0]}; napi_value cons; - NAPI_CALL(env, napi_get_reference_value(env, constructor, &cons)); + NODE_API_CALL(env, napi_get_reference_value(env, constructor, &cons)); napi_value instance; - NAPI_CALL(env, napi_new_instance(env, cons, argc, argv, &instance)); + NODE_API_CALL(env, napi_new_instance(env, cons, argc, argv, &instance)); return instance; } napi_value MyObject::GetValue(napi_env env, napi_callback_info info) { napi_value _this; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &_this, nullptr)); MyObject* obj; - NAPI_CALL(env, napi_unwrap(env, _this, reinterpret_cast(&obj))); + NODE_API_CALL(env, napi_unwrap(env, _this, reinterpret_cast(&obj))); napi_value num; - NAPI_CALL(env, napi_create_double(env, obj->value_, &num)); + NODE_API_CALL(env, napi_create_double(env, obj->value_, &num)); return num; } @@ -100,28 +98,28 @@ napi_value MyObject::SetValue(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; napi_value _this; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr)); MyObject* obj; - NAPI_CALL(env, napi_unwrap(env, _this, reinterpret_cast(&obj))); + NODE_API_CALL(env, napi_unwrap(env, _this, reinterpret_cast(&obj))); - NAPI_CALL(env, napi_get_value_double(env, args[0], &obj->value_)); + NODE_API_CALL(env, napi_get_value_double(env, args[0], &obj->value_)); return nullptr; } napi_value MyObject::PlusOne(napi_env env, napi_callback_info info) { napi_value _this; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &_this, nullptr)); MyObject* obj; - NAPI_CALL(env, napi_unwrap(env, _this, reinterpret_cast(&obj))); + NODE_API_CALL(env, napi_unwrap(env, _this, reinterpret_cast(&obj))); obj->value_ += 1; napi_value num; - NAPI_CALL(env, napi_create_double(env, obj->value_, &num)); + NODE_API_CALL(env, napi_create_double(env, obj->value_, &num)); return num; } @@ -130,25 +128,25 @@ napi_value MyObject::Multiply(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; napi_value _this; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr)); double multiple = 1; if (argc >= 1) { - NAPI_CALL(env, napi_get_value_double(env, args[0], &multiple)); + NODE_API_CALL(env, napi_get_value_double(env, args[0], &multiple)); } MyObject* obj; - NAPI_CALL(env, napi_unwrap(env, _this, reinterpret_cast(&obj))); + NODE_API_CALL(env, napi_unwrap(env, _this, reinterpret_cast(&obj))); napi_value cons; - NAPI_CALL(env, napi_get_reference_value(env, constructor, &cons)); + NODE_API_CALL(env, napi_get_reference_value(env, constructor, &cons)); const int kArgCount = 1; napi_value argv[kArgCount]; - NAPI_CALL(env, napi_create_double(env, obj->value_ * multiple, argv)); + NODE_API_CALL(env, napi_create_double(env, obj->value_ * multiple, argv)); napi_value instance; - NAPI_CALL(env, napi_new_instance(env, cons, kArgCount, argv, &instance)); + NODE_API_CALL(env, napi_new_instance(env, cons, kArgCount, argv, &instance)); return instance; } diff --git a/test/js-native-api/7_factory_wrap/binding.cc b/test/js-native-api/7_factory_wrap/binding.cc index 4a75156bd5359b..b1dbd8eee4945f 100644 --- a/test/js-native-api/7_factory_wrap/binding.cc +++ b/test/js-native-api/7_factory_wrap/binding.cc @@ -5,24 +5,25 @@ napi_value CreateObject(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + NODE_API_CALL(env, + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); napi_value instance; - NAPI_CALL(env, MyObject::NewInstance(env, args[0], &instance)); + NODE_API_CALL(env, MyObject::NewInstance(env, args[0], &instance)); return instance; } EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { - NAPI_CALL(env, MyObject::Init(env)); + NODE_API_CALL(env, MyObject::Init(env)); napi_property_descriptor descriptors[] = { - DECLARE_NAPI_GETTER("finalizeCount", MyObject::GetFinalizeCount), - DECLARE_NAPI_PROPERTY("createObject", CreateObject), + DECLARE_NODE_API_GETTER("finalizeCount", MyObject::GetFinalizeCount), + DECLARE_NODE_API_PROPERTY("createObject", CreateObject), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; diff --git a/test/js-native-api/7_factory_wrap/myobject.cc b/test/js-native-api/7_factory_wrap/myobject.cc index b7cc9c534f366a..a1a00972138a7f 100644 --- a/test/js-native-api/7_factory_wrap/myobject.cc +++ b/test/js-native-api/7_factory_wrap/myobject.cc @@ -17,7 +17,7 @@ void MyObject::Destructor(napi_env env, napi_value MyObject::GetFinalizeCount(napi_env env, napi_callback_info info) { napi_value result; - NAPI_CALL(env, napi_create_int32(env, finalize_count, &result)); + NODE_API_CALL(env, napi_create_int32(env, finalize_count, &result)); return result; } @@ -26,7 +26,7 @@ napi_ref MyObject::constructor; napi_status MyObject::Init(napi_env env) { napi_status status; napi_property_descriptor properties[] = { - DECLARE_NAPI_PROPERTY("plusOne", PlusOne), + DECLARE_NODE_API_PROPERTY("plusOne", PlusOne), }; napi_value cons; @@ -44,26 +44,24 @@ napi_value MyObject::New(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; napi_value _this; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr)); napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); MyObject* obj = new MyObject(); if (valuetype == napi_undefined) { obj->counter_ = 0; } else { - NAPI_CALL(env, napi_get_value_uint32(env, args[0], &obj->counter_)); + NODE_API_CALL(env, napi_get_value_uint32(env, args[0], &obj->counter_)); } obj->env_ = env; - NAPI_CALL(env, napi_wrap(env, - _this, - obj, - MyObject::Destructor, - nullptr, /* finalize_hint */ - &obj->wrapper_)); + NODE_API_CALL(env, + napi_wrap( + env, _this, obj, MyObject::Destructor, nullptr /* finalize_hint */, + &obj->wrapper_)); return _this; } @@ -88,16 +86,16 @@ napi_status MyObject::NewInstance(napi_env env, napi_value MyObject::PlusOne(napi_env env, napi_callback_info info) { napi_value _this; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &_this, nullptr)); MyObject* obj; - NAPI_CALL(env, napi_unwrap(env, _this, reinterpret_cast(&obj))); + NODE_API_CALL(env, napi_unwrap(env, _this, reinterpret_cast(&obj))); obj->counter_ += 1; napi_value num; - NAPI_CALL(env, napi_create_uint32(env, obj->counter_, &num)); + NODE_API_CALL(env, napi_create_uint32(env, obj->counter_, &num)); return num; } diff --git a/test/js-native-api/8_passing_wrapped/binding.cc b/test/js-native-api/8_passing_wrapped/binding.cc index 8670a86879eb1c..5b3b7909582e21 100644 --- a/test/js-native-api/8_passing_wrapped/binding.cc +++ b/test/js-native-api/8_passing_wrapped/binding.cc @@ -7,10 +7,11 @@ extern size_t finalize_count; static napi_value CreateObject(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + NODE_API_CALL(env, + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); napi_value instance; - NAPI_CALL(env, MyObject::NewInstance(env, args[0], &instance)); + NODE_API_CALL(env, MyObject::NewInstance(env, args[0], &instance)); return instance; } @@ -18,23 +19,26 @@ static napi_value CreateObject(napi_env env, napi_callback_info info) { static napi_value Add(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + NODE_API_CALL(env, + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); MyObject* obj1; - NAPI_CALL(env, napi_unwrap(env, args[0], reinterpret_cast(&obj1))); + NODE_API_CALL(env, + napi_unwrap(env, args[0], reinterpret_cast(&obj1))); MyObject* obj2; - NAPI_CALL(env, napi_unwrap(env, args[1], reinterpret_cast(&obj2))); + NODE_API_CALL(env, + napi_unwrap(env, args[1], reinterpret_cast(&obj2))); napi_value sum; - NAPI_CALL(env, napi_create_double(env, obj1->Val() + obj2->Val(), &sum)); + NODE_API_CALL(env, napi_create_double(env, obj1->Val() + obj2->Val(), &sum)); return sum; } static napi_value FinalizeCount(napi_env env, napi_callback_info info) { napi_value return_value; - NAPI_CALL(env, napi_create_uint32(env, finalize_count, &return_value)); + NODE_API_CALL(env, napi_create_uint32(env, finalize_count, &return_value)); return return_value; } @@ -43,12 +47,12 @@ napi_value Init(napi_env env, napi_value exports) { MyObject::Init(env); napi_property_descriptor desc[] = { - DECLARE_NAPI_PROPERTY("createObject", CreateObject), - DECLARE_NAPI_PROPERTY("add", Add), - DECLARE_NAPI_PROPERTY("finalizeCount", FinalizeCount), + DECLARE_NODE_API_PROPERTY("createObject", CreateObject), + DECLARE_NODE_API_PROPERTY("add", Add), + DECLARE_NODE_API_PROPERTY("finalizeCount", FinalizeCount), }; - NAPI_CALL(env, + NODE_API_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(*desc), desc)); return exports; diff --git a/test/js-native-api/8_passing_wrapped/myobject.cc b/test/js-native-api/8_passing_wrapped/myobject.cc index 28e207a4248d09..6ca61bb491ffe0 100644 --- a/test/js-native-api/8_passing_wrapped/myobject.cc +++ b/test/js-native-api/8_passing_wrapped/myobject.cc @@ -36,17 +36,17 @@ napi_value MyObject::New(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; napi_value _this; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr)); MyObject* obj = new MyObject(); napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); if (valuetype == napi_undefined) { obj->val_ = 0; } else { - NAPI_CALL(env, napi_get_value_double(env, args[0], &obj->val_)); + NODE_API_CALL(env, napi_get_value_double(env, args[0], &obj->val_)); } obj->env_ = env; @@ -54,12 +54,9 @@ napi_value MyObject::New(napi_env env, napi_callback_info info) { // The below call to napi_wrap() must request a reference to the wrapped // object via the out-parameter, because this ensures that we test the code // path that deals with a reference that is destroyed from its own finalizer. - NAPI_CALL(env, napi_wrap(env, - _this, - obj, - MyObject::Destructor, - nullptr, // finalize_hint - &obj->wrapper_)); + NODE_API_CALL(env, + napi_wrap(env, _this, obj, MyObject::Destructor, + nullptr /* finalize_hint */, &obj->wrapper_)); return _this; } diff --git a/test/js-native-api/common.c b/test/js-native-api/common.c index a6de256147c22a..865d2064bdef85 100644 --- a/test/js-native-api/common.c +++ b/test/js-native-api/common.c @@ -14,38 +14,35 @@ void add_returned_status(napi_env env, napi_value prop_value; if (actual_status != expected_status) { - snprintf(napi_message_string, sizeof(napi_message_string), "Invalid status [%d]", actual_status); + snprintf(napi_message_string, sizeof(napi_message_string), + "Invalid status [%d]", actual_status); } - NAPI_CALL_RETURN_VOID(env, - napi_create_string_utf8( - env, - (actual_status == expected_status ? - expected_message : - napi_message_string), - NAPI_AUTO_LENGTH, - &prop_value)); - NAPI_CALL_RETURN_VOID(env, - napi_set_named_property(env, - object, - key, - prop_value)); + NODE_API_CALL_RETURN_VOID(env, + napi_create_string_utf8( + env, + (actual_status == expected_status ? + expected_message : + napi_message_string), + NAPI_AUTO_LENGTH, + &prop_value)); + NODE_API_CALL_RETURN_VOID(env, + napi_set_named_property(env, object, key, prop_value)); } void add_last_status(napi_env env, const char* key, napi_value return_value) { napi_value prop_value; const napi_extended_error_info* p_last_error; - NAPI_CALL_RETURN_VOID(env, napi_get_last_error_info(env, &p_last_error)); + NODE_API_CALL_RETURN_VOID(env, + napi_get_last_error_info(env, &p_last_error)); - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_create_string_utf8(env, (p_last_error->error_message == NULL ? "napi_ok" : p_last_error->error_message), NAPI_AUTO_LENGTH, &prop_value)); - NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, - return_value, - key, - prop_value)); + NODE_API_CALL_RETURN_VOID(env, + napi_set_named_property(env, return_value, key, prop_value)); } diff --git a/test/js-native-api/common.h b/test/js-native-api/common.h index a524e8c7a75182..ab6785fb199b01 100644 --- a/test/js-native-api/common.h +++ b/test/js-native-api/common.h @@ -1,7 +1,7 @@ #include // Empty value so that macros here are able to return NULL or void -#define NAPI_RETVAL_NOTHING // Intentionally blank #define +#define NODE_API_RETVAL_NOTHING // Intentionally blank #define #define GET_AND_THROW_LAST_ERROR(env) \ do { \ @@ -18,7 +18,7 @@ } \ } while (0) -#define NAPI_ASSERT_BASE(env, assertion, message, ret_val) \ +#define NODE_API_ASSERT_BASE(env, assertion, message, ret_val) \ do { \ if (!(assertion)) { \ napi_throw_error( \ @@ -31,15 +31,15 @@ // Returns NULL on failed assertion. // This is meant to be used inside napi_callback methods. -#define NAPI_ASSERT(env, assertion, message) \ - NAPI_ASSERT_BASE(env, assertion, message, NULL) +#define NODE_API_ASSERT(env, assertion, message) \ + NODE_API_ASSERT_BASE(env, assertion, message, NULL) // Returns empty on failed assertion. // This is meant to be used inside functions with void return type. -#define NAPI_ASSERT_RETURN_VOID(env, assertion, message) \ - NAPI_ASSERT_BASE(env, assertion, message, NAPI_RETVAL_NOTHING) +#define NODE_API_ASSERT_RETURN_VOID(env, assertion, message) \ + NODE_API_ASSERT_BASE(env, assertion, message, NODE_API_RETVAL_NOTHING) -#define NAPI_CALL_BASE(env, the_call, ret_val) \ +#define NODE_API_CALL_BASE(env, the_call, ret_val) \ do { \ if ((the_call) != napi_ok) { \ GET_AND_THROW_LAST_ERROR((env)); \ @@ -48,17 +48,17 @@ } while (0) // Returns NULL if the_call doesn't return napi_ok. -#define NAPI_CALL(env, the_call) \ - NAPI_CALL_BASE(env, the_call, NULL) +#define NODE_API_CALL(env, the_call) \ + NODE_API_CALL_BASE(env, the_call, NULL) // Returns empty if the_call doesn't return napi_ok. -#define NAPI_CALL_RETURN_VOID(env, the_call) \ - NAPI_CALL_BASE(env, the_call, NAPI_RETVAL_NOTHING) +#define NODE_API_CALL_RETURN_VOID(env, the_call) \ + NODE_API_CALL_BASE(env, the_call, NODE_API_RETVAL_NOTHING) -#define DECLARE_NAPI_PROPERTY(name, func) \ +#define DECLARE_NODE_API_PROPERTY(name, func) \ { (name), NULL, (func), NULL, NULL, NULL, napi_default, NULL } -#define DECLARE_NAPI_GETTER(name, func) \ +#define DECLARE_NODE_API_GETTER(name, func) \ { (name), NULL, NULL, (func), NULL, NULL, napi_default, NULL } void add_returned_status(napi_env env, diff --git a/test/js-native-api/test_array/test_array.c b/test/js-native-api/test_array/test_array.c index 044f8636f5b9ce..846755a97b7059 100644 --- a/test/js-native-api/test_array/test_array.c +++ b/test/js-native-api/test_array/test_array.c @@ -5,42 +5,42 @@ static napi_value TestGetElement(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 2, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_object, + NODE_API_ASSERT(env, valuetype0 == napi_object, "Wrong type of arguments. Expects an array as first argument."); napi_valuetype valuetype1; - NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1)); - NAPI_ASSERT(env, valuetype1 == napi_number, + NODE_API_ASSERT(env, valuetype1 == napi_number, "Wrong type of arguments. Expects an integer as second argument."); napi_value array = args[0]; int32_t index; - NAPI_CALL(env, napi_get_value_int32(env, args[1], &index)); + NODE_API_CALL(env, napi_get_value_int32(env, args[1], &index)); - NAPI_ASSERT(env, index >= 0, "Invalid index. Expects a positive integer."); + NODE_API_ASSERT(env, index >= 0, "Invalid index. Expects a positive integer."); bool isarray; - NAPI_CALL(env, napi_is_array(env, array, &isarray)); + NODE_API_CALL(env, napi_is_array(env, array, &isarray)); if (!isarray) { return NULL; } uint32_t length; - NAPI_CALL(env, napi_get_array_length(env, array, &length)); + NODE_API_CALL(env, napi_get_array_length(env, array, &length)); - NAPI_ASSERT(env, ((uint32_t)index < length), "Index out of bounds!"); + NODE_API_ASSERT(env, ((uint32_t)index < length), "Index out of bounds!"); napi_value ret; - NAPI_CALL(env, napi_get_element(env, array, index, &ret)); + NODE_API_CALL(env, napi_get_element(env, array, index, &ret)); return ret; } @@ -48,38 +48,38 @@ static napi_value TestGetElement(napi_env env, napi_callback_info info) { static napi_value TestHasElement(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 2, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_object, + NODE_API_ASSERT(env, valuetype0 == napi_object, "Wrong type of arguments. Expects an array as first argument."); napi_valuetype valuetype1; - NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1)); - NAPI_ASSERT(env, valuetype1 == napi_number, + NODE_API_ASSERT(env, valuetype1 == napi_number, "Wrong type of arguments. Expects an integer as second argument."); napi_value array = args[0]; int32_t index; - NAPI_CALL(env, napi_get_value_int32(env, args[1], &index)); + NODE_API_CALL(env, napi_get_value_int32(env, args[1], &index)); bool isarray; - NAPI_CALL(env, napi_is_array(env, array, &isarray)); + NODE_API_CALL(env, napi_is_array(env, array, &isarray)); if (!isarray) { return NULL; } bool has_element; - NAPI_CALL(env, napi_has_element(env, array, index, &has_element)); + NODE_API_CALL(env, napi_has_element(env, array, index, &has_element)); napi_value ret; - NAPI_CALL(env, napi_get_boolean(env, has_element, &ret)); + NODE_API_CALL(env, napi_get_boolean(env, has_element, &ret)); return ret; } @@ -88,17 +88,17 @@ static napi_value TestDeleteElement(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 2, "Wrong number of arguments"); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_ASSERT(env, argc == 2, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_object, + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_ASSERT(env, valuetype0 == napi_object, "Wrong type of arguments. Expects an array as first argument."); napi_valuetype valuetype1; - NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); - NAPI_ASSERT(env, valuetype1 == napi_number, + NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1)); + NODE_API_ASSERT(env, valuetype1 == napi_number, "Wrong type of arguments. Expects an integer as second argument."); napi_value array = args[0]; @@ -106,15 +106,15 @@ static napi_value TestDeleteElement(napi_env env, napi_callback_info info) { bool result; napi_value ret; - NAPI_CALL(env, napi_get_value_int32(env, args[1], &index)); - NAPI_CALL(env, napi_is_array(env, array, &result)); + NODE_API_CALL(env, napi_get_value_int32(env, args[1], &index)); + NODE_API_CALL(env, napi_is_array(env, array, &result)); if (!result) { return NULL; } - NAPI_CALL(env, napi_delete_element(env, array, index, &result)); - NAPI_CALL(env, napi_get_boolean(env, result, &ret)); + NODE_API_CALL(env, napi_delete_element(env, array, index, &result)); + NODE_API_CALL(env, napi_get_boolean(env, result, &ret)); return ret; } @@ -122,26 +122,26 @@ static napi_value TestDeleteElement(napi_env env, napi_callback_info info) { static napi_value New(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_object, + NODE_API_ASSERT(env, valuetype0 == napi_object, "Wrong type of arguments. Expects an array as first argument."); napi_value ret; - NAPI_CALL(env, napi_create_array(env, &ret)); + NODE_API_CALL(env, napi_create_array(env, &ret)); uint32_t i, length; - NAPI_CALL(env, napi_get_array_length(env, args[0], &length)); + NODE_API_CALL(env, napi_get_array_length(env, args[0], &length)); for (i = 0; i < length; i++) { napi_value e; - NAPI_CALL(env, napi_get_element(env, args[0], i, &e)); - NAPI_CALL(env, napi_set_element(env, ret, i, e)); + NODE_API_CALL(env, napi_get_element(env, args[0], i, &e)); + NODE_API_CALL(env, napi_set_element(env, ret, i, e)); } return ret; @@ -150,21 +150,21 @@ static napi_value New(napi_env env, napi_callback_info info) { static napi_value NewWithLength(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_number, + NODE_API_ASSERT(env, valuetype0 == napi_number, "Wrong type of arguments. Expects an integer the first argument."); int32_t array_length; - NAPI_CALL(env, napi_get_value_int32(env, args[0], &array_length)); + NODE_API_CALL(env, napi_get_value_int32(env, args[0], &array_length)); napi_value ret; - NAPI_CALL(env, napi_create_array_with_length(env, array_length, &ret)); + NODE_API_CALL(env, napi_create_array_with_length(env, array_length, &ret)); return ret; } @@ -172,14 +172,14 @@ static napi_value NewWithLength(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("TestGetElement", TestGetElement), - DECLARE_NAPI_PROPERTY("TestHasElement", TestHasElement), - DECLARE_NAPI_PROPERTY("TestDeleteElement", TestDeleteElement), - DECLARE_NAPI_PROPERTY("New", New), - DECLARE_NAPI_PROPERTY("NewWithLength", NewWithLength), + DECLARE_NODE_API_PROPERTY("TestGetElement", TestGetElement), + DECLARE_NODE_API_PROPERTY("TestHasElement", TestHasElement), + DECLARE_NODE_API_PROPERTY("TestDeleteElement", TestDeleteElement), + DECLARE_NODE_API_PROPERTY("New", New), + DECLARE_NODE_API_PROPERTY("NewWithLength", NewWithLength), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; diff --git a/test/js-native-api/test_bigint/test_bigint.c b/test/js-native-api/test_bigint/test_bigint.c index 181f9103fa3399..063d37fa3a4d20 100644 --- a/test/js-native-api/test_bigint/test_bigint.c +++ b/test/js-native-api/test_bigint/test_bigint.c @@ -7,23 +7,23 @@ static napi_value IsLossless(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); bool is_signed; - NAPI_CALL(env, napi_get_value_bool(env, args[1], &is_signed)); + NODE_API_CALL(env, napi_get_value_bool(env, args[1], &is_signed)); bool lossless; if (is_signed) { int64_t input; - NAPI_CALL(env, napi_get_value_bigint_int64(env, args[0], &input, &lossless)); + NODE_API_CALL(env, napi_get_value_bigint_int64(env, args[0], &input, &lossless)); } else { uint64_t input; - NAPI_CALL(env, napi_get_value_bigint_uint64(env, args[0], &input, &lossless)); + NODE_API_CALL(env, napi_get_value_bigint_uint64(env, args[0], &input, &lossless)); } napi_value output; - NAPI_CALL(env, napi_get_boolean(env, lossless, &output)); + NODE_API_CALL(env, napi_get_boolean(env, lossless, &output)); return output; } @@ -31,22 +31,22 @@ static napi_value IsLossless(napi_env env, napi_callback_info info) { static napi_value TestInt64(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_bigint, + NODE_API_ASSERT(env, valuetype0 == napi_bigint, "Wrong type of arguments. Expects a bigint as first argument."); int64_t input; bool lossless; - NAPI_CALL(env, napi_get_value_bigint_int64(env, args[0], &input, &lossless)); + NODE_API_CALL(env, napi_get_value_bigint_int64(env, args[0], &input, &lossless)); napi_value output; - NAPI_CALL(env, napi_create_bigint_int64(env, input, &output)); + NODE_API_CALL(env, napi_create_bigint_int64(env, input, &output)); return output; } @@ -54,23 +54,23 @@ static napi_value TestInt64(napi_env env, napi_callback_info info) { static napi_value TestUint64(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_bigint, + NODE_API_ASSERT(env, valuetype0 == napi_bigint, "Wrong type of arguments. Expects a bigint as first argument."); uint64_t input; bool lossless; - NAPI_CALL(env, napi_get_value_bigint_uint64( + NODE_API_CALL(env, napi_get_value_bigint_uint64( env, args[0], &input, &lossless)); napi_value output; - NAPI_CALL(env, napi_create_bigint_uint64(env, input, &output)); + NODE_API_CALL(env, napi_create_bigint_uint64(env, input, &output)); return output; } @@ -78,32 +78,32 @@ static napi_value TestUint64(napi_env env, napi_callback_info info) { static napi_value TestWords(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_bigint, + NODE_API_ASSERT(env, valuetype0 == napi_bigint, "Wrong type of arguments. Expects a bigint as first argument."); size_t expected_word_count; - NAPI_CALL(env, napi_get_value_bigint_words( + NODE_API_CALL(env, napi_get_value_bigint_words( env, args[0], NULL, &expected_word_count, NULL)); int sign_bit; size_t word_count = 10; uint64_t words[10]; - NAPI_CALL(env, napi_get_value_bigint_words( + NODE_API_CALL(env, napi_get_value_bigint_words( env, args[0], &sign_bit, &word_count, words)); - NAPI_ASSERT(env, word_count == expected_word_count, + NODE_API_ASSERT(env, word_count == expected_word_count, "word counts do not match"); napi_value output; - NAPI_CALL(env, napi_create_bigint_words( + NODE_API_CALL(env, napi_create_bigint_words( env, sign_bit, word_count, words, &output)); return output; @@ -117,7 +117,7 @@ static napi_value CreateTooBigBigInt(napi_env env, napi_callback_info info) { napi_value output; - NAPI_CALL(env, napi_create_bigint_words( + NODE_API_CALL(env, napi_create_bigint_words( env, sign_bit, word_count, words, &output)); return output; @@ -142,15 +142,15 @@ static napi_value MakeBigIntWordsThrow(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("IsLossless", IsLossless), - DECLARE_NAPI_PROPERTY("TestInt64", TestInt64), - DECLARE_NAPI_PROPERTY("TestUint64", TestUint64), - DECLARE_NAPI_PROPERTY("TestWords", TestWords), - DECLARE_NAPI_PROPERTY("CreateTooBigBigInt", CreateTooBigBigInt), - DECLARE_NAPI_PROPERTY("MakeBigIntWordsThrow", MakeBigIntWordsThrow), + DECLARE_NODE_API_PROPERTY("IsLossless", IsLossless), + DECLARE_NODE_API_PROPERTY("TestInt64", TestInt64), + DECLARE_NODE_API_PROPERTY("TestUint64", TestUint64), + DECLARE_NODE_API_PROPERTY("TestWords", TestWords), + DECLARE_NODE_API_PROPERTY("CreateTooBigBigInt", CreateTooBigBigInt), + DECLARE_NODE_API_PROPERTY("MakeBigIntWordsThrow", MakeBigIntWordsThrow), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; diff --git a/test/js-native-api/test_constructor/test_constructor.c b/test/js-native-api/test_constructor/test_constructor.c index 6c14e39fe2e624..7582e53bb600c4 100644 --- a/test/js-native-api/test_constructor/test_constructor.c +++ b/test/js-native-api/test_constructor/test_constructor.c @@ -19,7 +19,7 @@ static napi_value TestDefineClass(napi_env env, napi_enumerable | napi_static, NULL}; - NAPI_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &return_value)); status = napi_define_class(NULL, "TrackedFunction", @@ -98,12 +98,12 @@ static napi_value TestDefineClass(napi_env env, static napi_value GetValue(napi_env env, napi_callback_info info) { size_t argc = 0; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, NULL, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, NULL, NULL, NULL)); - NAPI_ASSERT(env, argc == 0, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc == 0, "Wrong number of arguments"); napi_value number; - NAPI_CALL(env, napi_create_double(env, value_, &number)); + NODE_API_CALL(env, napi_create_double(env, value_, &number)); return number; } @@ -111,11 +111,11 @@ static napi_value GetValue(napi_env env, napi_callback_info info) { static napi_value SetValue(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); - NAPI_CALL(env, napi_get_value_double(env, args[0], &value_)); + NODE_API_CALL(env, napi_get_value_double(env, args[0], &value_)); return NULL; } @@ -123,28 +123,28 @@ static napi_value SetValue(napi_env env, napi_callback_info info) { static napi_value Echo(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); return args[0]; } static napi_value New(napi_env env, napi_callback_info info) { napi_value _this; - NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &_this, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &_this, NULL)); return _this; } static napi_value GetStaticValue(napi_env env, napi_callback_info info) { size_t argc = 0; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, NULL, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, NULL, NULL, NULL)); - NAPI_ASSERT(env, argc == 0, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc == 0, "Wrong number of arguments"); napi_value number; - NAPI_CALL(env, napi_create_double(env, static_value_, &number)); + NODE_API_CALL(env, napi_create_double(env, static_value_, &number)); return number; } @@ -152,7 +152,7 @@ static napi_value GetStaticValue(napi_env env, napi_callback_info info) { static napi_value NewExtra(napi_env env, napi_callback_info info) { napi_value _this; - NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &_this, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &_this, NULL)); return _this; } @@ -160,9 +160,9 @@ static napi_value NewExtra(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_value number, cons; - NAPI_CALL(env, napi_create_double(env, value_, &number)); + NODE_API_CALL(env, napi_create_double(env, value_, &number)); - NAPI_CALL(env, napi_define_class( + NODE_API_CALL(env, napi_define_class( env, "MyObject_Extra", 8, NewExtra, NULL, 0, NULL, &cons)); napi_property_descriptor properties[] = { @@ -188,7 +188,7 @@ napi_value Init(napi_env env, napi_value exports) { napi_enumerable | napi_static, NULL }, }; - NAPI_CALL(env, napi_define_class(env, "MyObject", NAPI_AUTO_LENGTH, New, + NODE_API_CALL(env, napi_define_class(env, "MyObject", NAPI_AUTO_LENGTH, New, NULL, sizeof(properties)/sizeof(*properties), properties, &cons)); return cons; diff --git a/test/js-native-api/test_conversions/test_conversions.c b/test/js-native-api/test_conversions/test_conversions.c index 4f8561a9acf13a..500962d5144e0f 100644 --- a/test/js-native-api/test_conversions/test_conversions.c +++ b/test/js-native-api/test_conversions/test_conversions.c @@ -5,13 +5,13 @@ static napi_value AsBool(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); bool value; - NAPI_CALL(env, napi_get_value_bool(env, args[0], &value)); + NODE_API_CALL(env, napi_get_value_bool(env, args[0], &value)); napi_value output; - NAPI_CALL(env, napi_get_boolean(env, value, &output)); + NODE_API_CALL(env, napi_get_boolean(env, value, &output)); return output; } @@ -19,13 +19,13 @@ static napi_value AsBool(napi_env env, napi_callback_info info) { static napi_value AsInt32(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); int32_t value; - NAPI_CALL(env, napi_get_value_int32(env, args[0], &value)); + NODE_API_CALL(env, napi_get_value_int32(env, args[0], &value)); napi_value output; - NAPI_CALL(env, napi_create_int32(env, value, &output)); + NODE_API_CALL(env, napi_create_int32(env, value, &output)); return output; } @@ -33,13 +33,13 @@ static napi_value AsInt32(napi_env env, napi_callback_info info) { static napi_value AsUInt32(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); uint32_t value; - NAPI_CALL(env, napi_get_value_uint32(env, args[0], &value)); + NODE_API_CALL(env, napi_get_value_uint32(env, args[0], &value)); napi_value output; - NAPI_CALL(env, napi_create_uint32(env, value, &output)); + NODE_API_CALL(env, napi_create_uint32(env, value, &output)); return output; } @@ -47,13 +47,13 @@ static napi_value AsUInt32(napi_env env, napi_callback_info info) { static napi_value AsInt64(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); int64_t value; - NAPI_CALL(env, napi_get_value_int64(env, args[0], &value)); + NODE_API_CALL(env, napi_get_value_int64(env, args[0], &value)); napi_value output; - NAPI_CALL(env, napi_create_int64(env, (double)value, &output)); + NODE_API_CALL(env, napi_create_int64(env, (double)value, &output)); return output; } @@ -61,13 +61,13 @@ static napi_value AsInt64(napi_env env, napi_callback_info info) { static napi_value AsDouble(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); double value; - NAPI_CALL(env, napi_get_value_double(env, args[0], &value)); + NODE_API_CALL(env, napi_get_value_double(env, args[0], &value)); napi_value output; - NAPI_CALL(env, napi_create_double(env, value, &output)); + NODE_API_CALL(env, napi_create_double(env, value, &output)); return output; } @@ -75,14 +75,14 @@ static napi_value AsDouble(napi_env env, napi_callback_info info) { static napi_value AsString(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); char value[100]; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_value_string_utf8(env, args[0], value, sizeof(value), NULL)); napi_value output; - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, value, NAPI_AUTO_LENGTH, &output)); return output; @@ -91,10 +91,10 @@ static napi_value AsString(napi_env env, napi_callback_info info) { static napi_value ToBool(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_value output; - NAPI_CALL(env, napi_coerce_to_bool(env, args[0], &output)); + NODE_API_CALL(env, napi_coerce_to_bool(env, args[0], &output)); return output; } @@ -102,10 +102,10 @@ static napi_value ToBool(napi_env env, napi_callback_info info) { static napi_value ToNumber(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_value output; - NAPI_CALL(env, napi_coerce_to_number(env, args[0], &output)); + NODE_API_CALL(env, napi_coerce_to_number(env, args[0], &output)); return output; } @@ -113,10 +113,10 @@ static napi_value ToNumber(napi_env env, napi_callback_info info) { static napi_value ToObject(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_value output; - NAPI_CALL(env, napi_coerce_to_object(env, args[0], &output)); + NODE_API_CALL(env, napi_coerce_to_object(env, args[0], &output)); return output; } @@ -124,10 +124,10 @@ static napi_value ToObject(napi_env env, napi_callback_info info) { static napi_value ToString(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_value output; - NAPI_CALL(env, napi_coerce_to_string(env, args[0], &output)); + NODE_API_CALL(env, napi_coerce_to_string(env, args[0], &output)); return output; } @@ -135,19 +135,19 @@ static napi_value ToString(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("asBool", AsBool), - DECLARE_NAPI_PROPERTY("asInt32", AsInt32), - DECLARE_NAPI_PROPERTY("asUInt32", AsUInt32), - DECLARE_NAPI_PROPERTY("asInt64", AsInt64), - DECLARE_NAPI_PROPERTY("asDouble", AsDouble), - DECLARE_NAPI_PROPERTY("asString", AsString), - DECLARE_NAPI_PROPERTY("toBool", ToBool), - DECLARE_NAPI_PROPERTY("toNumber", ToNumber), - DECLARE_NAPI_PROPERTY("toObject", ToObject), - DECLARE_NAPI_PROPERTY("toString", ToString), + DECLARE_NODE_API_PROPERTY("asBool", AsBool), + DECLARE_NODE_API_PROPERTY("asInt32", AsInt32), + DECLARE_NODE_API_PROPERTY("asUInt32", AsUInt32), + DECLARE_NODE_API_PROPERTY("asInt64", AsInt64), + DECLARE_NODE_API_PROPERTY("asDouble", AsDouble), + DECLARE_NODE_API_PROPERTY("asString", AsString), + DECLARE_NODE_API_PROPERTY("toBool", ToBool), + DECLARE_NODE_API_PROPERTY("toNumber", ToNumber), + DECLARE_NODE_API_PROPERTY("toObject", ToObject), + DECLARE_NODE_API_PROPERTY("toString", ToString), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); init_test_null(env, exports); diff --git a/test/js-native-api/test_conversions/test_null.c b/test/js-native-api/test_conversions/test_null.c index 9cf73bc2d4980f..bc0ea0474eab21 100644 --- a/test/js-native-api/test_conversions/test_null.c +++ b/test/js-native-api/test_conversions/test_null.c @@ -7,7 +7,7 @@ static napi_value binding_name(napi_env env, napi_callback_info info) { \ napi_value return_value; \ output_type result; \ - NAPI_CALL(env, napi_create_object(env, &return_value)); \ + NODE_API_CALL(env, napi_create_object(env, &return_value)); \ add_returned_status(env, \ "envIsNull", \ return_value, \ @@ -35,7 +35,7 @@ GEN_NULL_CHECK_BINDING(CoerceToString, napi_value, napi_coerce_to_string) #define GEN_NULL_CHECK_STRING_BINDING(binding_name, arg_type, api) \ static napi_value binding_name(napi_env env, napi_callback_info info) { \ napi_value return_value; \ - NAPI_CALL(env, napi_create_object(env, &return_value)); \ + NODE_API_CALL(env, napi_create_object(env, &return_value)); \ arg_type buf1[4]; \ size_t length1 = 3; \ add_returned_status(env, \ @@ -51,7 +51,7 @@ GEN_NULL_CHECK_BINDING(CoerceToString, napi_value, napi_coerce_to_string) api(env, return_value, NULL, 3, NULL); \ add_last_status(env, "wrongTypeIn", return_value); \ napi_value string; \ - NAPI_CALL(env, \ + NODE_API_CALL(env, \ napi_create_string_utf8(env, \ "Something", \ NAPI_AUTO_LENGTH, \ @@ -75,21 +75,21 @@ void init_test_null(napi_env env, napi_value exports) { napi_value test_null; const napi_property_descriptor test_null_props[] = { - DECLARE_NAPI_PROPERTY("getValueBool", GetValueBool), - DECLARE_NAPI_PROPERTY("getValueInt32", GetValueInt32), - DECLARE_NAPI_PROPERTY("getValueUint32", GetValueUint32), - DECLARE_NAPI_PROPERTY("getValueInt64", GetValueInt64), - DECLARE_NAPI_PROPERTY("getValueDouble", GetValueDouble), - DECLARE_NAPI_PROPERTY("coerceToBool", CoerceToBool), - DECLARE_NAPI_PROPERTY("coerceToObject", CoerceToObject), - DECLARE_NAPI_PROPERTY("coerceToString", CoerceToString), - DECLARE_NAPI_PROPERTY("getValueStringUtf8", GetValueStringUtf8), - DECLARE_NAPI_PROPERTY("getValueStringLatin1", GetValueStringLatin1), - DECLARE_NAPI_PROPERTY("getValueStringUtf16", GetValueStringUtf16), + DECLARE_NODE_API_PROPERTY("getValueBool", GetValueBool), + DECLARE_NODE_API_PROPERTY("getValueInt32", GetValueInt32), + DECLARE_NODE_API_PROPERTY("getValueUint32", GetValueUint32), + DECLARE_NODE_API_PROPERTY("getValueInt64", GetValueInt64), + DECLARE_NODE_API_PROPERTY("getValueDouble", GetValueDouble), + DECLARE_NODE_API_PROPERTY("coerceToBool", CoerceToBool), + DECLARE_NODE_API_PROPERTY("coerceToObject", CoerceToObject), + DECLARE_NODE_API_PROPERTY("coerceToString", CoerceToString), + DECLARE_NODE_API_PROPERTY("getValueStringUtf8", GetValueStringUtf8), + DECLARE_NODE_API_PROPERTY("getValueStringLatin1", GetValueStringLatin1), + DECLARE_NODE_API_PROPERTY("getValueStringUtf16", GetValueStringUtf16), }; - NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &test_null)); - NAPI_CALL_RETURN_VOID(env, napi_define_properties( + NODE_API_CALL_RETURN_VOID(env, napi_create_object(env, &test_null)); + NODE_API_CALL_RETURN_VOID(env, napi_define_properties( env, test_null, sizeof(test_null_props) / sizeof(*test_null_props), test_null_props)); @@ -97,6 +97,6 @@ void init_test_null(napi_env env, napi_value exports) { "testNull", NULL, NULL, NULL, NULL, test_null, napi_enumerable, NULL }; - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_define_properties(env, exports, 1, &test_null_set)); } diff --git a/test/js-native-api/test_dataview/test_dataview.c b/test/js-native-api/test_dataview/test_dataview.c index ff3b42e63aec1e..c614a79818cb85 100644 --- a/test/js-native-api/test_dataview/test_dataview.c +++ b/test/js-native-api/test_dataview/test_dataview.c @@ -5,44 +5,44 @@ static napi_value CreateDataView(napi_env env, napi_callback_info info) { size_t argc = 3; napi_value args [3]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 3, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc == 3, "Wrong number of arguments"); napi_valuetype valuetype0; napi_value arraybuffer = args[0]; - NAPI_CALL(env, napi_typeof(env, arraybuffer, &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_object, + NODE_API_CALL(env, napi_typeof(env, arraybuffer, &valuetype0)); + NODE_API_ASSERT(env, valuetype0 == napi_object, "Wrong type of arguments. Expects a ArrayBuffer as the first " "argument."); bool is_arraybuffer; - NAPI_CALL(env, napi_is_arraybuffer(env, arraybuffer, &is_arraybuffer)); - NAPI_ASSERT(env, is_arraybuffer, + NODE_API_CALL(env, napi_is_arraybuffer(env, arraybuffer, &is_arraybuffer)); + NODE_API_ASSERT(env, is_arraybuffer, "Wrong type of arguments. Expects a ArrayBuffer as the first " "argument."); napi_valuetype valuetype1; - NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1)); - NAPI_ASSERT(env, valuetype1 == napi_number, + NODE_API_ASSERT(env, valuetype1 == napi_number, "Wrong type of arguments. Expects a number as second argument."); size_t byte_offset = 0; - NAPI_CALL(env, napi_get_value_uint32(env, args[1], (uint32_t*)(&byte_offset))); + NODE_API_CALL(env, napi_get_value_uint32(env, args[1], (uint32_t*)(&byte_offset))); napi_valuetype valuetype2; - NAPI_CALL(env, napi_typeof(env, args[2], &valuetype2)); + NODE_API_CALL(env, napi_typeof(env, args[2], &valuetype2)); - NAPI_ASSERT(env, valuetype2 == napi_number, + NODE_API_ASSERT(env, valuetype2 == napi_number, "Wrong type of arguments. Expects a number as third argument."); size_t length = 0; - NAPI_CALL(env, napi_get_value_uint32(env, args[2], (uint32_t*)(&length))); + NODE_API_CALL(env, napi_get_value_uint32(env, args[2], (uint32_t*)(&length))); napi_value output_dataview; - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_dataview(env, length, arraybuffer, byte_offset, &output_dataview)); @@ -52,32 +52,32 @@ static napi_value CreateDataView(napi_env env, napi_callback_info info) { static napi_value CreateDataViewFromJSDataView(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args [1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); napi_valuetype valuetype; napi_value input_dataview = args[0]; - NAPI_CALL(env, napi_typeof(env, input_dataview, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, + NODE_API_CALL(env, napi_typeof(env, input_dataview, &valuetype)); + NODE_API_ASSERT(env, valuetype == napi_object, "Wrong type of arguments. Expects a DataView as the first " "argument."); bool is_dataview; - NAPI_CALL(env, napi_is_dataview(env, input_dataview, &is_dataview)); - NAPI_ASSERT(env, is_dataview, + NODE_API_CALL(env, napi_is_dataview(env, input_dataview, &is_dataview)); + NODE_API_ASSERT(env, is_dataview, "Wrong type of arguments. Expects a DataView as the first " "argument."); size_t byte_offset = 0; size_t length = 0; napi_value buffer; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_dataview_info(env, input_dataview, &length, NULL, &buffer, &byte_offset)); napi_value output_dataview; - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_dataview(env, length, buffer, byte_offset, &output_dataview)); @@ -88,12 +88,12 @@ static napi_value CreateDataViewFromJSDataView(napi_env env, napi_callback_info EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("CreateDataView", CreateDataView), - DECLARE_NAPI_PROPERTY("CreateDataViewFromJSDataView", + DECLARE_NODE_API_PROPERTY("CreateDataView", CreateDataView), + DECLARE_NODE_API_PROPERTY("CreateDataViewFromJSDataView", CreateDataViewFromJSDataView) }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; diff --git a/test/js-native-api/test_date/test_date.c b/test/js-native-api/test_date/test_date.c index 7ac5008cb9b288..d5e9c778a9cd8f 100644 --- a/test/js-native-api/test_date/test_date.c +++ b/test/js-native-api/test_date/test_date.c @@ -4,21 +4,21 @@ static napi_value createDate(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_number, - "Wrong type of arguments. Expects a number as first argument."); + NODE_API_ASSERT(env, valuetype0 == napi_number, + "Wrong type of arguments. Expects a number as first argument."); double time; - NAPI_CALL(env, napi_get_value_double(env, args[0], &time)); + NODE_API_CALL(env, napi_get_value_double(env, args[0], &time)); napi_value date; - NAPI_CALL(env, napi_create_date(env, time, &date)); + NODE_API_CALL(env, napi_create_date(env, time, &date)); return date; } @@ -28,9 +28,9 @@ static napi_value isDate(napi_env env, napi_callback_info info) { size_t argc = 1; bool is_date; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &date, NULL, NULL)); - NAPI_CALL(env, napi_is_date(env, date, &is_date)); - NAPI_CALL(env, napi_get_boolean(env, is_date, &result)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &date, NULL, NULL)); + NODE_API_CALL(env, napi_is_date(env, date, &is_date)); + NODE_API_CALL(env, napi_get_boolean(env, is_date, &result)); return result; } @@ -40,9 +40,9 @@ static napi_value getDateValue(napi_env env, napi_callback_info info) { size_t argc = 1; double value; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &date, NULL, NULL)); - NAPI_CALL(env, napi_get_date_value(env, date, &value)); - NAPI_CALL(env, napi_create_double(env, value, &result)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &date, NULL, NULL)); + NODE_API_CALL(env, napi_get_date_value(env, date, &value)); + NODE_API_CALL(env, napi_create_double(env, value, &result)); return result; } @@ -50,12 +50,12 @@ static napi_value getDateValue(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("createDate", createDate), - DECLARE_NAPI_PROPERTY("isDate", isDate), - DECLARE_NAPI_PROPERTY("getDateValue", getDateValue), + DECLARE_NODE_API_PROPERTY("createDate", createDate), + DECLARE_NODE_API_PROPERTY("isDate", isDate), + DECLARE_NODE_API_PROPERTY("getDateValue", getDateValue), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; diff --git a/test/js-native-api/test_error/test_error.c b/test/js-native-api/test_error/test_error.c index bb55272c537468..a164c38bea89b7 100644 --- a/test/js-native-api/test_error/test_error.c +++ b/test/js-native-api/test_error/test_error.c @@ -4,13 +4,13 @@ static napi_value checkError(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); bool r; - NAPI_CALL(env, napi_is_error(env, args[0], &r)); + NODE_API_CALL(env, napi_is_error(env, args[0], &r)); napi_value result; - NAPI_CALL(env, napi_get_boolean(env, r, &result)); + NODE_API_CALL(env, napi_get_boolean(env, r, &result)); return result; } @@ -18,44 +18,42 @@ static napi_value checkError(napi_env env, napi_callback_info info) { static napi_value throwExistingError(napi_env env, napi_callback_info info) { napi_value message; napi_value error; - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "existing error", NAPI_AUTO_LENGTH, &message)); - NAPI_CALL(env, napi_create_error(env, NULL, message, &error)); - NAPI_CALL(env, napi_throw(env, error)); + NODE_API_CALL(env, napi_create_error(env, NULL, message, &error)); + NODE_API_CALL(env, napi_throw(env, error)); return NULL; } static napi_value throwError(napi_env env, napi_callback_info info) { - NAPI_CALL(env, napi_throw_error(env, NULL, "error")); + NODE_API_CALL(env, napi_throw_error(env, NULL, "error")); return NULL; } static napi_value throwRangeError(napi_env env, napi_callback_info info) { - NAPI_CALL(env, napi_throw_range_error(env, NULL, "range error")); + NODE_API_CALL(env, napi_throw_range_error(env, NULL, "range error")); return NULL; } static napi_value throwTypeError(napi_env env, napi_callback_info info) { - NAPI_CALL(env, napi_throw_type_error(env, NULL, "type error")); + NODE_API_CALL(env, napi_throw_type_error(env, NULL, "type error")); return NULL; } static napi_value throwErrorCode(napi_env env, napi_callback_info info) { - NAPI_CALL(env, napi_throw_error(env, "ERR_TEST_CODE", "Error [error]")); + NODE_API_CALL(env, napi_throw_error(env, "ERR_TEST_CODE", "Error [error]")); return NULL; } static napi_value throwRangeErrorCode(napi_env env, napi_callback_info info) { - NAPI_CALL(env, napi_throw_range_error(env, - "ERR_TEST_CODE", - "RangeError [range error]")); + NODE_API_CALL(env, + napi_throw_range_error(env, "ERR_TEST_CODE", "RangeError [range error]")); return NULL; } static napi_value throwTypeErrorCode(napi_env env, napi_callback_info info) { - NAPI_CALL(env, napi_throw_type_error(env, - "ERR_TEST_CODE", - "TypeError [type error]")); + NODE_API_CALL(env, + napi_throw_type_error(env, "ERR_TEST_CODE", "TypeError [type error]")); return NULL; } @@ -63,27 +61,27 @@ static napi_value throwTypeErrorCode(napi_env env, napi_callback_info info) { static napi_value createError(napi_env env, napi_callback_info info) { napi_value result; napi_value message; - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "error", NAPI_AUTO_LENGTH, &message)); - NAPI_CALL(env, napi_create_error(env, NULL, message, &result)); + NODE_API_CALL(env, napi_create_error(env, NULL, message, &result)); return result; } static napi_value createRangeError(napi_env env, napi_callback_info info) { napi_value result; napi_value message; - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "range error", NAPI_AUTO_LENGTH, &message)); - NAPI_CALL(env, napi_create_range_error(env, NULL, message, &result)); + NODE_API_CALL(env, napi_create_range_error(env, NULL, message, &result)); return result; } static napi_value createTypeError(napi_env env, napi_callback_info info) { napi_value result; napi_value message; - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "type error", NAPI_AUTO_LENGTH, &message)); - NAPI_CALL(env, napi_create_type_error(env, NULL, message, &result)); + NODE_API_CALL(env, napi_create_type_error(env, NULL, message, &result)); return result; } @@ -91,11 +89,11 @@ static napi_value createErrorCode(napi_env env, napi_callback_info info) { napi_value result; napi_value message; napi_value code; - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "Error [error]", NAPI_AUTO_LENGTH, &message)); - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "ERR_TEST_CODE", NAPI_AUTO_LENGTH, &code)); - NAPI_CALL(env, napi_create_error(env, code, message, &result)); + NODE_API_CALL(env, napi_create_error(env, code, message, &result)); return result; } @@ -103,13 +101,12 @@ static napi_value createRangeErrorCode(napi_env env, napi_callback_info info) { napi_value result; napi_value message; napi_value code; - NAPI_CALL(env, napi_create_string_utf8(env, - "RangeError [range error]", - NAPI_AUTO_LENGTH, - &message)); - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, + napi_create_string_utf8( + env, "RangeError [range error]", NAPI_AUTO_LENGTH, &message)); + NODE_API_CALL(env, napi_create_string_utf8( env, "ERR_TEST_CODE", NAPI_AUTO_LENGTH, &code)); - NAPI_CALL(env, napi_create_range_error(env, code, message, &result)); + NODE_API_CALL(env, napi_create_range_error(env, code, message, &result)); return result; } @@ -117,45 +114,44 @@ static napi_value createTypeErrorCode(napi_env env, napi_callback_info info) { napi_value result; napi_value message; napi_value code; - NAPI_CALL(env, napi_create_string_utf8(env, - "TypeError [type error]", - NAPI_AUTO_LENGTH, - &message)); - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, + napi_create_string_utf8( + env, "TypeError [type error]", NAPI_AUTO_LENGTH, &message)); + NODE_API_CALL(env, napi_create_string_utf8( env, "ERR_TEST_CODE", NAPI_AUTO_LENGTH, &code)); - NAPI_CALL(env, napi_create_type_error(env, code, message, &result)); + NODE_API_CALL(env, napi_create_type_error(env, code, message, &result)); return result; } static napi_value throwArbitrary(napi_env env, napi_callback_info info) { napi_value arbitrary; size_t argc = 1; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &arbitrary, NULL, NULL)); - NAPI_CALL(env, napi_throw(env, arbitrary)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &arbitrary, NULL, NULL)); + NODE_API_CALL(env, napi_throw(env, arbitrary)); return NULL; } EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("checkError", checkError), - DECLARE_NAPI_PROPERTY("throwExistingError", throwExistingError), - DECLARE_NAPI_PROPERTY("throwError", throwError), - DECLARE_NAPI_PROPERTY("throwRangeError", throwRangeError), - DECLARE_NAPI_PROPERTY("throwTypeError", throwTypeError), - DECLARE_NAPI_PROPERTY("throwErrorCode", throwErrorCode), - DECLARE_NAPI_PROPERTY("throwRangeErrorCode", throwRangeErrorCode), - DECLARE_NAPI_PROPERTY("throwTypeErrorCode", throwTypeErrorCode), - DECLARE_NAPI_PROPERTY("throwArbitrary", throwArbitrary), - DECLARE_NAPI_PROPERTY("createError", createError), - DECLARE_NAPI_PROPERTY("createRangeError", createRangeError), - DECLARE_NAPI_PROPERTY("createTypeError", createTypeError), - DECLARE_NAPI_PROPERTY("createErrorCode", createErrorCode), - DECLARE_NAPI_PROPERTY("createRangeErrorCode", createRangeErrorCode), - DECLARE_NAPI_PROPERTY("createTypeErrorCode", createTypeErrorCode), + DECLARE_NODE_API_PROPERTY("checkError", checkError), + DECLARE_NODE_API_PROPERTY("throwExistingError", throwExistingError), + DECLARE_NODE_API_PROPERTY("throwError", throwError), + DECLARE_NODE_API_PROPERTY("throwRangeError", throwRangeError), + DECLARE_NODE_API_PROPERTY("throwTypeError", throwTypeError), + DECLARE_NODE_API_PROPERTY("throwErrorCode", throwErrorCode), + DECLARE_NODE_API_PROPERTY("throwRangeErrorCode", throwRangeErrorCode), + DECLARE_NODE_API_PROPERTY("throwTypeErrorCode", throwTypeErrorCode), + DECLARE_NODE_API_PROPERTY("throwArbitrary", throwArbitrary), + DECLARE_NODE_API_PROPERTY("createError", createError), + DECLARE_NODE_API_PROPERTY("createRangeError", createRangeError), + DECLARE_NODE_API_PROPERTY("createTypeError", createTypeError), + DECLARE_NODE_API_PROPERTY("createErrorCode", createErrorCode), + DECLARE_NODE_API_PROPERTY("createRangeErrorCode", createRangeErrorCode), + DECLARE_NODE_API_PROPERTY("createTypeErrorCode", createTypeErrorCode), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; diff --git a/test/js-native-api/test_exception/test_exception.c b/test/js-native-api/test_exception/test_exception.c index 01adf42c942b8f..791f5219fc61fe 100644 --- a/test/js-native-api/test_exception/test_exception.c +++ b/test/js-native-api/test_exception/test_exception.c @@ -6,16 +6,16 @@ static bool exceptionWasPending = false; static napi_value returnException(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_value global; - NAPI_CALL(env, napi_get_global(env, &global)); + NODE_API_CALL(env, napi_get_global(env, &global)); napi_value result; napi_status status = napi_call_function(env, global, args[0], 0, 0, &result); if (status == napi_pending_exception) { napi_value ex; - NAPI_CALL(env, napi_get_and_clear_last_exception(env, &ex)); + NODE_API_CALL(env, napi_get_and_clear_last_exception(env, &ex)); return ex; } @@ -25,35 +25,35 @@ static napi_value returnException(napi_env env, napi_callback_info info) { static napi_value allowException(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_value global; - NAPI_CALL(env, napi_get_global(env, &global)); + NODE_API_CALL(env, napi_get_global(env, &global)); napi_value result; napi_call_function(env, global, args[0], 0, 0, &result); // Ignore status and check napi_is_exception_pending() instead. - NAPI_CALL(env, napi_is_exception_pending(env, &exceptionWasPending)); + NODE_API_CALL(env, napi_is_exception_pending(env, &exceptionWasPending)); return NULL; } static napi_value wasPending(napi_env env, napi_callback_info info) { napi_value result; - NAPI_CALL(env, napi_get_boolean(env, exceptionWasPending, &result)); + NODE_API_CALL(env, napi_get_boolean(env, exceptionWasPending, &result)); return result; } static void finalizer(napi_env env, void *data, void *hint) { - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_throw_error(env, NULL, "Error during Finalize")); } static napi_value createExternal(napi_env env, napi_callback_info info) { napi_value external; - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_external(env, NULL, finalizer, NULL, &external)); return external; @@ -62,21 +62,21 @@ static napi_value createExternal(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("returnException", returnException), - DECLARE_NAPI_PROPERTY("allowException", allowException), - DECLARE_NAPI_PROPERTY("wasPending", wasPending), - DECLARE_NAPI_PROPERTY("createExternal", createExternal), + DECLARE_NODE_API_PROPERTY("returnException", returnException), + DECLARE_NODE_API_PROPERTY("allowException", allowException), + DECLARE_NODE_API_PROPERTY("wasPending", wasPending), + DECLARE_NODE_API_PROPERTY("createExternal", createExternal), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); napi_value error, code, message; - NAPI_CALL(env, napi_create_string_utf8(env, "Error during Init", + NODE_API_CALL(env, napi_create_string_utf8(env, "Error during Init", NAPI_AUTO_LENGTH, &message)); - NAPI_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &code)); - NAPI_CALL(env, napi_create_error(env, code, message, &error)); - NAPI_CALL(env, napi_set_named_property(env, error, "binding", exports)); - NAPI_CALL(env, napi_throw(env, error)); + NODE_API_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &code)); + NODE_API_CALL(env, napi_create_error(env, code, message, &error)); + NODE_API_CALL(env, napi_set_named_property(env, error, "binding", exports)); + NODE_API_CALL(env, napi_throw(env, error)); return exports; } diff --git a/test/js-native-api/test_function/test_function.c b/test/js-native-api/test_function/test_function.c index 713e935e08c972..26445f4736dbdc 100644 --- a/test/js-native-api/test_function/test_function.c +++ b/test/js-native-api/test_function/test_function.c @@ -6,7 +6,7 @@ static napi_value TestCreateFunctionParameters(napi_env env, napi_status status; napi_value result, return_value; - NAPI_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &return_value)); status = napi_create_function(NULL, "TrackedFunction", @@ -55,24 +55,24 @@ static napi_value TestCreateFunctionParameters(napi_env env, static napi_value TestCallFunction(napi_env env, napi_callback_info info) { size_t argc = 10; napi_value args[10]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc > 0, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_function, + NODE_API_ASSERT(env, valuetype0 == napi_function, "Wrong type of arguments. Expects a function as first argument."); napi_value* argv = args + 1; argc = argc - 1; napi_value global; - NAPI_CALL(env, napi_get_global(env, &global)); + NODE_API_CALL(env, napi_get_global(env, &global)); napi_value result; - NAPI_CALL(env, napi_call_function(env, global, args[0], argc, argv, &result)); + NODE_API_CALL(env, napi_call_function(env, global, args[0], argc, argv, &result)); return result; } @@ -86,24 +86,20 @@ static void finalize_function(napi_env env, void* data, void* hint) { // Retrieve the JavaScript undefined value. napi_value undefined; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NODE_API_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); // Retrieve the JavaScript function we must call. napi_value js_function; - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, ref, &js_function)); + NODE_API_CALL_RETURN_VOID(env, napi_get_reference_value(env, ref, &js_function)); // Call the JavaScript function to indicate that the generated JavaScript // function is about to be gc-ed. - NAPI_CALL_RETURN_VOID(env, napi_call_function(env, - undefined, - js_function, - 0, - NULL, - NULL)); + NODE_API_CALL_RETURN_VOID(env, + napi_call_function(env, undefined, js_function, 0, NULL, NULL)); // Destroy the persistent reference to the function we just called so as to // properly clean up. - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, ref)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, ref)); } static napi_value MakeTrackedFunction(napi_env env, napi_callback_info info) { @@ -114,41 +110,30 @@ static napi_value MakeTrackedFunction(napi_env env, napi_callback_info info) { // Retrieve and validate from the arguments the function we will use to // indicate to JavaScript that the function we are about to create is about to // be gc-ed. - NAPI_CALL(env, napi_get_cb_info(env, - info, - &argc, - &js_finalize_cb, - NULL, - NULL)); - NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); - NAPI_CALL(env, napi_typeof(env, js_finalize_cb, &arg_type)); - NAPI_ASSERT(env, arg_type == napi_function, "Argument must be a function"); + NODE_API_CALL(env, + napi_get_cb_info(env, info, &argc, &js_finalize_cb, NULL, NULL)); + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); + NODE_API_CALL(env, napi_typeof(env, js_finalize_cb, &arg_type)); + NODE_API_ASSERT(env, arg_type == napi_function, "Argument must be a function"); // Dynamically create a function. napi_value result; - NAPI_CALL(env, napi_create_function(env, - "TrackedFunction", - NAPI_AUTO_LENGTH, - TestFunctionName, - NULL, - &result)); + NODE_API_CALL(env, + napi_create_function( + env, "TrackedFunction", NAPI_AUTO_LENGTH, TestFunctionName, NULL, + &result)); // Create a strong reference to the function we will call when the tracked // function is about to be gc-ed. napi_ref js_finalize_cb_ref; - NAPI_CALL(env, napi_create_reference(env, - js_finalize_cb, - 1, - &js_finalize_cb_ref)); + NODE_API_CALL(env, + napi_create_reference(env, js_finalize_cb, 1, &js_finalize_cb_ref)); // Attach a finalizer to the dynamically created function and pass it the // strong reference we created in the previous step. - NAPI_CALL(env, napi_wrap(env, - result, - js_finalize_cb_ref, - finalize_function, - NULL, - NULL)); + NODE_API_CALL(env, + napi_wrap( + env, result, js_finalize_cb_ref, finalize_function, NULL, NULL)); return result; } @@ -156,45 +141,39 @@ static napi_value MakeTrackedFunction(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_value fn1; - NAPI_CALL(env, napi_create_function( + NODE_API_CALL(env, napi_create_function( env, NULL, NAPI_AUTO_LENGTH, TestCallFunction, NULL, &fn1)); napi_value fn2; - NAPI_CALL(env, napi_create_function( + NODE_API_CALL(env, napi_create_function( env, "Name", NAPI_AUTO_LENGTH, TestFunctionName, NULL, &fn2)); napi_value fn3; - NAPI_CALL(env, napi_create_function( + NODE_API_CALL(env, napi_create_function( env, "Name_extra", 5, TestFunctionName, NULL, &fn3)); napi_value fn4; - NAPI_CALL(env, napi_create_function(env, - "MakeTrackedFunction", - NAPI_AUTO_LENGTH, - MakeTrackedFunction, - NULL, - &fn4)); + NODE_API_CALL(env, + napi_create_function( + env, "MakeTrackedFunction", NAPI_AUTO_LENGTH, MakeTrackedFunction, + NULL, &fn4)); napi_value fn5; - NAPI_CALL(env, napi_create_function(env, - "TestCreateFunctionParameters", - NAPI_AUTO_LENGTH, - TestCreateFunctionParameters, - NULL, - &fn5)); - - NAPI_CALL(env, napi_set_named_property(env, exports, "TestCall", fn1)); - NAPI_CALL(env, napi_set_named_property(env, exports, "TestName", fn2)); - NAPI_CALL(env, napi_set_named_property(env, exports, "TestNameShort", fn3)); - NAPI_CALL(env, napi_set_named_property(env, - exports, - "MakeTrackedFunction", - fn4)); - - NAPI_CALL(env, napi_set_named_property(env, - exports, - "TestCreateFunctionParameters", - fn5)); + NODE_API_CALL(env, + napi_create_function( + env, "TestCreateFunctionParameters", NAPI_AUTO_LENGTH, + TestCreateFunctionParameters, NULL, &fn5)); + + NODE_API_CALL(env, napi_set_named_property(env, exports, "TestCall", fn1)); + NODE_API_CALL(env, napi_set_named_property(env, exports, "TestName", fn2)); + NODE_API_CALL(env, + napi_set_named_property(env, exports, "TestNameShort", fn3)); + NODE_API_CALL(env, + napi_set_named_property(env, exports, "MakeTrackedFunction", fn4)); + + NODE_API_CALL(env, + napi_set_named_property( + env, exports, "TestCreateFunctionParameters", fn5)); return exports; } diff --git a/test/js-native-api/test_general/test_general.c b/test/js-native-api/test_general/test_general.c index f6e641167d5bcc..7b755ce9a9f202 100644 --- a/test/js-native-api/test_general/test_general.c +++ b/test/js-native-api/test_general/test_general.c @@ -7,12 +7,12 @@ static napi_value testStrictEquals(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); bool bool_result; napi_value result; - NAPI_CALL(env, napi_strict_equals(env, args[0], args[1], &bool_result)); - NAPI_CALL(env, napi_get_boolean(env, bool_result, &result)); + NODE_API_CALL(env, napi_strict_equals(env, args[0], args[1], &bool_result)); + NODE_API_CALL(env, napi_get_boolean(env, bool_result, &result)); return result; } @@ -20,10 +20,10 @@ static napi_value testStrictEquals(napi_env env, napi_callback_info info) { static napi_value testGetPrototype(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_value result; - NAPI_CALL(env, napi_get_prototype(env, args[0], &result)); + NODE_API_CALL(env, napi_get_prototype(env, args[0], &result)); return result; } @@ -31,52 +31,52 @@ static napi_value testGetPrototype(napi_env env, napi_callback_info info) { static napi_value testGetVersion(napi_env env, napi_callback_info info) { uint32_t version; napi_value result; - NAPI_CALL(env, napi_get_version(env, &version)); - NAPI_CALL(env, napi_create_uint32(env, version, &result)); + NODE_API_CALL(env, napi_get_version(env, &version)); + NODE_API_CALL(env, napi_create_uint32(env, version, &result)); return result; } static napi_value doInstanceOf(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); bool instanceof; - NAPI_CALL(env, napi_instanceof(env, args[0], args[1], &instanceof)); + NODE_API_CALL(env, napi_instanceof(env, args[0], args[1], &instanceof)); napi_value result; - NAPI_CALL(env, napi_get_boolean(env, instanceof, &result)); + NODE_API_CALL(env, napi_get_boolean(env, instanceof, &result)); return result; } static napi_value getNull(napi_env env, napi_callback_info info) { napi_value result; - NAPI_CALL(env, napi_get_null(env, &result)); + NODE_API_CALL(env, napi_get_null(env, &result)); return result; } static napi_value getUndefined(napi_env env, napi_callback_info info) { napi_value result; - NAPI_CALL(env, napi_get_undefined(env, &result)); + NODE_API_CALL(env, napi_get_undefined(env, &result)); return result; } static napi_value createNapiError(napi_env env, napi_callback_info info) { napi_value value; - NAPI_CALL(env, napi_create_string_utf8(env, "xyz", 3, &value)); + NODE_API_CALL(env, napi_create_string_utf8(env, "xyz", 3, &value)); double double_value; napi_status status = napi_get_value_double(env, value, &double_value); - NAPI_ASSERT(env, status != napi_ok, "Failed to produce error condition"); + NODE_API_ASSERT(env, status != napi_ok, "Failed to produce error condition"); const napi_extended_error_info *error_info = 0; - NAPI_CALL(env, napi_get_last_error_info(env, &error_info)); + NODE_API_CALL(env, napi_get_last_error_info(env, &error_info)); - NAPI_ASSERT(env, error_info->error_code == status, + NODE_API_ASSERT(env, error_info->error_code == status, "Last error info code should match last status"); - NAPI_ASSERT(env, error_info->error_message, + NODE_API_ASSERT(env, error_info->error_message, "Last error info message should not be null"); return NULL; @@ -84,11 +84,11 @@ static napi_value createNapiError(napi_env env, napi_callback_info info) { static napi_value testNapiErrorCleanup(napi_env env, napi_callback_info info) { const napi_extended_error_info *error_info = 0; - NAPI_CALL(env, napi_get_last_error_info(env, &error_info)); + NODE_API_CALL(env, napi_get_last_error_info(env, &error_info)); napi_value result; bool is_ok = error_info->error_code == napi_ok; - NAPI_CALL(env, napi_get_boolean(env, is_ok, &result)); + NODE_API_CALL(env, napi_get_boolean(env, is_ok, &result)); return result; } @@ -96,35 +96,35 @@ static napi_value testNapiErrorCleanup(napi_env env, napi_callback_info info) { static napi_value testNapiTypeof(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_valuetype argument_type; - NAPI_CALL(env, napi_typeof(env, args[0], &argument_type)); + NODE_API_CALL(env, napi_typeof(env, args[0], &argument_type)); napi_value result = NULL; if (argument_type == napi_number) { - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "number", NAPI_AUTO_LENGTH, &result)); } else if (argument_type == napi_string) { - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "string", NAPI_AUTO_LENGTH, &result)); } else if (argument_type == napi_function) { - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "function", NAPI_AUTO_LENGTH, &result)); } else if (argument_type == napi_object) { - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "object", NAPI_AUTO_LENGTH, &result)); } else if (argument_type == napi_boolean) { - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "boolean", NAPI_AUTO_LENGTH, &result)); } else if (argument_type == napi_undefined) { - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "undefined", NAPI_AUTO_LENGTH, &result)); } else if (argument_type == napi_symbol) { - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "symbol", NAPI_AUTO_LENGTH, &result)); } else if (argument_type == napi_null) { - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "null", NAPI_AUTO_LENGTH, &result)); } return result; @@ -134,7 +134,7 @@ static bool deref_item_called = false; static void deref_item(napi_env env, void* data, void* hint) { (void) hint; - NAPI_ASSERT_RETURN_VOID(env, data == &deref_item_called, + NODE_API_ASSERT_RETURN_VOID(env, data == &deref_item_called, "Finalize callback was called with the correct pointer"); deref_item_called = true; @@ -143,7 +143,7 @@ static void deref_item(napi_env env, void* data, void* hint) { static napi_value deref_item_was_called(napi_env env, napi_callback_info info) { napi_value it_was_called; - NAPI_CALL(env, napi_get_boolean(env, deref_item_called, &it_was_called)); + NODE_API_CALL(env, napi_get_boolean(env, deref_item_called, &it_was_called)); return it_was_called; } @@ -155,8 +155,8 @@ static napi_value wrap_first_arg(napi_env env, size_t argc = 1; napi_value to_wrap; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &to_wrap, NULL, NULL)); - NAPI_CALL(env, napi_wrap(env, to_wrap, data, finalizer, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &to_wrap, NULL, NULL)); + NODE_API_CALL(env, napi_wrap(env, to_wrap, data, finalizer, NULL, NULL)); return to_wrap; } @@ -171,8 +171,8 @@ static napi_value unwrap(napi_env env, napi_callback_info info) { napi_value wrapped; void* data; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &wrapped, NULL, NULL)); - NAPI_CALL(env, napi_unwrap(env, wrapped, &data)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &wrapped, NULL, NULL)); + NODE_API_CALL(env, napi_unwrap(env, wrapped, &data)); return NULL; } @@ -182,8 +182,8 @@ static napi_value remove_wrap(napi_env env, napi_callback_info info) { napi_value wrapped; void* data; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &wrapped, NULL, NULL)); - NAPI_CALL(env, napi_remove_wrap(env, wrapped, &data)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &wrapped, NULL, NULL)); + NODE_API_CALL(env, napi_remove_wrap(env, wrapped, &data)); return NULL; } @@ -200,7 +200,7 @@ static napi_value test_finalize_wrap(napi_env env, napi_callback_info info) { static napi_value finalize_was_called(napi_env env, napi_callback_info info) { napi_value it_was_called; - NAPI_CALL(env, napi_get_boolean(env, finalize_called, &it_was_called)); + NODE_API_CALL(env, napi_get_boolean(env, finalize_called, &it_was_called)); return it_was_called; } @@ -209,8 +209,8 @@ static napi_value testAdjustExternalMemory(napi_env env, napi_callback_info info napi_value result; int64_t adjustedValue; - NAPI_CALL(env, napi_adjust_external_memory(env, 1, &adjustedValue)); - NAPI_CALL(env, napi_create_double(env, (double)adjustedValue, &result)); + NODE_API_CALL(env, napi_adjust_external_memory(env, 1, &adjustedValue)); + NODE_API_CALL(env, napi_create_double(env, (double)adjustedValue, &result)); return result; } @@ -219,9 +219,9 @@ static napi_value testNapiRun(napi_env env, napi_callback_info info) { napi_value script, result; size_t argc = 1; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &script, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &script, NULL, NULL)); - NAPI_CALL(env, napi_run_script(env, script, &result)); + NODE_API_CALL(env, napi_run_script(env, script, &result)); return result; } @@ -229,11 +229,11 @@ static napi_value testNapiRun(napi_env env, napi_callback_info info) { static void finalizer_only_callback(napi_env env, void* data, void* hint) { napi_ref js_cb_ref = data; napi_value js_cb, undefined; - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, js_cb_ref, &js_cb)); - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_get_reference_value(env, js_cb_ref, &js_cb)); + NODE_API_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NODE_API_CALL_RETURN_VOID(env, napi_call_function(env, undefined, js_cb, 0, NULL, NULL)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, js_cb_ref)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, js_cb_ref)); } static napi_value add_finalizer_only(napi_env env, napi_callback_info info) { @@ -241,15 +241,11 @@ static napi_value add_finalizer_only(napi_env env, napi_callback_info info) { napi_value argv[2]; napi_ref js_cb_ref; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); - NAPI_CALL(env, napi_create_reference(env, argv[1], 1, &js_cb_ref)); - NAPI_CALL(env, - napi_add_finalizer(env, - argv[0], - js_cb_ref, - finalizer_only_callback, - NULL, - NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + NODE_API_CALL(env, napi_create_reference(env, argv[1], 1, &js_cb_ref)); + NODE_API_CALL(env, + napi_add_finalizer( + env, argv[0], js_cb_ref, finalizer_only_callback, NULL, NULL)); return NULL; } @@ -273,9 +269,9 @@ static napi_value env_cleanup_wrap(napi_env env, napi_callback_info info) { napi_value argv[2]; uint32_t value; uintptr_t ptr_value; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); - NAPI_CALL(env, napi_get_value_uint32(env, argv[1], &value)); + NODE_API_CALL(env, napi_get_value_uint32(env, argv[1], &value)); ptr_value = value; return wrap_first_arg(env, info, cleanup_env_finalizer, (void*)ptr_value); @@ -284,28 +280,28 @@ static napi_value env_cleanup_wrap(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("testStrictEquals", testStrictEquals), - DECLARE_NAPI_PROPERTY("testGetPrototype", testGetPrototype), - DECLARE_NAPI_PROPERTY("testGetVersion", testGetVersion), - DECLARE_NAPI_PROPERTY("testNapiRun", testNapiRun), - DECLARE_NAPI_PROPERTY("doInstanceOf", doInstanceOf), - DECLARE_NAPI_PROPERTY("getUndefined", getUndefined), - DECLARE_NAPI_PROPERTY("getNull", getNull), - DECLARE_NAPI_PROPERTY("createNapiError", createNapiError), - DECLARE_NAPI_PROPERTY("testNapiErrorCleanup", testNapiErrorCleanup), - DECLARE_NAPI_PROPERTY("testNapiTypeof", testNapiTypeof), - DECLARE_NAPI_PROPERTY("wrap", wrap), - DECLARE_NAPI_PROPERTY("envCleanupWrap", env_cleanup_wrap), - DECLARE_NAPI_PROPERTY("unwrap", unwrap), - DECLARE_NAPI_PROPERTY("removeWrap", remove_wrap), - DECLARE_NAPI_PROPERTY("addFinalizerOnly", add_finalizer_only), - DECLARE_NAPI_PROPERTY("testFinalizeWrap", test_finalize_wrap), - DECLARE_NAPI_PROPERTY("finalizeWasCalled", finalize_was_called), - DECLARE_NAPI_PROPERTY("derefItemWasCalled", deref_item_was_called), - DECLARE_NAPI_PROPERTY("testAdjustExternalMemory", testAdjustExternalMemory) + DECLARE_NODE_API_PROPERTY("testStrictEquals", testStrictEquals), + DECLARE_NODE_API_PROPERTY("testGetPrototype", testGetPrototype), + DECLARE_NODE_API_PROPERTY("testGetVersion", testGetVersion), + DECLARE_NODE_API_PROPERTY("testNapiRun", testNapiRun), + DECLARE_NODE_API_PROPERTY("doInstanceOf", doInstanceOf), + DECLARE_NODE_API_PROPERTY("getUndefined", getUndefined), + DECLARE_NODE_API_PROPERTY("getNull", getNull), + DECLARE_NODE_API_PROPERTY("createNapiError", createNapiError), + DECLARE_NODE_API_PROPERTY("testNapiErrorCleanup", testNapiErrorCleanup), + DECLARE_NODE_API_PROPERTY("testNapiTypeof", testNapiTypeof), + DECLARE_NODE_API_PROPERTY("wrap", wrap), + DECLARE_NODE_API_PROPERTY("envCleanupWrap", env_cleanup_wrap), + DECLARE_NODE_API_PROPERTY("unwrap", unwrap), + DECLARE_NODE_API_PROPERTY("removeWrap", remove_wrap), + DECLARE_NODE_API_PROPERTY("addFinalizerOnly", add_finalizer_only), + DECLARE_NODE_API_PROPERTY("testFinalizeWrap", test_finalize_wrap), + DECLARE_NODE_API_PROPERTY("finalizeWasCalled", finalize_was_called), + DECLARE_NODE_API_PROPERTY("derefItemWasCalled", deref_item_was_called), + DECLARE_NODE_API_PROPERTY("testAdjustExternalMemory", testAdjustExternalMemory) }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; diff --git a/test/js-native-api/test_handle_scope/test_handle_scope.c b/test/js-native-api/test_handle_scope/test_handle_scope.c index e6029398aa66dc..681cc04c4f4b68 100644 --- a/test/js-native-api/test_handle_scope/test_handle_scope.c +++ b/test/js-native-api/test_handle_scope/test_handle_scope.c @@ -11,9 +11,9 @@ static napi_value NewScope(napi_env env, napi_callback_info info) { napi_handle_scope scope; napi_value output = NULL; - NAPI_CALL(env, napi_open_handle_scope(env, &scope)); - NAPI_CALL(env, napi_create_object(env, &output)); - NAPI_CALL(env, napi_close_handle_scope(env, scope)); + NODE_API_CALL(env, napi_open_handle_scope(env, &scope)); + NODE_API_CALL(env, napi_create_object(env, &output)); + NODE_API_CALL(env, napi_close_handle_scope(env, scope)); return NULL; } @@ -22,10 +22,10 @@ static napi_value NewScopeEscape(napi_env env, napi_callback_info info) { napi_value output = NULL; napi_value escapee = NULL; - NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); - NAPI_CALL(env, napi_create_object(env, &output)); - NAPI_CALL(env, napi_escape_handle(env, scope, output, &escapee)); - NAPI_CALL(env, napi_close_escapable_handle_scope(env, scope)); + NODE_API_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + NODE_API_CALL(env, napi_create_object(env, &output)); + NODE_API_CALL(env, napi_escape_handle(env, scope, output, &escapee)); + NODE_API_CALL(env, napi_close_escapable_handle_scope(env, scope)); return escapee; } @@ -35,12 +35,12 @@ static napi_value NewScopeEscapeTwice(napi_env env, napi_callback_info info) { napi_value escapee = NULL; napi_status status; - NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); - NAPI_CALL(env, napi_create_object(env, &output)); - NAPI_CALL(env, napi_escape_handle(env, scope, output, &escapee)); + NODE_API_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + NODE_API_CALL(env, napi_create_object(env, &output)); + NODE_API_CALL(env, napi_escape_handle(env, scope, output, &escapee)); status = napi_escape_handle(env, scope, output, &escapee); - NAPI_ASSERT(env, status == napi_escape_called_twice, "Escaping twice fails"); - NAPI_CALL(env, napi_close_escapable_handle_scope(env, scope)); + NODE_API_ASSERT(env, status == napi_escape_called_twice, "Escaping twice fails"); + NODE_API_CALL(env, napi_close_escapable_handle_scope(env, scope)); return NULL; } @@ -51,33 +51,33 @@ static napi_value NewScopeWithException(napi_env env, napi_callback_info info) { napi_status status; napi_value output = NULL; - NAPI_CALL(env, napi_open_handle_scope(env, &scope)); - NAPI_CALL(env, napi_create_object(env, &output)); + NODE_API_CALL(env, napi_open_handle_scope(env, &scope)); + NODE_API_CALL(env, napi_create_object(env, &output)); argc = 1; - NAPI_CALL(env, napi_get_cb_info( + NODE_API_CALL(env, napi_get_cb_info( env, info, &argc, &exception_function, NULL, NULL)); status = napi_call_function( env, output, exception_function, 0, NULL, NULL); - NAPI_ASSERT(env, status == napi_pending_exception, + NODE_API_ASSERT(env, status == napi_pending_exception, "Function should have thrown."); // Closing a handle scope should still work while an exception is pending. - NAPI_CALL(env, napi_close_handle_scope(env, scope)); + NODE_API_CALL(env, napi_close_handle_scope(env, scope)); return NULL; } EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { - DECLARE_NAPI_PROPERTY("NewScope", NewScope), - DECLARE_NAPI_PROPERTY("NewScopeEscape", NewScopeEscape), - DECLARE_NAPI_PROPERTY("NewScopeEscapeTwice", NewScopeEscapeTwice), - DECLARE_NAPI_PROPERTY("NewScopeWithException", NewScopeWithException), + DECLARE_NODE_API_PROPERTY("NewScope", NewScope), + DECLARE_NODE_API_PROPERTY("NewScopeEscape", NewScopeEscape), + DECLARE_NODE_API_PROPERTY("NewScopeEscapeTwice", NewScopeEscapeTwice), + DECLARE_NODE_API_PROPERTY("NewScopeWithException", NewScopeWithException), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(properties) / sizeof(*properties), properties)); return exports; diff --git a/test/js-native-api/test_instance_data/test_instance_data.c b/test/js-native-api/test_instance_data/test_instance_data.c index 5255c3e4a02b94..95d41ed5f64994 100644 --- a/test/js-native-api/test_instance_data/test_instance_data.c +++ b/test/js-native-api/test_instance_data/test_instance_data.c @@ -13,8 +13,8 @@ static napi_value Increment(napi_env env, napi_callback_info info) { AddonData* data; napi_value result; - NAPI_CALL(env, napi_get_instance_data(env, (void**)&data)); - NAPI_CALL(env, napi_create_uint32(env, ++data->value, &result)); + NODE_API_CALL(env, napi_get_instance_data(env, (void**)&data)); + NODE_API_CALL(env, napi_create_uint32(env, ++data->value, &result)); return result; } @@ -25,7 +25,7 @@ static void DeleteAddonData(napi_env env, void* raw_data, void* hint) { printf("deleting addon data\n"); } if (data->js_cb_ref != NULL) { - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, data->js_cb_ref)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, data->js_cb_ref)); } free(data); } @@ -33,7 +33,7 @@ static void DeleteAddonData(napi_env env, void* raw_data, void* hint) { static napi_value SetPrintOnDelete(napi_env env, napi_callback_info info) { AddonData* data; - NAPI_CALL(env, napi_get_instance_data(env, (void**)&data)); + NODE_API_CALL(env, napi_get_instance_data(env, (void**)&data)); data->print = true; return NULL; @@ -44,14 +44,14 @@ static void TestFinalizer(napi_env env, void* raw_data, void* hint) { (void) hint; AddonData* data; - NAPI_CALL_RETURN_VOID(env, napi_get_instance_data(env, (void**)&data)); + NODE_API_CALL_RETURN_VOID(env, napi_get_instance_data(env, (void**)&data)); napi_value js_cb, undefined; - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_get_reference_value(env, data->js_cb_ref, &js_cb)); - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NODE_API_CALL_RETURN_VOID(env, napi_call_function(env, undefined, js_cb, 0, NULL, NULL)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, data->js_cb_ref)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, data->js_cb_ref)); data->js_cb_ref = NULL; } @@ -60,13 +60,13 @@ static napi_value ObjectWithFinalizer(napi_env env, napi_callback_info info) { napi_value result, js_cb; size_t argc = 1; - NAPI_CALL(env, napi_get_instance_data(env, (void**)&data)); - NAPI_ASSERT(env, data->js_cb_ref == NULL, "reference must be NULL"); - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &js_cb, NULL, NULL)); - NAPI_CALL(env, napi_create_object(env, &result)); - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_instance_data(env, (void**)&data)); + NODE_API_ASSERT(env, data->js_cb_ref == NULL, "reference must be NULL"); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &js_cb, NULL, NULL)); + NODE_API_CALL(env, napi_create_object(env, &result)); + NODE_API_CALL(env, napi_add_finalizer(env, result, NULL, TestFinalizer, NULL, NULL)); - NAPI_CALL(env, napi_create_reference(env, js_cb, 1, &data->js_cb_ref)); + NODE_API_CALL(env, napi_create_reference(env, js_cb, 1, &data->js_cb_ref)); return result; } @@ -78,18 +78,17 @@ napi_value Init(napi_env env, napi_value exports) { data->print = false; data->js_cb_ref = NULL; - NAPI_CALL(env, napi_set_instance_data(env, data, DeleteAddonData, NULL)); + NODE_API_CALL(env, napi_set_instance_data(env, data, DeleteAddonData, NULL)); napi_property_descriptor props[] = { - DECLARE_NAPI_PROPERTY("increment", Increment), - DECLARE_NAPI_PROPERTY("setPrintOnDelete", SetPrintOnDelete), - DECLARE_NAPI_PROPERTY("objectWithFinalizer", ObjectWithFinalizer), + DECLARE_NODE_API_PROPERTY("increment", Increment), + DECLARE_NODE_API_PROPERTY("setPrintOnDelete", SetPrintOnDelete), + DECLARE_NODE_API_PROPERTY("objectWithFinalizer", ObjectWithFinalizer), }; - NAPI_CALL(env, napi_define_properties(env, - exports, - sizeof(props) / sizeof(*props), - props)); + NODE_API_CALL(env, + napi_define_properties( + env, exports, sizeof(props) / sizeof(*props), props)); return exports; } diff --git a/test/js-native-api/test_new_target/binding.c b/test/js-native-api/test_new_target/binding.c index bfb4138f719faf..d3fe5b0d2d9568 100644 --- a/test/js-native-api/test_new_target/binding.c +++ b/test/js-native-api/test_new_target/binding.c @@ -3,21 +3,21 @@ static napi_value BaseClass(napi_env env, napi_callback_info info) { napi_value newTargetArg; - NAPI_CALL(env, napi_get_new_target(env, info, &newTargetArg)); + NODE_API_CALL(env, napi_get_new_target(env, info, &newTargetArg)); napi_value thisArg; - NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &thisArg, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &thisArg, NULL)); napi_value undefined; - NAPI_CALL(env, napi_get_undefined(env, &undefined)); + NODE_API_CALL(env, napi_get_undefined(env, &undefined)); // this !== new.target since we are being invoked through super() bool result; - NAPI_CALL(env, napi_strict_equals(env, newTargetArg, thisArg, &result)); - NAPI_ASSERT(env, !result, "this !== new.target"); + NODE_API_CALL(env, napi_strict_equals(env, newTargetArg, thisArg, &result)); + NODE_API_ASSERT(env, !result, "this !== new.target"); // new.target !== undefined because we should be called as a new expression - NAPI_ASSERT(env, newTargetArg != NULL, "newTargetArg != NULL"); - NAPI_CALL(env, napi_strict_equals(env, newTargetArg, undefined, &result)); - NAPI_ASSERT(env, !result, "new.target !== undefined"); + NODE_API_ASSERT(env, newTargetArg != NULL, "newTargetArg != NULL"); + NODE_API_CALL(env, napi_strict_equals(env, newTargetArg, undefined, &result)); + NODE_API_ASSERT(env, !result, "new.target !== undefined"); return thisArg; } @@ -25,45 +25,45 @@ static napi_value BaseClass(napi_env env, napi_callback_info info) { static napi_value Constructor(napi_env env, napi_callback_info info) { bool result; napi_value newTargetArg; - NAPI_CALL(env, napi_get_new_target(env, info, &newTargetArg)); + NODE_API_CALL(env, napi_get_new_target(env, info, &newTargetArg)); size_t argc = 1; napi_value argv; napi_value thisArg; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisArg, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisArg, NULL)); napi_value undefined; - NAPI_CALL(env, napi_get_undefined(env, &undefined)); + NODE_API_CALL(env, napi_get_undefined(env, &undefined)); // new.target !== undefined because we should be called as a new expression - NAPI_ASSERT(env, newTargetArg != NULL, "newTargetArg != NULL"); - NAPI_CALL(env, napi_strict_equals(env, newTargetArg, undefined, &result)); - NAPI_ASSERT(env, !result, "new.target !== undefined"); + NODE_API_ASSERT(env, newTargetArg != NULL, "newTargetArg != NULL"); + NODE_API_CALL(env, napi_strict_equals(env, newTargetArg, undefined, &result)); + NODE_API_ASSERT(env, !result, "new.target !== undefined"); // arguments[0] should be Constructor itself (test harness passed it) - NAPI_CALL(env, napi_strict_equals(env, newTargetArg, argv, &result)); - NAPI_ASSERT(env, result, "new.target === Constructor"); + NODE_API_CALL(env, napi_strict_equals(env, newTargetArg, argv, &result)); + NODE_API_ASSERT(env, result, "new.target === Constructor"); return thisArg; } static napi_value OrdinaryFunction(napi_env env, napi_callback_info info) { napi_value newTargetArg; - NAPI_CALL(env, napi_get_new_target(env, info, &newTargetArg)); + NODE_API_CALL(env, napi_get_new_target(env, info, &newTargetArg)); - NAPI_ASSERT(env, newTargetArg == NULL, "newTargetArg == NULL"); + NODE_API_ASSERT(env, newTargetArg == NULL, "newTargetArg == NULL"); napi_value _true; - NAPI_CALL(env, napi_get_boolean(env, true, &_true)); + NODE_API_CALL(env, napi_get_boolean(env, true, &_true)); return _true; } EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { const napi_property_descriptor desc[] = { - DECLARE_NAPI_PROPERTY("BaseClass", BaseClass), - DECLARE_NAPI_PROPERTY("OrdinaryFunction", OrdinaryFunction), - DECLARE_NAPI_PROPERTY("Constructor", Constructor) + DECLARE_NODE_API_PROPERTY("BaseClass", BaseClass), + DECLARE_NODE_API_PROPERTY("OrdinaryFunction", OrdinaryFunction), + DECLARE_NODE_API_PROPERTY("Constructor", Constructor) }; - NAPI_CALL(env, napi_define_properties(env, exports, 3, desc)); + NODE_API_CALL(env, napi_define_properties(env, exports, 3, desc)); return exports; } EXTERN_C_END diff --git a/test/js-native-api/test_number/test_number.c b/test/js-native-api/test_number/test_number.c index d49bac29eff3f5..a5137c1f9f4ef0 100644 --- a/test/js-native-api/test_number/test_number.c +++ b/test/js-native-api/test_number/test_number.c @@ -4,21 +4,21 @@ static napi_value Test(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_number, + NODE_API_ASSERT(env, valuetype0 == napi_number, "Wrong type of arguments. Expects a number as first argument."); double input; - NAPI_CALL(env, napi_get_value_double(env, args[0], &input)); + NODE_API_CALL(env, napi_get_value_double(env, args[0], &input)); napi_value output; - NAPI_CALL(env, napi_create_double(env, input, &output)); + NODE_API_CALL(env, napi_create_double(env, input, &output)); return output; } @@ -26,21 +26,21 @@ static napi_value Test(napi_env env, napi_callback_info info) { static napi_value TestUint32Truncation(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_number, + NODE_API_ASSERT(env, valuetype0 == napi_number, "Wrong type of arguments. Expects a number as first argument."); uint32_t input; - NAPI_CALL(env, napi_get_value_uint32(env, args[0], &input)); + NODE_API_CALL(env, napi_get_value_uint32(env, args[0], &input)); napi_value output; - NAPI_CALL(env, napi_create_uint32(env, input, &output)); + NODE_API_CALL(env, napi_create_uint32(env, input, &output)); return output; } @@ -48,21 +48,21 @@ static napi_value TestUint32Truncation(napi_env env, napi_callback_info info) { static napi_value TestInt32Truncation(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_number, + NODE_API_ASSERT(env, valuetype0 == napi_number, "Wrong type of arguments. Expects a number as first argument."); int32_t input; - NAPI_CALL(env, napi_get_value_int32(env, args[0], &input)); + NODE_API_CALL(env, napi_get_value_int32(env, args[0], &input)); napi_value output; - NAPI_CALL(env, napi_create_int32(env, input, &output)); + NODE_API_CALL(env, napi_create_int32(env, input, &output)); return output; } @@ -70,21 +70,21 @@ static napi_value TestInt32Truncation(napi_env env, napi_callback_info info) { static napi_value TestInt64Truncation(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_number, + NODE_API_ASSERT(env, valuetype0 == napi_number, "Wrong type of arguments. Expects a number as first argument."); int64_t input; - NAPI_CALL(env, napi_get_value_int64(env, args[0], &input)); + NODE_API_CALL(env, napi_get_value_int64(env, args[0], &input)); napi_value output; - NAPI_CALL(env, napi_create_int64(env, input, &output)); + NODE_API_CALL(env, napi_create_int64(env, input, &output)); return output; } @@ -92,13 +92,13 @@ static napi_value TestInt64Truncation(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("Test", Test), - DECLARE_NAPI_PROPERTY("TestInt32Truncation", TestInt32Truncation), - DECLARE_NAPI_PROPERTY("TestUint32Truncation", TestUint32Truncation), - DECLARE_NAPI_PROPERTY("TestInt64Truncation", TestInt64Truncation), + DECLARE_NODE_API_PROPERTY("Test", Test), + DECLARE_NODE_API_PROPERTY("TestInt32Truncation", TestInt32Truncation), + DECLARE_NODE_API_PROPERTY("TestUint32Truncation", TestUint32Truncation), + DECLARE_NODE_API_PROPERTY("TestInt64Truncation", TestInt64Truncation), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; diff --git a/test/js-native-api/test_object/test_null.c b/test/js-native-api/test_object/test_null.c index b6bf4df31cc918..9e83841f38dc0b 100644 --- a/test/js-native-api/test_object/test_null.c +++ b/test/js-native-api/test_object/test_null.c @@ -6,9 +6,9 @@ static napi_value SetProperty(napi_env env, napi_callback_info info) { napi_value return_value, object, key; - NAPI_CALL(env, napi_create_object(env, &return_value)); - NAPI_CALL(env, napi_create_object(env, &object)); - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &object)); + NODE_API_CALL(env, napi_create_string_utf8(env, "someString", NAPI_AUTO_LENGTH, &key)); add_returned_status(env, @@ -33,9 +33,9 @@ static napi_value SetProperty(napi_env env, napi_callback_info info) { static napi_value GetProperty(napi_env env, napi_callback_info info) { napi_value return_value, object, key, prop; - NAPI_CALL(env, napi_create_object(env, &return_value)); - NAPI_CALL(env, napi_create_object(env, &object)); - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &object)); + NODE_API_CALL(env, napi_create_string_utf8(env, "someString", NAPI_AUTO_LENGTH, &key)); add_returned_status(env, @@ -62,9 +62,9 @@ static napi_value TestBoolValuedPropApi(napi_env env, napi_value return_value, object, key; bool result; - NAPI_CALL(env, napi_create_object(env, &return_value)); - NAPI_CALL(env, napi_create_object(env, &object)); - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &object)); + NODE_API_CALL(env, napi_create_string_utf8(env, "someString", NAPI_AUTO_LENGTH, &key)); add_returned_status(env, @@ -101,8 +101,8 @@ static napi_value DeleteProperty(napi_env env, napi_callback_info info) { static napi_value SetNamedProperty(napi_env env, napi_callback_info info) { napi_value return_value, object; - NAPI_CALL(env, napi_create_object(env, &return_value)); - NAPI_CALL(env, napi_create_object(env, &object)); + NODE_API_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &object)); add_returned_status(env, "envIsNull", @@ -126,8 +126,8 @@ static napi_value SetNamedProperty(napi_env env, napi_callback_info info) { static napi_value GetNamedProperty(napi_env env, napi_callback_info info) { napi_value return_value, object, prop; - NAPI_CALL(env, napi_create_object(env, &return_value)); - NAPI_CALL(env, napi_create_object(env, &object)); + NODE_API_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &object)); add_returned_status(env, "envIsNull", @@ -152,8 +152,8 @@ static napi_value HasNamedProperty(napi_env env, napi_callback_info info) { napi_value return_value, object; bool result; - NAPI_CALL(env, napi_create_object(env, &return_value)); - NAPI_CALL(env, napi_create_object(env, &object)); + NODE_API_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &object)); add_returned_status(env, "envIsNull", @@ -177,8 +177,8 @@ static napi_value HasNamedProperty(napi_env env, napi_callback_info info) { static napi_value SetElement(napi_env env, napi_callback_info info) { napi_value return_value, object; - NAPI_CALL(env, napi_create_object(env, &return_value)); - NAPI_CALL(env, napi_create_object(env, &object)); + NODE_API_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &object)); add_returned_status(env, "envIsNull", @@ -199,8 +199,8 @@ static napi_value SetElement(napi_env env, napi_callback_info info) { static napi_value GetElement(napi_env env, napi_callback_info info) { napi_value return_value, object, prop; - NAPI_CALL(env, napi_create_object(env, &return_value)); - NAPI_CALL(env, napi_create_object(env, &object)); + NODE_API_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &object)); add_returned_status(env, "envIsNull", @@ -223,8 +223,8 @@ static napi_value TestBoolValuedElementApi(napi_env env, napi_value return_value, object; bool result; - NAPI_CALL(env, napi_create_object(env, &return_value)); - NAPI_CALL(env, napi_create_object(env, &object)); + NODE_API_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &object)); add_returned_status(env, "envIsNull", @@ -257,8 +257,8 @@ static napi_value DefineProperties(napi_env env, napi_callback_info info) { "prop", NULL, DefineProperties, NULL, NULL, NULL, napi_enumerable, NULL }; - NAPI_CALL(env, napi_create_object(env, &object)); - NAPI_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &object)); + NODE_API_CALL(env, napi_create_object(env, &return_value)); add_returned_status(env, "envIsNull", @@ -289,7 +289,7 @@ static napi_value DefineProperties(napi_env env, napi_callback_info info) { static napi_value GetPropertyNames(napi_env env, napi_callback_info info) { napi_value return_value, props; - NAPI_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &return_value)); add_returned_status(env, "envIsNull", @@ -310,7 +310,7 @@ static napi_value GetPropertyNames(napi_env env, napi_callback_info info) { static napi_value GetAllPropertyNames(napi_env env, napi_callback_info info) { napi_value return_value, props; - NAPI_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &return_value)); add_returned_status(env, "envIsNull", @@ -346,7 +346,7 @@ static napi_value GetAllPropertyNames(napi_env env, napi_callback_info info) { static napi_value GetPrototype(napi_env env, napi_callback_info info) { napi_value return_value, proto; - NAPI_CALL(env, napi_create_object(env, &return_value)); + NODE_API_CALL(env, napi_create_object(env, &return_value)); add_returned_status(env, "envIsNull", @@ -368,26 +368,26 @@ void init_test_null(napi_env env, napi_value exports) { napi_value test_null; const napi_property_descriptor test_null_props[] = { - DECLARE_NAPI_PROPERTY("setProperty", SetProperty), - DECLARE_NAPI_PROPERTY("getProperty", GetProperty), - DECLARE_NAPI_PROPERTY("hasProperty", HasProperty), - DECLARE_NAPI_PROPERTY("hasOwnProperty", HasOwnProperty), - DECLARE_NAPI_PROPERTY("deleteProperty", DeleteProperty), - DECLARE_NAPI_PROPERTY("setNamedProperty", SetNamedProperty), - DECLARE_NAPI_PROPERTY("getNamedProperty", GetNamedProperty), - DECLARE_NAPI_PROPERTY("hasNamedProperty", HasNamedProperty), - DECLARE_NAPI_PROPERTY("setElement", SetElement), - DECLARE_NAPI_PROPERTY("getElement", GetElement), - DECLARE_NAPI_PROPERTY("hasElement", HasElement), - DECLARE_NAPI_PROPERTY("deleteElement", DeleteElement), - DECLARE_NAPI_PROPERTY("defineProperties", DefineProperties), - DECLARE_NAPI_PROPERTY("getPropertyNames", GetPropertyNames), - DECLARE_NAPI_PROPERTY("getAllPropertyNames", GetAllPropertyNames), - DECLARE_NAPI_PROPERTY("getPrototype", GetPrototype), + DECLARE_NODE_API_PROPERTY("setProperty", SetProperty), + DECLARE_NODE_API_PROPERTY("getProperty", GetProperty), + DECLARE_NODE_API_PROPERTY("hasProperty", HasProperty), + DECLARE_NODE_API_PROPERTY("hasOwnProperty", HasOwnProperty), + DECLARE_NODE_API_PROPERTY("deleteProperty", DeleteProperty), + DECLARE_NODE_API_PROPERTY("setNamedProperty", SetNamedProperty), + DECLARE_NODE_API_PROPERTY("getNamedProperty", GetNamedProperty), + DECLARE_NODE_API_PROPERTY("hasNamedProperty", HasNamedProperty), + DECLARE_NODE_API_PROPERTY("setElement", SetElement), + DECLARE_NODE_API_PROPERTY("getElement", GetElement), + DECLARE_NODE_API_PROPERTY("hasElement", HasElement), + DECLARE_NODE_API_PROPERTY("deleteElement", DeleteElement), + DECLARE_NODE_API_PROPERTY("defineProperties", DefineProperties), + DECLARE_NODE_API_PROPERTY("getPropertyNames", GetPropertyNames), + DECLARE_NODE_API_PROPERTY("getAllPropertyNames", GetAllPropertyNames), + DECLARE_NODE_API_PROPERTY("getPrototype", GetPrototype), }; - NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &test_null)); - NAPI_CALL_RETURN_VOID(env, napi_define_properties( + NODE_API_CALL_RETURN_VOID(env, napi_create_object(env, &test_null)); + NODE_API_CALL_RETURN_VOID(env, napi_define_properties( env, test_null, sizeof(test_null_props) / sizeof(*test_null_props), test_null_props)); @@ -395,6 +395,6 @@ void init_test_null(napi_env env, napi_value exports) { "testNull", NULL, NULL, NULL, NULL, test_null, napi_enumerable, NULL }; - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_define_properties(env, exports, 1, &test_null_set)); } diff --git a/test/js-native-api/test_object/test_object.c b/test/js-native-api/test_object/test_object.c index 70a85e03c725dd..5661b52063db83 100644 --- a/test/js-native-api/test_object/test_object.c +++ b/test/js-native-api/test_object/test_object.c @@ -9,25 +9,25 @@ static int test_value = 3; static napi_value Get(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 2, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_object, + NODE_API_ASSERT(env, valuetype0 == napi_object, "Wrong type of arguments. Expects an object as first argument."); napi_valuetype valuetype1; - NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1)); - NAPI_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol, + NODE_API_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol, "Wrong type of arguments. Expects a string or symbol as second."); napi_value object = args[0]; napi_value output; - NAPI_CALL(env, napi_get_property(env, object, args[1], &output)); + NODE_API_CALL(env, napi_get_property(env, object, args[1], &output)); return output; } @@ -37,30 +37,30 @@ static napi_value GetNamed(napi_env env, napi_callback_info info) { napi_value args[2]; char key[256] = ""; size_t key_length; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 2, "Wrong number of arguments"); napi_valuetype value_type0; - NAPI_CALL(env, napi_typeof(env, args[0], &value_type0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &value_type0)); - NAPI_ASSERT(env, value_type0 == napi_object, + NODE_API_ASSERT(env, value_type0 == napi_object, "Wrong type of arguments. Expects an object as first argument."); napi_valuetype value_type1; - NAPI_CALL(env, napi_typeof(env, args[1], &value_type1)); + NODE_API_CALL(env, napi_typeof(env, args[1], &value_type1)); - NAPI_ASSERT(env, value_type1 == napi_string, + NODE_API_ASSERT(env, value_type1 == napi_string, "Wrong type of arguments. Expects a string as second."); napi_value object = args[0]; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_value_string_utf8(env, args[1], key, 255, &key_length)); key[255] = 0; - NAPI_ASSERT(env, key_length <= 255, + NODE_API_ASSERT(env, key_length <= 255, "Cannot accommodate keys longer than 255 bytes"); napi_value output; - NAPI_CALL(env, napi_get_named_property(env, object, key, &output)); + NODE_API_CALL(env, napi_get_named_property(env, object, key, &output)); return output; } @@ -68,18 +68,18 @@ static napi_value GetNamed(napi_env env, napi_callback_info info) { static napi_value GetPropertyNames(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype value_type0; - NAPI_CALL(env, napi_typeof(env, args[0], &value_type0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &value_type0)); - NAPI_ASSERT(env, value_type0 == napi_object, + NODE_API_ASSERT(env, value_type0 == napi_object, "Wrong type of arguments. Expects an object as first argument."); napi_value output; - NAPI_CALL(env, napi_get_property_names(env, args[0], &output)); + NODE_API_CALL(env, napi_get_property_names(env, args[0], &output)); return output; } @@ -87,26 +87,22 @@ static napi_value GetPropertyNames(napi_env env, napi_callback_info info) { static napi_value GetSymbolNames(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype value_type0; - NAPI_CALL(env, napi_typeof(env, args[0], &value_type0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &value_type0)); - NAPI_ASSERT(env, + NODE_API_ASSERT(env, value_type0 == napi_object, "Wrong type of arguments. Expects an object as first argument."); napi_value output; - NAPI_CALL(env, - napi_get_all_property_names( - env, - args[0], - napi_key_include_prototypes, - napi_key_skip_strings, - napi_key_numbers_to_strings, - &output)); + NODE_API_CALL(env, + napi_get_all_property_names( + env, args[0], napi_key_include_prototypes, napi_key_skip_strings, + napi_key_numbers_to_strings, &output)); return output; } @@ -114,26 +110,26 @@ static napi_value GetSymbolNames(napi_env env, napi_callback_info info) { static napi_value Set(napi_env env, napi_callback_info info) { size_t argc = 3; napi_value args[3]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 3, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 3, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_object, + NODE_API_ASSERT(env, valuetype0 == napi_object, "Wrong type of arguments. Expects an object as first argument."); napi_valuetype valuetype1; - NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1)); - NAPI_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol, + NODE_API_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol, "Wrong type of arguments. Expects a string or symbol as second."); - NAPI_CALL(env, napi_set_property(env, args[0], args[1], args[2])); + NODE_API_CALL(env, napi_set_property(env, args[0], args[1], args[2])); napi_value valuetrue; - NAPI_CALL(env, napi_get_boolean(env, true, &valuetrue)); + NODE_API_CALL(env, napi_get_boolean(env, true, &valuetrue)); return valuetrue; } @@ -143,32 +139,32 @@ static napi_value SetNamed(napi_env env, napi_callback_info info) { napi_value args[3]; char key[256] = ""; size_t key_length; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 3, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 3, "Wrong number of arguments"); napi_valuetype value_type0; - NAPI_CALL(env, napi_typeof(env, args[0], &value_type0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &value_type0)); - NAPI_ASSERT(env, value_type0 == napi_object, + NODE_API_ASSERT(env, value_type0 == napi_object, "Wrong type of arguments. Expects an object as first argument."); napi_valuetype value_type1; - NAPI_CALL(env, napi_typeof(env, args[1], &value_type1)); + NODE_API_CALL(env, napi_typeof(env, args[1], &value_type1)); - NAPI_ASSERT(env, value_type1 == napi_string, + NODE_API_ASSERT(env, value_type1 == napi_string, "Wrong type of arguments. Expects a string as second."); - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_value_string_utf8(env, args[1], key, 255, &key_length)); key[255] = 0; - NAPI_ASSERT(env, key_length <= 255, + NODE_API_ASSERT(env, key_length <= 255, "Cannot accommodate keys longer than 255 bytes"); - NAPI_CALL(env, napi_set_named_property(env, args[0], key, args[2])); + NODE_API_CALL(env, napi_set_named_property(env, args[0], key, args[2])); napi_value value_true; - NAPI_CALL(env, napi_get_boolean(env, true, &value_true)); + NODE_API_CALL(env, napi_get_boolean(env, true, &value_true)); return value_true; } @@ -176,27 +172,27 @@ static napi_value SetNamed(napi_env env, napi_callback_info info) { static napi_value Has(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 2, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_object, + NODE_API_ASSERT(env, valuetype0 == napi_object, "Wrong type of arguments. Expects an object as first argument."); napi_valuetype valuetype1; - NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1)); - NAPI_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol, + NODE_API_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol, "Wrong type of arguments. Expects a string or symbol as second."); bool has_property; - NAPI_CALL(env, napi_has_property(env, args[0], args[1], &has_property)); + NODE_API_CALL(env, napi_has_property(env, args[0], args[1], &has_property)); napi_value ret; - NAPI_CALL(env, napi_get_boolean(env, has_property, &ret)); + NODE_API_CALL(env, napi_get_boolean(env, has_property, &ret)); return ret; } @@ -206,33 +202,33 @@ static napi_value HasNamed(napi_env env, napi_callback_info info) { napi_value args[2]; char key[256] = ""; size_t key_length; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 2, "Wrong number of arguments"); napi_valuetype value_type0; - NAPI_CALL(env, napi_typeof(env, args[0], &value_type0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &value_type0)); - NAPI_ASSERT(env, value_type0 == napi_object, + NODE_API_ASSERT(env, value_type0 == napi_object, "Wrong type of arguments. Expects an object as first argument."); napi_valuetype value_type1; - NAPI_CALL(env, napi_typeof(env, args[1], &value_type1)); + NODE_API_CALL(env, napi_typeof(env, args[1], &value_type1)); - NAPI_ASSERT(env, value_type1 == napi_string || value_type1 == napi_symbol, + NODE_API_ASSERT(env, value_type1 == napi_string || value_type1 == napi_symbol, "Wrong type of arguments. Expects a string as second."); - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_value_string_utf8(env, args[1], key, 255, &key_length)); key[255] = 0; - NAPI_ASSERT(env, key_length <= 255, + NODE_API_ASSERT(env, key_length <= 255, "Cannot accommodate keys longer than 255 bytes"); bool has_property; - NAPI_CALL(env, napi_has_named_property(env, args[0], key, &has_property)); + NODE_API_CALL(env, napi_has_named_property(env, args[0], key, &has_property)); napi_value ret; - NAPI_CALL(env, napi_get_boolean(env, has_property, &ret)); + NODE_API_CALL(env, napi_get_boolean(env, has_property, &ret)); return ret; } @@ -240,27 +236,27 @@ static napi_value HasNamed(napi_env env, napi_callback_info info) { static napi_value HasOwn(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 2, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc == 2, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_object, + NODE_API_ASSERT(env, valuetype0 == napi_object, "Wrong type of arguments. Expects an object as first argument."); // napi_valuetype valuetype1; - // NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + // NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1)); // - // NAPI_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol, + // NODE_API_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol, // "Wrong type of arguments. Expects a string or symbol as second."); bool has_property; - NAPI_CALL(env, napi_has_own_property(env, args[0], args[1], &has_property)); + NODE_API_CALL(env, napi_has_own_property(env, args[0], args[1], &has_property)); napi_value ret; - NAPI_CALL(env, napi_get_boolean(env, has_property, &ret)); + NODE_API_CALL(env, napi_get_boolean(env, has_property, &ret)); return ret; } @@ -269,42 +265,42 @@ static napi_value Delete(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 2, "Wrong number of arguments"); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_ASSERT(env, argc == 2, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_object, + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_ASSERT(env, valuetype0 == napi_object, "Wrong type of arguments. Expects an object as first argument."); napi_valuetype valuetype1; - NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); - NAPI_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol, + NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1)); + NODE_API_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol, "Wrong type of arguments. Expects a string or symbol as second."); bool result; napi_value ret; - NAPI_CALL(env, napi_delete_property(env, args[0], args[1], &result)); - NAPI_CALL(env, napi_get_boolean(env, result, &ret)); + NODE_API_CALL(env, napi_delete_property(env, args[0], args[1], &result)); + NODE_API_CALL(env, napi_get_boolean(env, result, &ret)); return ret; } static napi_value New(napi_env env, napi_callback_info info) { napi_value ret; - NAPI_CALL(env, napi_create_object(env, &ret)); + NODE_API_CALL(env, napi_create_object(env, &ret)); napi_value num; - NAPI_CALL(env, napi_create_int32(env, 987654321, &num)); + NODE_API_CALL(env, napi_create_int32(env, 987654321, &num)); - NAPI_CALL(env, napi_set_named_property(env, ret, "test_number", num)); + NODE_API_CALL(env, napi_set_named_property(env, ret, "test_number", num)); napi_value str; const char* str_val = "test string"; size_t str_len = strlen(str_val); - NAPI_CALL(env, napi_create_string_utf8(env, str_val, str_len, &str)); + NODE_API_CALL(env, napi_create_string_utf8(env, str_val, str_len, &str)); - NAPI_CALL(env, napi_set_named_property(env, ret, "test_string", str)); + NODE_API_CALL(env, napi_set_named_property(env, ret, "test_string", str)); return ret; } @@ -312,34 +308,34 @@ static napi_value New(napi_env env, napi_callback_info info) { static napi_value Inflate(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_object, + NODE_API_ASSERT(env, valuetype0 == napi_object, "Wrong type of arguments. Expects an object as first argument."); napi_value obj = args[0]; napi_value propertynames; - NAPI_CALL(env, napi_get_property_names(env, obj, &propertynames)); + NODE_API_CALL(env, napi_get_property_names(env, obj, &propertynames)); uint32_t i, length; - NAPI_CALL(env, napi_get_array_length(env, propertynames, &length)); + NODE_API_CALL(env, napi_get_array_length(env, propertynames, &length)); for (i = 0; i < length; i++) { napi_value property_str; - NAPI_CALL(env, napi_get_element(env, propertynames, i, &property_str)); + NODE_API_CALL(env, napi_get_element(env, propertynames, i, &property_str)); napi_value value; - NAPI_CALL(env, napi_get_property(env, obj, property_str, &value)); + NODE_API_CALL(env, napi_get_property(env, obj, property_str, &value)); double double_val; - NAPI_CALL(env, napi_get_value_double(env, value, &double_val)); - NAPI_CALL(env, napi_create_double(env, double_val + 1, &value)); - NAPI_CALL(env, napi_set_property(env, obj, property_str, value)); + NODE_API_CALL(env, napi_get_value_double(env, value, &double_val)); + NODE_API_CALL(env, napi_create_double(env, double_val + 1, &value)); + NODE_API_CALL(env, napi_set_property(env, obj, property_str, value)); } return obj; @@ -348,23 +344,23 @@ static napi_value Inflate(napi_env env, napi_callback_info info) { static napi_value Wrap(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value arg; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &arg, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &arg, NULL, NULL)); - NAPI_CALL(env, napi_wrap(env, arg, &test_value, NULL, NULL, NULL)); + NODE_API_CALL(env, napi_wrap(env, arg, &test_value, NULL, NULL, NULL)); return NULL; } static napi_value Unwrap(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value arg; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &arg, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &arg, NULL, NULL)); void* data; - NAPI_CALL(env, napi_unwrap(env, arg, &data)); + NODE_API_CALL(env, napi_unwrap(env, arg, &data)); bool is_expected = (data != NULL && *(int*)data == 3); napi_value result; - NAPI_CALL(env, napi_get_boolean(env, is_expected, &result)); + NODE_API_CALL(env, napi_get_boolean(env, is_expected, &result)); return result; } @@ -373,11 +369,11 @@ static napi_value TestSetProperty(napi_env env, napi_status status; napi_value object, key, value; - NAPI_CALL(env, napi_create_object(env, &object)); + NODE_API_CALL(env, napi_create_object(env, &object)); - NAPI_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &key)); + NODE_API_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &key)); - NAPI_CALL(env, napi_create_object(env, &value)); + NODE_API_CALL(env, napi_create_object(env, &value)); status = napi_set_property(NULL, object, key, value); @@ -409,9 +405,9 @@ static napi_value TestHasProperty(napi_env env, napi_value object, key; bool result; - NAPI_CALL(env, napi_create_object(env, &object)); + NODE_API_CALL(env, napi_create_object(env, &object)); - NAPI_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &key)); + NODE_API_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &key)); status = napi_has_property(NULL, object, key, &result); @@ -442,11 +438,11 @@ static napi_value TestGetProperty(napi_env env, napi_status status; napi_value object, key, result; - NAPI_CALL(env, napi_create_object(env, &object)); + NODE_API_CALL(env, napi_create_object(env, &object)); - NAPI_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &key)); + NODE_API_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &key)); - NAPI_CALL(env, napi_create_object(env, &result)); + NODE_API_CALL(env, napi_create_object(env, &result)); status = napi_get_property(NULL, object, key, &result); @@ -476,10 +472,10 @@ static napi_value TestFreeze(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_value object = args[0]; - NAPI_CALL(env, napi_object_freeze(env, object)); + NODE_API_CALL(env, napi_object_freeze(env, object)); return object; } @@ -488,10 +484,10 @@ static napi_value TestSeal(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_value object = args[0]; - NAPI_CALL(env, napi_object_seal(env, object)); + NODE_API_CALL(env, napi_object_seal(env, object)); return object; } @@ -508,10 +504,10 @@ TypeTaggedInstance(napi_env env, napi_callback_info info) { uint32_t type_index; napi_value instance, which_type; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL)); - NAPI_CALL(env, napi_get_value_uint32(env, which_type, &type_index)); - NAPI_CALL(env, napi_create_object(env, &instance)); - NAPI_CALL(env, napi_type_tag_object(env, instance, &type_tags[type_index])); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL)); + NODE_API_CALL(env, napi_get_value_uint32(env, which_type, &type_index)); + NODE_API_CALL(env, napi_create_object(env, &instance)); + NODE_API_CALL(env, napi_type_tag_object(env, instance, &type_tags[type_index])); return instance; } @@ -523,13 +519,13 @@ CheckTypeTag(napi_env env, napi_callback_info info) { napi_value argv[2], js_result; uint32_t type_index; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); - NAPI_CALL(env, napi_get_value_uint32(env, argv[0], &type_index)); - NAPI_CALL(env, napi_check_object_type_tag(env, + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + NODE_API_CALL(env, napi_get_value_uint32(env, argv[0], &type_index)); + NODE_API_CALL(env, napi_check_object_type_tag(env, argv[1], &type_tags[type_index], &result)); - NAPI_CALL(env, napi_get_boolean(env, result, &js_result)); + NODE_API_CALL(env, napi_get_boolean(env, result, &js_result)); return js_result; } @@ -537,32 +533,32 @@ CheckTypeTag(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("Get", Get), - DECLARE_NAPI_PROPERTY("GetNamed", GetNamed), - DECLARE_NAPI_PROPERTY("GetPropertyNames", GetPropertyNames), - DECLARE_NAPI_PROPERTY("GetSymbolNames", GetSymbolNames), - DECLARE_NAPI_PROPERTY("Set", Set), - DECLARE_NAPI_PROPERTY("SetNamed", SetNamed), - DECLARE_NAPI_PROPERTY("Has", Has), - DECLARE_NAPI_PROPERTY("HasNamed", HasNamed), - DECLARE_NAPI_PROPERTY("HasOwn", HasOwn), - DECLARE_NAPI_PROPERTY("Delete", Delete), - DECLARE_NAPI_PROPERTY("New", New), - DECLARE_NAPI_PROPERTY("Inflate", Inflate), - DECLARE_NAPI_PROPERTY("Wrap", Wrap), - DECLARE_NAPI_PROPERTY("Unwrap", Unwrap), - DECLARE_NAPI_PROPERTY("TestSetProperty", TestSetProperty), - DECLARE_NAPI_PROPERTY("TestHasProperty", TestHasProperty), - DECLARE_NAPI_PROPERTY("TypeTaggedInstance", TypeTaggedInstance), - DECLARE_NAPI_PROPERTY("CheckTypeTag", CheckTypeTag), - DECLARE_NAPI_PROPERTY("TestGetProperty", TestGetProperty), - DECLARE_NAPI_PROPERTY("TestFreeze", TestFreeze), - DECLARE_NAPI_PROPERTY("TestSeal", TestSeal), + DECLARE_NODE_API_PROPERTY("Get", Get), + DECLARE_NODE_API_PROPERTY("GetNamed", GetNamed), + DECLARE_NODE_API_PROPERTY("GetPropertyNames", GetPropertyNames), + DECLARE_NODE_API_PROPERTY("GetSymbolNames", GetSymbolNames), + DECLARE_NODE_API_PROPERTY("Set", Set), + DECLARE_NODE_API_PROPERTY("SetNamed", SetNamed), + DECLARE_NODE_API_PROPERTY("Has", Has), + DECLARE_NODE_API_PROPERTY("HasNamed", HasNamed), + DECLARE_NODE_API_PROPERTY("HasOwn", HasOwn), + DECLARE_NODE_API_PROPERTY("Delete", Delete), + DECLARE_NODE_API_PROPERTY("New", New), + DECLARE_NODE_API_PROPERTY("Inflate", Inflate), + DECLARE_NODE_API_PROPERTY("Wrap", Wrap), + DECLARE_NODE_API_PROPERTY("Unwrap", Unwrap), + DECLARE_NODE_API_PROPERTY("TestSetProperty", TestSetProperty), + DECLARE_NODE_API_PROPERTY("TestHasProperty", TestHasProperty), + DECLARE_NODE_API_PROPERTY("TypeTaggedInstance", TypeTaggedInstance), + DECLARE_NODE_API_PROPERTY("CheckTypeTag", CheckTypeTag), + DECLARE_NODE_API_PROPERTY("TestGetProperty", TestGetProperty), + DECLARE_NODE_API_PROPERTY("TestFreeze", TestFreeze), + DECLARE_NODE_API_PROPERTY("TestSeal", TestSeal), }; init_test_null(env, exports); - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; diff --git a/test/js-native-api/test_promise/test_promise.c b/test/js-native-api/test_promise/test_promise.c index 11f7dea1917723..488ecea7853601 100644 --- a/test/js-native-api/test_promise/test_promise.c +++ b/test/js-native-api/test_promise/test_promise.c @@ -11,7 +11,7 @@ static napi_value createPromise(napi_env env, napi_callback_info info) { return NULL; } - NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + NODE_API_CALL(env, napi_create_promise(env, &deferred, &promise)); return promise; } @@ -22,12 +22,12 @@ concludeCurrentPromise(napi_env env, napi_callback_info info) { size_t argc = 2; bool resolution; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); - NAPI_CALL(env, napi_get_value_bool(env, argv[1], &resolution)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + NODE_API_CALL(env, napi_get_value_bool(env, argv[1], &resolution)); if (resolution) { - NAPI_CALL(env, napi_resolve_deferred(env, deferred, argv[0])); + NODE_API_CALL(env, napi_resolve_deferred(env, deferred, argv[0])); } else { - NAPI_CALL(env, napi_reject_deferred(env, deferred, argv[0])); + NODE_API_CALL(env, napi_reject_deferred(env, deferred, argv[0])); } deferred = NULL; @@ -40,9 +40,9 @@ static napi_value isPromise(napi_env env, napi_callback_info info) { size_t argc = 1; bool is_promise; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &promise, NULL, NULL)); - NAPI_CALL(env, napi_is_promise(env, promise, &is_promise)); - NAPI_CALL(env, napi_get_boolean(env, is_promise, &result)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &promise, NULL, NULL)); + NODE_API_CALL(env, napi_is_promise(env, promise, &is_promise)); + NODE_API_CALL(env, napi_get_boolean(env, is_promise, &result)); return result; } @@ -50,12 +50,12 @@ static napi_value isPromise(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("createPromise", createPromise), - DECLARE_NAPI_PROPERTY("concludeCurrentPromise", concludeCurrentPromise), - DECLARE_NAPI_PROPERTY("isPromise", isPromise), + DECLARE_NODE_API_PROPERTY("createPromise", createPromise), + DECLARE_NODE_API_PROPERTY("concludeCurrentPromise", concludeCurrentPromise), + DECLARE_NODE_API_PROPERTY("isPromise", isPromise), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; diff --git a/test/js-native-api/test_properties/test_properties.c b/test/js-native-api/test_properties/test_properties.c index f26335ef1be842..c778601aa7489b 100644 --- a/test/js-native-api/test_properties/test_properties.c +++ b/test/js-native-api/test_properties/test_properties.c @@ -5,12 +5,12 @@ static double value_ = 1; static napi_value GetValue(napi_env env, napi_callback_info info) { size_t argc = 0; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, NULL, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, NULL, NULL, NULL)); - NAPI_ASSERT(env, argc == 0, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc == 0, "Wrong number of arguments"); napi_value number; - NAPI_CALL(env, napi_create_double(env, value_, &number)); + NODE_API_CALL(env, napi_create_double(env, value_, &number)); return number; } @@ -18,11 +18,11 @@ static napi_value GetValue(napi_env env, napi_callback_info info) { static napi_value SetValue(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); - NAPI_CALL(env, napi_get_value_double(env, args[0], &value_)); + NODE_API_CALL(env, napi_get_value_double(env, args[0], &value_)); return NULL; } @@ -30,9 +30,9 @@ static napi_value SetValue(napi_env env, napi_callback_info info) { static napi_value Echo(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); return args[0]; } @@ -40,21 +40,21 @@ static napi_value Echo(napi_env env, napi_callback_info info) { static napi_value HasNamedProperty(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 2, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc == 2, "Wrong number of arguments"); // Extract the name of the property to check char buffer[128]; size_t copied; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_value_string_utf8(env, args[1], buffer, sizeof(buffer), &copied)); // do the check and create the boolean return value bool value; napi_value result; - NAPI_CALL(env, napi_has_named_property(env, args[0], buffer, &value)); - NAPI_CALL(env, napi_get_boolean(env, value, &result)); + NODE_API_CALL(env, napi_has_named_property(env, args[0], buffer, &value)); + NODE_API_CALL(env, napi_get_boolean(env, value, &result)); return result; } @@ -62,23 +62,20 @@ static napi_value HasNamedProperty(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_value number; - NAPI_CALL(env, napi_create_double(env, value_, &number)); + NODE_API_CALL(env, napi_create_double(env, value_, &number)); napi_value name_value; - NAPI_CALL(env, napi_create_string_utf8(env, - "NameKeyValue", - NAPI_AUTO_LENGTH, - &name_value)); + NODE_API_CALL(env, + napi_create_string_utf8( + env, "NameKeyValue", NAPI_AUTO_LENGTH, &name_value)); napi_value symbol_description; napi_value name_symbol; - NAPI_CALL(env, napi_create_string_utf8(env, - "NameKeySymbol", - NAPI_AUTO_LENGTH, - &symbol_description)); - NAPI_CALL(env, napi_create_symbol(env, - symbol_description, - &name_symbol)); + NODE_API_CALL(env, + napi_create_string_utf8( + env, "NameKeySymbol", NAPI_AUTO_LENGTH, &symbol_description)); + NODE_API_CALL(env, + napi_create_symbol(env, symbol_description, &name_symbol)); napi_property_descriptor properties[] = { { "echo", 0, Echo, 0, 0, 0, napi_enumerable, 0 }, @@ -94,7 +91,7 @@ napi_value Init(napi_env env, napi_value exports) { { "hasNamedProperty", 0, HasNamedProperty, 0, 0, 0, napi_default, 0 }, }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(properties) / sizeof(*properties), properties)); return exports; diff --git a/test/js-native-api/test_reference/test_reference.c b/test/js-native-api/test_reference/test_reference.c index 05d5ae3eab8eb5..9d69baa0257a05 100644 --- a/test/js-native-api/test_reference/test_reference.c +++ b/test/js-native-api/test_reference/test_reference.c @@ -9,13 +9,13 @@ static napi_ref test_reference = NULL; static napi_value GetFinalizeCount(napi_env env, napi_callback_info info) { napi_value result; - NAPI_CALL(env, napi_create_int32(env, finalize_count, &result)); + NODE_API_CALL(env, napi_create_int32(env, finalize_count, &result)); return result; } static void FinalizeExternal(napi_env env, void* data, void* hint) { int *actual_value = data; - NAPI_ASSERT_RETURN_VOID(env, actual_value == &test_value, + NODE_API_ASSERT_RETURN_VOID(env, actual_value == &test_value, "The correct pointer was passed to the finalizer"); finalize_count++; } @@ -24,7 +24,7 @@ static napi_value CreateExternal(napi_env env, napi_callback_info info) { int* data = &test_value; napi_value result; - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_external(env, data, NULL, /* finalize_cb */ @@ -38,7 +38,7 @@ static napi_value CreateExternal(napi_env env, napi_callback_info info) { static napi_value CreateExternalWithFinalize(napi_env env, napi_callback_info info) { napi_value result; - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_external(env, &test_value, FinalizeExternal, @@ -52,84 +52,84 @@ CreateExternalWithFinalize(napi_env env, napi_callback_info info) { static napi_value CheckExternal(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value arg; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &arg, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &arg, NULL, NULL)); - NAPI_ASSERT(env, argc == 1, "Expected one argument."); + NODE_API_ASSERT(env, argc == 1, "Expected one argument."); napi_valuetype argtype; - NAPI_CALL(env, napi_typeof(env, arg, &argtype)); + NODE_API_CALL(env, napi_typeof(env, arg, &argtype)); - NAPI_ASSERT(env, argtype == napi_external, "Expected an external value."); + NODE_API_ASSERT(env, argtype == napi_external, "Expected an external value."); void* data; - NAPI_CALL(env, napi_get_value_external(env, arg, &data)); + NODE_API_CALL(env, napi_get_value_external(env, arg, &data)); - NAPI_ASSERT(env, data != NULL && *(int*)data == test_value, + NODE_API_ASSERT(env, data != NULL && *(int*)data == test_value, "An external data value of 1 was expected."); return NULL; } static napi_value CreateReference(napi_env env, napi_callback_info info) { - NAPI_ASSERT(env, test_reference == NULL, + NODE_API_ASSERT(env, test_reference == NULL, "The test allows only one reference at a time."); size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 2, "Expected two arguments."); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_ASSERT(env, argc == 2, "Expected two arguments."); uint32_t initial_refcount; - NAPI_CALL(env, napi_get_value_uint32(env, args[1], &initial_refcount)); + NODE_API_CALL(env, napi_get_value_uint32(env, args[1], &initial_refcount)); - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_reference(env, args[0], initial_refcount, &test_reference)); - NAPI_ASSERT(env, test_reference != NULL, + NODE_API_ASSERT(env, test_reference != NULL, "A reference should have been created."); return NULL; } static napi_value DeleteReference(napi_env env, napi_callback_info info) { - NAPI_ASSERT(env, test_reference != NULL, + NODE_API_ASSERT(env, test_reference != NULL, "A reference must have been created."); - NAPI_CALL(env, napi_delete_reference(env, test_reference)); + NODE_API_CALL(env, napi_delete_reference(env, test_reference)); test_reference = NULL; return NULL; } static napi_value IncrementRefcount(napi_env env, napi_callback_info info) { - NAPI_ASSERT(env, test_reference != NULL, + NODE_API_ASSERT(env, test_reference != NULL, "A reference must have been created."); uint32_t refcount; - NAPI_CALL(env, napi_reference_ref(env, test_reference, &refcount)); + NODE_API_CALL(env, napi_reference_ref(env, test_reference, &refcount)); napi_value result; - NAPI_CALL(env, napi_create_uint32(env, refcount, &result)); + NODE_API_CALL(env, napi_create_uint32(env, refcount, &result)); return result; } static napi_value DecrementRefcount(napi_env env, napi_callback_info info) { - NAPI_ASSERT(env, test_reference != NULL, + NODE_API_ASSERT(env, test_reference != NULL, "A reference must have been created."); uint32_t refcount; - NAPI_CALL(env, napi_reference_unref(env, test_reference, &refcount)); + NODE_API_CALL(env, napi_reference_unref(env, test_reference, &refcount)); napi_value result; - NAPI_CALL(env, napi_create_uint32(env, refcount, &result)); + NODE_API_CALL(env, napi_create_uint32(env, refcount, &result)); return result; } static napi_value GetReferenceValue(napi_env env, napi_callback_info info) { - NAPI_ASSERT(env, test_reference != NULL, + NODE_API_ASSERT(env, test_reference != NULL, "A reference must have been created."); napi_value result; - NAPI_CALL(env, napi_get_reference_value(env, test_reference, &result)); + NODE_API_CALL(env, napi_get_reference_value(env, test_reference, &result)); return result; } @@ -146,15 +146,12 @@ static void DeleteBeforeFinalizeFinalizer( static napi_value ValidateDeleteBeforeFinalize(napi_env env, napi_callback_info info) { napi_value wrapObject; size_t argc = 1; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &wrapObject, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &wrapObject, NULL, NULL)); napi_ref* ref_t = malloc(sizeof(napi_ref)); - NAPI_CALL(env, napi_wrap(env, - wrapObject, - ref_t, - DeleteBeforeFinalizeFinalizer, - NULL, - NULL)); + NODE_API_CALL(env, + napi_wrap( + env, wrapObject, ref_t, DeleteBeforeFinalizeFinalizer, NULL, NULL)); // Create a reference that will be eligible for collection at the same // time as the wrapped object by passing in the same wrapObject. @@ -165,28 +162,28 @@ static napi_value ValidateDeleteBeforeFinalize(napi_env env, napi_callback_info // for the reference) calls napi_delete_reference validating that // napi_delete_reference can be called before the finalizer for the // reference runs. - NAPI_CALL(env, napi_create_reference(env, wrapObject, 0, ref_t)); + NODE_API_CALL(env, napi_create_reference(env, wrapObject, 0, ref_t)); return wrapObject; } EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_GETTER("finalizeCount", GetFinalizeCount), - DECLARE_NAPI_PROPERTY("createExternal", CreateExternal), - DECLARE_NAPI_PROPERTY("createExternalWithFinalize", + DECLARE_NODE_API_GETTER("finalizeCount", GetFinalizeCount), + DECLARE_NODE_API_PROPERTY("createExternal", CreateExternal), + DECLARE_NODE_API_PROPERTY("createExternalWithFinalize", CreateExternalWithFinalize), - DECLARE_NAPI_PROPERTY("checkExternal", CheckExternal), - DECLARE_NAPI_PROPERTY("createReference", CreateReference), - DECLARE_NAPI_PROPERTY("deleteReference", DeleteReference), - DECLARE_NAPI_PROPERTY("incrementRefcount", IncrementRefcount), - DECLARE_NAPI_PROPERTY("decrementRefcount", DecrementRefcount), - DECLARE_NAPI_GETTER("referenceValue", GetReferenceValue), - DECLARE_NAPI_PROPERTY("validateDeleteBeforeFinalize", - ValidateDeleteBeforeFinalize), + DECLARE_NODE_API_PROPERTY("checkExternal", CheckExternal), + DECLARE_NODE_API_PROPERTY("createReference", CreateReference), + DECLARE_NODE_API_PROPERTY("deleteReference", DeleteReference), + DECLARE_NODE_API_PROPERTY("incrementRefcount", IncrementRefcount), + DECLARE_NODE_API_PROPERTY("decrementRefcount", DecrementRefcount), + DECLARE_NODE_API_GETTER("referenceValue", GetReferenceValue), + DECLARE_NODE_API_PROPERTY("validateDeleteBeforeFinalize", + ValidateDeleteBeforeFinalize), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; diff --git a/test/js-native-api/test_string/test_string.c b/test/js-native-api/test_string/test_string.c index e840feeacf2110..1dc1bf75774472 100644 --- a/test/js-native-api/test_string/test_string.c +++ b/test/js-native-api/test_string/test_string.c @@ -6,25 +6,25 @@ static napi_value TestLatin1(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); - NAPI_ASSERT(env, valuetype == napi_string, + NODE_API_ASSERT(env, valuetype == napi_string, "Wrong type of argment. Expects a string."); char buffer[128]; size_t buffer_size = 128; size_t copied; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_value_string_latin1(env, args[0], buffer, buffer_size, &copied)); napi_value output; - NAPI_CALL(env, napi_create_string_latin1(env, buffer, copied, &output)); + NODE_API_CALL(env, napi_create_string_latin1(env, buffer, copied, &output)); return output; } @@ -32,25 +32,25 @@ static napi_value TestLatin1(napi_env env, napi_callback_info info) { static napi_value TestUtf8(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); - NAPI_ASSERT(env, valuetype == napi_string, + NODE_API_ASSERT(env, valuetype == napi_string, "Wrong type of argment. Expects a string."); char buffer[128]; size_t buffer_size = 128; size_t copied; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_value_string_utf8(env, args[0], buffer, buffer_size, &copied)); napi_value output; - NAPI_CALL(env, napi_create_string_utf8(env, buffer, copied, &output)); + NODE_API_CALL(env, napi_create_string_utf8(env, buffer, copied, &output)); return output; } @@ -58,25 +58,25 @@ static napi_value TestUtf8(napi_env env, napi_callback_info info) { static napi_value TestUtf16(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); - NAPI_ASSERT(env, valuetype == napi_string, + NODE_API_ASSERT(env, valuetype == napi_string, "Wrong type of argment. Expects a string."); char16_t buffer[128]; size_t buffer_size = 128; size_t copied; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_value_string_utf16(env, args[0], buffer, buffer_size, &copied)); napi_value output; - NAPI_CALL(env, napi_create_string_utf16(env, buffer, copied, &output)); + NODE_API_CALL(env, napi_create_string_utf16(env, buffer, copied, &output)); return output; } @@ -85,25 +85,25 @@ static napi_value TestLatin1Insufficient(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); - NAPI_ASSERT(env, valuetype == napi_string, + NODE_API_ASSERT(env, valuetype == napi_string, "Wrong type of argment. Expects a string."); char buffer[4]; size_t buffer_size = 4; size_t copied; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_value_string_latin1(env, args[0], buffer, buffer_size, &copied)); napi_value output; - NAPI_CALL(env, napi_create_string_latin1(env, buffer, copied, &output)); + NODE_API_CALL(env, napi_create_string_latin1(env, buffer, copied, &output)); return output; } @@ -111,25 +111,25 @@ TestLatin1Insufficient(napi_env env, napi_callback_info info) { static napi_value TestUtf8Insufficient(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); - NAPI_ASSERT(env, valuetype == napi_string, + NODE_API_ASSERT(env, valuetype == napi_string, "Wrong type of argment. Expects a string."); char buffer[4]; size_t buffer_size = 4; size_t copied; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_value_string_utf8(env, args[0], buffer, buffer_size, &copied)); napi_value output; - NAPI_CALL(env, napi_create_string_utf8(env, buffer, copied, &output)); + NODE_API_CALL(env, napi_create_string_utf8(env, buffer, copied, &output)); return output; } @@ -137,25 +137,25 @@ static napi_value TestUtf8Insufficient(napi_env env, napi_callback_info info) { static napi_value TestUtf16Insufficient(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); - NAPI_ASSERT(env, valuetype == napi_string, + NODE_API_ASSERT(env, valuetype == napi_string, "Wrong type of argment. Expects a string."); char16_t buffer[4]; size_t buffer_size = 4; size_t copied; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_value_string_utf16(env, args[0], buffer, buffer_size, &copied)); napi_value output; - NAPI_CALL(env, napi_create_string_utf16(env, buffer, copied, &output)); + NODE_API_CALL(env, napi_create_string_utf16(env, buffer, copied, &output)); return output; } @@ -163,21 +163,21 @@ static napi_value TestUtf16Insufficient(napi_env env, napi_callback_info info) { static napi_value Utf16Length(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); - NAPI_ASSERT(env, valuetype == napi_string, + NODE_API_ASSERT(env, valuetype == napi_string, "Wrong type of argment. Expects a string."); size_t length; - NAPI_CALL(env, napi_get_value_string_utf16(env, args[0], NULL, 0, &length)); + NODE_API_CALL(env, napi_get_value_string_utf16(env, args[0], NULL, 0, &length)); napi_value output; - NAPI_CALL(env, napi_create_uint32(env, (uint32_t)length, &output)); + NODE_API_CALL(env, napi_create_uint32(env, (uint32_t)length, &output)); return output; } @@ -185,21 +185,22 @@ static napi_value Utf16Length(napi_env env, napi_callback_info info) { static napi_value Utf8Length(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); - NAPI_ASSERT(env, valuetype == napi_string, + NODE_API_ASSERT(env, valuetype == napi_string, "Wrong type of argment. Expects a string."); size_t length; - NAPI_CALL(env, napi_get_value_string_utf8(env, args[0], NULL, 0, &length)); + NODE_API_CALL(env, + napi_get_value_string_utf8(env, args[0], NULL, 0, &length)); napi_value output; - NAPI_CALL(env, napi_create_uint32(env, (uint32_t)length, &output)); + NODE_API_CALL(env, napi_create_uint32(env, (uint32_t)length, &output)); return output; } @@ -207,11 +208,12 @@ static napi_value Utf8Length(napi_env env, napi_callback_info info) { static napi_value TestLargeUtf8(napi_env env, napi_callback_info info) { napi_value output; if (SIZE_MAX > INT_MAX) { - NAPI_CALL(env, napi_create_string_utf8(env, "", ((size_t)INT_MAX) + 1, &output)); + NODE_API_CALL(env, + napi_create_string_utf8(env, "", ((size_t)INT_MAX) + 1, &output)); } else { // just throw the expected error as there is nothing to test // in this case since we can't overflow - NAPI_CALL(env, napi_throw_error(env, NULL, "Invalid argument")); + NODE_API_CALL(env, napi_throw_error(env, NULL, "Invalid argument")); } return output; @@ -220,11 +222,12 @@ static napi_value TestLargeUtf8(napi_env env, napi_callback_info info) { static napi_value TestLargeLatin1(napi_env env, napi_callback_info info) { napi_value output; if (SIZE_MAX > INT_MAX) { - NAPI_CALL(env, napi_create_string_latin1(env, "", ((size_t)INT_MAX) + 1, &output)); + NODE_API_CALL(env, + napi_create_string_latin1(env, "", ((size_t)INT_MAX) + 1, &output)); } else { // just throw the expected error as there is nothing to test // in this case since we can't overflow - NAPI_CALL(env, napi_throw_error(env, NULL, "Invalid argument")); + NODE_API_CALL(env, napi_throw_error(env, NULL, "Invalid argument")); } return output; @@ -233,13 +236,13 @@ static napi_value TestLargeLatin1(napi_env env, napi_callback_info info) { static napi_value TestLargeUtf16(napi_env env, napi_callback_info info) { napi_value output; if (SIZE_MAX > INT_MAX) { - NAPI_CALL(env, napi_create_string_utf16(env, - ((const char16_t*)""), - ((size_t)INT_MAX) + 1, &output)); + NODE_API_CALL(env, + napi_create_string_utf16( + env, ((const char16_t*)""), ((size_t)INT_MAX) + 1, &output)); } else { // just throw the expected error as there is nothing to test // in this case since we can't overflow - NAPI_CALL(env, napi_throw_error(env, NULL, "Invalid argument")); + NODE_API_CALL(env, napi_throw_error(env, NULL, "Invalid argument")); } return output; @@ -248,16 +251,16 @@ static napi_value TestLargeUtf16(napi_env env, napi_callback_info info) { static napi_value TestMemoryCorruption(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); char buf[10] = { 0 }; - NAPI_CALL(env, napi_get_value_string_utf8(env, args[0], buf, 0, NULL)); + NODE_API_CALL(env, napi_get_value_string_utf8(env, args[0], buf, 0, NULL)); char zero[10] = { 0 }; if (memcmp(buf, zero, sizeof(buf)) != 0) { - NAPI_CALL(env, napi_throw_error(env, NULL, "Buffer overwritten")); + NODE_API_CALL(env, napi_throw_error(env, NULL, "Buffer overwritten")); } return NULL; @@ -266,21 +269,21 @@ static napi_value TestMemoryCorruption(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { - DECLARE_NAPI_PROPERTY("TestLatin1", TestLatin1), - DECLARE_NAPI_PROPERTY("TestLatin1Insufficient", TestLatin1Insufficient), - DECLARE_NAPI_PROPERTY("TestUtf8", TestUtf8), - DECLARE_NAPI_PROPERTY("TestUtf8Insufficient", TestUtf8Insufficient), - DECLARE_NAPI_PROPERTY("TestUtf16", TestUtf16), - DECLARE_NAPI_PROPERTY("TestUtf16Insufficient", TestUtf16Insufficient), - DECLARE_NAPI_PROPERTY("Utf16Length", Utf16Length), - DECLARE_NAPI_PROPERTY("Utf8Length", Utf8Length), - DECLARE_NAPI_PROPERTY("TestLargeUtf8", TestLargeUtf8), - DECLARE_NAPI_PROPERTY("TestLargeLatin1", TestLargeLatin1), - DECLARE_NAPI_PROPERTY("TestLargeUtf16", TestLargeUtf16), - DECLARE_NAPI_PROPERTY("TestMemoryCorruption", TestMemoryCorruption), + DECLARE_NODE_API_PROPERTY("TestLatin1", TestLatin1), + DECLARE_NODE_API_PROPERTY("TestLatin1Insufficient", TestLatin1Insufficient), + DECLARE_NODE_API_PROPERTY("TestUtf8", TestUtf8), + DECLARE_NODE_API_PROPERTY("TestUtf8Insufficient", TestUtf8Insufficient), + DECLARE_NODE_API_PROPERTY("TestUtf16", TestUtf16), + DECLARE_NODE_API_PROPERTY("TestUtf16Insufficient", TestUtf16Insufficient), + DECLARE_NODE_API_PROPERTY("Utf16Length", Utf16Length), + DECLARE_NODE_API_PROPERTY("Utf8Length", Utf8Length), + DECLARE_NODE_API_PROPERTY("TestLargeUtf8", TestLargeUtf8), + DECLARE_NODE_API_PROPERTY("TestLargeLatin1", TestLargeLatin1), + DECLARE_NODE_API_PROPERTY("TestLargeUtf16", TestLargeUtf16), + DECLARE_NODE_API_PROPERTY("TestMemoryCorruption", TestMemoryCorruption), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(properties) / sizeof(*properties), properties)); return exports; diff --git a/test/js-native-api/test_symbol/test_symbol.c b/test/js-native-api/test_symbol/test_symbol.c index b50ae78928f84f..a87b275c938fbf 100644 --- a/test/js-native-api/test_symbol/test_symbol.c +++ b/test/js-native-api/test_symbol/test_symbol.c @@ -4,21 +4,21 @@ static napi_value New(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_value description = NULL; if (argc >= 1) { napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); - NAPI_ASSERT(env, valuetype == napi_string, + NODE_API_ASSERT(env, valuetype == napi_string, "Wrong type of arguments. Expects a string."); description = args[0]; } napi_value symbol; - NAPI_CALL(env, napi_create_symbol(env, description, &symbol)); + NODE_API_CALL(env, napi_create_symbol(env, description, &symbol)); return symbol; } @@ -26,10 +26,10 @@ static napi_value New(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { - DECLARE_NAPI_PROPERTY("New", New), + DECLARE_NODE_API_PROPERTY("New", New), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(properties) / sizeof(*properties), properties)); return exports; diff --git a/test/js-native-api/test_typedarray/test_typedarray.c b/test/js-native-api/test_typedarray/test_typedarray.c index 1714b5fe717f87..9a2031d256604d 100644 --- a/test/js-native-api/test_typedarray/test_typedarray.c +++ b/test/js-native-api/test_typedarray/test_typedarray.c @@ -6,51 +6,51 @@ static napi_value Multiply(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 2, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc == 2, "Wrong number of arguments"); napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_object, + NODE_API_ASSERT(env, valuetype0 == napi_object, "Wrong type of arguments. Expects a typed array as first argument."); napi_value input_array = args[0]; bool is_typedarray; - NAPI_CALL(env, napi_is_typedarray(env, input_array, &is_typedarray)); + NODE_API_CALL(env, napi_is_typedarray(env, input_array, &is_typedarray)); - NAPI_ASSERT(env, is_typedarray, + NODE_API_ASSERT(env, is_typedarray, "Wrong type of arguments. Expects a typed array as first argument."); napi_valuetype valuetype1; - NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1)); - NAPI_ASSERT(env, valuetype1 == napi_number, + NODE_API_ASSERT(env, valuetype1 == napi_number, "Wrong type of arguments. Expects a number as second argument."); double multiplier; - NAPI_CALL(env, napi_get_value_double(env, args[1], &multiplier)); + NODE_API_CALL(env, napi_get_value_double(env, args[1], &multiplier)); napi_typedarray_type type; napi_value input_buffer; size_t byte_offset; size_t i, length; - NAPI_CALL(env, napi_get_typedarray_info( + NODE_API_CALL(env, napi_get_typedarray_info( env, input_array, &type, &length, NULL, &input_buffer, &byte_offset)); void* data; size_t byte_length; - NAPI_CALL(env, napi_get_arraybuffer_info( + NODE_API_CALL(env, napi_get_arraybuffer_info( env, input_buffer, &data, &byte_length)); napi_value output_buffer; void* output_ptr = NULL; - NAPI_CALL(env, napi_create_arraybuffer( + NODE_API_CALL(env, napi_create_arraybuffer( env, byte_length, &output_ptr, &output_buffer)); napi_value output_array; - NAPI_CALL(env, napi_create_typedarray( + NODE_API_CALL(env, napi_create_typedarray( env, type, length, output_buffer, byte_offset, &output_array)); if (type == napi_uint8_array) { @@ -89,7 +89,7 @@ static napi_value External(napi_env env, napi_callback_info info) { externalData[2] = 2; napi_value output_buffer; - NAPI_CALL(env, napi_create_external_arraybuffer( + NODE_API_CALL(env, napi_create_external_arraybuffer( env, externalData, nElem*sizeof(int8_t), @@ -98,7 +98,7 @@ static napi_value External(napi_env env, napi_callback_info info) { &output_buffer)); napi_value output_array; - NAPI_CALL(env, napi_create_typedarray(env, + NODE_API_CALL(env, napi_create_typedarray(env, napi_int8_array, nElem, output_buffer, @@ -112,7 +112,7 @@ static napi_value External(napi_env env, napi_callback_info info) { static napi_value NullArrayBuffer(napi_env env, napi_callback_info info) { static void* data = NULL; napi_value arraybuffer; - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_external_arraybuffer(env, data, 0, NULL, NULL, &arraybuffer)); return arraybuffer; } @@ -120,67 +120,67 @@ static napi_value NullArrayBuffer(napi_env env, napi_callback_info info) { static napi_value CreateTypedArray(napi_env env, napi_callback_info info) { size_t argc = 4; napi_value args[4]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 2 || argc == 4, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc == 2 || argc == 4, "Wrong number of arguments"); napi_value input_array = args[0]; napi_valuetype valuetype0; - NAPI_CALL(env, napi_typeof(env, input_array, &valuetype0)); + NODE_API_CALL(env, napi_typeof(env, input_array, &valuetype0)); - NAPI_ASSERT(env, valuetype0 == napi_object, + NODE_API_ASSERT(env, valuetype0 == napi_object, "Wrong type of arguments. Expects a typed array as first argument."); bool is_typedarray; - NAPI_CALL(env, napi_is_typedarray(env, input_array, &is_typedarray)); + NODE_API_CALL(env, napi_is_typedarray(env, input_array, &is_typedarray)); - NAPI_ASSERT(env, is_typedarray, + NODE_API_ASSERT(env, is_typedarray, "Wrong type of arguments. Expects a typed array as first argument."); napi_valuetype valuetype1; napi_value input_buffer = args[1]; - NAPI_CALL(env, napi_typeof(env, input_buffer, &valuetype1)); + NODE_API_CALL(env, napi_typeof(env, input_buffer, &valuetype1)); - NAPI_ASSERT(env, valuetype1 == napi_object, + NODE_API_ASSERT(env, valuetype1 == napi_object, "Wrong type of arguments. Expects an array buffer as second argument."); bool is_arraybuffer; - NAPI_CALL(env, napi_is_arraybuffer(env, input_buffer, &is_arraybuffer)); + NODE_API_CALL(env, napi_is_arraybuffer(env, input_buffer, &is_arraybuffer)); - NAPI_ASSERT(env, is_arraybuffer, + NODE_API_ASSERT(env, is_arraybuffer, "Wrong type of arguments. Expects an array buffer as second argument."); napi_typedarray_type type; napi_value in_array_buffer; size_t byte_offset; size_t length; - NAPI_CALL(env, napi_get_typedarray_info( + NODE_API_CALL(env, napi_get_typedarray_info( env, input_array, &type, &length, NULL, &in_array_buffer, &byte_offset)); if (argc == 4) { napi_valuetype valuetype2; - NAPI_CALL(env, napi_typeof(env, args[2], &valuetype2)); + NODE_API_CALL(env, napi_typeof(env, args[2], &valuetype2)); - NAPI_ASSERT(env, valuetype2 == napi_number, + NODE_API_ASSERT(env, valuetype2 == napi_number, "Wrong type of arguments. Expects a number as third argument."); uint32_t uint32_length; - NAPI_CALL(env, napi_get_value_uint32(env, args[2], &uint32_length)); + NODE_API_CALL(env, napi_get_value_uint32(env, args[2], &uint32_length)); length = uint32_length; napi_valuetype valuetype3; - NAPI_CALL(env, napi_typeof(env, args[3], &valuetype3)); + NODE_API_CALL(env, napi_typeof(env, args[3], &valuetype3)); - NAPI_ASSERT(env, valuetype3 == napi_number, + NODE_API_ASSERT(env, valuetype3 == napi_number, "Wrong type of arguments. Expects a number as third argument."); uint32_t uint32_byte_offset; - NAPI_CALL(env, napi_get_value_uint32(env, args[3], &uint32_byte_offset)); + NODE_API_CALL(env, napi_get_value_uint32(env, args[3], &uint32_byte_offset)); byte_offset = uint32_byte_offset; } napi_value output_array; - NAPI_CALL(env, napi_create_typedarray( + NODE_API_CALL(env, napi_create_typedarray( env, type, length, input_buffer, byte_offset, &output_array)); return output_array; @@ -189,16 +189,20 @@ static napi_value CreateTypedArray(napi_env env, napi_callback_info info) { static napi_value Detach(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 1, "Wrong number of arguments."); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments."); bool is_typedarray; - NAPI_CALL(env, napi_is_typedarray(env, args[0], &is_typedarray)); - NAPI_ASSERT(env, is_typedarray, "Wrong type of arguments. Expects a typedarray as first argument."); + NODE_API_CALL(env, napi_is_typedarray(env, args[0], &is_typedarray)); + NODE_API_ASSERT( + env, is_typedarray, + "Wrong type of arguments. Expects a typedarray as first argument."); napi_value arraybuffer; - NAPI_CALL(env, napi_get_typedarray_info(env, args[0], NULL, NULL, NULL, &arraybuffer, NULL)); - NAPI_CALL(env, napi_detach_arraybuffer(env, arraybuffer)); + NODE_API_CALL(env, + napi_get_typedarray_info( + env, args[0], NULL, NULL, NULL, &arraybuffer, NULL)); + NODE_API_CALL(env, napi_detach_arraybuffer(env, arraybuffer)); return NULL; } @@ -206,20 +210,21 @@ static napi_value Detach(napi_env env, napi_callback_info info) { static napi_value IsDetached(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 1, "Wrong number of arguments."); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments."); napi_value array_buffer = args[0]; bool is_arraybuffer; - NAPI_CALL(env, napi_is_arraybuffer(env, array_buffer, &is_arraybuffer)); - NAPI_ASSERT(env, is_arraybuffer, + NODE_API_CALL(env, napi_is_arraybuffer(env, array_buffer, &is_arraybuffer)); + NODE_API_ASSERT(env, is_arraybuffer, "Wrong type of arguments. Expects an array buffer as first argument."); bool is_detached; - NAPI_CALL(env, napi_is_detached_arraybuffer(env, array_buffer, &is_detached)); + NODE_API_CALL(env, + napi_is_detached_arraybuffer(env, array_buffer, &is_detached)); napi_value result; - NAPI_CALL(env, napi_get_boolean(env, is_detached, &result)); + NODE_API_CALL(env, napi_get_boolean(env, is_detached, &result)); return result; } @@ -227,15 +232,15 @@ static napi_value IsDetached(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("Multiply", Multiply), - DECLARE_NAPI_PROPERTY("External", External), - DECLARE_NAPI_PROPERTY("NullArrayBuffer", NullArrayBuffer), - DECLARE_NAPI_PROPERTY("CreateTypedArray", CreateTypedArray), - DECLARE_NAPI_PROPERTY("Detach", Detach), - DECLARE_NAPI_PROPERTY("IsDetached", IsDetached), + DECLARE_NODE_API_PROPERTY("Multiply", Multiply), + DECLARE_NODE_API_PROPERTY("External", External), + DECLARE_NODE_API_PROPERTY("NullArrayBuffer", NullArrayBuffer), + DECLARE_NODE_API_PROPERTY("CreateTypedArray", CreateTypedArray), + DECLARE_NODE_API_PROPERTY("Detach", Detach), + DECLARE_NODE_API_PROPERTY("IsDetached", IsDetached), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; diff --git a/test/node-api/1_hello_world/binding.c b/test/node-api/1_hello_world/binding.c index b896da2cba4d84..3be31e18456bd9 100644 --- a/test/node-api/1_hello_world/binding.c +++ b/test/node-api/1_hello_world/binding.c @@ -6,12 +6,12 @@ static napi_value Method(napi_env env, napi_callback_info info) { napi_value world; const char* str = "world"; size_t str_len = strlen(str); - NAPI_CALL(env, napi_create_string_utf8(env, str, str_len, &world)); + NODE_API_CALL(env, napi_create_string_utf8(env, str, str_len, &world)); return world; } NAPI_MODULE_INIT() { - napi_property_descriptor desc = DECLARE_NAPI_PROPERTY("hello", Method); - NAPI_CALL(env, napi_define_properties(env, exports, 1, &desc)); + napi_property_descriptor desc = DECLARE_NODE_API_PROPERTY("hello", Method); + NODE_API_CALL(env, napi_define_properties(env, exports, 1, &desc)); return exports; } diff --git a/test/node-api/test_async/test_async.c b/test/node-api/test_async/test_async.c index 44ad08366b1908..650cf2d6241643 100644 --- a/test/node-api/test_async/test_async.c +++ b/test/node-api/test_async/test_async.c @@ -50,20 +50,20 @@ static void Complete(napi_env env, napi_status status, void* data) { napi_value argv[2]; - NAPI_CALL_RETURN_VOID(env, napi_get_null(env, &argv[0])); - NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, c->_output, &argv[1])); + NODE_API_CALL_RETURN_VOID(env, napi_get_null(env, &argv[0])); + NODE_API_CALL_RETURN_VOID(env, napi_create_int32(env, c->_output, &argv[1])); napi_value callback; - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_get_reference_value(env, c->_callback, &callback)); napi_value global; - NAPI_CALL_RETURN_VOID(env, napi_get_global(env, &global)); + NODE_API_CALL_RETURN_VOID(env, napi_get_global(env, &global)); napi_value result; - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_call_function(env, global, callback, 2, argv, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, c->_callback)); - NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, c->_request)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, c->_callback)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_async_work(env, c->_request)); } static napi_value Test(napi_env env, napi_callback_info info) { @@ -72,33 +72,33 @@ static napi_value Test(napi_env env, napi_callback_info info) { napi_value _this; napi_value resource_name; void* data; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, &_this, &data)); - NAPI_ASSERT(env, argc >= 3, "Not enough arguments, expected 2."); + NODE_API_ASSERT(env, argc >= 3, "Not enough arguments, expected 2."); napi_valuetype t; - NAPI_CALL(env, napi_typeof(env, argv[0], &t)); - NAPI_ASSERT(env, t == napi_number, + NODE_API_CALL(env, napi_typeof(env, argv[0], &t)); + NODE_API_ASSERT(env, t == napi_number, "Wrong first argument, integer expected."); - NAPI_CALL(env, napi_typeof(env, argv[1], &t)); - NAPI_ASSERT(env, t == napi_object, + NODE_API_CALL(env, napi_typeof(env, argv[1], &t)); + NODE_API_ASSERT(env, t == napi_object, "Wrong second argument, object expected."); - NAPI_CALL(env, napi_typeof(env, argv[2], &t)); - NAPI_ASSERT(env, t == napi_function, + NODE_API_CALL(env, napi_typeof(env, argv[2], &t)); + NODE_API_ASSERT(env, t == napi_function, "Wrong third argument, function expected."); the_carrier._output = 0; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_value_int32(env, argv[0], &the_carrier._input)); - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_reference(env, argv[2], 1, &the_carrier._callback)); - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "TestResource", NAPI_AUTO_LENGTH, &resource_name)); - NAPI_CALL(env, napi_create_async_work(env, argv[1], resource_name, + NODE_API_CALL(env, napi_create_async_work(env, argv[1], resource_name, Execute, Complete, &the_carrier, &the_carrier._request)); - NAPI_CALL(env, + NODE_API_CALL(env, napi_queue_async_work(env, the_carrier._request)); return NULL; @@ -106,7 +106,7 @@ static napi_value Test(napi_env env, napi_callback_info info) { static void BusyCancelComplete(napi_env env, napi_status status, void* data) { carrier* c = (carrier*)(data); - NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, c->_request)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_async_work(env, c->_request)); } static void CancelComplete(napi_env env, napi_status status, void* data) { @@ -116,17 +116,17 @@ static void CancelComplete(napi_env env, napi_status status, void* data) { // ok we got the status we expected so make the callback to // indicate the cancel succeeded. napi_value callback; - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_get_reference_value(env, c->_callback, &callback)); napi_value global; - NAPI_CALL_RETURN_VOID(env, napi_get_global(env, &global)); + NODE_API_CALL_RETURN_VOID(env, napi_get_global(env, &global)); napi_value result; - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_call_function(env, global, callback, 0, NULL, &result)); } - NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, c->_request)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, c->_callback)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_async_work(env, c->_request)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, c->_callback)); } static void CancelExecute(napi_env env, void* data) { @@ -144,31 +144,31 @@ static napi_value TestCancel(napi_env env, napi_callback_info info) { napi_value resource_name; void* data; - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "TestResource", NAPI_AUTO_LENGTH, &resource_name)); // make sure the work we are going to cancel will not be // able to start by using all the threads in the pool for (int i = 1; i < MAX_CANCEL_THREADS; i++) { - NAPI_CALL(env, napi_create_async_work(env, NULL, resource_name, + NODE_API_CALL(env, napi_create_async_work(env, NULL, resource_name, CancelExecute, BusyCancelComplete, &async_carrier[i], &async_carrier[i]._request)); - NAPI_CALL(env, napi_queue_async_work(env, async_carrier[i]._request)); + NODE_API_CALL(env, napi_queue_async_work(env, async_carrier[i]._request)); } // now queue the work we are going to cancel and then cancel it. // cancel will fail if the work has already started, but // we have prevented it from starting by consuming all of the // workers above. - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, &_this, &data)); - NAPI_CALL(env, napi_create_async_work(env, NULL, resource_name, + NODE_API_CALL(env, napi_create_async_work(env, NULL, resource_name, CancelExecute, CancelComplete, &async_carrier[0], &async_carrier[0]._request)); - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_reference(env, argv[0], 1, &async_carrier[0]._callback)); - NAPI_CALL(env, napi_queue_async_work(env, async_carrier[0]._request)); - NAPI_CALL(env, napi_cancel_async_work(env, async_carrier[0]._request)); + NODE_API_CALL(env, napi_queue_async_work(env, async_carrier[0]._request)); + NODE_API_CALL(env, napi_cancel_async_work(env, async_carrier[0]._request)); return NULL; } @@ -181,46 +181,46 @@ static void RepeatedWorkerThread(napi_env env, void* data) {} static void RepeatedWorkComplete(napi_env env, napi_status status, void* data) { napi_value cb, js_status; - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_get_reference_value(env, repeated_work_info.ref, &cb)); - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_delete_async_work(env, repeated_work_info.work)); - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, repeated_work_info.ref)); repeated_work_info.work = NULL; repeated_work_info.ref = NULL; - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_create_uint32(env, (uint32_t)status, &js_status)); - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_call_function(env, cb, cb, 1, &js_status, NULL)); } static napi_value DoRepeatedWork(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value cb, name; - NAPI_ASSERT(env, repeated_work_info.ref == NULL, + NODE_API_ASSERT(env, repeated_work_info.ref == NULL, "Reference left over from previous work"); - NAPI_ASSERT(env, repeated_work_info.work == NULL, + NODE_API_ASSERT(env, repeated_work_info.work == NULL, "Work pointer left over from previous work"); - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &cb, NULL, NULL)); - NAPI_CALL(env, napi_create_reference(env, cb, 1, &repeated_work_info.ref)); - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &cb, NULL, NULL)); + NODE_API_CALL(env, napi_create_reference(env, cb, 1, &repeated_work_info.ref)); + NODE_API_CALL(env, napi_create_string_utf8(env, "Repeated Work", NAPI_AUTO_LENGTH, &name)); - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_async_work(env, NULL, name, RepeatedWorkerThread, RepeatedWorkComplete, &repeated_work_info, &repeated_work_info.work)); - NAPI_CALL(env, napi_queue_async_work(env, repeated_work_info.work)); + NODE_API_CALL(env, napi_queue_async_work(env, repeated_work_info.work)); return NULL; } static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { - DECLARE_NAPI_PROPERTY("Test", Test), - DECLARE_NAPI_PROPERTY("TestCancel", TestCancel), - DECLARE_NAPI_PROPERTY("DoRepeatedWork", DoRepeatedWork), + DECLARE_NODE_API_PROPERTY("Test", Test), + DECLARE_NODE_API_PROPERTY("TestCancel", TestCancel), + DECLARE_NODE_API_PROPERTY("DoRepeatedWork", DoRepeatedWork), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(properties) / sizeof(*properties), properties)); return exports; diff --git a/test/node-api/test_async_context/binding.c b/test/node-api/test_async_context/binding.c index 3dab0fd0e818dd..768cb362f46356 100644 --- a/test/node-api/test_async_context/binding.c +++ b/test/node-api/test_async_context/binding.c @@ -10,9 +10,9 @@ static napi_value MakeCallback(napi_env env, napi_callback_info info) { size_t n; napi_value args[MAX_ARGUMENTS]; // NOLINTNEXTLINE (readability/null_usage) - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc > 0, "Wrong number of arguments"); napi_value async_context_wrap = args[0]; napi_value recv = args[1]; @@ -24,17 +24,17 @@ static napi_value MakeCallback(napi_env env, napi_callback_info info) { } napi_valuetype func_type; - NAPI_CALL(env, napi_typeof(env, func, &func_type)); + NODE_API_CALL(env, napi_typeof(env, func, &func_type)); napi_async_context context; - NAPI_CALL(env, napi_unwrap(env, async_context_wrap, (void**)&context)); + NODE_API_CALL(env, napi_unwrap(env, async_context_wrap, (void**)&context)); napi_value result; if (func_type == napi_function) { - NAPI_CALL(env, napi_make_callback( + NODE_API_CALL(env, napi_make_callback( env, context, recv, func, argc - RESERVED_ARGS, argv, &result)); } else { - NAPI_ASSERT(env, false, "Unexpected argument type"); + NODE_API_ASSERT(env, false, "Unexpected argument type"); } return result; @@ -42,8 +42,8 @@ static napi_value MakeCallback(napi_env env, napi_callback_info info) { static void AsyncDestroyCb(napi_env env, void* data, void* hint) { napi_status status = napi_async_destroy(env, (napi_async_context)data); - // We cannot use NAPI_ASSERT_RETURN_VOID because we need to have a JS stack - // below in order to use exceptions. + // We cannot use NODE_API_ASSERT_RETURN_VOID because we need to have a JS + // stack below in order to use exceptions. assert(status == napi_ok); } @@ -51,37 +51,37 @@ static void AsyncDestroyCb(napi_env env, void* data, void* hint) { static napi_value CreateAsyncResource(napi_env env, napi_callback_info info) { napi_value async_context_wrap; - NAPI_CALL(env, napi_create_object(env, &async_context_wrap)); + NODE_API_CALL(env, napi_create_object(env, &async_context_wrap)); size_t argc = CREATE_ASYNC_RESOURCE_ARGC; napi_value args[CREATE_ASYNC_RESOURCE_ARGC]; // NOLINTNEXTLINE (readability/null_usage) - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_value resource = args[0]; napi_value js_destroy_on_finalizer = args[1]; napi_valuetype resource_type; - NAPI_CALL(env, napi_typeof(env, resource, &resource_type)); + NODE_API_CALL(env, napi_typeof(env, resource, &resource_type)); if (resource_type != napi_object) { resource = NULL; } napi_value resource_name; - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "test_async", NAPI_AUTO_LENGTH, &resource_name)); napi_async_context context; - NAPI_CALL(env, napi_async_init(env, resource, resource_name, &context)); + NODE_API_CALL(env, napi_async_init(env, resource, resource_name, &context)); bool destroy_on_finalizer = true; if (argc == 2) { - NAPI_CALL(env, napi_get_value_bool(env, js_destroy_on_finalizer, &destroy_on_finalizer)); + NODE_API_CALL(env, napi_get_value_bool(env, js_destroy_on_finalizer, &destroy_on_finalizer)); } if (resource_type == napi_object && destroy_on_finalizer) { - NAPI_CALL(env, napi_add_finalizer( + NODE_API_CALL(env, napi_add_finalizer( env, resource, (void*)context, AsyncDestroyCb, NULL, NULL)); } - NAPI_CALL(env, napi_wrap(env, async_context_wrap, context, NULL, NULL, NULL)); + NODE_API_CALL(env, napi_wrap(env, async_context_wrap, context, NULL, NULL, NULL)); return async_context_wrap; } @@ -91,15 +91,15 @@ static napi_value DestroyAsyncResource(napi_env env, napi_callback_info info) { size_t argc = DESTROY_ASYNC_RESOURCE_ARGC; napi_value args[DESTROY_ASYNC_RESOURCE_ARGC]; // NOLINTNEXTLINE (readability/null_usage) - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); napi_value async_context_wrap = args[0]; napi_async_context async_context; - NAPI_CALL(env, + NODE_API_CALL(env, napi_remove_wrap(env, async_context_wrap, (void**)&async_context)); - NAPI_CALL(env, napi_async_destroy(env, async_context)); + NODE_API_CALL(env, napi_async_destroy(env, async_context)); return async_context_wrap; } @@ -107,20 +107,20 @@ static napi_value DestroyAsyncResource(napi_env env, napi_callback_info info) { static napi_value Init(napi_env env, napi_value exports) { napi_value fn; - NAPI_CALL(env, napi_create_function( + NODE_API_CALL(env, napi_create_function( // NOLINTNEXTLINE (readability/null_usage) env, NULL, NAPI_AUTO_LENGTH, MakeCallback, NULL, &fn)); - NAPI_CALL(env, napi_set_named_property(env, exports, "makeCallback", fn)); - NAPI_CALL(env, napi_create_function( + NODE_API_CALL(env, napi_set_named_property(env, exports, "makeCallback", fn)); + NODE_API_CALL(env, napi_create_function( // NOLINTNEXTLINE (readability/null_usage) env, NULL, NAPI_AUTO_LENGTH, CreateAsyncResource, NULL, &fn)); - NAPI_CALL(env, napi_set_named_property( + NODE_API_CALL(env, napi_set_named_property( env, exports, "createAsyncResource", fn)); - NAPI_CALL(env, napi_create_function( + NODE_API_CALL(env, napi_create_function( // NOLINTNEXTLINE (readability/null_usage) env, NULL, NAPI_AUTO_LENGTH, DestroyAsyncResource, NULL, &fn)); - NAPI_CALL(env, napi_set_named_property( + NODE_API_CALL(env, napi_set_named_property( env, exports, "destroyAsyncResource", fn)); return exports; diff --git a/test/node-api/test_buffer/test_buffer.c b/test/node-api/test_buffer/test_buffer.c index 15d7c46e975d9a..abe21626468ec9 100644 --- a/test/node-api/test_buffer/test_buffer.c +++ b/test/node-api/test_buffer/test_buffer.c @@ -8,14 +8,16 @@ static const char theText[] = static int deleterCallCount = 0; static void deleteTheText(napi_env env, void* data, void* finalize_hint) { - NAPI_ASSERT_RETURN_VOID(env, data != NULL && strcmp(data, theText) == 0, "invalid data"); + NODE_API_ASSERT_RETURN_VOID( + env, data != NULL && strcmp(data, theText) == 0, "invalid data"); (void)finalize_hint; free(data); deleterCallCount++; } static void noopDeleter(napi_env env, void* data, void* finalize_hint) { - NAPI_ASSERT_RETURN_VOID(env, data != NULL && strcmp(data, theText) == 0, "invalid data"); + NODE_API_ASSERT_RETURN_VOID( + env, data != NULL && strcmp(data, theText) == 0, "invalid data"); (void)finalize_hint; deleterCallCount++; } @@ -25,13 +27,10 @@ static napi_value newBuffer(napi_env env, napi_callback_info info) { char* theCopy; const unsigned int kBufferSize = sizeof(theText); - NAPI_CALL(env, - napi_create_buffer( - env, - sizeof(theText), - (void**)(&theCopy), - &theBuffer)); - NAPI_ASSERT(env, theCopy, "Failed to copy static text for newBuffer"); + NODE_API_CALL(env, + napi_create_buffer( + env, sizeof(theText), (void**)(&theCopy), &theBuffer)); + NODE_API_ASSERT(env, theCopy, "Failed to copy static text for newBuffer"); memcpy(theCopy, theText, kBufferSize); return theBuffer; @@ -40,28 +39,25 @@ static napi_value newBuffer(napi_env env, napi_callback_info info) { static napi_value newExternalBuffer(napi_env env, napi_callback_info info) { napi_value theBuffer; char* theCopy = strdup(theText); - NAPI_ASSERT(env, theCopy, "Failed to copy static text for newExternalBuffer"); - NAPI_CALL(env, - napi_create_external_buffer( - env, - sizeof(theText), - theCopy, - deleteTheText, - NULL, // finalize_hint - &theBuffer)); + NODE_API_ASSERT( + env, theCopy, "Failed to copy static text for newExternalBuffer"); + NODE_API_CALL(env, + napi_create_external_buffer( + env, sizeof(theText), theCopy, deleteTheText, + NULL /* finalize_hint */, &theBuffer)); return theBuffer; } static napi_value getDeleterCallCount(napi_env env, napi_callback_info info) { napi_value callCount; - NAPI_CALL(env, napi_create_int32(env, deleterCallCount, &callCount)); + NODE_API_CALL(env, napi_create_int32(env, deleterCallCount, &callCount)); return callCount; } static napi_value copyBuffer(napi_env env, napi_callback_info info) { napi_value theBuffer; - NAPI_CALL(env, napi_create_buffer_copy( + NODE_API_CALL(env, napi_create_buffer_copy( env, sizeof(theText), theText, NULL, &theBuffer)); return theBuffer; } @@ -69,38 +65,34 @@ static napi_value copyBuffer(napi_env env, napi_callback_info info) { static napi_value bufferHasInstance(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); napi_value theBuffer = args[0]; bool hasInstance; napi_valuetype theType; - NAPI_CALL(env, napi_typeof(env, theBuffer, &theType)); - NAPI_ASSERT(env, - theType == napi_object, - "bufferHasInstance: instance is not an object"); - NAPI_CALL(env, napi_is_buffer(env, theBuffer, &hasInstance)); - NAPI_ASSERT(env, hasInstance, "bufferHasInstance: instance is not a buffer"); + NODE_API_CALL(env, napi_typeof(env, theBuffer, &theType)); + NODE_API_ASSERT(env, + theType == napi_object, "bufferHasInstance: instance is not an object"); + NODE_API_CALL(env, napi_is_buffer(env, theBuffer, &hasInstance)); + NODE_API_ASSERT(env, hasInstance, "bufferHasInstance: instance is not a buffer"); napi_value returnValue; - NAPI_CALL(env, napi_get_boolean(env, hasInstance, &returnValue)); + NODE_API_CALL(env, napi_get_boolean(env, hasInstance, &returnValue)); return returnValue; } static napi_value bufferInfo(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); napi_value theBuffer = args[0]; char *bufferData; napi_value returnValue; size_t bufferLength; - NAPI_CALL(env, - napi_get_buffer_info( - env, - theBuffer, - (void**)(&bufferData), - &bufferLength)); - NAPI_CALL(env, napi_get_boolean(env, + NODE_API_CALL(env, + napi_get_buffer_info( + env, theBuffer, (void**)(&bufferData), &bufferLength)); + NODE_API_CALL(env, napi_get_boolean(env, !strcmp(bufferData, theText) && bufferLength == sizeof(theText), &returnValue)); return returnValue; @@ -108,35 +100,32 @@ static napi_value bufferInfo(napi_env env, napi_callback_info info) { static napi_value staticBuffer(napi_env env, napi_callback_info info) { napi_value theBuffer; - NAPI_CALL( - env, - napi_create_external_buffer(env, - sizeof(theText), - (void*)theText, - noopDeleter, - NULL, // finalize_hint - &theBuffer)); + NODE_API_CALL(env, + napi_create_external_buffer( + env, sizeof(theText), (void*)theText, noopDeleter, + NULL /* finalize_hint */, &theBuffer)); return theBuffer; } static napi_value Init(napi_env env, napi_value exports) { napi_value theValue; - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_string_utf8(env, theText, sizeof(theText), &theValue)); - NAPI_CALL(env, napi_set_named_property(env, exports, "theText", theValue)); + NODE_API_CALL(env, + napi_set_named_property(env, exports, "theText", theValue)); napi_property_descriptor methods[] = { - DECLARE_NAPI_PROPERTY("newBuffer", newBuffer), - DECLARE_NAPI_PROPERTY("newExternalBuffer", newExternalBuffer), - DECLARE_NAPI_PROPERTY("getDeleterCallCount", getDeleterCallCount), - DECLARE_NAPI_PROPERTY("copyBuffer", copyBuffer), - DECLARE_NAPI_PROPERTY("bufferHasInstance", bufferHasInstance), - DECLARE_NAPI_PROPERTY("bufferInfo", bufferInfo), - DECLARE_NAPI_PROPERTY("staticBuffer", staticBuffer), + DECLARE_NODE_API_PROPERTY("newBuffer", newBuffer), + DECLARE_NODE_API_PROPERTY("newExternalBuffer", newExternalBuffer), + DECLARE_NODE_API_PROPERTY("getDeleterCallCount", getDeleterCallCount), + DECLARE_NODE_API_PROPERTY("copyBuffer", copyBuffer), + DECLARE_NODE_API_PROPERTY("bufferHasInstance", bufferHasInstance), + DECLARE_NODE_API_PROPERTY("bufferInfo", bufferInfo), + DECLARE_NODE_API_PROPERTY("staticBuffer", staticBuffer), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(methods) / sizeof(methods[0]), methods)); return exports; diff --git a/test/node-api/test_callback_scope/binding.c b/test/node-api/test_callback_scope/binding.c index d512219e7bfa58..e028d517a52e37 100644 --- a/test/node-api/test_callback_scope/binding.c +++ b/test/node-api/test_callback_scope/binding.c @@ -7,37 +7,34 @@ static napi_value RunInCallbackScope(napi_env env, napi_callback_info info) { size_t argc; napi_value args[3]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, NULL, NULL, NULL)); - NAPI_ASSERT(env, argc == 3 , "Wrong number of arguments"); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, NULL, NULL, NULL)); + NODE_API_ASSERT(env, argc == 3 , "Wrong number of arguments"); - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, + NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); + NODE_API_ASSERT(env, valuetype == napi_object, "Wrong type of arguments. Expects an object as first argument."); - NAPI_CALL(env, napi_typeof(env, args[1], &valuetype)); - NAPI_ASSERT(env, valuetype == napi_string, + NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype)); + NODE_API_ASSERT(env, valuetype == napi_string, "Wrong type of arguments. Expects a string as second argument."); - NAPI_CALL(env, napi_typeof(env, args[2], &valuetype)); - NAPI_ASSERT(env, valuetype == napi_function, + NODE_API_CALL(env, napi_typeof(env, args[2], &valuetype)); + NODE_API_ASSERT(env, valuetype == napi_function, "Wrong type of arguments. Expects a function as third argument."); napi_async_context context; - NAPI_CALL(env, napi_async_init(env, args[0], args[1], &context)); + NODE_API_CALL(env, napi_async_init(env, args[0], args[1], &context)); napi_callback_scope scope = NULL; - NAPI_CALL( - env, - napi_open_callback_scope(env, - args[0], - context, - &scope)); - - // if the function has an exception pending after the call that is ok - // so we don't use NAPI_CALL as we must close the callback scope regardless + NODE_API_CALL(env, + napi_open_callback_scope(env, args[0], context, &scope)); + + // If the function has an exception pending after the call that is ok + // so we don't use NODE_API_CALL as we must close the callback scope + // regardless. napi_value result = NULL; napi_status function_call_result = napi_call_function(env, args[0], args[2], 0, NULL, &result); @@ -45,8 +42,8 @@ static napi_value RunInCallbackScope(napi_env env, napi_callback_info info) { GET_AND_THROW_LAST_ERROR((env)); } - NAPI_CALL(env, napi_close_callback_scope(env, scope)); - NAPI_CALL(env, napi_async_destroy(env, context)); + NODE_API_CALL(env, napi_close_callback_scope(env, scope)); + NODE_API_CALL(env, napi_async_destroy(env, context)); return result; } @@ -58,34 +55,32 @@ static void Callback(uv_work_t* req, int ignored) { napi_env env = shared_env; napi_handle_scope handle_scope = NULL; - NAPI_CALL_RETURN_VOID(env, napi_open_handle_scope(env, &handle_scope)); + NODE_API_CALL_RETURN_VOID(env, napi_open_handle_scope(env, &handle_scope)); napi_value resource_name; - NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8( + NODE_API_CALL_RETURN_VOID(env, napi_create_string_utf8( env, "test", NAPI_AUTO_LENGTH, &resource_name)); napi_async_context context; - NAPI_CALL_RETURN_VOID(env, - napi_async_init(env, NULL, resource_name, &context)); + NODE_API_CALL_RETURN_VOID(env, + napi_async_init(env, NULL, resource_name, &context)); napi_value resource_object; - NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &resource_object)); + NODE_API_CALL_RETURN_VOID(env, napi_create_object(env, &resource_object)); napi_value undefined_value; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined_value)); + NODE_API_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined_value)); napi_callback_scope scope = NULL; - NAPI_CALL_RETURN_VOID(env, napi_open_callback_scope(env, - resource_object, - context, - &scope)); + NODE_API_CALL_RETURN_VOID(env, + napi_open_callback_scope(env, resource_object, context, &scope)); - NAPI_CALL_RETURN_VOID(env, - napi_resolve_deferred(env, deferred, undefined_value)); + NODE_API_CALL_RETURN_VOID(env, + napi_resolve_deferred(env, deferred, undefined_value)); - NAPI_CALL_RETURN_VOID(env, napi_close_callback_scope(env, scope)); + NODE_API_CALL_RETURN_VOID(env, napi_close_callback_scope(env, scope)); - NAPI_CALL_RETURN_VOID(env, napi_close_handle_scope(env, handle_scope)); - NAPI_CALL_RETURN_VOID(env, napi_async_destroy(env, context)); + NODE_API_CALL_RETURN_VOID(env, napi_close_handle_scope(env, handle_scope)); + NODE_API_CALL_RETURN_VOID(env, napi_async_destroy(env, context)); free(req); } @@ -95,10 +90,10 @@ static napi_value TestResolveAsync(napi_env env, napi_callback_info info) { napi_value promise = NULL; if (deferred == NULL) { shared_env = env; - NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + NODE_API_CALL(env, napi_create_promise(env, &deferred, &promise)); uv_loop_t* loop = NULL; - NAPI_CALL(env, napi_get_uv_event_loop(env, &loop)); + NODE_API_CALL(env, napi_get_uv_event_loop(env, &loop)); uv_work_t* req = malloc(sizeof(*req)); uv_queue_work(loop, @@ -111,11 +106,11 @@ static napi_value TestResolveAsync(napi_env env, napi_callback_info info) { static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("runInCallbackScope", RunInCallbackScope), - DECLARE_NAPI_PROPERTY("testResolveAsync", TestResolveAsync) + DECLARE_NODE_API_PROPERTY("runInCallbackScope", RunInCallbackScope), + DECLARE_NODE_API_PROPERTY("testResolveAsync", TestResolveAsync) }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; diff --git a/test/node-api/test_exception/test_exception.c b/test/node-api/test_exception/test_exception.c index 78744bee2cc60f..674ce2a4fc1dc8 100644 --- a/test/node-api/test_exception/test_exception.c +++ b/test/node-api/test_exception/test_exception.c @@ -2,7 +2,7 @@ #include "../../js-native-api/common.h" static void finalizer(napi_env env, void *data, void *hint) { - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_throw_error(env, NULL, "Error during Finalize")); } @@ -10,16 +10,16 @@ static char buffer_data[12]; static napi_value createExternalBuffer(napi_env env, napi_callback_info info) { napi_value buffer; - NAPI_CALL(env, napi_create_external_buffer(env, sizeof(buffer_data), + NODE_API_CALL(env, napi_create_external_buffer(env, sizeof(buffer_data), buffer_data, finalizer, NULL, &buffer)); return buffer; } static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("createExternalBuffer", createExternalBuffer), + DECLARE_NODE_API_PROPERTY("createExternalBuffer", createExternalBuffer), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; } diff --git a/test/node-api/test_fatal/test_fatal.c b/test/node-api/test_fatal/test_fatal.c index 70bb458ef20e4e..9072bfd080bc2c 100644 --- a/test/node-api/test_fatal/test_fatal.c +++ b/test/node-api/test_fatal/test_fatal.c @@ -14,11 +14,11 @@ static napi_value TestStringLength(napi_env env, napi_callback_info info) { static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { - DECLARE_NAPI_PROPERTY("Test", Test), - DECLARE_NAPI_PROPERTY("TestStringLength", TestStringLength), + DECLARE_NODE_API_PROPERTY("Test", Test), + DECLARE_NODE_API_PROPERTY("TestStringLength", TestStringLength), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(properties) / sizeof(*properties), properties)); return exports; diff --git a/test/node-api/test_fatal_exception/test_fatal_exception.c b/test/node-api/test_fatal_exception/test_fatal_exception.c index 0e14b9b435871a..a3274cf10070fc 100644 --- a/test/node-api/test_fatal_exception/test_fatal_exception.c +++ b/test/node-api/test_fatal_exception/test_fatal_exception.c @@ -5,19 +5,19 @@ static napi_value Test(napi_env env, napi_callback_info info) { napi_value err; size_t argc = 1; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &err, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &err, NULL, NULL)); - NAPI_CALL(env, napi_fatal_exception(env, err)); + NODE_API_CALL(env, napi_fatal_exception(env, err)); return NULL; } static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { - DECLARE_NAPI_PROPERTY("Test", Test), + DECLARE_NODE_API_PROPERTY("Test", Test), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(properties) / sizeof(*properties), properties)); return exports; diff --git a/test/node-api/test_general/test_general.c b/test/node-api/test_general/test_general.c index be805f782be8d5..a7b7c34047c717 100644 --- a/test/node-api/test_general/test_general.c +++ b/test/node-api/test_general/test_general.c @@ -5,28 +5,27 @@ static napi_value testGetNodeVersion(napi_env env, napi_callback_info info) { const napi_node_version* node_version; napi_value result, major, minor, patch, release; - NAPI_CALL(env, napi_get_node_version(env, &node_version)); - NAPI_CALL(env, napi_create_uint32(env, node_version->major, &major)); - NAPI_CALL(env, napi_create_uint32(env, node_version->minor, &minor)); - NAPI_CALL(env, napi_create_uint32(env, node_version->patch, &patch)); - NAPI_CALL(env, napi_create_string_utf8(env, - node_version->release, - NAPI_AUTO_LENGTH, - &release)); - NAPI_CALL(env, napi_create_array_with_length(env, 4, &result)); - NAPI_CALL(env, napi_set_element(env, result, 0, major)); - NAPI_CALL(env, napi_set_element(env, result, 1, minor)); - NAPI_CALL(env, napi_set_element(env, result, 2, patch)); - NAPI_CALL(env, napi_set_element(env, result, 3, release)); + NODE_API_CALL(env, napi_get_node_version(env, &node_version)); + NODE_API_CALL(env, napi_create_uint32(env, node_version->major, &major)); + NODE_API_CALL(env, napi_create_uint32(env, node_version->minor, &minor)); + NODE_API_CALL(env, napi_create_uint32(env, node_version->patch, &patch)); + NODE_API_CALL(env, + napi_create_string_utf8( + env, node_version->release, NAPI_AUTO_LENGTH, &release)); + NODE_API_CALL(env, napi_create_array_with_length(env, 4, &result)); + NODE_API_CALL(env, napi_set_element(env, result, 0, major)); + NODE_API_CALL(env, napi_set_element(env, result, 1, minor)); + NODE_API_CALL(env, napi_set_element(env, result, 2, patch)); + NODE_API_CALL(env, napi_set_element(env, result, 3, release)); return result; } static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("testGetNodeVersion", testGetNodeVersion), + DECLARE_NODE_API_PROPERTY("testGetNodeVersion", testGetNodeVersion), }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; diff --git a/test/node-api/test_instance_data/test_instance_data.c b/test/node-api/test_instance_data/test_instance_data.c index 24fd502e836176..ef79e3c52b778b 100644 --- a/test/node-api/test_instance_data/test_instance_data.c +++ b/test/node-api/test_instance_data/test_instance_data.c @@ -20,21 +20,16 @@ static void call_cb_and_delete_ref(napi_env env, napi_ref* optional_ref) { if (optional_ref == NULL) { AddonData* data; - NAPI_CALL_RETURN_VOID(env, napi_get_instance_data(env, (void**)&data)); + NODE_API_CALL_RETURN_VOID(env, napi_get_instance_data(env, (void**)&data)); optional_ref = &data->js_cb_ref; } - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, - *optional_ref, - &js_cb)); - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_call_function(env, - undefined, - js_cb, - 0, - NULL, - NULL)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, *optional_ref)); + NODE_API_CALL_RETURN_VOID(env, + napi_get_reference_value(env, *optional_ref, &js_cb)); + NODE_API_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NODE_API_CALL_RETURN_VOID(env, + napi_call_function(env, undefined, js_cb, 0, NULL, NULL)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, *optional_ref)); *optional_ref = NULL; } @@ -52,17 +47,13 @@ static bool establish_callback_ref(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value js_cb; - NAPI_CALL_BASE(env, napi_get_instance_data(env, (void**)&data), false); - NAPI_ASSERT_BASE(env, - data->js_cb_ref == NULL, - "reference must be NULL", - false); - NAPI_CALL_BASE(env, - napi_get_cb_info(env, info, &argc, &js_cb, NULL, NULL), - false); - NAPI_CALL_BASE(env, - napi_create_reference(env, js_cb, 1, &data->js_cb_ref), - false); + NODE_API_CALL_BASE(env, napi_get_instance_data(env, (void**)&data), false); + NODE_API_ASSERT_BASE( + env, data->js_cb_ref == NULL, "reference must be NULL", false); + NODE_API_CALL_BASE( + env, napi_get_cb_info(env, info, &argc, &js_cb, NULL, NULL), false); + NODE_API_CALL_BASE( + env, napi_create_reference(env, js_cb, 1, &data->js_cb_ref), false); return true; } @@ -72,18 +63,14 @@ static napi_value AsyncWorkCallback(napi_env env, napi_callback_info info) { napi_value resource_name; napi_async_work work; - NAPI_CALL(env, napi_create_string_utf8(env, - "AsyncIncrement", - NAPI_AUTO_LENGTH, - &resource_name)); - NAPI_CALL(env, napi_create_async_work(env, - NULL, - resource_name, - AsyncWorkCbExecute, - AsyncWorkCbComplete, - NULL, - &work)); - NAPI_CALL(env, napi_queue_async_work(env, work)); + NODE_API_CALL(env, + napi_create_string_utf8( + env, "AsyncIncrement", NAPI_AUTO_LENGTH, &resource_name)); + NODE_API_CALL(env, + napi_create_async_work( + env, NULL, resource_name, AsyncWorkCbExecute, AsyncWorkCbComplete, + NULL, &work)); + NODE_API_CALL(env, napi_queue_async_work(env, work)); } return NULL; @@ -98,12 +85,10 @@ static void TestBufferFinalizerCallback(napi_env env, void* data, void* hint) { static napi_value TestBufferFinalizer(napi_env env, napi_callback_info info) { napi_value buffer = NULL; if (establish_callback_ref(env, info)) { - NAPI_CALL(env, napi_create_external_buffer(env, - sizeof(napi_callback), - TestBufferFinalizer, - TestBufferFinalizerCallback, - NULL, - &buffer)); + NODE_API_CALL(env, + napi_create_external_buffer( + env, sizeof(napi_callback), TestBufferFinalizer, + TestBufferFinalizerCallback, NULL, &buffer)); } return buffer; } @@ -147,10 +132,9 @@ static void ThreadsafeFunctionTestThread(void* raw_data) { static void FinalizeThreadsafeFunction(napi_env env, void* raw, void* hint) { AddonData* data; - NAPI_CALL_RETURN_VOID(env, napi_get_instance_data(env, (void**)&data)); - NAPI_ASSERT_RETURN_VOID(env, - uv_thread_join(&data->thread) == 0, - "Failed to join the thread"); + NODE_API_CALL_RETURN_VOID(env, napi_get_instance_data(env, (void**)&data)); + NODE_API_ASSERT_RETURN_VOID(env, + uv_thread_join(&data->thread) == 0, "Failed to join the thread"); call_cb_and_delete_ref(env, &data->js_tsfn_finalizer_ref); data->tsfn = NULL; } @@ -163,37 +147,26 @@ TestThreadsafeFunction(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value argv[2], resource_name; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); - NAPI_CALL(env, napi_get_instance_data(env, (void**)&data)); - NAPI_ASSERT(env, data->js_cb_ref == NULL, "reference must be NULL"); - NAPI_ASSERT(env, - data->js_tsfn_finalizer_ref == NULL, - "tsfn finalizer reference must be NULL"); - NAPI_CALL(env, napi_create_reference(env, argv[0], 1, &data->js_cb_ref)); - NAPI_CALL(env, napi_create_reference(env, - argv[1], - 1, - &data->js_tsfn_finalizer_ref)); - NAPI_CALL(env, napi_create_string_utf8(env, - "TSFN instance data test", - NAPI_AUTO_LENGTH, - &resource_name)); - NAPI_CALL(env, napi_create_threadsafe_function(env, - NULL, - NULL, - resource_name, - 0, - 1, - NULL, - FinalizeThreadsafeFunction, - NULL, - ThreadsafeFunctionCallJS, - &data->tsfn)); - NAPI_ASSERT(env, - uv_thread_create(&data->thread, - ThreadsafeFunctionTestThread, - data) == 0, - "uv_thread_create failed"); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + NODE_API_CALL(env, napi_get_instance_data(env, (void**)&data)); + NODE_API_ASSERT(env, data->js_cb_ref == NULL, "reference must be NULL"); + NODE_API_ASSERT( + env, data->js_tsfn_finalizer_ref == NULL, + "tsfn finalizer reference must be NULL"); + NODE_API_CALL(env, napi_create_reference(env, argv[0], 1, &data->js_cb_ref)); + NODE_API_CALL(env, + napi_create_reference(env, argv[1], 1, &data->js_tsfn_finalizer_ref)); + NODE_API_CALL(env, + napi_create_string_utf8( + env, "TSFN instance data test", NAPI_AUTO_LENGTH, &resource_name)); + NODE_API_CALL(env, + napi_create_threadsafe_function( + env, NULL, NULL, resource_name, 0, 1, NULL, + FinalizeThreadsafeFunction, NULL, ThreadsafeFunctionCallJS, + &data->tsfn)); + NODE_API_ASSERT(env, + uv_thread_create(&data->thread, ThreadsafeFunctionTestThread, data) == 0, + "uv_thread_create failed"); return NULL; } @@ -201,12 +174,11 @@ TestThreadsafeFunction(napi_env env, napi_callback_info info) { static void DeleteAddonData(napi_env env, void* raw_data, void* hint) { AddonData* data = raw_data; if (data->js_cb_ref) { - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, data->js_cb_ref)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, data->js_cb_ref)); } if (data->js_tsfn_finalizer_ref) { - NAPI_CALL_RETURN_VOID(env, - napi_delete_reference(env, - data->js_tsfn_finalizer_ref)); + NODE_API_CALL_RETURN_VOID(env, + napi_delete_reference(env, data->js_tsfn_finalizer_ref)); } free(data); } @@ -216,18 +188,17 @@ static napi_value Init(napi_env env, napi_value exports) { data->js_cb_ref = NULL; data->js_tsfn_finalizer_ref = NULL; - NAPI_CALL(env, napi_set_instance_data(env, data, DeleteAddonData, NULL)); + NODE_API_CALL(env, napi_set_instance_data(env, data, DeleteAddonData, NULL)); napi_property_descriptor props[] = { - DECLARE_NAPI_PROPERTY("asyncWorkCallback", AsyncWorkCallback), - DECLARE_NAPI_PROPERTY("testBufferFinalizer", TestBufferFinalizer), - DECLARE_NAPI_PROPERTY("testThreadsafeFunction", TestThreadsafeFunction), + DECLARE_NODE_API_PROPERTY("asyncWorkCallback", AsyncWorkCallback), + DECLARE_NODE_API_PROPERTY("testBufferFinalizer", TestBufferFinalizer), + DECLARE_NODE_API_PROPERTY("testThreadsafeFunction", TestThreadsafeFunction), }; - NAPI_CALL(env, napi_define_properties(env, - exports, - sizeof(props) / sizeof(*props), - props)); + NODE_API_CALL(env, + napi_define_properties( + env, exports, sizeof(props) / sizeof(*props), props)); return exports; } diff --git a/test/node-api/test_make_callback/binding.c b/test/node-api/test_make_callback/binding.c index 214e0a4e182385..369145efadea90 100644 --- a/test/node-api/test_make_callback/binding.c +++ b/test/node-api/test_make_callback/binding.c @@ -10,9 +10,9 @@ static napi_value MakeCallback(napi_env env, napi_callback_info info) { size_t n; napi_value args[MAX_ARGUMENTS]; // NOLINTNEXTLINE (readability/null_usage) - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + NODE_API_ASSERT(env, argc > 0, "Wrong number of arguments"); napi_value resource = args[0]; napi_value recv = args[1]; @@ -25,24 +25,24 @@ static napi_value MakeCallback(napi_env env, napi_callback_info info) { napi_valuetype func_type; - NAPI_CALL(env, napi_typeof(env, func, &func_type)); + NODE_API_CALL(env, napi_typeof(env, func, &func_type)); napi_value resource_name; - NAPI_CALL(env, napi_create_string_utf8( + NODE_API_CALL(env, napi_create_string_utf8( env, "test", NAPI_AUTO_LENGTH, &resource_name)); napi_async_context context; - NAPI_CALL(env, napi_async_init(env, resource, resource_name, &context)); + NODE_API_CALL(env, napi_async_init(env, resource, resource_name, &context)); napi_value result; if (func_type == napi_function) { - NAPI_CALL(env, napi_make_callback( + NODE_API_CALL(env, napi_make_callback( env, context, recv, func, argc - RESERVED_ARGS, argv, &result)); } else { - NAPI_ASSERT(env, false, "Unexpected argument type"); + NODE_API_ASSERT(env, false, "Unexpected argument type"); } - NAPI_CALL(env, napi_async_destroy(env, context)); + NODE_API_CALL(env, napi_async_destroy(env, context)); return result; } @@ -50,10 +50,10 @@ static napi_value MakeCallback(napi_env env, napi_callback_info info) { static napi_value Init(napi_env env, napi_value exports) { napi_value fn; - NAPI_CALL(env, napi_create_function( + NODE_API_CALL(env, napi_create_function( // NOLINTNEXTLINE (readability/null_usage) env, NULL, NAPI_AUTO_LENGTH, MakeCallback, NULL, &fn)); - NAPI_CALL(env, napi_set_named_property(env, exports, "makeCallback", fn)); + NODE_API_CALL(env, napi_set_named_property(env, exports, "makeCallback", fn)); return exports; } diff --git a/test/node-api/test_make_callback_recurse/binding.c b/test/node-api/test_make_callback_recurse/binding.c index 78f27e370babde..551a4d7122d0f7 100644 --- a/test/node-api/test_make_callback_recurse/binding.c +++ b/test/node-api/test_make_callback_recurse/binding.c @@ -5,7 +5,7 @@ static napi_value MakeCallback(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; // NOLINTNEXTLINE (readability/null_usage) - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_value recv = args[0]; napi_value func = args[1]; @@ -14,13 +14,13 @@ static napi_value MakeCallback(napi_env env, napi_callback_info info) { recv, func, 0 /* argc */, NULL /* argv */, NULL /* result */); bool isExceptionPending; - NAPI_CALL(env, napi_is_exception_pending(env, &isExceptionPending)); + NODE_API_CALL(env, napi_is_exception_pending(env, &isExceptionPending)); if (isExceptionPending && !(status == napi_pending_exception)) { // if there is an exception pending we don't expect any // other error napi_value pending_error; status = napi_get_and_clear_last_exception(env, &pending_error); - NAPI_CALL(env, + NODE_API_CALL(env, napi_throw_error((env), NULL, "error when only pending exception expected")); @@ -31,10 +31,10 @@ static napi_value MakeCallback(napi_env env, napi_callback_info info) { static napi_value Init(napi_env env, napi_value exports) { napi_value fn; - NAPI_CALL(env, napi_create_function( + NODE_API_CALL(env, napi_create_function( // NOLINTNEXTLINE (readability/null_usage) env, NULL, NAPI_AUTO_LENGTH, MakeCallback, NULL, &fn)); - NAPI_CALL(env, napi_set_named_property(env, exports, "makeCallback", fn)); + NODE_API_CALL(env, napi_set_named_property(env, exports, "makeCallback", fn)); return exports; } diff --git a/test/node-api/test_policy/binding.c b/test/node-api/test_policy/binding.c index b896da2cba4d84..3be31e18456bd9 100644 --- a/test/node-api/test_policy/binding.c +++ b/test/node-api/test_policy/binding.c @@ -6,12 +6,12 @@ static napi_value Method(napi_env env, napi_callback_info info) { napi_value world; const char* str = "world"; size_t str_len = strlen(str); - NAPI_CALL(env, napi_create_string_utf8(env, str, str_len, &world)); + NODE_API_CALL(env, napi_create_string_utf8(env, str, str_len, &world)); return world; } NAPI_MODULE_INIT() { - napi_property_descriptor desc = DECLARE_NAPI_PROPERTY("hello", Method); - NAPI_CALL(env, napi_define_properties(env, exports, 1, &desc)); + napi_property_descriptor desc = DECLARE_NODE_API_PROPERTY("hello", Method); + NODE_API_CALL(env, napi_define_properties(env, exports, 1, &desc)); return exports; } diff --git a/test/node-api/test_threadsafe_function/binding.c b/test/node-api/test_threadsafe_function/binding.c index c9c526153804c6..00c4ff88be81b6 100644 --- a/test/node-api/test_threadsafe_function/binding.c +++ b/test/node-api/test_threadsafe_function/binding.c @@ -122,9 +122,9 @@ static void data_source_thread(void* data) { static void call_js(napi_env env, napi_value cb, void* hint, void* data) { if (!(env == NULL || cb == NULL)) { napi_value argv, undefined; - NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, *(int*)data, &argv)); - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, cb, 1, &argv, + NODE_API_CALL_RETURN_VOID(env, napi_create_int32(env, *(int*)data, &argv)); + NODE_API_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NODE_API_CALL_RETURN_VOID(env, napi_call_function(env, undefined, cb, 1, &argv, NULL)); } } @@ -134,10 +134,10 @@ static napi_ref alt_ref; static void call_ref(napi_env env, napi_value _, void* hint, void* data) { if (!(env == NULL || alt_ref == NULL)) { napi_value fn, argv, undefined; - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, alt_ref, &fn)); - NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, *(int*)data, &argv)); - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, fn, 1, &argv, + NODE_API_CALL_RETURN_VOID(env, napi_get_reference_value(env, alt_ref, &fn)); + NODE_API_CALL_RETURN_VOID(env, napi_create_int32(env, *(int*)data, &argv)); + NODE_API_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NODE_API_CALL_RETURN_VOID(env, napi_call_function(env, undefined, fn, 1, &argv, NULL)); } } @@ -146,17 +146,17 @@ static void call_ref(napi_env env, napi_value _, void* hint, void* data) { static napi_value StopThread(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value argv[2]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); napi_valuetype value_type; - NAPI_CALL(env, napi_typeof(env, argv[0], &value_type)); - NAPI_ASSERT(env, value_type == napi_function, + NODE_API_CALL(env, napi_typeof(env, argv[0], &value_type)); + NODE_API_ASSERT(env, value_type == napi_function, "StopThread argument is a function"); - NAPI_ASSERT(env, (ts_fn != NULL), "Existing threadsafe function"); - NAPI_CALL(env, + NODE_API_ASSERT(env, (ts_fn != NULL), "Existing threadsafe function"); + NODE_API_CALL(env, napi_create_reference(env, argv[0], 1, &(ts_info.js_finalize_cb))); bool abort; - NAPI_CALL(env, napi_get_value_bool(env, argv[1], &abort)); - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_value_bool(env, argv[1], &abort)); + NODE_API_CALL(env, napi_release_threadsafe_function(ts_fn, abort ? napi_tsfn_abort : napi_tsfn_release)); ts_fn = NULL; @@ -174,15 +174,15 @@ static void join_the_threads(napi_env env, void *data, void *hint) { uv_thread_join(&the_threads[1]); } - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_get_reference_value(env, the_hint->js_finalize_cb, &js_cb)); - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, + NODE_API_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NODE_API_CALL_RETURN_VOID(env, napi_call_function(env, undefined, js_cb, 0, NULL, NULL)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, the_hint->js_finalize_cb)); if (alt_ref != NULL) { - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, alt_ref)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, alt_ref)); alt_ref = NULL; } } @@ -196,37 +196,39 @@ static napi_value StartThreadInternal(napi_env env, size_t argc = 4; napi_value argv[4]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); if (alt_ref_js_cb) { - NAPI_CALL(env, napi_create_reference(env, argv[0], 1, &alt_ref)); + NODE_API_CALL(env, napi_create_reference(env, argv[0], 1, &alt_ref)); argv[0] = NULL; } ts_info.block_on_full = (block_on_full ? napi_tsfn_blocking : napi_tsfn_nonblocking); - NAPI_ASSERT(env, (ts_fn == NULL), "Existing thread-safe function"); + NODE_API_ASSERT(env, (ts_fn == NULL), "Existing thread-safe function"); napi_value async_name; - NAPI_CALL(env, napi_create_string_utf8(env, "N-API Thread-safe Function Test", - NAPI_AUTO_LENGTH, &async_name)); - NAPI_CALL(env, napi_get_value_uint32(env, argv[3], &ts_info.max_queue_size)); - NAPI_CALL(env, napi_create_threadsafe_function(env, - argv[0], - NULL, - async_name, - ts_info.max_queue_size, - 2, - uv_threads, - join_the_threads, - &ts_info, - cb, - &ts_fn)); + NODE_API_CALL(env, napi_create_string_utf8(env, + "N-API Thread-safe Function Test", NAPI_AUTO_LENGTH, &async_name)); + NODE_API_CALL(env, + napi_get_value_uint32(env, argv[3], &ts_info.max_queue_size)); + NODE_API_CALL(env, napi_create_threadsafe_function(env, + argv[0], + NULL, + async_name, + ts_info.max_queue_size, + 2, + uv_threads, + join_the_threads, + &ts_info, + cb, + &ts_fn)); bool abort; - NAPI_CALL(env, napi_get_value_bool(env, argv[1], &abort)); + NODE_API_CALL(env, napi_get_value_bool(env, argv[1], &abort)); ts_info.abort = abort ? napi_tsfn_abort : napi_tsfn_release; - NAPI_CALL(env, napi_get_value_bool(env, argv[2], &(ts_info.start_secondary))); + NODE_API_CALL(env, + napi_get_value_bool(env, argv[2], &(ts_info.start_secondary))); - NAPI_ASSERT(env, + NODE_API_ASSERT(env, (uv_thread_create(&uv_threads[0], data_source_thread, ts_fn) == 0), "Thread creation"); @@ -234,14 +236,14 @@ static napi_value StartThreadInternal(napi_env env, } static napi_value Unref(napi_env env, napi_callback_info info) { - NAPI_ASSERT(env, ts_fn != NULL, "No existing thread-safe function"); - NAPI_CALL(env, napi_unref_threadsafe_function(env, ts_fn)); + NODE_API_ASSERT(env, ts_fn != NULL, "No existing thread-safe function"); + NODE_API_CALL(env, napi_unref_threadsafe_function(env, ts_fn)); return NULL; } static napi_value Release(napi_env env, napi_callback_info info) { - NAPI_ASSERT(env, ts_fn != NULL, "No existing thread-safe function"); - NAPI_CALL(env, napi_release_threadsafe_function(ts_fn, napi_tsfn_release)); + NODE_API_ASSERT(env, ts_fn != NULL, "No existing thread-safe function"); + NODE_API_CALL(env, napi_release_threadsafe_function(ts_fn, napi_tsfn_release)); return NULL; } @@ -298,16 +300,16 @@ static napi_value Init(napi_env env, napi_value exports) { napi_enumerable, NULL }, - DECLARE_NAPI_PROPERTY("StartThread", StartThread), - DECLARE_NAPI_PROPERTY("StartThreadNoNative", StartThreadNoNative), - DECLARE_NAPI_PROPERTY("StartThreadNonblocking", StartThreadNonblocking), - DECLARE_NAPI_PROPERTY("StartThreadNoJsFunc", StartThreadNoJsFunc), - DECLARE_NAPI_PROPERTY("StopThread", StopThread), - DECLARE_NAPI_PROPERTY("Unref", Unref), - DECLARE_NAPI_PROPERTY("Release", Release), + DECLARE_NODE_API_PROPERTY("StartThread", StartThread), + DECLARE_NODE_API_PROPERTY("StartThreadNoNative", StartThreadNoNative), + DECLARE_NODE_API_PROPERTY("StartThreadNonblocking", StartThreadNonblocking), + DECLARE_NODE_API_PROPERTY("StartThreadNoJsFunc", StartThreadNoJsFunc), + DECLARE_NODE_API_PROPERTY("StopThread", StopThread), + DECLARE_NODE_API_PROPERTY("Unref", Unref), + DECLARE_NODE_API_PROPERTY("Release", Release), }; - NAPI_CALL(env, napi_define_properties(env, exports, + NODE_API_CALL(env, napi_define_properties(env, exports, sizeof(properties)/sizeof(properties[0]), properties)); return exports; diff --git a/test/node-api/test_uv_loop/test_uv_loop.cc b/test/node-api/test_uv_loop/test_uv_loop.cc index 51b10f32bb7900..68c3b71f933592 100644 --- a/test/node-api/test_uv_loop/test_uv_loop.cc +++ b/test/node-api/test_uv_loop/test_uv_loop.cc @@ -13,7 +13,7 @@ void* SetImmediate(napi_env env, T&& cb) { uv_loop_t* loop = nullptr; uv_check_t* check = new uv_check_t; check->data = ptr; - NAPI_ASSERT(env, + NODE_API_ASSERT(env, napi_get_uv_event_loop(env, &loop) == napi_ok, "can get event loop"); uv_check_init(loop, check); @@ -45,30 +45,30 @@ napi_value SetImmediateBinding(napi_env env, napi_callback_info info) { napi_value argv[1]; napi_value _this; void* data; - NAPI_CALL(env, + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, &_this, &data)); - NAPI_ASSERT(env, argc >= 1, "Not enough arguments, expected 1."); + NODE_API_ASSERT(env, argc >= 1, "Not enough arguments, expected 1."); napi_valuetype t; - NAPI_CALL(env, napi_typeof(env, argv[0], &t)); - NAPI_ASSERT(env, t == napi_function, + NODE_API_CALL(env, napi_typeof(env, argv[0], &t)); + NODE_API_ASSERT(env, t == napi_function, "Wrong first argument, function expected."); napi_ref cbref; - NAPI_CALL(env, + NODE_API_CALL(env, napi_create_reference(env, argv[0], 1, &cbref)); SetImmediate(env, [=]() -> char* { napi_value undefined; napi_value callback; napi_handle_scope scope; - NAPI_CALL(env, napi_open_handle_scope(env, &scope)); - NAPI_CALL(env, napi_get_undefined(env, &undefined)); - NAPI_CALL(env, napi_get_reference_value(env, cbref, &callback)); - NAPI_CALL(env, napi_delete_reference(env, cbref)); - NAPI_CALL(env, + NODE_API_CALL(env, napi_open_handle_scope(env, &scope)); + NODE_API_CALL(env, napi_get_undefined(env, &undefined)); + NODE_API_CALL(env, napi_get_reference_value(env, cbref, &callback)); + NODE_API_CALL(env, napi_delete_reference(env, cbref)); + NODE_API_CALL(env, napi_call_function(env, undefined, callback, 0, nullptr, nullptr)); - NAPI_CALL(env, napi_close_handle_scope(env, scope)); + NODE_API_CALL(env, napi_close_handle_scope(env, scope)); return &dummy; }); @@ -77,10 +77,10 @@ napi_value SetImmediateBinding(napi_env env, napi_callback_info info) { napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { - DECLARE_NAPI_PROPERTY("SetImmediate", SetImmediateBinding) + DECLARE_NODE_API_PROPERTY("SetImmediate", SetImmediateBinding) }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(properties) / sizeof(*properties), properties)); return exports; diff --git a/test/node-api/test_worker_buffer_callback/test_worker_buffer_callback.c b/test/node-api/test_worker_buffer_callback/test_worker_buffer_callback.c index b4f2e288ece31b..bf4a101763d091 100644 --- a/test/node-api/test_worker_buffer_callback/test_worker_buffer_callback.c +++ b/test/node-api/test_worker_buffer_callback/test_worker_buffer_callback.c @@ -8,7 +8,7 @@ uint32_t free_call_count = 0; napi_value GetFreeCallCount(napi_env env, napi_callback_info info) { napi_value value; - NAPI_CALL(env, napi_create_uint32(env, free_call_count, &value)); + NODE_API_CALL(env, napi_create_uint32(env, free_call_count, &value)); return value; } @@ -19,10 +19,10 @@ static void finalize_cb(napi_env env, void* finalize_data, void* hint) { NAPI_MODULE_INIT() { napi_property_descriptor properties[] = { - DECLARE_NAPI_PROPERTY("getFreeCallCount", GetFreeCallCount) + DECLARE_NODE_API_PROPERTY("getFreeCallCount", GetFreeCallCount) }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(properties) / sizeof(*properties), properties)); // This is a slight variation on the non-N-API test: We create an ArrayBuffer @@ -32,7 +32,7 @@ NAPI_MODULE_INIT() { char* data = malloc(sizeof(char)); - NAPI_CALL(env, napi_create_external_arraybuffer( + NODE_API_CALL(env, napi_create_external_arraybuffer( env, data, sizeof(char), @@ -40,7 +40,7 @@ NAPI_MODULE_INIT() { NULL, &buffer)); - NAPI_CALL(env, napi_set_named_property(env, exports, "buffer", buffer)); + NODE_API_CALL(env, napi_set_named_property(env, exports, "buffer", buffer)); return exports; } diff --git a/test/node-api/test_worker_terminate/test_worker_terminate.c b/test/node-api/test_worker_terminate/test_worker_terminate.c index 517cae42037323..3c428195b9a571 100644 --- a/test/node-api/test_worker_terminate/test_worker_terminate.c +++ b/test/node-api/test_worker_terminate/test_worker_terminate.c @@ -9,12 +9,12 @@ napi_value Test(napi_env env, napi_callback_info info) { napi_value argv[1]; napi_status status; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &recv, NULL)); - NAPI_ASSERT(env, argc >= 1, "Not enough arguments, expected 1."); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, &recv, NULL)); + NODE_API_ASSERT(env, argc >= 1, "Not enough arguments, expected 1."); napi_valuetype t; - NAPI_CALL(env, napi_typeof(env, argv[0], &t)); - NAPI_ASSERT(env, t == napi_function, + NODE_API_CALL(env, napi_typeof(env, argv[0], &t)); + NODE_API_ASSERT(env, t == napi_function, "Wrong first argument, function expected."); status = napi_call_function(env, recv, argv[0], 0, NULL, NULL); @@ -27,10 +27,10 @@ napi_value Test(napi_env env, napi_callback_info info) { napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { - DECLARE_NAPI_PROPERTY("Test", Test) + DECLARE_NODE_API_PROPERTY("Test", Test) }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(properties) / sizeof(*properties), properties)); return exports; diff --git a/test/node-api/test_worker_terminate_finalization/test_worker_terminate_finalization.c b/test/node-api/test_worker_terminate_finalization/test_worker_terminate_finalization.c index bb23830ecd2731..5a26718d3fca31 100644 --- a/test/node-api/test_worker_terminate_finalization/test_worker_terminate_finalization.c +++ b/test/node-api/test_worker_terminate_finalization/test_worker_terminate_finalization.c @@ -10,8 +10,8 @@ int wrappedNativeData; napi_ref ref; void WrapFinalizer(napi_env env, void* data, void* hint) { uint32_t count; - NAPI_CALL_RETURN_VOID(env, napi_reference_unref(env, ref, &count)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, ref)); + NODE_API_CALL_RETURN_VOID(env, napi_reference_unref(env, ref, &count)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, ref)); } void BufferFinalizer(napi_env env, void* data, void* hint) { @@ -24,19 +24,23 @@ napi_value Test(napi_env env, napi_callback_info info) { napi_value result; void* bufferData = malloc(BUFFER_SIZE); - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); - NAPI_CALL(env, napi_create_external_buffer(env, BUFFER_SIZE, bufferData, BufferFinalizer, bufferData, &result)); - NAPI_CALL(env, napi_create_reference(env, result, 1, &ref)); - NAPI_CALL(env, napi_wrap(env, argv[0], (void*) &wrappedNativeData, WrapFinalizer, NULL, NULL)); + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + NODE_API_CALL(env, + napi_create_external_buffer( + env, BUFFER_SIZE, bufferData, BufferFinalizer, bufferData, &result)); + NODE_API_CALL(env, napi_create_reference(env, result, 1, &ref)); + NODE_API_CALL(env, + napi_wrap( + env, argv[0], (void*) &wrappedNativeData, WrapFinalizer, NULL, NULL)); return NULL; } napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { - DECLARE_NAPI_PROPERTY("Test", Test) + DECLARE_NODE_API_PROPERTY("Test", Test) }; - NAPI_CALL(env, napi_define_properties( + NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(properties) / sizeof(*properties), properties)); return exports; From c30245072a714839d9dd93636e0b1cc3a4f93752 Mon Sep 17 00:00:00 2001 From: Darshan Sen Date: Fri, 29 Jan 2021 19:31:52 +0530 Subject: [PATCH 035/108] fs: allow passing negative zero fd Fixes: https://github.com/nodejs/node/issues/37122 PR-URL: https://github.com/nodejs/node/pull/37123 Reviewed-By: Antoine du Hamel Reviewed-By: Zijian Liu Reviewed-By: Rich Trott --- lib/fs.js | 50 +++++++++++++++++------------------ lib/internal/fs/utils.js | 12 +++++++++ test/parallel/test-fs-stat.js | 2 ++ 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index d1280d20718569..2bb629d58af081 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -89,6 +89,7 @@ const { Dirent, getDirents, getOptions, + getValidatedFd, getValidatedPath, getValidMode, handleErrorFromBinding, @@ -128,7 +129,6 @@ const { validateCallback, validateFunction, validateInteger, - validateInt32, } = require('internal/validators'); // 2 ** 32 - 1 const kMaxUserId = 4294967295; @@ -443,7 +443,7 @@ function defaultCloseCallback(err) { } function close(fd, callback = defaultCloseCallback) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); if (callback !== defaultCloseCallback) callback = makeCallback(callback); @@ -453,7 +453,7 @@ function close(fd, callback = defaultCloseCallback) { } function closeSync(fd) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); const ctx = {}; binding.close(fd, undefined, ctx); @@ -503,7 +503,7 @@ function openSync(path, flags, mode) { // OR // fs.read(fd, {}, callback) function read(fd, buffer, offset, length, position, callback) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); if (arguments.length <= 3) { // Assume fs.read(fd, options, callback) @@ -576,7 +576,7 @@ ObjectDefineProperty(read, internalUtil.customPromisifyArgs, // OR // fs.readSync(fd, buffer, {}) or fs.readSync(fd, buffer) function readSync(fd, buffer, offset, length, position) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); if (arguments.length <= 3) { // Assume fs.read(fd, buffer, options) @@ -623,7 +623,7 @@ function readv(fd, buffers, position, callback) { callback(err, read || 0, buffers); } - validateInt32(fd, 'fd', /* min */ 0); + fd = getValidatedFd(fd); validateBufferArray(buffers); callback = maybeCallback(callback || position); @@ -640,7 +640,7 @@ ObjectDefineProperty(readv, internalUtil.customPromisifyArgs, { value: ['bytesRead', 'buffers'], enumerable: false }); function readvSync(fd, buffers, position) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); validateBufferArray(buffers); const ctx = {}; @@ -663,7 +663,7 @@ function write(fd, buffer, offset, length, position, callback) { callback(err, written || 0, buffer); } - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); if (isArrayBufferView(buffer)) { callback = maybeCallback(callback || position || length || offset); @@ -709,7 +709,7 @@ ObjectDefineProperty(write, internalUtil.customPromisifyArgs, // OR // fs.writeSync(fd, string[, position[, encoding]]); function writeSync(fd, buffer, offset, length, position) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); const ctx = {}; let result; if (isArrayBufferView(buffer)) { @@ -744,7 +744,7 @@ function writev(fd, buffers, position, callback) { callback(err, written || 0, buffers); } - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); validateBufferArray(buffers); callback = maybeCallback(callback || position); @@ -763,7 +763,7 @@ ObjectDefineProperty(writev, internalUtil.customPromisifyArgs, { }); function writevSync(fd, buffers, position) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); validateBufferArray(buffers); const ctx = {}; @@ -849,7 +849,7 @@ function ftruncate(fd, len = 0, callback) { callback = len; len = 0; } - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); validateInteger(len, 'len'); len = MathMax(0, len); callback = makeCallback(callback); @@ -860,7 +860,7 @@ function ftruncate(fd, len = 0, callback) { } function ftruncateSync(fd, len = 0) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); validateInteger(len, 'len'); len = MathMax(0, len); const ctx = {}; @@ -942,28 +942,28 @@ function rmSync(path, options) { } function fdatasync(fd, callback) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); const req = new FSReqCallback(); req.oncomplete = makeCallback(callback); binding.fdatasync(fd, req); } function fdatasyncSync(fd) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); const ctx = {}; binding.fdatasync(fd, undefined, ctx); handleErrorFromBinding(ctx); } function fsync(fd, callback) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); const req = new FSReqCallback(); req.oncomplete = makeCallback(callback); binding.fsync(fd, req); } function fsyncSync(fd) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); const ctx = {}; binding.fsync(fd, undefined, ctx); handleErrorFromBinding(ctx); @@ -1054,7 +1054,7 @@ function fstat(fd, options = { bigint: false }, callback) { callback = options; options = {}; } - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); callback = makeStatsCallback(callback); const req = new FSReqCallback(options.bigint); @@ -1102,7 +1102,7 @@ function hasNoEntryError(ctx) { } function fstatSync(fd, options = { bigint: false, throwIfNoEntry: true }) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); const ctx = { fd }; const stats = binding.fstat(fd, options.bigint, undefined, ctx); handleErrorFromBinding(ctx); @@ -1255,7 +1255,7 @@ function unlinkSync(path) { } function fchmod(fd, mode, callback) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); mode = parseFileMode(mode, 'mode'); callback = makeCallback(callback); @@ -1265,7 +1265,7 @@ function fchmod(fd, mode, callback) { } function fchmodSync(fd, mode) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); mode = parseFileMode(mode, 'mode'); const ctx = {}; binding.fchmod(fd, mode, undefined, ctx); @@ -1343,7 +1343,7 @@ function lchownSync(path, uid, gid) { } function fchown(fd, uid, gid, callback) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); validateInteger(uid, 'uid', -1, kMaxUserId); validateInteger(gid, 'gid', -1, kMaxUserId); callback = makeCallback(callback); @@ -1354,7 +1354,7 @@ function fchown(fd, uid, gid, callback) { } function fchownSync(fd, uid, gid) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); validateInteger(uid, 'uid', -1, kMaxUserId); validateInteger(gid, 'gid', -1, kMaxUserId); @@ -1405,7 +1405,7 @@ function utimesSync(path, atime, mtime) { } function futimes(fd, atime, mtime, callback) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); atime = toUnixTimestamp(atime, 'atime'); mtime = toUnixTimestamp(mtime, 'mtime'); callback = makeCallback(callback); @@ -1416,7 +1416,7 @@ function futimes(fd, atime, mtime, callback) { } function futimesSync(fd, atime, mtime) { - validateInt32(fd, 'fd', 0); + fd = getValidatedFd(fd); atime = toUnixTimestamp(atime, 'atime'); mtime = toUnixTimestamp(mtime, 'mtime'); const ctx = {}; diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index 41b74ce652137a..842c5266c6f677 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -12,6 +12,7 @@ const { NumberIsFinite, NumberIsInteger, MathMin, + ObjectIs, ObjectPrototypeHasOwnProperty, ObjectSetPrototypeOf, ReflectApply, @@ -649,6 +650,16 @@ const getValidatedPath = hideStackFrames((fileURLOrPath, propName = 'path') => { return path; }); +const getValidatedFd = hideStackFrames((fd, propName = 'fd') => { + if (ObjectIs(fd, -0)) { + return 0; + } + + validateInt32(fd, propName, 0); + + return fd; +}); + const validateBufferArray = hideStackFrames((buffers, propName = 'buffers') => { if (!ArrayIsArray(buffers)) throw new ERR_INVALID_ARG_TYPE(propName, 'ArrayBufferView[]', buffers); @@ -843,6 +854,7 @@ module.exports = { getDirent, getDirents, getOptions, + getValidatedFd, getValidatedPath, getValidMode, handleErrorFromBinding, diff --git a/test/parallel/test-fs-stat.js b/test/parallel/test-fs-stat.js index 31aec8fab00450..92a6ec8fa3280c 100644 --- a/test/parallel/test-fs-stat.js +++ b/test/parallel/test-fs-stat.js @@ -47,6 +47,8 @@ fs.lstat('.', common.mustSucceed(function(stats) { fs.open('.', 'r', undefined, common.mustSucceed(function(fd) { assert.ok(fd); + fs.fstat(-0, common.mustSucceed()); + fs.fstat(fd, common.mustSucceed(function(stats) { assert.ok(stats.mtime instanceof Date); fs.close(fd, assert.ifError); From 3fee5b22195779161dad942da9441777dc2f8817 Mon Sep 17 00:00:00 2001 From: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> Date: Tue, 2 Feb 2021 02:10:00 +0100 Subject: [PATCH 036/108] =?UTF-8?q?repl:=20add=C2=A0auto=E2=80=91completio?= =?UTF-8?q?n=20for=C2=A0dynamic=C2=A0import=C2=A0calls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs: https://github.com/nodejs/node/issues/33238 Refs: https://github.com/nodejs/node/pull/33282 Co-authored-by: Antoine du Hamel PR-URL: https://github.com/nodejs/node/pull/37178 Reviewed-By: Antoine du Hamel Reviewed-By: Juan José Arboleda Reviewed-By: Rich Trott --- lib/internal/modules/esm/get_format.js | 11 +- lib/repl.js | 79 ++++++++- test/parallel/test-repl-autocomplete.js | 3 + .../parallel/test-repl-tab-complete-import.js | 158 ++++++++++++++++++ 4 files changed, 247 insertions(+), 4 deletions(-) create mode 100644 test/parallel/test-repl-tab-complete-import.js diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index b48741c422c47f..f02bb5cde70772 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -7,7 +7,7 @@ const { extname } = require('path'); const { getOptionValue } = require('internal/options'); const experimentalJsonModules = getOptionValue('--experimental-json-modules'); -const experimentalSpeciferResolution = +const experimentalSpecifierResolution = getOptionValue('--experimental-specifier-resolution'); const experimentalWasmModules = getOptionValue('--experimental-wasm-modules'); const { getPackageType } = require('internal/modules/esm/resolve'); @@ -62,7 +62,7 @@ function defaultGetFormat(url, context, defaultGetFormatUnused) { format = extensionFormatMap[ext]; } if (!format) { - if (experimentalSpeciferResolution === 'node') { + if (experimentalSpecifierResolution === 'node') { process.emitWarning( 'The Node.js specifier resolution in ESM is experimental.', 'ExperimentalWarning'); @@ -75,4 +75,9 @@ function defaultGetFormat(url, context, defaultGetFormatUnused) { } return { format: null }; } -exports.defaultGetFormat = defaultGetFormat; + +module.exports = { + defaultGetFormat, + extensionFormatMap, + legacyExtensionFormatMap, +}; diff --git a/lib/repl.js b/lib/repl.js index d5d9371de34428..acbfe8a9b709ae 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -54,6 +54,7 @@ const { ArrayPrototypePush, ArrayPrototypeReverse, ArrayPrototypeShift, + ArrayPrototypeSlice, ArrayPrototypeSome, ArrayPrototypeSort, ArrayPrototypeSplice, @@ -126,6 +127,8 @@ let _builtinLibs = ArrayPrototypeFilter( CJSModule.builtinModules, (e) => !StringPrototypeStartsWith(e, '_') && !StringPrototypeIncludes(e, '/') ); +const nodeSchemeBuiltinLibs = ArrayPrototypeMap( + _builtinLibs, (lib) => `node:${lib}`); const domain = require('domain'); let debug = require('internal/util/debuglog').debuglog('repl', (fn) => { debug = fn; @@ -171,6 +174,10 @@ const { } = internalBinding('contextify'); const history = require('internal/repl/history'); +const { + extensionFormatMap, + legacyExtensionFormatMap, +} = require('internal/modules/esm/get_format'); let nextREPLResourceNumber = 1; // This prevents v8 code cache from getting confused and using a different @@ -1105,10 +1112,12 @@ REPLServer.prototype.setPrompt = function setPrompt(prompt) { ReflectApply(Interface.prototype.setPrompt, this, [prompt]); }; +const importRE = /\bimport\s*\(\s*['"`](([\w@./:-]+\/)?(?:[\w@./:-]*))(?![^'"`])$/; const requireRE = /\brequire\s*\(\s*['"`](([\w@./-]+\/)?(?:[\w@./-]*))(?![^'"`])$/; const fsAutoCompleteRE = /fs(?:\.promises)?\.\s*[a-z][a-zA-Z]+\(\s*["'](.*)/; const simpleExpressionRE = /(?:[a-zA-Z_$](?:\w|\$)*\??\.)*[a-zA-Z_$](?:\w|\$)*\??\.?$/; +const versionedFileNamesRe = /-\d+\.\d+/; function isIdentifier(str) { if (str === '') { @@ -1215,7 +1224,6 @@ function complete(line, callback) { const indexes = ArrayPrototypeMap(extensions, (extension) => `index${extension}`); ArrayPrototypePush(indexes, 'package.json', 'index'); - const versionedFileNamesRe = /-\d+\.\d+/; const match = StringPrototypeMatch(line, requireRE); completeOn = match[1]; @@ -1269,6 +1277,75 @@ function complete(line, callback) { if (!subdir) { ArrayPrototypePush(completionGroups, _builtinLibs); } + } else if (RegExpPrototypeTest(importRE, line) && + this.allowBlockingCompletions) { + // import('...') + // File extensions that can be imported: + const extensions = ObjectKeys( + getOptionValue('--experimental-specifier-resolution') === 'node' ? + legacyExtensionFormatMap : + extensionFormatMap); + + // Only used when loading bare module specifiers from `node_modules`: + const indexes = ArrayPrototypeMap(extensions, (ext) => `index${ext}`); + ArrayPrototypePush(indexes, 'package.json'); + + const match = StringPrototypeMatch(line, importRE); + completeOn = match[1]; + const subdir = match[2] || ''; + filter = completeOn; + group = []; + let paths = []; + if (completeOn === '.') { + group = ['./', '../']; + } else if (completeOn === '..') { + group = ['../']; + } else if (RegExpPrototypeTest(/^\.\.?\//, completeOn)) { + paths = [process.cwd()]; + } else { + paths = ArrayPrototypeSlice(module.paths); + } + + ArrayPrototypeForEach(paths, (dir) => { + dir = path.resolve(dir, subdir); + const isInNodeModules = path.basename(dir) === 'node_modules'; + const dirents = gracefulReaddir(dir, { withFileTypes: true }) || []; + ArrayPrototypeForEach(dirents, (dirent) => { + const { name } = dirent; + if (RegExpPrototypeTest(versionedFileNamesRe, name) || + name === '.npm') { + // Exclude versioned names that 'npm' installs. + return; + } + + if (!dirent.isDirectory()) { + const extension = path.extname(name); + if (StringPrototypeIncludes(extensions, extension)) { + ArrayPrototypePush(group, `${subdir}${name}`); + } + return; + } + + ArrayPrototypePush(group, `${subdir}${name}/`); + if (!subdir && isInNodeModules) { + const absolute = path.resolve(dir, name); + const subfiles = gracefulReaddir(absolute) || []; + if (ArrayPrototypeSome(subfiles, (subfile) => { + return ArrayPrototypeIncludes(indexes, subfile); + })) { + ArrayPrototypePush(group, `${subdir}${name}`); + } + } + }); + }); + + if (group.length) { + ArrayPrototypePush(completionGroups, group); + } + + if (!subdir) { + ArrayPrototypePush(completionGroups, _builtinLibs, nodeSchemeBuiltinLibs); + } } else if (RegExpPrototypeTest(fsAutoCompleteRE, line) && this.allowBlockingCompletions) { ({ 0: completionGroups, 1: completeOn } = completeFSFunctions(line)); diff --git a/test/parallel/test-repl-autocomplete.js b/test/parallel/test-repl-autocomplete.js index e1d2189fdb17cb..b107053183080a 100644 --- a/test/parallel/test-repl-autocomplete.js +++ b/test/parallel/test-repl-autocomplete.js @@ -103,6 +103,9 @@ const tests = [ yield 'require("./'; yield TABULATION; yield SIGINT; + yield 'import("./'; + yield TABULATION; + yield SIGINT; yield 'Array.proto'; yield RIGHT; yield '.pu'; diff --git a/test/parallel/test-repl-tab-complete-import.js b/test/parallel/test-repl-tab-complete-import.js new file mode 100644 index 00000000000000..414b5cc4eac103 --- /dev/null +++ b/test/parallel/test-repl-tab-complete-import.js @@ -0,0 +1,158 @@ +'use strict'; + +const common = require('../common'); +const ArrayStream = require('../common/arraystream'); +const fixtures = require('../common/fixtures'); +const assert = require('assert'); +const { builtinModules } = require('module'); +const publicModules = builtinModules.filter( + (lib) => !lib.startsWith('_') && !lib.includes('/'), +); + +if (!common.isMainThread) + common.skip('process.chdir is not available in Workers'); + +// We have to change the directory to ../fixtures before requiring repl +// in order to make the tests for completion of node_modules work properly +// since repl modifies module.paths. +process.chdir(fixtures.fixturesDir); + +const repl = require('repl'); + +const putIn = new ArrayStream(); +const testMe = repl.start({ + prompt: '', + input: putIn, + output: process.stdout, + allowBlockingCompletions: true +}); + +// Some errors are passed to the domain, but do not callback +testMe._domain.on('error', assert.ifError); + +// Tab complete provides built in libs for import() +testMe.complete('import(\'', common.mustCall((error, data) => { + assert.strictEqual(error, null); + publicModules.forEach((lib) => { + assert( + data[0].includes(lib) && data[0].includes(`node:${lib}`), + `${lib} not found`, + ); + }); + const newModule = 'foobar'; + assert(!builtinModules.includes(newModule)); + repl.builtinModules.push(newModule); + testMe.complete('import(\'', common.mustCall((_, [modules]) => { + assert.strictEqual(data[0].length + 1, modules.length); + assert(modules.includes(newModule) && + !modules.includes(`node:${newModule}`)); + })); +})); + +testMe.complete("import\t( 'n", common.mustCall((error, data) => { + assert.strictEqual(error, null); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[1], 'n'); + const completions = data[0]; + // import(...) completions include `node:` URL modules: + publicModules.forEach((lib, index) => + assert.strictEqual(completions[index], `node:${lib}`)); + assert.strictEqual(completions[publicModules.length], ''); + // There is only one Node.js module that starts with n: + assert.strictEqual(completions[publicModules.length + 1], 'net'); + assert.strictEqual(completions[publicModules.length + 2], ''); + // It's possible to pick up non-core modules too + completions.slice(publicModules.length + 3).forEach((completion) => { + assert.match(completion, /^n/); + }); +})); + +{ + const expected = ['@nodejsscope', '@nodejsscope/']; + // Import calls should handle all types of quotation marks. + for (const quotationMark of ["'", '"', '`']) { + putIn.run(['.clear']); + testMe.complete('import(`@nodejs', common.mustCall((err, data) => { + assert.strictEqual(err, null); + assert.deepStrictEqual(data, [expected, '@nodejs']); + })); + + putIn.run(['.clear']); + // Completions should not be greedy in case the quotation ends. + const input = `import(${quotationMark}@nodejsscope${quotationMark}`; + testMe.complete(input, common.mustCall((err, data) => { + assert.strictEqual(err, null); + assert.deepStrictEqual(data, [[], undefined]); + })); + } +} + +{ + putIn.run(['.clear']); + // Completions should find modules and handle whitespace after the opening + // bracket. + testMe.complete('import \t("no_ind', common.mustCall((err, data) => { + assert.strictEqual(err, null); + assert.deepStrictEqual(data, [['no_index', 'no_index/'], 'no_ind']); + })); +} + +// Test tab completion for import() relative to the current directory +{ + putIn.run(['.clear']); + + const cwd = process.cwd(); + process.chdir(__dirname); + + ['import(\'.', 'import(".'].forEach((input) => { + testMe.complete(input, common.mustCall((err, data) => { + assert.strictEqual(err, null); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[1], '.'); + assert.strictEqual(data[0].length, 2); + assert.ok(data[0].includes('./')); + assert.ok(data[0].includes('../')); + })); + }); + + ['import(\'..', 'import("..'].forEach((input) => { + testMe.complete(input, common.mustCall((err, data) => { + assert.strictEqual(err, null); + assert.deepStrictEqual(data, [['../'], '..']); + })); + }); + + ['./', './test-'].forEach((path) => { + [`import('${path}`, `import("${path}`].forEach((input) => { + testMe.complete(input, common.mustCall((err, data) => { + assert.strictEqual(err, null); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[1], path); + assert.ok(data[0].includes('./test-repl-tab-complete.js')); + })); + }); + }); + + ['../parallel/', '../parallel/test-'].forEach((path) => { + [`import('${path}`, `import("${path}`].forEach((input) => { + testMe.complete(input, common.mustCall((err, data) => { + assert.strictEqual(err, null); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[1], path); + assert.ok(data[0].includes('../parallel/test-repl-tab-complete.js')); + })); + }); + }); + + { + const path = '../fixtures/repl-folder-extensions/f'; + testMe.complete(`import('${path}`, common.mustSucceed((data) => { + assert.strictEqual(data.length, 2); + assert.strictEqual(data[1], path); + assert.ok(data[0].includes( + '../fixtures/repl-folder-extensions/foo.js/')); + })); + } + + process.chdir(cwd); +} From dc38dd2c6fa2af3fd423d88092c7f31b00a28e6b Mon Sep 17 00:00:00 2001 From: Darshan Sen Date: Thu, 4 Feb 2021 18:19:37 +0530 Subject: [PATCH 037/108] timers: fix unsafe array iteration Fixes: https://github.com/nodejs/node/issues/37222 PR-URL: https://github.com/nodejs/node/pull/37223 Reviewed-By: Antoine du Hamel Reviewed-By: Rich Trott --- lib/internal/timers.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/internal/timers.js b/lib/internal/timers.js index a5b5c10010e95b..050d356b202d70 100644 --- a/lib/internal/timers.js +++ b/lib/internal/timers.js @@ -79,6 +79,7 @@ const { NumberMIN_SAFE_INTEGER, ObjectCreate, Symbol, + ReflectApply, } = primordials; const { @@ -555,7 +556,7 @@ function getTimerCallbacks(runNextTicks) { if (args === undefined) timer._onTimeout(); else - timer._onTimeout(...args); + ReflectApply(timer._onTimeout, timer, args); } finally { if (timer._repeat && timer._idleTimeout !== -1) { timer._idleTimeout = timer._repeat; From 9dac99a11a388dd166380b23cf92bcf48b71b28d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Mon, 1 Feb 2021 02:06:25 +0100 Subject: [PATCH 038/108] crypto: fix and simplify prime option validation PR-URL: https://github.com/nodejs/node/pull/37164 Reviewed-By: James M Snell Reviewed-By: Rich Trott --- lib/internal/crypto/random.js | 99 ++++++++++-------------------- test/parallel/test-crypto-prime.js | 22 +++++++ 2 files changed, 55 insertions(+), 66 deletions(-) diff --git a/lib/internal/crypto/random.js b/lib/internal/crypto/random.js index 3073a42615ffd6..45be27edfe56c0 100644 --- a/lib/internal/crypto/random.js +++ b/lib/internal/crypto/random.js @@ -391,14 +391,9 @@ function randomUUID(options) { return uuid.latin1Slice(0, 36); } -function generatePrime(size, options, callback) { - validateUint32(size, 'size', true); - if (typeof options === 'function') { - callback = options; - options = {}; - } - validateCallback(callback); +function createRandomPrimeJob(type, size, options) { validateObject(options, 'options'); + const { safe = false, bigint = false, @@ -413,7 +408,7 @@ function generatePrime(size, options, callback) { if (add !== undefined) { if (typeof add === 'bigint') { - add = Buffer.from(toHexPadded(add), 'hex'); + add = unsignedBigIntToBuffer(add, 'options.add'); } else if (!isAnyArrayBuffer(add) && !isArrayBufferView(add)) { throw new ERR_INVALID_ARG_TYPE( 'options.add', @@ -430,7 +425,7 @@ function generatePrime(size, options, callback) { if (rem !== undefined) { if (typeof rem === 'bigint') { - rem = Buffer.from(toHexPadded(rem), 'hex'); + rem = unsignedBigIntToBuffer(rem, 'options.rem'); } else if (!isAnyArrayBuffer(rem) && !isArrayBufferView(rem)) { throw new ERR_INVALID_ARG_TYPE( 'options.rem', @@ -445,7 +440,20 @@ function generatePrime(size, options, callback) { } } - const job = new RandomPrimeJob(kCryptoJobAsync, size, safe, add, rem); + const job = new RandomPrimeJob(type, size, safe, add, rem); + job.result = bigint ? arrayBufferToUnsignedBigInt : (p) => p; + return job; +} + +function generatePrime(size, options, callback) { + validateUint32(size, 'size', true); + if (typeof options === 'function') { + callback = options; + options = {}; + } + validateCallback(callback); + + const job = createRandomPrimeJob(kCryptoJobAsync, size, options); job.ondone = (err, prime) => { if (err) { callback(err); @@ -454,79 +462,38 @@ function generatePrime(size, options, callback) { callback( undefined, - bigint ? - BigInt(`0x${Buffer.from(prime).toString('hex')}`) : - prime); + job.result(prime)); }; job.run(); } function generatePrimeSync(size, options = {}) { validateUint32(size, 'size', true); - validateObject(options, 'options'); - const { - safe = false, - bigint = false, - } = options; - let { - add, - rem, - } = options; - validateBoolean(safe, 'options.safe'); - validateBoolean(bigint, 'options.bigint'); - - if (add !== undefined) { - if (typeof add === 'bigint') { - add = Buffer.from(toHexPadded(add), 'hex'); - } else if (!isAnyArrayBuffer(add) && !isArrayBufferView(add)) { - throw new ERR_INVALID_ARG_TYPE( - 'options.add', - [ - 'ArrayBuffer', - 'TypedArray', - 'Buffer', - 'DataView', - 'bigint', - ], - add); - } - } - - if (rem !== undefined) { - if (typeof rem === 'bigint') { - rem = Buffer.from(toHexPadded(rem), 'hex'); - } else if (!isAnyArrayBuffer(rem) && !isArrayBufferView(rem)) { - throw new ERR_INVALID_ARG_TYPE( - 'options.rem', - [ - 'ArrayBuffer', - 'TypedArray', - 'Buffer', - 'DataView', - 'bigint', - ], - rem); - } - } - const job = new RandomPrimeJob(kCryptoJobSync, size, safe, add, rem); + const job = createRandomPrimeJob(kCryptoJobSync, size, options); const [err, prime] = job.run(); if (err) throw err; + return job.result(prime); +} - return bigint ? - BigInt(`0x${Buffer.from(prime).toString('hex')}`) : - prime; +function arrayBufferToUnsignedBigInt(arrayBuffer) { + return BigInt(`0x${Buffer.from(arrayBuffer).toString('hex')}`); } -function toHexPadded(bigint) { +function unsignedBigIntToBuffer(bigint, name) { + if (bigint < 0) { + throw new ERR_OUT_OF_RANGE(name, '>= 0', bigint); + } + const hex = bigint.toString(16); - return hex.padStart(hex.length + (hex.length % 2), 0); + const padded = hex.padStart(hex.length + (hex.length % 2), 0); + return Buffer.from(padded, 'hex'); } function checkPrime(candidate, options = {}, callback) { if (typeof candidate === 'bigint') - candidate = Buffer.from(toHexPadded(candidate), 'hex'); + candidate = unsignedBigIntToBuffer(candidate, 'candidate'); if (!isAnyArrayBuffer(candidate) && !isArrayBufferView(candidate)) { throw new ERR_INVALID_ARG_TYPE( 'candidate', @@ -559,7 +526,7 @@ function checkPrime(candidate, options = {}, callback) { function checkPrimeSync(candidate, options = {}) { if (typeof candidate === 'bigint') - candidate = Buffer.from(toHexPadded(candidate), 'hex'); + candidate = unsignedBigIntToBuffer(candidate, 'candidate'); if (!isAnyArrayBuffer(candidate) && !isArrayBufferView(candidate)) { throw new ERR_INVALID_ARG_TYPE( 'candidate', diff --git a/test/parallel/test-crypto-prime.js b/test/parallel/test-crypto-prime.js index 27f34adea36d9e..f51b091f536b45 100644 --- a/test/parallel/test-crypto-prime.js +++ b/test/parallel/test-crypto-prime.js @@ -71,6 +71,28 @@ const pCheckPrime = promisify(checkPrime); }); }); +{ + // Negative BigInts should not be converted to 0 silently. + + assert.throws(() => generatePrime(20, { add: -1n }, common.mustNotCall()), { + code: 'ERR_OUT_OF_RANGE', + message: 'The value of "options.add" is out of range. It must be >= 0. ' + + 'Received -1n' + }); + + assert.throws(() => generatePrime(20, { rem: -1n }, common.mustNotCall()), { + code: 'ERR_OUT_OF_RANGE', + message: 'The value of "options.rem" is out of range. It must be >= 0. ' + + 'Received -1n' + }); + + assert.throws(() => checkPrime(-1n, common.mustNotCall()), { + code: 'ERR_OUT_OF_RANGE', + message: 'The value of "candidate" is out of range. It must be >= 0. ' + + 'Received -1n' + }); +} + generatePrime(80, common.mustSucceed((prime) => { assert(checkPrimeSync(prime)); checkPrime(prime, common.mustSucceed((result) => { From acabe08b10efeee68900e9356a3d4bcced103bb1 Mon Sep 17 00:00:00 2001 From: Benjamin Gruenbaum Date: Thu, 4 Feb 2021 12:17:44 +0200 Subject: [PATCH 039/108] lib: add weak event handlers PR-URL: https://github.com/nodejs/node/pull/36607 Reviewed-By: James M Snell Reviewed-By: Gus Caplan --- lib/events.js | 4 +- lib/internal/event_target.js | 66 +++++++++++++++---- .../test-events-static-geteventlisteners.js | 11 +++- test/parallel/test-eventtarget.js | 31 ++++++++- 4 files changed, 95 insertions(+), 17 deletions(-) diff --git a/lib/events.js b/lib/events.js index 7a7abc5c4b3339..797b5bc90c6bb8 100644 --- a/lib/events.js +++ b/lib/events.js @@ -697,7 +697,9 @@ function getEventListeners(emitterOrTarget, type) { const listeners = []; let handler = root?.next; while (handler?.listener !== undefined) { - ArrayPrototypePush(listeners, handler.listener); + const listener = handler.listener?.deref ? + handler.listener.deref() : handler.listener; + ArrayPrototypePush(listeners, listener); handler = handler.next; } return listeners; diff --git a/lib/internal/event_target.js b/lib/internal/event_target.js index fe588088cc81f1..f79d1eb23faf70 100644 --- a/lib/internal/event_target.js +++ b/lib/internal/event_target.js @@ -15,11 +15,12 @@ const { ReflectApply, SafeArrayIterator, SafeMap, + SafeWeakMap, + SafeWeakSet, String, Symbol, SymbolFor, SymbolToStringTag, - SafeWeakSet, } = primordials; const { @@ -47,6 +48,7 @@ const kEvents = Symbol('kEvents'); const kStop = Symbol('kStop'); const kTarget = Symbol('kTarget'); const kHandlers = Symbol('khandlers'); +const kWeakHandler = Symbol('kWeak'); const kHybridDispatch = SymbolFor('nodejs.internal.kHybridDispatch'); const kCreateEvent = Symbol('kCreateEvent'); @@ -190,6 +192,21 @@ class NodeCustomEvent extends Event { } } } + +// Weak listener cleanup +// This has to be lazy for snapshots to work +let weakListenersState = null; +// The resource needs to retain the callback so that it doesn't +// get garbage collected now that it's weak. +let objectToWeakListenerMap = null; +function weakListeners() { + weakListenersState ??= new globalThis.FinalizationRegistry( + (listener) => listener.remove() + ); + objectToWeakListenerMap ??= new SafeWeakMap(); + return { registry: weakListenersState, map: objectToWeakListenerMap }; +} + // The listeners for an EventTarget are maintained as a linked list. // Unfortunately, the way EventTarget is defined, listeners are accounted // using the tuple [handler,capture], and even if we don't actually make @@ -198,7 +215,8 @@ class NodeCustomEvent extends Event { // the linked list makes dispatching faster, even if adding/removing is // slower. class Listener { - constructor(previous, listener, once, capture, passive, isNodeStyleListener) { + constructor(previous, listener, once, capture, passive, + isNodeStyleListener, weak) { this.next = undefined; if (previous !== undefined) previous.next = this; @@ -210,15 +228,26 @@ class Listener { this.passive = passive; this.isNodeStyleListener = isNodeStyleListener; this.removed = false; - - this.callback = - typeof listener === 'function' ? - listener : - FunctionPrototypeBind(listener.handleEvent, listener); + this.weak = Boolean(weak); // Don't retain the object + + if (this.weak) { + this.callback = new globalThis.WeakRef(listener); + weakListeners().registry.register(listener, this, this); + // Make the retainer retain the listener in a WeakMap + weakListeners().map.set(weak, listener); + this.listener = this.callback; + } else if (typeof listener === 'function') { + this.callback = listener; + this.listener = listener; + } else { + this.callback = FunctionPrototypeBind(listener.handleEvent, listener); + this.listener = listener; + } } same(listener, capture) { - return this.listener === listener && this.capture === capture; + const myListener = this.weak ? this.listener.deref() : this.listener; + return myListener === listener && this.capture === capture; } remove() { @@ -227,6 +256,8 @@ class Listener { if (this.next !== undefined) this.next.previous = this.previous; this.removed = true; + if (this.weak) + weakListeners().registry.unregister(this); } } @@ -277,7 +308,8 @@ class EventTarget { capture, passive, signal, - isNodeStyleListener + isNodeStyleListener, + weak, } = validateEventListenerOptions(options); if (!shouldAddListener(listener)) { @@ -302,7 +334,7 @@ class EventTarget { // not prevent the event target from GC. signal.addEventListener('abort', () => { this.removeEventListener(type, listener, options); - }, { once: true }); + }, { once: true, [kWeakHandler]: this }); } let root = this[kEvents].get(type); @@ -310,7 +342,8 @@ class EventTarget { if (root === undefined) { root = { size: 1, next: undefined }; // This is the first handler in our linked list. - new Listener(root, listener, once, capture, passive, isNodeStyleListener); + new Listener(root, listener, once, capture, passive, + isNodeStyleListener, weak); this[kNewListener](root.size, type, listener, once, capture, passive); this[kEvents].set(type, root); return; @@ -330,7 +363,7 @@ class EventTarget { } new Listener(previous, listener, once, capture, passive, - isNodeStyleListener); + isNodeStyleListener, weak); root.size++; this[kNewListener](root.size, type, listener, once, capture, passive); } @@ -418,7 +451,12 @@ class EventTarget { } else { arg = createEvent(); } - const result = FunctionPrototypeCall(handler.callback, this, arg); + const callback = handler.weak ? + handler.callback.deref() : handler.callback; + let result; + if (callback) { + result = FunctionPrototypeCall(callback, this, arg); + } if (result !== undefined && result !== null) addCatch(this, result, createEvent()); } catch (err) { @@ -569,6 +607,7 @@ function validateEventListenerOptions(options) { capture: Boolean(options.capture), passive: Boolean(options.passive), signal: options.signal, + weak: options[kWeakHandler], isNodeStyleListener: Boolean(options[kIsNodeStyleListener]) }; } @@ -671,5 +710,6 @@ module.exports = { kTrustEvent, kRemoveListener, kEvents, + kWeakHandler, isEventTarget, }; diff --git a/test/parallel/test-events-static-geteventlisteners.js b/test/parallel/test-events-static-geteventlisteners.js index 71d9b0a28ddc75..eba92de4a00c90 100644 --- a/test/parallel/test-events-static-geteventlisteners.js +++ b/test/parallel/test-events-static-geteventlisteners.js @@ -1,6 +1,7 @@ 'use strict'; - +// Flags: --expose-internals --no-warnings const common = require('../common'); +const { kWeakHandler } = require('internal/event_target'); const { deepStrictEqual, @@ -41,3 +42,11 @@ const { getEventListeners, EventEmitter } = require('events'); getEventListeners('INVALID_EMITTER'); }, /ERR_INVALID_ARG_TYPE/); } +{ + // Test weak listeners + const target = new EventTarget(); + const fn = common.mustNotCall(); + target.addEventListener('foo', fn, { [kWeakHandler]: {} }); + const listeners = getEventListeners(target, 'foo'); + deepStrictEqual(listeners, [fn]); +} diff --git a/test/parallel/test-eventtarget.js b/test/parallel/test-eventtarget.js index dd3a5a106b5a01..1789d794f41ea3 100644 --- a/test/parallel/test-eventtarget.js +++ b/test/parallel/test-eventtarget.js @@ -1,8 +1,11 @@ -// Flags: --expose-internals --no-warnings +// Flags: --expose-internals --no-warnings --expose-gc 'use strict'; const common = require('../common'); -const { defineEventHandler } = require('internal/event_target'); +const { + defineEventHandler, + kWeakHandler, +} = require('internal/event_target'); const { ok, @@ -570,3 +573,27 @@ let asyncTest = Promise.resolve(); const et = new EventTarget(); strictEqual(et.constructor.name, 'EventTarget'); } +{ + // Weak event handlers work + const et = new EventTarget(); + const listener = common.mustCall(); + et.addEventListener('foo', listener, { [kWeakHandler]: et }); + et.dispatchEvent(new Event('foo')); +} +{ + // Weak event handlers can be removed and weakness is not part of the key + const et = new EventTarget(); + const listener = common.mustNotCall(); + et.addEventListener('foo', listener, { [kWeakHandler]: et }); + et.removeEventListener('foo', listener); + et.dispatchEvent(new Event('foo')); +} +{ + // Test listeners are held weakly + const et = new EventTarget(); + et.addEventListener('foo', common.mustNotCall(), { [kWeakHandler]: {} }); + setImmediate(() => { + global.gc(); + et.dispatchEvent(new Event('foo')); + }); +} From 354df9e8a179778d709a91e023a8f790c05aa0c5 Mon Sep 17 00:00:00 2001 From: Yash Ladha Date: Sat, 30 Jan 2021 13:50:21 +0530 Subject: [PATCH 040/108] src: use make_shared for safe allocation Using the reset does a double allocation and is error prone if some exception occured which is very unlikely but can happen. make_shared_ptr gives hedge over this and handle the failure in allocation. PR-URL: https://github.com/nodejs/node/pull/37139 Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Rich Trott --- src/env.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/env.cc b/src/env.cc index 16c6fcc3db4749..91789c3476f307 100644 --- a/src/env.cc +++ b/src/env.cc @@ -379,9 +379,10 @@ Environment::Environment(IsolateData* isolate_data, // easier to modify them after Environment creation. The defaults are // part of the per-Isolate option set, for which in turn the defaults are // part of the per-process option set. - options_.reset(new EnvironmentOptions(*isolate_data->options()->per_env)); - inspector_host_port_.reset( - new ExclusiveAccess(options_->debug_options().host_port)); + options_ = std::make_shared( + *isolate_data->options()->per_env); + inspector_host_port_ = std::make_shared>( + options_->debug_options().host_port); if (!(flags_ & EnvironmentFlags::kOwnsProcessState)) { set_abort_on_uncaught_exception(false); From a6053dc14a99aa98f0440707e0912d0a0b423e3a Mon Sep 17 00:00:00 2001 From: Yash Ladha Date: Sat, 30 Jan 2021 14:25:32 +0530 Subject: [PATCH 041/108] src: add context for TODO comment in env.cc Add more context around the TODO change required for achieving the task. When destructuring the isolate and environment_vars from the environment object, it is leading to recursive dependency and thus not able to refactor it in a better way. PR-URL: https://github.com/nodejs/node/pull/37140 Reviewed-By: Joyee Cheung Reviewed-By: Pooja D P Reviewed-By: Rich Trott --- src/env.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/env.cc b/src/env.cc index 91789c3476f307..49d8ffd31308a0 100644 --- a/src/env.cc +++ b/src/env.cc @@ -372,7 +372,8 @@ Environment::Environment(IsolateData* isolate_data, set_env_vars(per_process::system_environment); // TODO(joyeecheung): pass Isolate* and env_vars to it instead of the entire - // env + // env, when the recursive dependency inclusion in "debug-utils.h" is + // resolved. enabled_debug_list_.Parse(this); // We create new copies of the per-Environment option sets, so that it is From 20c65b00c28b46d01d432059d56ef29d87eaa337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Sun, 7 Feb 2021 10:23:33 +0100 Subject: [PATCH 042/108] deps: V8: backport dfcf1e86fac0 Original commit message: [wasm] PostMessage of Memory.buffer should throw PostMessage of an ArrayBuffer that is not detachable should result in a DataCloneError. Bug: chromium:1170176, chromium:961059 Change-Id: Ib89bbc10d2b58918067fd1a90365cad10a0db9ec Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2653810 Reviewed-by: Adam Klein Reviewed-by: Andreas Haas Commit-Queue: Deepti Gandluri Cr-Commit-Position: refs/heads/master@{#72415} Refs: https://github.com/v8/v8/commit/dfcf1e86fac0a7b067caf8fdfc13eaf3e3f445e4 PR-URL: https://github.com/nodejs/node/pull/37245 Reviewed-By: Daniel Bevenius Reviewed-By: Antoine du Hamel Reviewed-By: Rich Trott Reviewed-By: Matteo Collina Reviewed-By: Vladimir de Turckheim Reviewed-By: Colin Ihrig --- common.gypi | 2 +- deps/v8/src/common/message-template.h | 2 ++ deps/v8/src/objects/value-serializer.cc | 5 +++++ deps/v8/test/mjsunit/wasm/worker-memory.js | 7 +++++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/common.gypi b/common.gypi index 3b01d806407129..46f4f32a8dfcf8 100644 --- a/common.gypi +++ b/common.gypi @@ -36,7 +36,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.23', + 'v8_embedder_string': '-node.24', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/common/message-template.h b/deps/v8/src/common/message-template.h index c4edee49212489..dba4865250c8aa 100644 --- a/deps/v8/src/common/message-template.h +++ b/deps/v8/src/common/message-template.h @@ -573,6 +573,8 @@ namespace internal { T(DataCloneErrorOutOfMemory, "Data cannot be cloned, out of memory.") \ T(DataCloneErrorDetachedArrayBuffer, \ "An ArrayBuffer is detached and could not be cloned.") \ + T(DataCloneErrorNonDetachableArrayBuffer, \ + "ArrayBuffer is not detachable and could not be cloned.") \ T(DataCloneErrorSharedArrayBufferTransferred, \ "A SharedArrayBuffer could not be cloned. SharedArrayBuffer must not be " \ "transferred.") \ diff --git a/deps/v8/src/objects/value-serializer.cc b/deps/v8/src/objects/value-serializer.cc index 58b1db67492857..9e79f9ba434193 100644 --- a/deps/v8/src/objects/value-serializer.cc +++ b/deps/v8/src/objects/value-serializer.cc @@ -860,6 +860,11 @@ Maybe ValueSerializer::WriteJSArrayBuffer( WriteVarint(index.FromJust()); return ThrowIfOutOfMemory(); } + if (!array_buffer->is_detachable()) { + ThrowDataCloneError( + MessageTemplate::kDataCloneErrorNonDetachableArrayBuffer); + return Nothing(); + } uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer); if (transfer_entry) { diff --git a/deps/v8/test/mjsunit/wasm/worker-memory.js b/deps/v8/test/mjsunit/wasm/worker-memory.js index c5b99ede7e2836..bf5430f7139815 100644 --- a/deps/v8/test/mjsunit/wasm/worker-memory.js +++ b/deps/v8/test/mjsunit/wasm/worker-memory.js @@ -11,6 +11,13 @@ assertThrows(() => worker.postMessage(memory), Error); })(); +(function TestPostMessageUnsharedMemoryBuffer() { + let worker = new Worker('', {type: 'string'}); + let memory = new WebAssembly.Memory({initial: 1, maximum: 2}); + + assertThrows(() => worker.postMessage(memory.buffer), Error); +})(); + // Can't use assert in a worker. let workerHelpers = `function assertTrue(value, msg) { From eb0daaedf9bd5330c198483dbc2468c721db4668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Wed, 3 Feb 2021 13:04:40 +0100 Subject: [PATCH 043/108] tools: fix d8 macOS build libv8_base doesn't exist anymore. PR-URL: https://github.com/nodejs/node/pull/37211 Reviewed-By: Colin Ihrig Reviewed-By: Evan Lucas Reviewed-By: Jiawen Geng Reviewed-By: Rich Trott --- tools/v8_gypfiles/d8.gyp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tools/v8_gypfiles/d8.gyp b/tools/v8_gypfiles/d8.gyp index 7e7e426cbfcf2f..1780e1ab0dbccf 100644 --- a/tools/v8_gypfiles/d8.gyp +++ b/tools/v8_gypfiles/d8.gyp @@ -51,17 +51,6 @@ [ 'OS=="win"', { 'sources': [ '<(V8_ROOT)/src/d8/d8-windows.cc', ] }], - [ 'component!="shared_library"', { - 'conditions': [ - [ 'v8_postmortem_support==1', { - 'xcode_settings': { - 'OTHER_LDFLAGS': [ - '-Wl,-force_load,<(PRODUCT_DIR)/libv8_base.a' - ], - }, - }], - ], - }], ['v8_enable_i18n_support==1', { 'dependencies': [ '<(icu_gyp_path):icui18n', From 3079a78428ccf0f5a0c8dabb2c93f888caead247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Sat, 30 Jan 2021 16:59:54 +0100 Subject: [PATCH 044/108] src: avoid implicit type conversions This fixes a bunch of C4244 ('conversion' conversion from 'type1' to 'type2', possible loss of data) MSVC warnings in the code base. PR-URL: https://github.com/nodejs/node/pull/37149 Reviewed-By: Darshan Sen Reviewed-By: Benjamin Gruenbaum Reviewed-By: Rich Trott Reviewed-By: James M Snell --- src/base64.h | 6 ++--- src/cares_wrap.cc | 2 +- src/heap_utils.cc | 14 ++++++------ src/js_stream.cc | 2 +- src/js_udp_wrap.cc | 2 +- src/node.cc | 2 +- src/node_dir.cc | 12 +++++----- src/node_file.cc | 34 ++++++++++++++-------------- src/node_http_parser.cc | 22 ++++++++++--------- src/node_options.cc | 10 +++++---- src/node_os.cc | 19 ++++++++++------ src/node_perf.cc | 2 +- src/node_process_methods.cc | 44 +++++++++++++++++++------------------ src/node_worker.cc | 9 ++++---- 14 files changed, 98 insertions(+), 82 deletions(-) diff --git a/src/base64.h b/src/base64.h index cf6e82539a5f91..0db096810cd4a8 100644 --- a/src/base64.h +++ b/src/base64.h @@ -36,9 +36,9 @@ static inline const char* base64_select_table(Base64Mode mode) { static inline constexpr size_t base64_encoded_size( size_t size, Base64Mode mode = Base64Mode::NORMAL) { - return mode == Base64Mode::NORMAL - ? ((size + 2) / 3 * 4) - : std::ceil(static_cast(size * 4) / 3); + return mode == Base64Mode::NORMAL ? ((size + 2) / 3 * 4) + : static_cast(std::ceil( + static_cast(size * 4) / 3)); } // Doesn't check for padding at the end. Can be 1-2 bytes over. diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index 2bf4211b118602..bd00cd25624a67 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -1901,7 +1901,7 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) { Null(env->isolate()) }; - uint64_t n = 0; + uint32_t n = 0; const bool verbatim = req_wrap->verbatim(); if (status == 0) { diff --git a/src/heap_utils.cc b/src/heap_utils.cc index 71bfd59ac3ea69..c0c9ac2bdc7cee 100644 --- a/src/heap_utils.cc +++ b/src/heap_utils.cc @@ -118,16 +118,16 @@ class JSGraph : public EmbedderGraph { name_str += " "; name_str += n->Name(); } - if (!String::NewFromUtf8(isolate_, name_str.c_str()) - .ToLocal(&value) || + if (!String::NewFromUtf8(isolate_, name_str.c_str()).ToLocal(&value) || obj->Set(context, name_string, value).IsNothing() || obj->Set(context, is_root_string, Boolean::New(isolate_, n->IsRootNode())) .IsNothing() || - obj->Set(context, - size_string, - Number::New(isolate_, n->SizeInBytes())) + obj->Set( + context, + size_string, + Number::New(isolate_, static_cast(n->SizeInBytes()))) .IsNothing() || obj->Set(context, edges_string, Array::New(isolate_)).IsNothing()) { return MaybeLocal(); @@ -172,7 +172,7 @@ class JSGraph : public EmbedderGraph { return MaybeLocal(); } } else { - edge_name_value = Number::New(isolate_, j++); + edge_name_value = Number::New(isolate_, static_cast(j++)); } if (edge_obj->Set(context, name_string, edge_name_value).IsNothing() || edge_obj->Set(context, to_string, to_object).IsNothing() || @@ -262,7 +262,7 @@ class HeapSnapshotStream : public AsyncWrap, avail = buf.len; memcpy(buf.base, data, avail); data += avail; - len -= avail; + len -= static_cast(avail); EmitRead(size, buf); } return kContinue; diff --git a/src/js_stream.cc b/src/js_stream.cc index 399e073efba697..720008ecefcb48 100644 --- a/src/js_stream.cc +++ b/src/js_stream.cc @@ -178,7 +178,7 @@ void JSStream::ReadBuffer(const FunctionCallbackInfo& args) { memcpy(buf.base, data, avail); data += avail; - len -= avail; + len -= static_cast(avail); wrap->EmitRead(avail, buf); } } diff --git a/src/js_udp_wrap.cc b/src/js_udp_wrap.cc index 6a9bda5cad1ecb..c01289033e6764 100644 --- a/src/js_udp_wrap.cc +++ b/src/js_udp_wrap.cc @@ -161,7 +161,7 @@ void JSUDPWrap::EmitReceived(const FunctionCallbackInfo& args) { ssize_t avail = std::min(buf.len, len); memcpy(buf.base, data, avail); data += avail; - len -= avail; + len -= static_cast(avail); wrap->listener()->OnRecv( avail, buf, reinterpret_cast(&addr), flags); } diff --git a/src/node.cc b/src/node.cc index decaa755e39f12..c2ef9235d50c57 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1068,7 +1068,7 @@ InitializationResult InitializeOncePerProcess(int argc, char** argv) { #endif // HAVE_OPENSSL per_process::v8_platform.Initialize( - per_process::cli_options->v8_thread_pool_size); + static_cast(per_process::cli_options->v8_thread_pool_size)); V8::Initialize(); performance::performance_v8_start = PERFORMANCE_NOW(); per_process::v8_initialized = true; diff --git a/src/node_dir.cc b/src/node_dir.cc index a8bb2a7083c4fc..d94d78f560bf39 100644 --- a/src/node_dir.cc +++ b/src/node_dir.cc @@ -217,9 +217,10 @@ static void AfterDirRead(uv_fs_t* req) { Local js_array; if (!DirentListToArray(env, dir->dirents, - req->result, + static_cast(req->result), req_wrap->encoding(), - &error).ToLocal(&js_array)) { + &error) + .ToLocal(&js_array)) { // Clear libuv resources *before* delivering results to JS land because // that can schedule another operation on the same uv_dir_t. Ditto below. after.Clear(); @@ -244,7 +245,7 @@ void DirHandle::Read(const FunctionCallbackInfo& args) { ASSIGN_OR_RETURN_UNWRAP(&dir, args.Holder()); CHECK(args[1]->IsNumber()); - uint64_t buffer_size = args[1].As()->Value(); + uint64_t buffer_size = static_cast(args[1].As()->Value()); if (buffer_size != dir->dirents_.size()) { dir->dirents_.resize(buffer_size); @@ -280,9 +281,10 @@ void DirHandle::Read(const FunctionCallbackInfo& args) { Local js_array; if (!DirentListToArray(env, dir->dir()->dirents, - req_wrap_sync.req.result, + static_cast(req_wrap_sync.req.result), encoding, - &error).ToLocal(&js_array)) { + &error) + .ToLocal(&js_array)) { Local ctx = args[2].As(); USE(ctx->Set(env->context(), env->error_string(), error)); return; diff --git a/src/node_file.cc b/src/node_file.cc index a210aea3368bee..8c1ea9053f3519 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -367,7 +367,8 @@ MaybeLocal FileHandle::ClosePromise() { Isolate* isolate = close->env()->isolate(); if (req->result < 0) { HandleScope handle_scope(isolate); - close->Reject(UVException(isolate, req->result, "close")); + close->Reject( + UVException(isolate, static_cast(req->result), "close")); } else { close->Resolve(); } @@ -491,7 +492,7 @@ int FileHandle::ReadStart() { BaseObjectPtr read_wrap = std::move(handle->current_read_); - int result = req->result; + ssize_t result = req->result; uv_buf_t buffer = read_wrap->buffer_; uv_fs_req_cleanup(req); @@ -555,7 +556,7 @@ int FileHandle::DoShutdown(ShutdownWrap* req_wrap) { FileHandle* handle = static_cast(wrap->stream()); handle->AfterClose(); - int result = req->result; + int result = static_cast(req->result); uv_fs_req_cleanup(req); wrap->Done(result); }}); @@ -623,13 +624,12 @@ void FSReqAfterScope::Clear() { // in JS for more flexibility. void FSReqAfterScope::Reject(uv_fs_t* req) { BaseObjectPtr wrap { wrap_ }; - Local exception = - UVException(wrap_->env()->isolate(), - req->result, - wrap_->syscall(), - nullptr, - req->path, - wrap_->data()); + Local exception = UVException(wrap_->env()->isolate(), + static_cast(req->result), + wrap_->syscall(), + nullptr, + req->path, + wrap_->data()); Clear(); wrap->Reject(exception); } @@ -663,11 +663,12 @@ void AfterInteger(uv_fs_t* req) { FSReqBase* req_wrap = FSReqBase::from_req(req); FSReqAfterScope after(req_wrap, req); - if (req->result >= 0 && req_wrap->is_plain_open()) - req_wrap->env()->AddUnmanagedFd(req->result); + int result = static_cast(req->result); + if (result >= 0 && req_wrap->is_plain_open()) + req_wrap->env()->AddUnmanagedFd(result); if (after.Proceed()) - req_wrap->Resolve(Integer::New(req_wrap->env()->isolate(), req->result)); + req_wrap->Resolve(Integer::New(req_wrap->env()->isolate(), result)); } void AfterOpenFileHandle(uv_fs_t* req) { @@ -675,7 +676,8 @@ void AfterOpenFileHandle(uv_fs_t* req) { FSReqAfterScope after(req_wrap, req); if (after.Proceed()) { - FileHandle* fd = FileHandle::New(req_wrap->binding_data(), req->result); + FileHandle* fd = FileHandle::New(req_wrap->binding_data(), + static_cast(req->result)); if (fd == nullptr) return; req_wrap->Resolve(fd->object()); } @@ -1430,7 +1432,7 @@ int MKDirpAsync(uv_loop_t* loop, Environment* env = req_wrap->env(); uv_loop_t* loop = env->event_loop(); std::string path = req->path; - int err = req->result; + int err = static_cast(req->result); while (true) { switch (err) { @@ -1476,7 +1478,7 @@ int MKDirpAsync(uv_loop_t* loop, int err = uv_fs_stat(loop, req, path.c_str(), uv_fs_callback_t{[](uv_fs_t* req) { FSReqBase* req_wrap = FSReqBase::from_req(req); - int err = req->result; + int err = static_cast(req->result); if (reinterpret_cast(req->data) == UV_EEXIST && req_wrap->continuation_data()->paths().size() > 0) { if (err == 0 && S_ISDIR(req->statbuf.st_mode)) { diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index affc66585ed89a..b2841772aa3779 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -380,7 +380,7 @@ class Parser : public AsyncWrap, public StreamListener { return -1; } - return val; + return static_cast(val); } @@ -403,10 +403,10 @@ class Parser : public AsyncWrap, public StreamListener { } Local argv[3] = { - current_buffer_, - Integer::NewFromUnsigned(env()->isolate(), at - current_buffer_data_), - Integer::NewFromUnsigned(env()->isolate(), length) - }; + current_buffer_, + Integer::NewFromUnsigned( + env()->isolate(), static_cast(at - current_buffer_data_)), + Integer::NewFromUnsigned(env()->isolate(), length)}; MaybeLocal r = MakeCallback(cb.As(), arraysize(argv), @@ -549,7 +549,8 @@ class Parser : public AsyncWrap, public StreamListener { if (args.Length() > 2) { CHECK(args[2]->IsNumber()); - max_http_header_size = args[2].As()->Value(); + max_http_header_size = + static_cast(args[2].As()->Value()); } if (max_http_header_size == 0) { max_http_header_size = env->options()->max_http_header_size; @@ -557,7 +558,7 @@ class Parser : public AsyncWrap, public StreamListener { if (args.Length() > 4) { CHECK(args[4]->IsInt32()); - headers_timeout = args[4].As()->Value(); + headers_timeout = args[4].As()->Value(); } llhttp_type_t type = @@ -683,7 +684,7 @@ class Parser : public AsyncWrap, public StreamListener { // check header parsing time if (header_parsing_start_time_ != 0 && headers_timeout_ != 0) { uint64_t now = uv_hrtime(); - uint64_t parsing_time = (now - header_parsing_start_time_) / 1e6; + uint64_t parsing_time = (now - header_parsing_start_time_) / 1000000; if (parsing_time > headers_timeout_) { Local cb = @@ -781,8 +782,9 @@ class Parser : public AsyncWrap, public StreamListener { if (err == HPE_USER) { const char* colon = strchr(errno_reason, ':'); CHECK_NOT_NULL(colon); - code = OneByteString(env()->isolate(), errno_reason, - colon - errno_reason); + code = OneByteString(env()->isolate(), + errno_reason, + static_cast(colon - errno_reason)); reason = OneByteString(env()->isolate(), colon + 1); } else { code = OneByteString(env()->isolate(), llhttp_errno_name(err)); diff --git a/src/node_options.cc b/src/node_options.cc index 08b5fda6991ea6..d292231218f1fc 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -945,12 +945,14 @@ void GetOptions(const FunctionCallbackInfo& args) { *_ppop_instance.Lookup(field, opts)); break; case kInteger: - value = Number::New(isolate, - *_ppop_instance.Lookup(field, opts)); + value = Number::New( + isolate, + static_cast(*_ppop_instance.Lookup(field, opts))); break; case kUInteger: - value = Number::New(isolate, - *_ppop_instance.Lookup(field, opts)); + value = Number::New( + isolate, + static_cast(*_ppop_instance.Lookup(field, opts))); break; case kString: if (!ToV8Value(context, diff --git a/src/node_os.cc b/src/node_os.cc index 3cde80996f095f..2bbb56aabfcb83 100644 --- a/src/node_os.cc +++ b/src/node_os.cc @@ -118,11 +118,16 @@ static void GetCPUInfo(const FunctionCallbackInfo& args) { uv_cpu_info_t* ci = cpu_infos + i; result.emplace_back(OneByteString(isolate, ci->model)); result.emplace_back(Number::New(isolate, ci->speed)); - result.emplace_back(Number::New(isolate, ci->cpu_times.user)); - result.emplace_back(Number::New(isolate, ci->cpu_times.nice)); - result.emplace_back(Number::New(isolate, ci->cpu_times.sys)); - result.emplace_back(Number::New(isolate, ci->cpu_times.idle)); - result.emplace_back(Number::New(isolate, ci->cpu_times.irq)); + result.emplace_back( + Number::New(isolate, static_cast(ci->cpu_times.user))); + result.emplace_back( + Number::New(isolate, static_cast(ci->cpu_times.nice))); + result.emplace_back( + Number::New(isolate, static_cast(ci->cpu_times.sys))); + result.emplace_back( + Number::New(isolate, static_cast(ci->cpu_times.idle))); + result.emplace_back( + Number::New(isolate, static_cast(ci->cpu_times.irq))); } uv_free_cpu_info(cpu_infos, count); @@ -131,13 +136,13 @@ static void GetCPUInfo(const FunctionCallbackInfo& args) { static void GetFreeMemory(const FunctionCallbackInfo& args) { - double amount = uv_get_free_memory(); + double amount = static_cast(uv_get_free_memory()); args.GetReturnValue().Set(amount); } static void GetTotalMemory(const FunctionCallbackInfo& args) { - double amount = uv_get_total_memory(); + double amount = static_cast(uv_get_total_memory()); args.GetReturnValue().Set(amount); } diff --git a/src/node_perf.cc b/src/node_perf.cc index 4d977d4ba61789..e7ffd31445fbc3 100644 --- a/src/node_perf.cc +++ b/src/node_perf.cc @@ -88,7 +88,7 @@ std::ostream& operator<<(std::ostream& o, void PerformanceState::Mark(enum PerformanceMilestone milestone, uint64_t ts) { - this->milestones[milestone] = ts; + this->milestones[milestone] = static_cast(ts); TRACE_EVENT_INSTANT_WITH_TIMESTAMP0( TRACING_CATEGORY_NODE1(bootstrap), GetPerformanceMilestoneName(milestone), diff --git a/src/node_process_methods.cc b/src/node_process_methods.cc index 2c303a7693b774..5030ab872f4f16 100644 --- a/src/node_process_methods.cc +++ b/src/node_process_methods.cc @@ -203,12 +203,14 @@ static void MemoryUsage(const FunctionCallbackInfo& args) { if (err) return env->ThrowUVException(err, "uv_resident_set_memory"); - fields[0] = rss; - fields[1] = v8_heap_stats.total_heap_size(); - fields[2] = v8_heap_stats.used_heap_size(); - fields[3] = v8_heap_stats.external_memory(); - fields[4] = array_buffer_allocator == nullptr ? - 0 : array_buffer_allocator->total_mem_usage(); + fields[0] = static_cast(rss); + fields[1] = static_cast(v8_heap_stats.total_heap_size()); + fields[2] = static_cast(v8_heap_stats.used_heap_size()); + fields[3] = static_cast(v8_heap_stats.external_memory()); + fields[4] = + array_buffer_allocator == nullptr + ? 0 + : static_cast(array_buffer_allocator->total_mem_usage()); } void RawDebug(const FunctionCallbackInfo& args) { @@ -291,20 +293,20 @@ static void ResourceUsage(const FunctionCallbackInfo& args) { fields[0] = MICROS_PER_SEC * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec; fields[1] = MICROS_PER_SEC * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec; - fields[2] = rusage.ru_maxrss; - fields[3] = rusage.ru_ixrss; - fields[4] = rusage.ru_idrss; - fields[5] = rusage.ru_isrss; - fields[6] = rusage.ru_minflt; - fields[7] = rusage.ru_majflt; - fields[8] = rusage.ru_nswap; - fields[9] = rusage.ru_inblock; - fields[10] = rusage.ru_oublock; - fields[11] = rusage.ru_msgsnd; - fields[12] = rusage.ru_msgrcv; - fields[13] = rusage.ru_nsignals; - fields[14] = rusage.ru_nvcsw; - fields[15] = rusage.ru_nivcsw; + fields[2] = static_cast(rusage.ru_maxrss); + fields[3] = static_cast(rusage.ru_ixrss); + fields[4] = static_cast(rusage.ru_idrss); + fields[5] = static_cast(rusage.ru_isrss); + fields[6] = static_cast(rusage.ru_minflt); + fields[7] = static_cast(rusage.ru_majflt); + fields[8] = static_cast(rusage.ru_nswap); + fields[9] = static_cast(rusage.ru_inblock); + fields[10] = static_cast(rusage.ru_oublock); + fields[11] = static_cast(rusage.ru_msgsnd); + fields[12] = static_cast(rusage.ru_msgrcv); + fields[13] = static_cast(rusage.ru_nsignals); + fields[14] = static_cast(rusage.ru_nvcsw); + fields[15] = static_cast(rusage.ru_nivcsw); } #ifdef __POSIX__ @@ -355,7 +357,7 @@ static void DebugProcess(const FunctionCallbackInfo& args) { }); CHECK(args[0]->IsNumber()); - pid = args[0].As()->Value(); + pid = static_cast(args[0].As()->Value()); process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | diff --git a/src/node_worker.cc b/src/node_worker.cc index d163ec2461da07..6f7ccc33ba5cd6 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -99,7 +99,7 @@ void Worker::UpdateResourceConstraints(ResourceConstraints* constraints) { if (resource_limits_[kMaxYoungGenerationSizeMb] > 0) { constraints->set_max_young_generation_size_in_bytes( - resource_limits_[kMaxYoungGenerationSizeMb] * kMB); + static_cast(resource_limits_[kMaxYoungGenerationSizeMb] * kMB)); } else { resource_limits_[kMaxYoungGenerationSizeMb] = constraints->max_young_generation_size_in_bytes() / kMB; @@ -107,7 +107,7 @@ void Worker::UpdateResourceConstraints(ResourceConstraints* constraints) { if (resource_limits_[kMaxOldGenerationSizeMb] > 0) { constraints->set_max_old_generation_size_in_bytes( - resource_limits_[kMaxOldGenerationSizeMb] * kMB); + static_cast(resource_limits_[kMaxOldGenerationSizeMb] * kMB)); } else { resource_limits_[kMaxOldGenerationSizeMb] = constraints->max_old_generation_size_in_bytes() / kMB; @@ -115,7 +115,7 @@ void Worker::UpdateResourceConstraints(ResourceConstraints* constraints) { if (resource_limits_[kCodeRangeSizeMb] > 0) { constraints->set_code_range_size_in_bytes( - resource_limits_[kCodeRangeSizeMb] * kMB); + static_cast(resource_limits_[kCodeRangeSizeMb] * kMB)); } else { resource_limits_[kCodeRangeSizeMb] = constraints->code_range_size_in_bytes() / kMB; @@ -575,7 +575,8 @@ void Worker::StartThread(const FunctionCallbackInfo& args) { w->resource_limits_[kStackSizeMb] = kStackBufferSize / kMB; w->stack_size_ = kStackBufferSize; } else { - w->stack_size_ = w->resource_limits_[kStackSizeMb] * kMB; + w->stack_size_ = + static_cast(w->resource_limits_[kStackSizeMb] * kMB); } } else { w->resource_limits_[kStackSizeMb] = w->stack_size_ / kMB; From 54d36b00afa66102d55c6353a2f6c00459b97242 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 28 Jan 2021 23:22:18 +0800 Subject: [PATCH 045/108] src: rename binding_data_name to type_name in BindingData MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, this was a per-class string constant for BindingData which is used as keys for identifying these objects in the binding data map. These are just type names of the BindingData. This patch renames the variable to type_name so that we can generalize this constant for other BaseObjects and use it for debugging and logging the types of other BaseObjects. PR-URL: https://github.com/nodejs/node/pull/37112 Refs: https://github.com/nodejs/node/pull/36943 Reviewed-By: Juan José Arboleda --- src/README.md | 4 ++-- src/env-inl.h | 4 ++-- src/node_file.cc | 2 +- src/node_file.h | 2 +- src/node_http2.cc | 2 +- src/node_http2_state.h | 2 +- src/node_http_parser.cc | 4 ++-- src/node_v8.cc | 4 ++-- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/README.md b/src/README.md index aec56e7a7ba05a..a3b54416a0d2f5 100644 --- a/src/README.md +++ b/src/README.md @@ -422,7 +422,7 @@ that state is through the use of `Environment::AddBindingData`, which gives binding functions access to an object for storing such state. That object is always a [`BaseObject`][]. -Its class needs to have a static `binding_data_name` field based on a +Its class needs to have a static `type_name` field based on a constant string, in order to disambiguate it from other classes of this type, and which could e.g. match the binding’s name (in the example above, that would be `cares_wrap`). @@ -433,7 +433,7 @@ class BindingData : public BaseObject { public: BindingData(Environment* env, Local obj) : BaseObject(env, obj) {} - static constexpr FastStringKey binding_data_name { "http_parser" }; + static constexpr FastStringKey type_name { "http_parser" }; std::vector parser_buffer; bool parser_buffer_in_use = false; diff --git a/src/env-inl.h b/src/env-inl.h index 95b818373b9a0a..93d2423580a88b 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -358,7 +358,7 @@ inline T* Environment::GetBindingData(v8::Local context) { context->GetAlignedPointerFromEmbedderData( ContextEmbedderIndex::kBindingListIndex)); DCHECK_NOT_NULL(map); - auto it = map->find(T::binding_data_name); + auto it = map->find(T::type_name); if (UNLIKELY(it == map->end())) return nullptr; T* result = static_cast(it->second.get()); DCHECK_NOT_NULL(result); @@ -377,7 +377,7 @@ inline T* Environment::AddBindingData( context->GetAlignedPointerFromEmbedderData( ContextEmbedderIndex::kBindingListIndex)); DCHECK_NOT_NULL(map); - auto result = map->emplace(T::binding_data_name, item); + auto result = map->emplace(T::type_name, item); CHECK(result.second); DCHECK_EQ(GetBindingData(context), item.get()); return item.get(); diff --git a/src/node_file.cc b/src/node_file.cc index 8c1ea9053f3519..31494e8d2e8370 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -2399,7 +2399,7 @@ void BindingData::MemoryInfo(MemoryTracker* tracker) const { } // TODO(addaleax): Remove once we're on C++17. -constexpr FastStringKey BindingData::binding_data_name; +constexpr FastStringKey BindingData::type_name; void Initialize(Local target, Local unused, diff --git a/src/node_file.h b/src/node_file.h index 95a68b5d89a704..9e652dc7a4afa4 100644 --- a/src/node_file.h +++ b/src/node_file.h @@ -27,7 +27,7 @@ class BindingData : public BaseObject { std::vector> file_handle_read_wrap_freelist; - static constexpr FastStringKey binding_data_name { "fs" }; + static constexpr FastStringKey type_name { "fs" }; void MemoryInfo(MemoryTracker* tracker) const override; SET_SELF_SIZE(BindingData) diff --git a/src/node_http2.cc b/src/node_http2.cc index 930167418e18db..a4b8e4d2ac7d50 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -3001,7 +3001,7 @@ void Http2State::MemoryInfo(MemoryTracker* tracker) const { } // TODO(addaleax): Remove once we're on C++17. -constexpr FastStringKey Http2State::binding_data_name; +constexpr FastStringKey Http2State::type_name; // Set up the process.binding('http2') binding. void Initialize(Local target, diff --git a/src/node_http2_state.h b/src/node_http2_state.h index cd29b207498dc0..7cf40ff1017ca3 100644 --- a/src/node_http2_state.h +++ b/src/node_http2_state.h @@ -127,7 +127,7 @@ class Http2State : public BaseObject { SET_SELF_SIZE(Http2State) SET_MEMORY_INFO_NAME(Http2State) - static constexpr FastStringKey binding_data_name { "http2" }; + static constexpr FastStringKey type_name { "http2" }; private: struct http2_state_internal { diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index b2841772aa3779..dfe0273d06f0e3 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -88,7 +88,7 @@ class BindingData : public BaseObject { BindingData(Environment* env, Local obj) : BaseObject(env, obj) {} - static constexpr FastStringKey binding_data_name { "http_parser" }; + static constexpr FastStringKey type_name { "http_parser" }; std::vector parser_buffer; bool parser_buffer_in_use = false; @@ -101,7 +101,7 @@ class BindingData : public BaseObject { }; // TODO(addaleax): Remove once we're on C++17. -constexpr FastStringKey BindingData::binding_data_name; +constexpr FastStringKey BindingData::type_name; // helper class for the Parser struct StringPtr { diff --git a/src/node_v8.cc b/src/node_v8.cc index 4ab87dce326bb1..d66b5e03b8620c 100644 --- a/src/node_v8.cc +++ b/src/node_v8.cc @@ -95,7 +95,7 @@ class BindingData : public BaseObject { heap_code_statistics_buffer(env->isolate(), kHeapCodeStatisticsPropertiesCount) {} - static constexpr FastStringKey binding_data_name { "v8" }; + static constexpr FastStringKey type_name { "v8" }; AliasedFloat64Array heap_statistics_buffer; AliasedFloat64Array heap_space_statistics_buffer; @@ -113,7 +113,7 @@ class BindingData : public BaseObject { }; // TODO(addaleax): Remove once we're on C++17. -constexpr FastStringKey BindingData::binding_data_name; +constexpr FastStringKey BindingData::type_name; void CachedDataVersionTag(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); From 1a9bcdf1d9445d603befd4476bc2eb9d513cdb27 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 28 Jan 2021 23:37:21 +0800 Subject: [PATCH 046/108] src: refactor v8 binding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Put the v8 binding data class into a header so we can reuse the class definition during deserialization. 2. Put the v8 binding code into node::v8_utils namespace for clarity. 3. Move the binding data property initialization into its constructor so that we can reuse it during deserialization 4. Reorder the v8 binding initialization so that we don't unnecessarily initialize the properties in a loop PR-URL: https://github.com/nodejs/node/pull/37112 Refs: https://github.com/nodejs/node/pull/36943 Reviewed-By: Juan José Arboleda --- node.gyp | 1 + src/node_v8.cc | 100 ++++++++++++++++++++----------------------------- src/node_v8.h | 36 ++++++++++++++++++ 3 files changed, 77 insertions(+), 60 deletions(-) create mode 100644 src/node_v8.h diff --git a/node.gyp b/node.gyp index 03868ab2ef1507..5d2e63db5d1cab 100644 --- a/node.gyp +++ b/node.gyp @@ -746,6 +746,7 @@ 'src/node_union_bytes.h', 'src/node_url.h', 'src/node_version.h', + 'src/node_v8.h', 'src/node_v8_platform-inl.h', 'src/node_wasi.h', 'src/node_watchdog.h', diff --git a/src/node_v8.cc b/src/node_v8.cc index d66b5e03b8620c..4354e1e1772d82 100644 --- a/src/node_v8.cc +++ b/src/node_v8.cc @@ -19,15 +19,16 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -#include "node.h" +#include "node_v8.h" #include "base_object-inl.h" #include "env-inl.h" #include "memory_tracker-inl.h" +#include "node.h" #include "util-inl.h" #include "v8.h" namespace node { - +namespace v8_utils { using v8::Array; using v8::Context; using v8::FunctionCallbackInfo; @@ -44,7 +45,6 @@ using v8::Uint32; using v8::V8; using v8::Value; - #define HEAP_STATISTICS_PROPERTIES(V) \ V(0, total_heap_size, kTotalHeapSizeIndex) \ V(1, total_heap_size_executable, kTotalHeapSizeExecutableIndex) \ @@ -63,7 +63,6 @@ static constexpr size_t kHeapStatisticsPropertiesCount = HEAP_STATISTICS_PROPERTIES(V); #undef V - #define HEAP_SPACE_STATISTICS_PROPERTIES(V) \ V(0, space_size, kSpaceSizeIndex) \ V(1, space_used_size, kSpaceUsedSizeIndex) \ @@ -85,32 +84,34 @@ static const size_t kHeapCodeStatisticsPropertiesCount = HEAP_CODE_STATISTICS_PROPERTIES(V); #undef V -class BindingData : public BaseObject { - public: - BindingData(Environment* env, Local obj) - : BaseObject(env, obj), - heap_statistics_buffer(env->isolate(), kHeapStatisticsPropertiesCount), - heap_space_statistics_buffer(env->isolate(), - kHeapSpaceStatisticsPropertiesCount), - heap_code_statistics_buffer(env->isolate(), - kHeapCodeStatisticsPropertiesCount) {} - - static constexpr FastStringKey type_name { "v8" }; - - AliasedFloat64Array heap_statistics_buffer; - AliasedFloat64Array heap_space_statistics_buffer; - AliasedFloat64Array heap_code_statistics_buffer; - - void MemoryInfo(MemoryTracker* tracker) const override { - tracker->TrackField("heap_statistics_buffer", heap_statistics_buffer); - tracker->TrackField("heap_space_statistics_buffer", - heap_space_statistics_buffer); - tracker->TrackField("heap_code_statistics_buffer", - heap_code_statistics_buffer); - } - SET_SELF_SIZE(BindingData) - SET_MEMORY_INFO_NAME(BindingData) -}; +BindingData::BindingData(Environment* env, Local obj) + : BaseObject(env, obj), + heap_statistics_buffer(env->isolate(), kHeapStatisticsPropertiesCount), + heap_space_statistics_buffer(env->isolate(), + kHeapSpaceStatisticsPropertiesCount), + heap_code_statistics_buffer(env->isolate(), + kHeapCodeStatisticsPropertiesCount) { + obj->Set(env->context(), + FIXED_ONE_BYTE_STRING(env->isolate(), "heapStatisticsBuffer"), + heap_statistics_buffer.GetJSArray()) + .Check(); + obj->Set(env->context(), + FIXED_ONE_BYTE_STRING(env->isolate(), "heapCodeStatisticsBuffer"), + heap_code_statistics_buffer.GetJSArray()) + .Check(); + obj->Set(env->context(), + FIXED_ONE_BYTE_STRING(env->isolate(), "heapSpaceStatisticsBuffer"), + heap_space_statistics_buffer.GetJSArray()) + .Check(); +} + +void BindingData::MemoryInfo(MemoryTracker* tracker) const { + tracker->TrackField("heap_statistics_buffer", heap_statistics_buffer); + tracker->TrackField("heap_space_statistics_buffer", + heap_space_statistics_buffer); + tracker->TrackField("heap_code_statistics_buffer", + heap_code_statistics_buffer); +} // TODO(addaleax): Remove once we're on C++17. constexpr FastStringKey BindingData::type_name; @@ -179,36 +180,12 @@ void Initialize(Local target, env->SetMethodNoSideEffect(target, "cachedDataVersionTag", CachedDataVersionTag); - - // Export symbols used by v8.getHeapStatistics() env->SetMethod( target, "updateHeapStatisticsBuffer", UpdateHeapStatisticsBuffer); - target - ->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "heapStatisticsBuffer"), - binding_data->heap_statistics_buffer.GetJSArray()) - .Check(); - -#define V(i, _, name) \ - target->Set(env->context(), \ - FIXED_ONE_BYTE_STRING(env->isolate(), #name), \ - Uint32::NewFromUnsigned(env->isolate(), i)).Check(); - - HEAP_STATISTICS_PROPERTIES(V) - - // Export symbols used by v8.getHeapCodeStatistics() env->SetMethod( target, "updateHeapCodeStatisticsBuffer", UpdateHeapCodeStatisticsBuffer); - target - ->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "heapCodeStatisticsBuffer"), - binding_data->heap_code_statistics_buffer.GetJSArray()) - .Check(); - - HEAP_CODE_STATISTICS_PROPERTIES(V) - size_t number_of_heap_spaces = env->isolate()->NumberOfHeapSpaces(); // Heap space names are extracted once and exposed to JavaScript to @@ -230,13 +207,15 @@ void Initialize(Local target, "updateHeapSpaceStatisticsBuffer", UpdateHeapSpaceStatisticsBuffer); - target - ->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), - "heapSpaceStatisticsBuffer"), - binding_data->heap_space_statistics_buffer.GetJSArray()) +#define V(i, _, name) \ + target \ + ->Set(env->context(), \ + FIXED_ONE_BYTE_STRING(env->isolate(), #name), \ + Uint32::NewFromUnsigned(env->isolate(), i)) \ .Check(); + HEAP_STATISTICS_PROPERTIES(V) + HEAP_CODE_STATISTICS_PROPERTIES(V) HEAP_SPACE_STATISTICS_PROPERTIES(V) #undef V @@ -244,6 +223,7 @@ void Initialize(Local target, env->SetMethod(target, "setFlagsFromString", SetFlagsFromString); } +} // namespace v8_utils } // namespace node -NODE_MODULE_CONTEXT_AWARE_INTERNAL(v8, node::Initialize) +NODE_MODULE_CONTEXT_AWARE_INTERNAL(v8, node::v8_utils::Initialize) diff --git a/src/node_v8.h b/src/node_v8.h new file mode 100644 index 00000000000000..745c6580b844f4 --- /dev/null +++ b/src/node_v8.h @@ -0,0 +1,36 @@ +#ifndef SRC_NODE_V8_H_ +#define SRC_NODE_V8_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "aliased_buffer.h" +#include "base_object.h" +#include "util.h" +#include "v8.h" + +namespace node { +class Environment; + +namespace v8_utils { +class BindingData : public BaseObject { + public: + BindingData(Environment* env, v8::Local obj); + + static constexpr FastStringKey type_name{"node::v8::BindingData"}; + + AliasedFloat64Array heap_statistics_buffer; + AliasedFloat64Array heap_space_statistics_buffer; + AliasedFloat64Array heap_code_statistics_buffer; + + void MemoryInfo(MemoryTracker* tracker) const override; + SET_SELF_SIZE(BindingData) + SET_MEMORY_INFO_NAME(BindingData) +}; + +} // namespace v8_utils + +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_NODE_V8_H_ From d8d851ac5cdbb94facbb6fc89b896a0ce0d1720a Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sun, 7 Feb 2021 22:18:42 -0800 Subject: [PATCH 047/108] tools: bump remark-present-lint-node from 2.0.0 to 2.0.1 This is a prerequisite for https://github.com/nodejs/node/pull/37259. PR-URL: https://github.com/nodejs/node/pull/37270 Reviewed-By: Antoine du Hamel Reviewed-By: Richard Lau Reviewed-By: Beth Griggs --- tools/lint-md.js | 3834 ++++++++++++++++- .../node-lint-md-cli-rollup/package-lock.json | 49 +- tools/node-lint-md-cli-rollup/package.json | 2 +- 3 files changed, 3872 insertions(+), 13 deletions(-) diff --git a/tools/lint-md.js b/tools/lint-md.js index 332fdd63ed44e1..ed09bd170affed 100644 --- a/tools/lint-md.js +++ b/tools/lint-md.js @@ -39713,7 +39713,7 @@ const dependencies$1 = { remark: "^13.0.0", "remark-gfm": "^1.0.0", "remark-lint": "^8.0.0", - "remark-preset-lint-node": "^2.0.0", + "remark-preset-lint-node": "^2.0.1", "unified-args": "^8.1.0" }; const main = "dist/index.js"; @@ -45047,6 +45047,3834 @@ function noTrailingSpaces(ast, file) { } } +function isNothing$1(subject) { + return (typeof subject === 'undefined') || (subject === null); +} + + +function isObject$4(subject) { + return (typeof subject === 'object') && (subject !== null); +} + + +function toArray$1(sequence) { + if (Array.isArray(sequence)) return sequence; + else if (isNothing$1(sequence)) return []; + + return [ sequence ]; +} + + +function extend$3(target, source) { + var index, length, key, sourceKeys; + + if (source) { + sourceKeys = Object.keys(source); + + for (index = 0, length = sourceKeys.length; index < length; index += 1) { + key = sourceKeys[index]; + target[key] = source[key]; + } + } + + return target; +} + + +function repeat$2(string, count) { + var result = '', cycle; + + for (cycle = 0; cycle < count; cycle += 1) { + result += string; + } + + return result; +} + + +function isNegativeZero$1(number) { + return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number); +} + + +var isNothing_1$1 = isNothing$1; +var isObject_1$1 = isObject$4; +var toArray_1$1 = toArray$1; +var repeat_1$1 = repeat$2; +var isNegativeZero_1$1 = isNegativeZero$1; +var extend_1$1 = extend$3; + +var common$3 = { + isNothing: isNothing_1$1, + isObject: isObject_1$1, + toArray: toArray_1$1, + repeat: repeat_1$1, + isNegativeZero: isNegativeZero_1$1, + extend: extend_1$1 +}; + +// YAML error class. http://stackoverflow.com/questions/8458984 + + +function formatError(exception, compact) { + var where = '', message = exception.reason || '(unknown reason)'; + + if (!exception.mark) return message; + + if (exception.mark.name) { + where += 'in "' + exception.mark.name + '" '; + } + + where += '(' + (exception.mark.line + 1) + ':' + (exception.mark.column + 1) + ')'; + + if (!compact && exception.mark.snippet) { + where += '\n\n' + exception.mark.snippet; + } + + return message + ' ' + where; +} + + +function YAMLException$2(reason, mark) { + // Super constructor + Error.call(this); + + this.name = 'YAMLException'; + this.reason = reason; + this.mark = mark; + this.message = formatError(this, false); + + // Include stack trace in error object + if (Error.captureStackTrace) { + // Chrome and NodeJS + Error.captureStackTrace(this, this.constructor); + } else { + // FF, IE 10+ and Safari 6+. Fallback for others + this.stack = (new Error()).stack || ''; + } +} + + +// Inherit from Error +YAMLException$2.prototype = Object.create(Error.prototype); +YAMLException$2.prototype.constructor = YAMLException$2; + + +YAMLException$2.prototype.toString = function toString(compact) { + return this.name + ': ' + formatError(this, compact); +}; + + +var exception$1 = YAMLException$2; + +// get snippet for a single line, respecting maxLength +function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { + var head = ''; + var tail = ''; + var maxHalfLength = Math.floor(maxLineLength / 2) - 1; + + if (position - lineStart > maxHalfLength) { + head = ' ... '; + lineStart = position - maxHalfLength + head.length; + } + + if (lineEnd - position > maxHalfLength) { + tail = ' ...'; + lineEnd = position + maxHalfLength - tail.length; + } + + return { + str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, '→') + tail, + pos: position - lineStart + head.length // relative position + }; +} + + +function padStart(string, max) { + return common$3.repeat(' ', max - string.length) + string; +} + + +function makeSnippet(mark, options) { + options = Object.create(options || null); + + if (!mark.buffer) return null; + + if (!options.maxLength) options.maxLength = 79; + if (typeof options.indent !== 'number') options.indent = 1; + if (typeof options.linesBefore !== 'number') options.linesBefore = 3; + if (typeof options.linesAfter !== 'number') options.linesAfter = 2; + + var re = /\r?\n|\r|\0/g; + var lineStarts = [ 0 ]; + var lineEnds = []; + var match; + var foundLineNo = -1; + + while ((match = re.exec(mark.buffer))) { + lineEnds.push(match.index); + lineStarts.push(match.index + match[0].length); + + if (mark.position <= match.index && foundLineNo < 0) { + foundLineNo = lineStarts.length - 2; + } + } + + if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; + + var result = '', i, line; + var lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length; + var maxLineLength = options.maxLength - (options.indent + lineNoLength + 3); + + for (i = 1; i <= options.linesBefore; i++) { + if (foundLineNo - i < 0) break; + line = getLine( + mark.buffer, + lineStarts[foundLineNo - i], + lineEnds[foundLineNo - i], + mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), + maxLineLength + ); + result = common$3.repeat(' ', options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) + + ' | ' + line.str + '\n' + result; + } + + line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); + result += common$3.repeat(' ', options.indent) + padStart((mark.line + 1).toString(), lineNoLength) + + ' | ' + line.str + '\n'; + result += common$3.repeat('-', options.indent + lineNoLength + 3 + line.pos) + '^' + '\n'; + + for (i = 1; i <= options.linesAfter; i++) { + if (foundLineNo + i >= lineEnds.length) break; + line = getLine( + mark.buffer, + lineStarts[foundLineNo + i], + lineEnds[foundLineNo + i], + mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), + maxLineLength + ); + result += common$3.repeat(' ', options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) + + ' | ' + line.str + '\n'; + } + + return result.replace(/\n$/, ''); +} + + +var snippet = makeSnippet; + +var TYPE_CONSTRUCTOR_OPTIONS$1 = [ + 'kind', + 'multi', + 'resolve', + 'construct', + 'instanceOf', + 'predicate', + 'represent', + 'representName', + 'defaultStyle', + 'styleAliases' +]; + +var YAML_NODE_KINDS$1 = [ + 'scalar', + 'sequence', + 'mapping' +]; + +function compileStyleAliases$1(map) { + var result = {}; + + if (map !== null) { + Object.keys(map).forEach(function (style) { + map[style].forEach(function (alias) { + result[String(alias)] = style; + }); + }); + } + + return result; +} + +function Type$2(tag, options) { + options = options || {}; + + Object.keys(options).forEach(function (name) { + if (TYPE_CONSTRUCTOR_OPTIONS$1.indexOf(name) === -1) { + throw new exception$1('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.'); + } + }); + + // TODO: Add tag format check. + this.tag = tag; + this.kind = options['kind'] || null; + this.resolve = options['resolve'] || function () { return true; }; + this.construct = options['construct'] || function (data) { return data; }; + this.instanceOf = options['instanceOf'] || null; + this.predicate = options['predicate'] || null; + this.represent = options['represent'] || null; + this.representName = options['representName'] || null; + this.defaultStyle = options['defaultStyle'] || null; + this.multi = options['multi'] || false; + this.styleAliases = compileStyleAliases$1(options['styleAliases'] || null); + + if (YAML_NODE_KINDS$1.indexOf(this.kind) === -1) { + throw new exception$1('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.'); + } +} + +var type$1 = Type$2; + +/*eslint-disable max-len*/ + + + + + +function compileList$1(schema, name, result) { + var exclude = []; + + schema[name].forEach(function (currentType) { + result.forEach(function (previousType, previousIndex) { + if (previousType.tag === currentType.tag && + previousType.kind === currentType.kind && + previousType.multi === currentType.multi) { + + exclude.push(previousIndex); + } + }); + + result.push(currentType); + }); + + return result.filter(function (type, index) { + return exclude.indexOf(index) === -1; + }); +} + + +function compileMap$1(/* lists... */) { + var result = { + scalar: {}, + sequence: {}, + mapping: {}, + fallback: {}, + multi: { + scalar: [], + sequence: [], + mapping: [], + fallback: [] + } + }, index, length; + + function collectType(type) { + if (type.multi) { + result.multi[type.kind].push(type); + result.multi['fallback'].push(type); + } else { + result[type.kind][type.tag] = result['fallback'][type.tag] = type; + } + } + + for (index = 0, length = arguments.length; index < length; index += 1) { + arguments[index].forEach(collectType); + } + return result; +} + + +function Schema$2(definition) { + return this.extend(definition); +} + + +Schema$2.prototype.extend = function extend(definition) { + var implicit = []; + var explicit = []; + + if (definition instanceof type$1) { + // Schema.extend(type) + explicit.push(definition); + + } else if (Array.isArray(definition)) { + // Schema.extend([ type1, type2, ... ]) + explicit = explicit.concat(definition); + + } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) { + // Schema.extend({ explicit: [ type1, type2, ... ], implicit: [ type1, type2, ... ] }) + if (definition.implicit) implicit = implicit.concat(definition.implicit); + if (definition.explicit) explicit = explicit.concat(definition.explicit); + + } else { + throw new exception$1('Schema.extend argument should be a Type, [ Type ], ' + + 'or a schema definition ({ implicit: [...], explicit: [...] })'); + } + + implicit.forEach(function (type) { + if (!(type instanceof type$1)) { + throw new exception$1('Specified list of YAML types (or a single Type object) contains a non-Type object.'); + } + + if (type.loadKind && type.loadKind !== 'scalar') { + throw new exception$1('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.'); + } + + if (type.multi) { + throw new exception$1('There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.'); + } + }); + + explicit.forEach(function (type) { + if (!(type instanceof type$1)) { + throw new exception$1('Specified list of YAML types (or a single Type object) contains a non-Type object.'); + } + }); + + var result = Object.create(Schema$2.prototype); + + result.implicit = (this.implicit || []).concat(implicit); + result.explicit = (this.explicit || []).concat(explicit); + + result.compiledImplicit = compileList$1(result, 'implicit', []); + result.compiledExplicit = compileList$1(result, 'explicit', []); + result.compiledTypeMap = compileMap$1(result.compiledImplicit, result.compiledExplicit); + + return result; +}; + + +var schema$2 = Schema$2; + +var str$1 = new type$1('tag:yaml.org,2002:str', { + kind: 'scalar', + construct: function (data) { return data !== null ? data : ''; } +}); + +var seq$1 = new type$1('tag:yaml.org,2002:seq', { + kind: 'sequence', + construct: function (data) { return data !== null ? data : []; } +}); + +var map$5 = new type$1('tag:yaml.org,2002:map', { + kind: 'mapping', + construct: function (data) { return data !== null ? data : {}; } +}); + +var failsafe$1 = new schema$2({ + explicit: [ + str$1, + seq$1, + map$5 + ] +}); + +function resolveYamlNull$1(data) { + if (data === null) return true; + + var max = data.length; + + return (max === 1 && data === '~') || + (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL')); +} + +function constructYamlNull$1() { + return null; +} + +function isNull$1(object) { + return object === null; +} + +var _null$1 = new type$1('tag:yaml.org,2002:null', { + kind: 'scalar', + resolve: resolveYamlNull$1, + construct: constructYamlNull$1, + predicate: isNull$1, + represent: { + canonical: function () { return '~'; }, + lowercase: function () { return 'null'; }, + uppercase: function () { return 'NULL'; }, + camelcase: function () { return 'Null'; }, + empty: function () { return ''; } + }, + defaultStyle: 'lowercase' +}); + +function resolveYamlBoolean$1(data) { + if (data === null) return false; + + var max = data.length; + + return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) || + (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE')); +} + +function constructYamlBoolean$1(data) { + return data === 'true' || + data === 'True' || + data === 'TRUE'; +} + +function isBoolean$1(object) { + return Object.prototype.toString.call(object) === '[object Boolean]'; +} + +var bool$1 = new type$1('tag:yaml.org,2002:bool', { + kind: 'scalar', + resolve: resolveYamlBoolean$1, + construct: constructYamlBoolean$1, + predicate: isBoolean$1, + represent: { + lowercase: function (object) { return object ? 'true' : 'false'; }, + uppercase: function (object) { return object ? 'TRUE' : 'FALSE'; }, + camelcase: function (object) { return object ? 'True' : 'False'; } + }, + defaultStyle: 'lowercase' +}); + +function isHexCode$1(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) || + ((0x41/* A */ <= c) && (c <= 0x46/* F */)) || + ((0x61/* a */ <= c) && (c <= 0x66/* f */)); +} + +function isOctCode$1(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */)); +} + +function isDecCode$1(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)); +} + +function resolveYamlInteger$1(data) { + if (data === null) return false; + + var max = data.length, + index = 0, + hasDigits = false, + ch; + + if (!max) return false; + + ch = data[index]; + + // sign + if (ch === '-' || ch === '+') { + ch = data[++index]; + } + + if (ch === '0') { + // 0 + if (index + 1 === max) return true; + ch = data[++index]; + + // base 2, base 8, base 16 + + if (ch === 'b') { + // base 2 + index++; + + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (ch !== '0' && ch !== '1') return false; + hasDigits = true; + } + return hasDigits && ch !== '_'; + } + + + if (ch === 'x') { + // base 16 + index++; + + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (!isHexCode$1(data.charCodeAt(index))) return false; + hasDigits = true; + } + return hasDigits && ch !== '_'; + } + + + if (ch === 'o') { + // base 8 + index++; + + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (!isOctCode$1(data.charCodeAt(index))) return false; + hasDigits = true; + } + return hasDigits && ch !== '_'; + } + } + + // base 10 (except 0) + + // value should not start with `_`; + if (ch === '_') return false; + + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (!isDecCode$1(data.charCodeAt(index))) { + return false; + } + hasDigits = true; + } + + // Should have digits and should not end with `_` + if (!hasDigits || ch === '_') return false; + + return true; +} + +function constructYamlInteger$1(data) { + var value = data, sign = 1, ch; + + if (value.indexOf('_') !== -1) { + value = value.replace(/_/g, ''); + } + + ch = value[0]; + + if (ch === '-' || ch === '+') { + if (ch === '-') sign = -1; + value = value.slice(1); + ch = value[0]; + } + + if (value === '0') return 0; + + if (ch === '0') { + if (value[1] === 'b') return sign * parseInt(value.slice(2), 2); + if (value[1] === 'x') return sign * parseInt(value.slice(2), 16); + if (value[1] === 'o') return sign * parseInt(value.slice(2), 8); + } + + return sign * parseInt(value, 10); +} + +function isInteger$1(object) { + return (Object.prototype.toString.call(object)) === '[object Number]' && + (object % 1 === 0 && !common$3.isNegativeZero(object)); +} + +var int$2 = new type$1('tag:yaml.org,2002:int', { + kind: 'scalar', + resolve: resolveYamlInteger$1, + construct: constructYamlInteger$1, + predicate: isInteger$1, + represent: { + binary: function (obj) { return obj >= 0 ? '0b' + obj.toString(2) : '-0b' + obj.toString(2).slice(1); }, + octal: function (obj) { return obj >= 0 ? '0o' + obj.toString(8) : '-0o' + obj.toString(8).slice(1); }, + decimal: function (obj) { return obj.toString(10); }, + /* eslint-disable max-len */ + hexadecimal: function (obj) { return obj >= 0 ? '0x' + obj.toString(16).toUpperCase() : '-0x' + obj.toString(16).toUpperCase().slice(1); } + }, + defaultStyle: 'decimal', + styleAliases: { + binary: [ 2, 'bin' ], + octal: [ 8, 'oct' ], + decimal: [ 10, 'dec' ], + hexadecimal: [ 16, 'hex' ] + } +}); + +var YAML_FLOAT_PATTERN$1 = new RegExp( + // 2.5e4, 2.5 and integers + '^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?' + + // .2e4, .2 + // special case, seems not from spec + '|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?' + + // .inf + '|[-+]?\\.(?:inf|Inf|INF)' + + // .nan + '|\\.(?:nan|NaN|NAN))$'); + +function resolveYamlFloat$1(data) { + if (data === null) return false; + + if (!YAML_FLOAT_PATTERN$1.test(data) || + // Quick hack to not allow integers end with `_` + // Probably should update regexp & check speed + data[data.length - 1] === '_') { + return false; + } + + return true; +} + +function constructYamlFloat$1(data) { + var value, sign; + + value = data.replace(/_/g, '').toLowerCase(); + sign = value[0] === '-' ? -1 : 1; + + if ('+-'.indexOf(value[0]) >= 0) { + value = value.slice(1); + } + + if (value === '.inf') { + return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + + } else if (value === '.nan') { + return NaN; + } + return sign * parseFloat(value, 10); +} + + +var SCIENTIFIC_WITHOUT_DOT$1 = /^[-+]?[0-9]+e/; + +function representYamlFloat$1(object, style) { + var res; + + if (isNaN(object)) { + switch (style) { + case 'lowercase': return '.nan'; + case 'uppercase': return '.NAN'; + case 'camelcase': return '.NaN'; + } + } else if (Number.POSITIVE_INFINITY === object) { + switch (style) { + case 'lowercase': return '.inf'; + case 'uppercase': return '.INF'; + case 'camelcase': return '.Inf'; + } + } else if (Number.NEGATIVE_INFINITY === object) { + switch (style) { + case 'lowercase': return '-.inf'; + case 'uppercase': return '-.INF'; + case 'camelcase': return '-.Inf'; + } + } else if (common$3.isNegativeZero(object)) { + return '-0.0'; + } + + res = object.toString(10); + + // JS stringifier can build scientific format without dots: 5e-100, + // while YAML requres dot: 5.e-100. Fix it with simple hack + + return SCIENTIFIC_WITHOUT_DOT$1.test(res) ? res.replace('e', '.e') : res; +} + +function isFloat$1(object) { + return (Object.prototype.toString.call(object) === '[object Number]') && + (object % 1 !== 0 || common$3.isNegativeZero(object)); +} + +var float$1 = new type$1('tag:yaml.org,2002:float', { + kind: 'scalar', + resolve: resolveYamlFloat$1, + construct: constructYamlFloat$1, + predicate: isFloat$1, + represent: representYamlFloat$1, + defaultStyle: 'lowercase' +}); + +var json$1 = failsafe$1.extend({ + implicit: [ + _null$1, + bool$1, + int$2, + float$1 + ] +}); + +var core$3 = json$1; + +var YAML_DATE_REGEXP$1 = new RegExp( + '^([0-9][0-9][0-9][0-9])' + // [1] year + '-([0-9][0-9])' + // [2] month + '-([0-9][0-9])$'); // [3] day + +var YAML_TIMESTAMP_REGEXP$1 = new RegExp( + '^([0-9][0-9][0-9][0-9])' + // [1] year + '-([0-9][0-9]?)' + // [2] month + '-([0-9][0-9]?)' + // [3] day + '(?:[Tt]|[ \\t]+)' + // ... + '([0-9][0-9]?)' + // [4] hour + ':([0-9][0-9])' + // [5] minute + ':([0-9][0-9])' + // [6] second + '(?:\\.([0-9]*))?' + // [7] fraction + '(?:[ \\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tz_hour + '(?::([0-9][0-9]))?))?$'); // [11] tz_minute + +function resolveYamlTimestamp$1(data) { + if (data === null) return false; + if (YAML_DATE_REGEXP$1.exec(data) !== null) return true; + if (YAML_TIMESTAMP_REGEXP$1.exec(data) !== null) return true; + return false; +} + +function constructYamlTimestamp$1(data) { + var match, year, month, day, hour, minute, second, fraction = 0, + delta = null, tz_hour, tz_minute, date; + + match = YAML_DATE_REGEXP$1.exec(data); + if (match === null) match = YAML_TIMESTAMP_REGEXP$1.exec(data); + + if (match === null) throw new Error('Date resolve error'); + + // match: [1] year [2] month [3] day + + year = +(match[1]); + month = +(match[2]) - 1; // JS month starts with 0 + day = +(match[3]); + + if (!match[4]) { // no hour + return new Date(Date.UTC(year, month, day)); + } + + // match: [4] hour [5] minute [6] second [7] fraction + + hour = +(match[4]); + minute = +(match[5]); + second = +(match[6]); + + if (match[7]) { + fraction = match[7].slice(0, 3); + while (fraction.length < 3) { // milli-seconds + fraction += '0'; + } + fraction = +fraction; + } + + // match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute + + if (match[9]) { + tz_hour = +(match[10]); + tz_minute = +(match[11] || 0); + delta = (tz_hour * 60 + tz_minute) * 60000; // delta in mili-seconds + if (match[9] === '-') delta = -delta; + } + + date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + + if (delta) date.setTime(date.getTime() - delta); + + return date; +} + +function representYamlTimestamp$1(object /*, style*/) { + return object.toISOString(); +} + +var timestamp$1 = new type$1('tag:yaml.org,2002:timestamp', { + kind: 'scalar', + resolve: resolveYamlTimestamp$1, + construct: constructYamlTimestamp$1, + instanceOf: Date, + represent: representYamlTimestamp$1 +}); + +function resolveYamlMerge$1(data) { + return data === '<<' || data === null; +} + +var merge$1 = new type$1('tag:yaml.org,2002:merge', { + kind: 'scalar', + resolve: resolveYamlMerge$1 +}); + +/*eslint-disable no-bitwise*/ + + + + + +// [ 64, 65, 66 ] -> [ padding, CR, LF ] +var BASE64_MAP$1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r'; + + +function resolveYamlBinary$1(data) { + if (data === null) return false; + + var code, idx, bitlen = 0, max = data.length, map = BASE64_MAP$1; + + // Convert one by one. + for (idx = 0; idx < max; idx++) { + code = map.indexOf(data.charAt(idx)); + + // Skip CR/LF + if (code > 64) continue; + + // Fail on illegal characters + if (code < 0) return false; + + bitlen += 6; + } + + // If there are any bits left, source was corrupted + return (bitlen % 8) === 0; +} + +function constructYamlBinary$1(data) { + var idx, tailbits, + input = data.replace(/[\r\n=]/g, ''), // remove CR/LF & padding to simplify scan + max = input.length, + map = BASE64_MAP$1, + bits = 0, + result = []; + + // Collect by 6*4 bits (3 bytes) + + for (idx = 0; idx < max; idx++) { + if ((idx % 4 === 0) && idx) { + result.push((bits >> 16) & 0xFF); + result.push((bits >> 8) & 0xFF); + result.push(bits & 0xFF); + } + + bits = (bits << 6) | map.indexOf(input.charAt(idx)); + } + + // Dump tail + + tailbits = (max % 4) * 6; + + if (tailbits === 0) { + result.push((bits >> 16) & 0xFF); + result.push((bits >> 8) & 0xFF); + result.push(bits & 0xFF); + } else if (tailbits === 18) { + result.push((bits >> 10) & 0xFF); + result.push((bits >> 2) & 0xFF); + } else if (tailbits === 12) { + result.push((bits >> 4) & 0xFF); + } + + return new Uint8Array(result); +} + +function representYamlBinary$1(object /*, style*/) { + var result = '', bits = 0, idx, tail, + max = object.length, + map = BASE64_MAP$1; + + // Convert every three bytes to 4 ASCII characters. + + for (idx = 0; idx < max; idx++) { + if ((idx % 3 === 0) && idx) { + result += map[(bits >> 18) & 0x3F]; + result += map[(bits >> 12) & 0x3F]; + result += map[(bits >> 6) & 0x3F]; + result += map[bits & 0x3F]; + } + + bits = (bits << 8) + object[idx]; + } + + // Dump tail + + tail = max % 3; + + if (tail === 0) { + result += map[(bits >> 18) & 0x3F]; + result += map[(bits >> 12) & 0x3F]; + result += map[(bits >> 6) & 0x3F]; + result += map[bits & 0x3F]; + } else if (tail === 2) { + result += map[(bits >> 10) & 0x3F]; + result += map[(bits >> 4) & 0x3F]; + result += map[(bits << 2) & 0x3F]; + result += map[64]; + } else if (tail === 1) { + result += map[(bits >> 2) & 0x3F]; + result += map[(bits << 4) & 0x3F]; + result += map[64]; + result += map[64]; + } + + return result; +} + +function isBinary$1(obj) { + return Object.prototype.toString.call(obj) === '[object Uint8Array]'; +} + +var binary$1 = new type$1('tag:yaml.org,2002:binary', { + kind: 'scalar', + resolve: resolveYamlBinary$1, + construct: constructYamlBinary$1, + predicate: isBinary$1, + represent: representYamlBinary$1 +}); + +var _hasOwnProperty$4 = Object.prototype.hasOwnProperty; +var _toString$3 = Object.prototype.toString; + +function resolveYamlOmap$1(data) { + if (data === null) return true; + + var objectKeys = [], index, length, pair, pairKey, pairHasKey, + object = data; + + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; + pairHasKey = false; + + if (_toString$3.call(pair) !== '[object Object]') return false; + + for (pairKey in pair) { + if (_hasOwnProperty$4.call(pair, pairKey)) { + if (!pairHasKey) pairHasKey = true; + else return false; + } + } + + if (!pairHasKey) return false; + + if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey); + else return false; + } + + return true; +} + +function constructYamlOmap$1(data) { + return data !== null ? data : []; +} + +var omap$1 = new type$1('tag:yaml.org,2002:omap', { + kind: 'sequence', + resolve: resolveYamlOmap$1, + construct: constructYamlOmap$1 +}); + +var _toString$4 = Object.prototype.toString; + +function resolveYamlPairs$1(data) { + if (data === null) return true; + + var index, length, pair, keys, result, + object = data; + + result = new Array(object.length); + + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; + + if (_toString$4.call(pair) !== '[object Object]') return false; + + keys = Object.keys(pair); + + if (keys.length !== 1) return false; + + result[index] = [ keys[0], pair[keys[0]] ]; + } + + return true; +} + +function constructYamlPairs$1(data) { + if (data === null) return []; + + var index, length, pair, keys, result, + object = data; + + result = new Array(object.length); + + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; + + keys = Object.keys(pair); + + result[index] = [ keys[0], pair[keys[0]] ]; + } + + return result; +} + +var pairs$1 = new type$1('tag:yaml.org,2002:pairs', { + kind: 'sequence', + resolve: resolveYamlPairs$1, + construct: constructYamlPairs$1 +}); + +var _hasOwnProperty$5 = Object.prototype.hasOwnProperty; + +function resolveYamlSet$1(data) { + if (data === null) return true; + + var key, object = data; + + for (key in object) { + if (_hasOwnProperty$5.call(object, key)) { + if (object[key] !== null) return false; + } + } + + return true; +} + +function constructYamlSet$1(data) { + return data !== null ? data : {}; +} + +var set$1 = new type$1('tag:yaml.org,2002:set', { + kind: 'mapping', + resolve: resolveYamlSet$1, + construct: constructYamlSet$1 +}); + +var _default$8 = core$3.extend({ + implicit: [ + timestamp$1, + merge$1 + ], + explicit: [ + binary$1, + omap$1, + pairs$1, + set$1 + ] +}); + +/*eslint-disable max-len,no-use-before-define*/ + + + + + + + +var _hasOwnProperty$6 = Object.prototype.hasOwnProperty; + + +var CONTEXT_FLOW_IN$1 = 1; +var CONTEXT_FLOW_OUT$1 = 2; +var CONTEXT_BLOCK_IN$1 = 3; +var CONTEXT_BLOCK_OUT$1 = 4; + + +var CHOMPING_CLIP$1 = 1; +var CHOMPING_STRIP$1 = 2; +var CHOMPING_KEEP$1 = 3; + + +var PATTERN_NON_PRINTABLE$1 = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; +var PATTERN_NON_ASCII_LINE_BREAKS$1 = /[\x85\u2028\u2029]/; +var PATTERN_FLOW_INDICATORS$1 = /[,\[\]\{\}]/; +var PATTERN_TAG_HANDLE$1 = /^(?:!|!!|![a-z\-]+!)$/i; +var PATTERN_TAG_URI$1 = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i; + + +function _class$1(obj) { return Object.prototype.toString.call(obj); } + +function is_EOL$1(c) { + return (c === 0x0A/* LF */) || (c === 0x0D/* CR */); +} + +function is_WHITE_SPACE$1(c) { + return (c === 0x09/* Tab */) || (c === 0x20/* Space */); +} + +function is_WS_OR_EOL$1(c) { + return (c === 0x09/* Tab */) || + (c === 0x20/* Space */) || + (c === 0x0A/* LF */) || + (c === 0x0D/* CR */); +} + +function is_FLOW_INDICATOR$1(c) { + return c === 0x2C/* , */ || + c === 0x5B/* [ */ || + c === 0x5D/* ] */ || + c === 0x7B/* { */ || + c === 0x7D/* } */; +} + +function fromHexCode$1(c) { + var lc; + + if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) { + return c - 0x30; + } + + /*eslint-disable no-bitwise*/ + lc = c | 0x20; + + if ((0x61/* a */ <= lc) && (lc <= 0x66/* f */)) { + return lc - 0x61 + 10; + } + + return -1; +} + +function escapedHexLen$1(c) { + if (c === 0x78/* x */) { return 2; } + if (c === 0x75/* u */) { return 4; } + if (c === 0x55/* U */) { return 8; } + return 0; +} + +function fromDecimalCode$1(c) { + if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) { + return c - 0x30; + } + + return -1; +} + +function simpleEscapeSequence$1(c) { + /* eslint-disable indent */ + return (c === 0x30/* 0 */) ? '\x00' : + (c === 0x61/* a */) ? '\x07' : + (c === 0x62/* b */) ? '\x08' : + (c === 0x74/* t */) ? '\x09' : + (c === 0x09/* Tab */) ? '\x09' : + (c === 0x6E/* n */) ? '\x0A' : + (c === 0x76/* v */) ? '\x0B' : + (c === 0x66/* f */) ? '\x0C' : + (c === 0x72/* r */) ? '\x0D' : + (c === 0x65/* e */) ? '\x1B' : + (c === 0x20/* Space */) ? ' ' : + (c === 0x22/* " */) ? '\x22' : + (c === 0x2F/* / */) ? '/' : + (c === 0x5C/* \ */) ? '\x5C' : + (c === 0x4E/* N */) ? '\x85' : + (c === 0x5F/* _ */) ? '\xA0' : + (c === 0x4C/* L */) ? '\u2028' : + (c === 0x50/* P */) ? '\u2029' : ''; +} + +function charFromCodepoint$1(c) { + if (c <= 0xFFFF) { + return String.fromCharCode(c); + } + // Encode UTF-16 surrogate pair + // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF + return String.fromCharCode( + ((c - 0x010000) >> 10) + 0xD800, + ((c - 0x010000) & 0x03FF) + 0xDC00 + ); +} + +var simpleEscapeCheck$1 = new Array(256); // integer, for fast access +var simpleEscapeMap$1 = new Array(256); +for (var i$1 = 0; i$1 < 256; i$1++) { + simpleEscapeCheck$1[i$1] = simpleEscapeSequence$1(i$1) ? 1 : 0; + simpleEscapeMap$1[i$1] = simpleEscapeSequence$1(i$1); +} + + +function State$2(input, options) { + this.input = input; + + this.filename = options['filename'] || null; + this.schema = options['schema'] || _default$8; + this.onWarning = options['onWarning'] || null; + // (Hidden) Remove? makes the loader to expect YAML 1.1 documents + // if such documents have no explicit %YAML directive + this.legacy = options['legacy'] || false; + + this.json = options['json'] || false; + this.listener = options['listener'] || null; + + this.implicitTypes = this.schema.compiledImplicit; + this.typeMap = this.schema.compiledTypeMap; + + this.length = input.length; + this.position = 0; + this.line = 0; + this.lineStart = 0; + this.lineIndent = 0; + + // position of first leading tab in the current line, + // used to make sure there are no tabs in the indentation + this.firstTabInLine = -1; + + this.documents = []; + + /* + this.version; + this.checkLineBreaks; + this.tagMap; + this.anchorMap; + this.tag; + this.anchor; + this.kind; + this.result;*/ + +} + + +function generateError$1(state, message) { + var mark = { + name: state.filename, + buffer: state.input.slice(0, -1), // omit trailing \0 + position: state.position, + line: state.line, + column: state.position - state.lineStart + }; + + mark.snippet = snippet(mark); + + return new exception$1(message, mark); +} + +function throwError$2(state, message) { + throw generateError$1(state, message); +} + +function throwWarning$1(state, message) { + if (state.onWarning) { + state.onWarning.call(null, generateError$1(state, message)); + } +} + + +var directiveHandlers$1 = { + + YAML: function handleYamlDirective(state, name, args) { + + var match, major, minor; + + if (state.version !== null) { + throwError$2(state, 'duplication of %YAML directive'); + } + + if (args.length !== 1) { + throwError$2(state, 'YAML directive accepts exactly one argument'); + } + + match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + + if (match === null) { + throwError$2(state, 'ill-formed argument of the YAML directive'); + } + + major = parseInt(match[1], 10); + minor = parseInt(match[2], 10); + + if (major !== 1) { + throwError$2(state, 'unacceptable YAML version of the document'); + } + + state.version = args[0]; + state.checkLineBreaks = (minor < 2); + + if (minor !== 1 && minor !== 2) { + throwWarning$1(state, 'unsupported YAML version of the document'); + } + }, + + TAG: function handleTagDirective(state, name, args) { + + var handle, prefix; + + if (args.length !== 2) { + throwError$2(state, 'TAG directive accepts exactly two arguments'); + } + + handle = args[0]; + prefix = args[1]; + + if (!PATTERN_TAG_HANDLE$1.test(handle)) { + throwError$2(state, 'ill-formed tag handle (first argument) of the TAG directive'); + } + + if (_hasOwnProperty$6.call(state.tagMap, handle)) { + throwError$2(state, 'there is a previously declared suffix for "' + handle + '" tag handle'); + } + + if (!PATTERN_TAG_URI$1.test(prefix)) { + throwError$2(state, 'ill-formed tag prefix (second argument) of the TAG directive'); + } + + try { + prefix = decodeURIComponent(prefix); + } catch (err) { + throwError$2(state, 'tag prefix is malformed: ' + prefix); + } + + state.tagMap[handle] = prefix; + } +}; + + +function captureSegment$1(state, start, end, checkJson) { + var _position, _length, _character, _result; + + if (start < end) { + _result = state.input.slice(start, end); + + if (checkJson) { + for (_position = 0, _length = _result.length; _position < _length; _position += 1) { + _character = _result.charCodeAt(_position); + if (!(_character === 0x09 || + (0x20 <= _character && _character <= 0x10FFFF))) { + throwError$2(state, 'expected valid JSON character'); + } + } + } else if (PATTERN_NON_PRINTABLE$1.test(_result)) { + throwError$2(state, 'the stream contains non-printable characters'); + } + + state.result += _result; + } +} + +function mergeMappings$1(state, destination, source, overridableKeys) { + var sourceKeys, key, index, quantity; + + if (!common$3.isObject(source)) { + throwError$2(state, 'cannot merge mappings; the provided source object is unacceptable'); + } + + sourceKeys = Object.keys(source); + + for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) { + key = sourceKeys[index]; + + if (!_hasOwnProperty$6.call(destination, key)) { + destination[key] = source[key]; + overridableKeys[key] = true; + } + } +} + +function storeMappingPair$1(state, _result, overridableKeys, keyTag, keyNode, valueNode, + startLine, startLineStart, startPos) { + + var index, quantity; + + // The output is a plain object here, so keys can only be strings. + // We need to convert keyNode to a string, but doing so can hang the process + // (deeply nested arrays that explode exponentially using aliases). + if (Array.isArray(keyNode)) { + keyNode = Array.prototype.slice.call(keyNode); + + for (index = 0, quantity = keyNode.length; index < quantity; index += 1) { + if (Array.isArray(keyNode[index])) { + throwError$2(state, 'nested arrays are not supported inside keys'); + } + + if (typeof keyNode === 'object' && _class$1(keyNode[index]) === '[object Object]') { + keyNode[index] = '[object Object]'; + } + } + } + + // Avoid code execution in load() via toString property + // (still use its own toString for arrays, timestamps, + // and whatever user schema extensions happen to have @@toStringTag) + if (typeof keyNode === 'object' && _class$1(keyNode) === '[object Object]') { + keyNode = '[object Object]'; + } + + + keyNode = String(keyNode); + + if (_result === null) { + _result = {}; + } + + if (keyTag === 'tag:yaml.org,2002:merge') { + if (Array.isArray(valueNode)) { + for (index = 0, quantity = valueNode.length; index < quantity; index += 1) { + mergeMappings$1(state, _result, valueNode[index], overridableKeys); + } + } else { + mergeMappings$1(state, _result, valueNode, overridableKeys); + } + } else { + if (!state.json && + !_hasOwnProperty$6.call(overridableKeys, keyNode) && + _hasOwnProperty$6.call(_result, keyNode)) { + state.line = startLine || state.line; + state.lineStart = startLineStart || state.lineStart; + state.position = startPos || state.position; + throwError$2(state, 'duplicated mapping key'); + } + + // used for this specific key only because Object.defineProperty is slow + if (keyNode === '__proto__') { + Object.defineProperty(_result, keyNode, { + configurable: true, + enumerable: true, + writable: true, + value: valueNode + }); + } else { + _result[keyNode] = valueNode; + } + delete overridableKeys[keyNode]; + } + + return _result; +} + +function readLineBreak$1(state) { + var ch; + + ch = state.input.charCodeAt(state.position); + + if (ch === 0x0A/* LF */) { + state.position++; + } else if (ch === 0x0D/* CR */) { + state.position++; + if (state.input.charCodeAt(state.position) === 0x0A/* LF */) { + state.position++; + } + } else { + throwError$2(state, 'a line break is expected'); + } + + state.line += 1; + state.lineStart = state.position; + state.firstTabInLine = -1; +} + +function skipSeparationSpace$1(state, allowComments, checkIndent) { + var lineBreaks = 0, + ch = state.input.charCodeAt(state.position); + + while (ch !== 0) { + while (is_WHITE_SPACE$1(ch)) { + if (ch === 0x09/* Tab */ && state.firstTabInLine === -1) { + state.firstTabInLine = state.position; + } + ch = state.input.charCodeAt(++state.position); + } + + if (allowComments && ch === 0x23/* # */) { + do { + ch = state.input.charCodeAt(++state.position); + } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0); + } + + if (is_EOL$1(ch)) { + readLineBreak$1(state); + + ch = state.input.charCodeAt(state.position); + lineBreaks++; + state.lineIndent = 0; + + while (ch === 0x20/* Space */) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + } else { + break; + } + } + + if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) { + throwWarning$1(state, 'deficient indentation'); + } + + return lineBreaks; +} + +function testDocumentSeparator$1(state) { + var _position = state.position, + ch; + + ch = state.input.charCodeAt(_position); + + // Condition state.position === state.lineStart is tested + // in parent on each call, for efficiency. No needs to test here again. + if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) && + ch === state.input.charCodeAt(_position + 1) && + ch === state.input.charCodeAt(_position + 2)) { + + _position += 3; + + ch = state.input.charCodeAt(_position); + + if (ch === 0 || is_WS_OR_EOL$1(ch)) { + return true; + } + } + + return false; +} + +function writeFoldedLines$1(state, count) { + if (count === 1) { + state.result += ' '; + } else if (count > 1) { + state.result += common$3.repeat('\n', count - 1); + } +} + + +function readPlainScalar$1(state, nodeIndent, withinFlowCollection) { + var preceding, + following, + captureStart, + captureEnd, + hasPendingContent, + _line, + _lineStart, + _lineIndent, + _kind = state.kind, + _result = state.result, + ch; + + ch = state.input.charCodeAt(state.position); + + if (is_WS_OR_EOL$1(ch) || + is_FLOW_INDICATOR$1(ch) || + ch === 0x23/* # */ || + ch === 0x26/* & */ || + ch === 0x2A/* * */ || + ch === 0x21/* ! */ || + ch === 0x7C/* | */ || + ch === 0x3E/* > */ || + ch === 0x27/* ' */ || + ch === 0x22/* " */ || + ch === 0x25/* % */ || + ch === 0x40/* @ */ || + ch === 0x60/* ` */) { + return false; + } + + if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) { + following = state.input.charCodeAt(state.position + 1); + + if (is_WS_OR_EOL$1(following) || + withinFlowCollection && is_FLOW_INDICATOR$1(following)) { + return false; + } + } + + state.kind = 'scalar'; + state.result = ''; + captureStart = captureEnd = state.position; + hasPendingContent = false; + + while (ch !== 0) { + if (ch === 0x3A/* : */) { + following = state.input.charCodeAt(state.position + 1); + + if (is_WS_OR_EOL$1(following) || + withinFlowCollection && is_FLOW_INDICATOR$1(following)) { + break; + } + + } else if (ch === 0x23/* # */) { + preceding = state.input.charCodeAt(state.position - 1); + + if (is_WS_OR_EOL$1(preceding)) { + break; + } + + } else if ((state.position === state.lineStart && testDocumentSeparator$1(state)) || + withinFlowCollection && is_FLOW_INDICATOR$1(ch)) { + break; + + } else if (is_EOL$1(ch)) { + _line = state.line; + _lineStart = state.lineStart; + _lineIndent = state.lineIndent; + skipSeparationSpace$1(state, false, -1); + + if (state.lineIndent >= nodeIndent) { + hasPendingContent = true; + ch = state.input.charCodeAt(state.position); + continue; + } else { + state.position = captureEnd; + state.line = _line; + state.lineStart = _lineStart; + state.lineIndent = _lineIndent; + break; + } + } + + if (hasPendingContent) { + captureSegment$1(state, captureStart, captureEnd, false); + writeFoldedLines$1(state, state.line - _line); + captureStart = captureEnd = state.position; + hasPendingContent = false; + } + + if (!is_WHITE_SPACE$1(ch)) { + captureEnd = state.position + 1; + } + + ch = state.input.charCodeAt(++state.position); + } + + captureSegment$1(state, captureStart, captureEnd, false); + + if (state.result) { + return true; + } + + state.kind = _kind; + state.result = _result; + return false; +} + +function readSingleQuotedScalar$1(state, nodeIndent) { + var ch, + captureStart, captureEnd; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x27/* ' */) { + return false; + } + + state.kind = 'scalar'; + state.result = ''; + state.position++; + captureStart = captureEnd = state.position; + + while ((ch = state.input.charCodeAt(state.position)) !== 0) { + if (ch === 0x27/* ' */) { + captureSegment$1(state, captureStart, state.position, true); + ch = state.input.charCodeAt(++state.position); + + if (ch === 0x27/* ' */) { + captureStart = state.position; + state.position++; + captureEnd = state.position; + } else { + return true; + } + + } else if (is_EOL$1(ch)) { + captureSegment$1(state, captureStart, captureEnd, true); + writeFoldedLines$1(state, skipSeparationSpace$1(state, false, nodeIndent)); + captureStart = captureEnd = state.position; + + } else if (state.position === state.lineStart && testDocumentSeparator$1(state)) { + throwError$2(state, 'unexpected end of the document within a single quoted scalar'); + + } else { + state.position++; + captureEnd = state.position; + } + } + + throwError$2(state, 'unexpected end of the stream within a single quoted scalar'); +} + +function readDoubleQuotedScalar$1(state, nodeIndent) { + var captureStart, + captureEnd, + hexLength, + hexResult, + tmp, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x22/* " */) { + return false; + } + + state.kind = 'scalar'; + state.result = ''; + state.position++; + captureStart = captureEnd = state.position; + + while ((ch = state.input.charCodeAt(state.position)) !== 0) { + if (ch === 0x22/* " */) { + captureSegment$1(state, captureStart, state.position, true); + state.position++; + return true; + + } else if (ch === 0x5C/* \ */) { + captureSegment$1(state, captureStart, state.position, true); + ch = state.input.charCodeAt(++state.position); + + if (is_EOL$1(ch)) { + skipSeparationSpace$1(state, false, nodeIndent); + + // TODO: rework to inline fn with no type cast? + } else if (ch < 256 && simpleEscapeCheck$1[ch]) { + state.result += simpleEscapeMap$1[ch]; + state.position++; + + } else if ((tmp = escapedHexLen$1(ch)) > 0) { + hexLength = tmp; + hexResult = 0; + + for (; hexLength > 0; hexLength--) { + ch = state.input.charCodeAt(++state.position); + + if ((tmp = fromHexCode$1(ch)) >= 0) { + hexResult = (hexResult << 4) + tmp; + + } else { + throwError$2(state, 'expected hexadecimal character'); + } + } + + state.result += charFromCodepoint$1(hexResult); + + state.position++; + + } else { + throwError$2(state, 'unknown escape sequence'); + } + + captureStart = captureEnd = state.position; + + } else if (is_EOL$1(ch)) { + captureSegment$1(state, captureStart, captureEnd, true); + writeFoldedLines$1(state, skipSeparationSpace$1(state, false, nodeIndent)); + captureStart = captureEnd = state.position; + + } else if (state.position === state.lineStart && testDocumentSeparator$1(state)) { + throwError$2(state, 'unexpected end of the document within a double quoted scalar'); + + } else { + state.position++; + captureEnd = state.position; + } + } + + throwError$2(state, 'unexpected end of the stream within a double quoted scalar'); +} + +function readFlowCollection$1(state, nodeIndent) { + var readNext = true, + _line, + _lineStart, + _pos, + _tag = state.tag, + _result, + _anchor = state.anchor, + following, + terminator, + isPair, + isExplicitPair, + isMapping, + overridableKeys = Object.create(null), + keyNode, + keyTag, + valueNode, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch === 0x5B/* [ */) { + terminator = 0x5D;/* ] */ + isMapping = false; + _result = []; + } else if (ch === 0x7B/* { */) { + terminator = 0x7D;/* } */ + isMapping = true; + _result = {}; + } else { + return false; + } + + if (state.anchor !== null) { + state.anchorMap[state.anchor] = _result; + } + + ch = state.input.charCodeAt(++state.position); + + while (ch !== 0) { + skipSeparationSpace$1(state, true, nodeIndent); + + ch = state.input.charCodeAt(state.position); + + if (ch === terminator) { + state.position++; + state.tag = _tag; + state.anchor = _anchor; + state.kind = isMapping ? 'mapping' : 'sequence'; + state.result = _result; + return true; + } else if (!readNext) { + throwError$2(state, 'missed comma between flow collection entries'); + } else if (ch === 0x2C/* , */) { + // "flow collection entries can never be completely empty", as per YAML 1.2, section 7.4 + throwError$2(state, "expected the node content, but found ','"); + } + + keyTag = keyNode = valueNode = null; + isPair = isExplicitPair = false; + + if (ch === 0x3F/* ? */) { + following = state.input.charCodeAt(state.position + 1); + + if (is_WS_OR_EOL$1(following)) { + isPair = isExplicitPair = true; + state.position++; + skipSeparationSpace$1(state, true, nodeIndent); + } + } + + _line = state.line; // Save the current line. + _lineStart = state.lineStart; + _pos = state.position; + composeNode$1(state, nodeIndent, CONTEXT_FLOW_IN$1, false, true); + keyTag = state.tag; + keyNode = state.result; + skipSeparationSpace$1(state, true, nodeIndent); + + ch = state.input.charCodeAt(state.position); + + if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) { + isPair = true; + ch = state.input.charCodeAt(++state.position); + skipSeparationSpace$1(state, true, nodeIndent); + composeNode$1(state, nodeIndent, CONTEXT_FLOW_IN$1, false, true); + valueNode = state.result; + } + + if (isMapping) { + storeMappingPair$1(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos); + } else if (isPair) { + _result.push(storeMappingPair$1(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos)); + } else { + _result.push(keyNode); + } + + skipSeparationSpace$1(state, true, nodeIndent); + + ch = state.input.charCodeAt(state.position); + + if (ch === 0x2C/* , */) { + readNext = true; + ch = state.input.charCodeAt(++state.position); + } else { + readNext = false; + } + } + + throwError$2(state, 'unexpected end of the stream within a flow collection'); +} + +function readBlockScalar$1(state, nodeIndent) { + var captureStart, + folding, + chomping = CHOMPING_CLIP$1, + didReadContent = false, + detectedIndent = false, + textIndent = nodeIndent, + emptyLines = 0, + atMoreIndented = false, + tmp, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch === 0x7C/* | */) { + folding = false; + } else if (ch === 0x3E/* > */) { + folding = true; + } else { + return false; + } + + state.kind = 'scalar'; + state.result = ''; + + while (ch !== 0) { + ch = state.input.charCodeAt(++state.position); + + if (ch === 0x2B/* + */ || ch === 0x2D/* - */) { + if (CHOMPING_CLIP$1 === chomping) { + chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP$1 : CHOMPING_STRIP$1; + } else { + throwError$2(state, 'repeat of a chomping mode identifier'); + } + + } else if ((tmp = fromDecimalCode$1(ch)) >= 0) { + if (tmp === 0) { + throwError$2(state, 'bad explicit indentation width of a block scalar; it cannot be less than one'); + } else if (!detectedIndent) { + textIndent = nodeIndent + tmp - 1; + detectedIndent = true; + } else { + throwError$2(state, 'repeat of an indentation width identifier'); + } + + } else { + break; + } + } + + if (is_WHITE_SPACE$1(ch)) { + do { ch = state.input.charCodeAt(++state.position); } + while (is_WHITE_SPACE$1(ch)); + + if (ch === 0x23/* # */) { + do { ch = state.input.charCodeAt(++state.position); } + while (!is_EOL$1(ch) && (ch !== 0)); + } + } + + while (ch !== 0) { + readLineBreak$1(state); + state.lineIndent = 0; + + ch = state.input.charCodeAt(state.position); + + while ((!detectedIndent || state.lineIndent < textIndent) && + (ch === 0x20/* Space */)) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + + if (!detectedIndent && state.lineIndent > textIndent) { + textIndent = state.lineIndent; + } + + if (is_EOL$1(ch)) { + emptyLines++; + continue; + } + + // End of the scalar. + if (state.lineIndent < textIndent) { + + // Perform the chomping. + if (chomping === CHOMPING_KEEP$1) { + state.result += common$3.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines); + } else if (chomping === CHOMPING_CLIP$1) { + if (didReadContent) { // i.e. only if the scalar is not empty. + state.result += '\n'; + } + } + + // Break this `while` cycle and go to the funciton's epilogue. + break; + } + + // Folded style: use fancy rules to handle line breaks. + if (folding) { + + // Lines starting with white space characters (more-indented lines) are not folded. + if (is_WHITE_SPACE$1(ch)) { + atMoreIndented = true; + // except for the first content line (cf. Example 8.1) + state.result += common$3.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines); + + // End of more-indented block. + } else if (atMoreIndented) { + atMoreIndented = false; + state.result += common$3.repeat('\n', emptyLines + 1); + + // Just one line break - perceive as the same line. + } else if (emptyLines === 0) { + if (didReadContent) { // i.e. only if we have already read some scalar content. + state.result += ' '; + } + + // Several line breaks - perceive as different lines. + } else { + state.result += common$3.repeat('\n', emptyLines); + } + + // Literal style: just add exact number of line breaks between content lines. + } else { + // Keep all line breaks except the header line break. + state.result += common$3.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines); + } + + didReadContent = true; + detectedIndent = true; + emptyLines = 0; + captureStart = state.position; + + while (!is_EOL$1(ch) && (ch !== 0)) { + ch = state.input.charCodeAt(++state.position); + } + + captureSegment$1(state, captureStart, state.position, false); + } + + return true; +} + +function readBlockSequence$1(state, nodeIndent) { + var _line, + _tag = state.tag, + _anchor = state.anchor, + _result = [], + following, + detected = false, + ch; + + // there is a leading tab before this token, so it can't be a block sequence/mapping; + // it can still be flow sequence/mapping or a scalar + if (state.firstTabInLine !== -1) return false; + + if (state.anchor !== null) { + state.anchorMap[state.anchor] = _result; + } + + ch = state.input.charCodeAt(state.position); + + while (ch !== 0) { + if (state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError$2(state, 'tab characters must not be used in indentation'); + } + + if (ch !== 0x2D/* - */) { + break; + } + + following = state.input.charCodeAt(state.position + 1); + + if (!is_WS_OR_EOL$1(following)) { + break; + } + + detected = true; + state.position++; + + if (skipSeparationSpace$1(state, true, -1)) { + if (state.lineIndent <= nodeIndent) { + _result.push(null); + ch = state.input.charCodeAt(state.position); + continue; + } + } + + _line = state.line; + composeNode$1(state, nodeIndent, CONTEXT_BLOCK_IN$1, false, true); + _result.push(state.result); + skipSeparationSpace$1(state, true, -1); + + ch = state.input.charCodeAt(state.position); + + if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) { + throwError$2(state, 'bad indentation of a sequence entry'); + } else if (state.lineIndent < nodeIndent) { + break; + } + } + + if (detected) { + state.tag = _tag; + state.anchor = _anchor; + state.kind = 'sequence'; + state.result = _result; + return true; + } + return false; +} + +function readBlockMapping$1(state, nodeIndent, flowIndent) { + var following, + allowCompact, + _line, + _keyLine, + _keyLineStart, + _keyPos, + _tag = state.tag, + _anchor = state.anchor, + _result = {}, + overridableKeys = Object.create(null), + keyTag = null, + keyNode = null, + valueNode = null, + atExplicitKey = false, + detected = false, + ch; + + // there is a leading tab before this token, so it can't be a block sequence/mapping; + // it can still be flow sequence/mapping or a scalar + if (state.firstTabInLine !== -1) return false; + + if (state.anchor !== null) { + state.anchorMap[state.anchor] = _result; + } + + ch = state.input.charCodeAt(state.position); + + while (ch !== 0) { + if (!atExplicitKey && state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError$2(state, 'tab characters must not be used in indentation'); + } + + following = state.input.charCodeAt(state.position + 1); + _line = state.line; // Save the current line. + + // + // Explicit notation case. There are two separate blocks: + // first for the key (denoted by "?") and second for the value (denoted by ":") + // + if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && is_WS_OR_EOL$1(following)) { + + if (ch === 0x3F/* ? */) { + if (atExplicitKey) { + storeMappingPair$1(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos); + keyTag = keyNode = valueNode = null; + } + + detected = true; + atExplicitKey = true; + allowCompact = true; + + } else if (atExplicitKey) { + // i.e. 0x3A/* : */ === character after the explicit key. + atExplicitKey = false; + allowCompact = true; + + } else { + throwError$2(state, 'incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line'); + } + + state.position += 1; + ch = following; + + // + // Implicit notation case. Flow-style node as the key first, then ":", and the value. + // + } else { + _keyLine = state.line; + _keyLineStart = state.lineStart; + _keyPos = state.position; + + if (!composeNode$1(state, flowIndent, CONTEXT_FLOW_OUT$1, false, true)) { + // Neither implicit nor explicit notation. + // Reading is done. Go to the epilogue. + break; + } + + if (state.line === _line) { + ch = state.input.charCodeAt(state.position); + + while (is_WHITE_SPACE$1(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (ch === 0x3A/* : */) { + ch = state.input.charCodeAt(++state.position); + + if (!is_WS_OR_EOL$1(ch)) { + throwError$2(state, 'a whitespace character is expected after the key-value separator within a block mapping'); + } + + if (atExplicitKey) { + storeMappingPair$1(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos); + keyTag = keyNode = valueNode = null; + } + + detected = true; + atExplicitKey = false; + allowCompact = false; + keyTag = state.tag; + keyNode = state.result; + + } else if (detected) { + throwError$2(state, 'can not read an implicit mapping pair; a colon is missed'); + + } else { + state.tag = _tag; + state.anchor = _anchor; + return true; // Keep the result of `composeNode`. + } + + } else if (detected) { + throwError$2(state, 'can not read a block mapping entry; a multiline key may not be an implicit key'); + + } else { + state.tag = _tag; + state.anchor = _anchor; + return true; // Keep the result of `composeNode`. + } + } + + // + // Common reading code for both explicit and implicit notations. + // + if (state.line === _line || state.lineIndent > nodeIndent) { + if (atExplicitKey) { + _keyLine = state.line; + _keyLineStart = state.lineStart; + _keyPos = state.position; + } + + if (composeNode$1(state, nodeIndent, CONTEXT_BLOCK_OUT$1, true, allowCompact)) { + if (atExplicitKey) { + keyNode = state.result; + } else { + valueNode = state.result; + } + } + + if (!atExplicitKey) { + storeMappingPair$1(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos); + keyTag = keyNode = valueNode = null; + } + + skipSeparationSpace$1(state, true, -1); + ch = state.input.charCodeAt(state.position); + } + + if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) { + throwError$2(state, 'bad indentation of a mapping entry'); + } else if (state.lineIndent < nodeIndent) { + break; + } + } + + // + // Epilogue. + // + + // Special case: last mapping's node contains only the key in explicit notation. + if (atExplicitKey) { + storeMappingPair$1(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos); + } + + // Expose the resulting mapping. + if (detected) { + state.tag = _tag; + state.anchor = _anchor; + state.kind = 'mapping'; + state.result = _result; + } + + return detected; +} + +function readTagProperty$1(state) { + var _position, + isVerbatim = false, + isNamed = false, + tagHandle, + tagName, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x21/* ! */) return false; + + if (state.tag !== null) { + throwError$2(state, 'duplication of a tag property'); + } + + ch = state.input.charCodeAt(++state.position); + + if (ch === 0x3C/* < */) { + isVerbatim = true; + ch = state.input.charCodeAt(++state.position); + + } else if (ch === 0x21/* ! */) { + isNamed = true; + tagHandle = '!!'; + ch = state.input.charCodeAt(++state.position); + + } else { + tagHandle = '!'; + } + + _position = state.position; + + if (isVerbatim) { + do { ch = state.input.charCodeAt(++state.position); } + while (ch !== 0 && ch !== 0x3E/* > */); + + if (state.position < state.length) { + tagName = state.input.slice(_position, state.position); + ch = state.input.charCodeAt(++state.position); + } else { + throwError$2(state, 'unexpected end of the stream within a verbatim tag'); + } + } else { + while (ch !== 0 && !is_WS_OR_EOL$1(ch)) { + + if (ch === 0x21/* ! */) { + if (!isNamed) { + tagHandle = state.input.slice(_position - 1, state.position + 1); + + if (!PATTERN_TAG_HANDLE$1.test(tagHandle)) { + throwError$2(state, 'named tag handle cannot contain such characters'); + } + + isNamed = true; + _position = state.position + 1; + } else { + throwError$2(state, 'tag suffix cannot contain exclamation marks'); + } + } + + ch = state.input.charCodeAt(++state.position); + } + + tagName = state.input.slice(_position, state.position); + + if (PATTERN_FLOW_INDICATORS$1.test(tagName)) { + throwError$2(state, 'tag suffix cannot contain flow indicator characters'); + } + } + + if (tagName && !PATTERN_TAG_URI$1.test(tagName)) { + throwError$2(state, 'tag name cannot contain such characters: ' + tagName); + } + + try { + tagName = decodeURIComponent(tagName); + } catch (err) { + throwError$2(state, 'tag name is malformed: ' + tagName); + } + + if (isVerbatim) { + state.tag = tagName; + + } else if (_hasOwnProperty$6.call(state.tagMap, tagHandle)) { + state.tag = state.tagMap[tagHandle] + tagName; + + } else if (tagHandle === '!') { + state.tag = '!' + tagName; + + } else if (tagHandle === '!!') { + state.tag = 'tag:yaml.org,2002:' + tagName; + + } else { + throwError$2(state, 'undeclared tag handle "' + tagHandle + '"'); + } + + return true; +} + +function readAnchorProperty$1(state) { + var _position, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x26/* & */) return false; + + if (state.anchor !== null) { + throwError$2(state, 'duplication of an anchor property'); + } + + ch = state.input.charCodeAt(++state.position); + _position = state.position; + + while (ch !== 0 && !is_WS_OR_EOL$1(ch) && !is_FLOW_INDICATOR$1(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (state.position === _position) { + throwError$2(state, 'name of an anchor node must contain at least one character'); + } + + state.anchor = state.input.slice(_position, state.position); + return true; +} + +function readAlias$1(state) { + var _position, alias, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x2A/* * */) return false; + + ch = state.input.charCodeAt(++state.position); + _position = state.position; + + while (ch !== 0 && !is_WS_OR_EOL$1(ch) && !is_FLOW_INDICATOR$1(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (state.position === _position) { + throwError$2(state, 'name of an alias node must contain at least one character'); + } + + alias = state.input.slice(_position, state.position); + + if (!_hasOwnProperty$6.call(state.anchorMap, alias)) { + throwError$2(state, 'unidentified alias "' + alias + '"'); + } + + state.result = state.anchorMap[alias]; + skipSeparationSpace$1(state, true, -1); + return true; +} + +function composeNode$1(state, parentIndent, nodeContext, allowToSeek, allowCompact) { + var allowBlockStyles, + allowBlockScalars, + allowBlockCollections, + indentStatus = 1, // 1: this>parent, 0: this=parent, -1: this parentIndent) { + indentStatus = 1; + } else if (state.lineIndent === parentIndent) { + indentStatus = 0; + } else if (state.lineIndent < parentIndent) { + indentStatus = -1; + } + } + } + + if (indentStatus === 1) { + while (readTagProperty$1(state) || readAnchorProperty$1(state)) { + if (skipSeparationSpace$1(state, true, -1)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; + + if (state.lineIndent > parentIndent) { + indentStatus = 1; + } else if (state.lineIndent === parentIndent) { + indentStatus = 0; + } else if (state.lineIndent < parentIndent) { + indentStatus = -1; + } + } else { + allowBlockCollections = false; + } + } + } + + if (allowBlockCollections) { + allowBlockCollections = atNewLine || allowCompact; + } + + if (indentStatus === 1 || CONTEXT_BLOCK_OUT$1 === nodeContext) { + if (CONTEXT_FLOW_IN$1 === nodeContext || CONTEXT_FLOW_OUT$1 === nodeContext) { + flowIndent = parentIndent; + } else { + flowIndent = parentIndent + 1; + } + + blockIndent = state.position - state.lineStart; + + if (indentStatus === 1) { + if (allowBlockCollections && + (readBlockSequence$1(state, blockIndent) || + readBlockMapping$1(state, blockIndent, flowIndent)) || + readFlowCollection$1(state, flowIndent)) { + hasContent = true; + } else { + if ((allowBlockScalars && readBlockScalar$1(state, flowIndent)) || + readSingleQuotedScalar$1(state, flowIndent) || + readDoubleQuotedScalar$1(state, flowIndent)) { + hasContent = true; + + } else if (readAlias$1(state)) { + hasContent = true; + + if (state.tag !== null || state.anchor !== null) { + throwError$2(state, 'alias node should not have any properties'); + } + + } else if (readPlainScalar$1(state, flowIndent, CONTEXT_FLOW_IN$1 === nodeContext)) { + hasContent = true; + + if (state.tag === null) { + state.tag = '?'; + } + } + + if (state.anchor !== null) { + state.anchorMap[state.anchor] = state.result; + } + } + } else if (indentStatus === 0) { + // Special case: block sequences are allowed to have same indentation level as the parent. + // http://www.yaml.org/spec/1.2/spec.html#id2799784 + hasContent = allowBlockCollections && readBlockSequence$1(state, blockIndent); + } + } + + if (state.tag === null) { + if (state.anchor !== null) { + state.anchorMap[state.anchor] = state.result; + } + + } else if (state.tag === '?') { + // Implicit resolving is not allowed for non-scalar types, and '?' + // non-specific tag is only automatically assigned to plain scalars. + // + // We only need to check kind conformity in case user explicitly assigns '?' + // tag, for example like this: "! [0]" + // + if (state.result !== null && state.kind !== 'scalar') { + throwError$2(state, 'unacceptable node kind for ! tag; it should be "scalar", not "' + state.kind + '"'); + } + + for (typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) { + type = state.implicitTypes[typeIndex]; + + if (type.resolve(state.result)) { // `state.result` updated in resolver if matched + state.result = type.construct(state.result); + state.tag = type.tag; + if (state.anchor !== null) { + state.anchorMap[state.anchor] = state.result; + } + break; + } + } + } else if (state.tag !== '!') { + if (_hasOwnProperty$6.call(state.typeMap[state.kind || 'fallback'], state.tag)) { + type = state.typeMap[state.kind || 'fallback'][state.tag]; + } else { + // looking for multi type + type = null; + typeList = state.typeMap.multi[state.kind || 'fallback']; + + for (typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) { + if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) { + type = typeList[typeIndex]; + break; + } + } + } + + if (!type) { + throwError$2(state, 'unknown tag !<' + state.tag + '>'); + } + + if (state.result !== null && type.kind !== state.kind) { + throwError$2(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be "' + type.kind + '", not "' + state.kind + '"'); + } + + if (!type.resolve(state.result, state.tag)) { // `state.result` updated in resolver if matched + throwError$2(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag'); + } else { + state.result = type.construct(state.result, state.tag); + if (state.anchor !== null) { + state.anchorMap[state.anchor] = state.result; + } + } + } + + if (state.listener !== null) { + state.listener('close', state); + } + return state.tag !== null || state.anchor !== null || hasContent; +} + +function readDocument$1(state) { + var documentStart = state.position, + _position, + directiveName, + directiveArgs, + hasDirectives = false, + ch; + + state.version = null; + state.checkLineBreaks = state.legacy; + state.tagMap = Object.create(null); + state.anchorMap = Object.create(null); + + while ((ch = state.input.charCodeAt(state.position)) !== 0) { + skipSeparationSpace$1(state, true, -1); + + ch = state.input.charCodeAt(state.position); + + if (state.lineIndent > 0 || ch !== 0x25/* % */) { + break; + } + + hasDirectives = true; + ch = state.input.charCodeAt(++state.position); + _position = state.position; + + while (ch !== 0 && !is_WS_OR_EOL$1(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + directiveName = state.input.slice(_position, state.position); + directiveArgs = []; + + if (directiveName.length < 1) { + throwError$2(state, 'directive name must not be less than one character in length'); + } + + while (ch !== 0) { + while (is_WHITE_SPACE$1(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (ch === 0x23/* # */) { + do { ch = state.input.charCodeAt(++state.position); } + while (ch !== 0 && !is_EOL$1(ch)); + break; + } + + if (is_EOL$1(ch)) break; + + _position = state.position; + + while (ch !== 0 && !is_WS_OR_EOL$1(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + directiveArgs.push(state.input.slice(_position, state.position)); + } + + if (ch !== 0) readLineBreak$1(state); + + if (_hasOwnProperty$6.call(directiveHandlers$1, directiveName)) { + directiveHandlers$1[directiveName](state, directiveName, directiveArgs); + } else { + throwWarning$1(state, 'unknown document directive "' + directiveName + '"'); + } + } + + skipSeparationSpace$1(state, true, -1); + + if (state.lineIndent === 0 && + state.input.charCodeAt(state.position) === 0x2D/* - */ && + state.input.charCodeAt(state.position + 1) === 0x2D/* - */ && + state.input.charCodeAt(state.position + 2) === 0x2D/* - */) { + state.position += 3; + skipSeparationSpace$1(state, true, -1); + + } else if (hasDirectives) { + throwError$2(state, 'directives end mark is expected'); + } + + composeNode$1(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT$1, false, true); + skipSeparationSpace$1(state, true, -1); + + if (state.checkLineBreaks && + PATTERN_NON_ASCII_LINE_BREAKS$1.test(state.input.slice(documentStart, state.position))) { + throwWarning$1(state, 'non-ASCII line breaks are interpreted as content'); + } + + state.documents.push(state.result); + + if (state.position === state.lineStart && testDocumentSeparator$1(state)) { + + if (state.input.charCodeAt(state.position) === 0x2E/* . */) { + state.position += 3; + skipSeparationSpace$1(state, true, -1); + } + return; + } + + if (state.position < (state.length - 1)) { + throwError$2(state, 'end of the stream or a document separator is expected'); + } else { + return; + } +} + + +function loadDocuments$1(input, options) { + input = String(input); + options = options || {}; + + if (input.length !== 0) { + + // Add tailing `\n` if not exists + if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ && + input.charCodeAt(input.length - 1) !== 0x0D/* CR */) { + input += '\n'; + } + + // Strip BOM + if (input.charCodeAt(0) === 0xFEFF) { + input = input.slice(1); + } + } + + var state = new State$2(input, options); + + var nullpos = input.indexOf('\0'); + + if (nullpos !== -1) { + state.position = nullpos; + throwError$2(state, 'null byte is not allowed in input'); + } + + // Use 0 as string terminator. That significantly simplifies bounds check. + state.input += '\0'; + + while (state.input.charCodeAt(state.position) === 0x20/* Space */) { + state.lineIndent += 1; + state.position += 1; + } + + while (state.position < (state.length - 1)) { + readDocument$1(state); + } + + return state.documents; +} + + +function loadAll$2(input, iterator, options) { + if (iterator !== null && typeof iterator === 'object' && typeof options === 'undefined') { + options = iterator; + iterator = null; + } + + var documents = loadDocuments$1(input, options); + + if (typeof iterator !== 'function') { + return documents; + } + + for (var index = 0, length = documents.length; index < length; index += 1) { + iterator(documents[index]); + } +} + + +function load$3(input, options) { + var documents = loadDocuments$1(input, options); + + if (documents.length === 0) { + /*eslint-disable no-undefined*/ + return undefined; + } else if (documents.length === 1) { + return documents[0]; + } + throw new exception$1('expected a single document in the stream, but found more'); +} + + +var loadAll_1$1 = loadAll$2; +var load_1$1 = load$3; + +var loader$1 = { + loadAll: loadAll_1$1, + load: load_1$1 +}; + +/*eslint-disable no-use-before-define*/ + + + + + +var _toString$5 = Object.prototype.toString; +var _hasOwnProperty$7 = Object.prototype.hasOwnProperty; + +var CHAR_BOM = 0xFEFF; +var CHAR_TAB$1 = 0x09; /* Tab */ +var CHAR_LINE_FEED$1 = 0x0A; /* LF */ +var CHAR_CARRIAGE_RETURN$1 = 0x0D; /* CR */ +var CHAR_SPACE$1 = 0x20; /* Space */ +var CHAR_EXCLAMATION$1 = 0x21; /* ! */ +var CHAR_DOUBLE_QUOTE$2 = 0x22; /* " */ +var CHAR_SHARP$1 = 0x23; /* # */ +var CHAR_PERCENT$1 = 0x25; /* % */ +var CHAR_AMPERSAND$1 = 0x26; /* & */ +var CHAR_SINGLE_QUOTE$2 = 0x27; /* ' */ +var CHAR_ASTERISK$2 = 0x2A; /* * */ +var CHAR_COMMA$3 = 0x2C; /* , */ +var CHAR_MINUS$1 = 0x2D; /* - */ +var CHAR_COLON$1 = 0x3A; /* : */ +var CHAR_EQUALS$1 = 0x3D; /* = */ +var CHAR_GREATER_THAN$1 = 0x3E; /* > */ +var CHAR_QUESTION$1 = 0x3F; /* ? */ +var CHAR_COMMERCIAL_AT$1 = 0x40; /* @ */ +var CHAR_LEFT_SQUARE_BRACKET$3 = 0x5B; /* [ */ +var CHAR_RIGHT_SQUARE_BRACKET$3 = 0x5D; /* ] */ +var CHAR_GRAVE_ACCENT$1 = 0x60; /* ` */ +var CHAR_LEFT_CURLY_BRACKET$1 = 0x7B; /* { */ +var CHAR_VERTICAL_LINE$1 = 0x7C; /* | */ +var CHAR_RIGHT_CURLY_BRACKET$1 = 0x7D; /* } */ + +var ESCAPE_SEQUENCES$1 = {}; + +ESCAPE_SEQUENCES$1[0x00] = '\\0'; +ESCAPE_SEQUENCES$1[0x07] = '\\a'; +ESCAPE_SEQUENCES$1[0x08] = '\\b'; +ESCAPE_SEQUENCES$1[0x09] = '\\t'; +ESCAPE_SEQUENCES$1[0x0A] = '\\n'; +ESCAPE_SEQUENCES$1[0x0B] = '\\v'; +ESCAPE_SEQUENCES$1[0x0C] = '\\f'; +ESCAPE_SEQUENCES$1[0x0D] = '\\r'; +ESCAPE_SEQUENCES$1[0x1B] = '\\e'; +ESCAPE_SEQUENCES$1[0x22] = '\\"'; +ESCAPE_SEQUENCES$1[0x5C] = '\\\\'; +ESCAPE_SEQUENCES$1[0x85] = '\\N'; +ESCAPE_SEQUENCES$1[0xA0] = '\\_'; +ESCAPE_SEQUENCES$1[0x2028] = '\\L'; +ESCAPE_SEQUENCES$1[0x2029] = '\\P'; + +var DEPRECATED_BOOLEANS_SYNTAX$1 = [ + 'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON', + 'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF' +]; + +var DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/; + +function compileStyleMap$1(schema, map) { + var result, keys, index, length, tag, style, type; + + if (map === null) return {}; + + result = {}; + keys = Object.keys(map); + + for (index = 0, length = keys.length; index < length; index += 1) { + tag = keys[index]; + style = String(map[tag]); + + if (tag.slice(0, 2) === '!!') { + tag = 'tag:yaml.org,2002:' + tag.slice(2); + } + type = schema.compiledTypeMap['fallback'][tag]; + + if (type && _hasOwnProperty$7.call(type.styleAliases, style)) { + style = type.styleAliases[style]; + } + + result[tag] = style; + } + + return result; +} + +function encodeHex$1(character) { + var string, handle, length; + + string = character.toString(16).toUpperCase(); + + if (character <= 0xFF) { + handle = 'x'; + length = 2; + } else if (character <= 0xFFFF) { + handle = 'u'; + length = 4; + } else if (character <= 0xFFFFFFFF) { + handle = 'U'; + length = 8; + } else { + throw new exception$1('code point within a string may not be greater than 0xFFFFFFFF'); + } + + return '\\' + handle + common$3.repeat('0', length - string.length) + string; +} + + +var QUOTING_TYPE_SINGLE = 1, + QUOTING_TYPE_DOUBLE = 2; + +function State$3(options) { + this.schema = options['schema'] || _default$8; + this.indent = Math.max(1, (options['indent'] || 2)); + this.noArrayIndent = options['noArrayIndent'] || false; + this.skipInvalid = options['skipInvalid'] || false; + this.flowLevel = (common$3.isNothing(options['flowLevel']) ? -1 : options['flowLevel']); + this.styleMap = compileStyleMap$1(this.schema, options['styles'] || null); + this.sortKeys = options['sortKeys'] || false; + this.lineWidth = options['lineWidth'] || 80; + this.noRefs = options['noRefs'] || false; + this.noCompatMode = options['noCompatMode'] || false; + this.condenseFlow = options['condenseFlow'] || false; + this.quotingType = options['quotingType'] === '"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE; + this.forceQuotes = options['forceQuotes'] || false; + this.replacer = typeof options['replacer'] === 'function' ? options['replacer'] : null; + + this.implicitTypes = this.schema.compiledImplicit; + this.explicitTypes = this.schema.compiledExplicit; + + this.tag = null; + this.result = ''; + + this.duplicates = []; + this.usedDuplicates = null; +} + +// Indents every line in a string. Empty lines (\n only) are not indented. +function indentString$1(string, spaces) { + var ind = common$3.repeat(' ', spaces), + position = 0, + next = -1, + result = '', + line, + length = string.length; + + while (position < length) { + next = string.indexOf('\n', position); + if (next === -1) { + line = string.slice(position); + position = length; + } else { + line = string.slice(position, next + 1); + position = next + 1; + } + + if (line.length && line !== '\n') result += ind; + + result += line; + } + + return result; +} + +function generateNextLine$1(state, level) { + return '\n' + common$3.repeat(' ', state.indent * level); +} + +function testImplicitResolving$1(state, str) { + var index, length, type; + + for (index = 0, length = state.implicitTypes.length; index < length; index += 1) { + type = state.implicitTypes[index]; + + if (type.resolve(str)) { + return true; + } + } + + return false; +} + +// [33] s-white ::= s-space | s-tab +function isWhitespace$1(c) { + return c === CHAR_SPACE$1 || c === CHAR_TAB$1; +} + +// Returns true if the character can be printed without escaping. +// From YAML 1.2: "any allowed characters known to be non-printable +// should also be escaped. [However,] This isn’t mandatory" +// Derived from nb-char - \t - #x85 - #xA0 - #x2028 - #x2029. +function isPrintable$1(c) { + return (0x00020 <= c && c <= 0x00007E) + || ((0x000A1 <= c && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029) + || ((0x0E000 <= c && c <= 0x00FFFD) && c !== CHAR_BOM) + || (0x10000 <= c && c <= 0x10FFFF); +} + +// [34] ns-char ::= nb-char - s-white +// [27] nb-char ::= c-printable - b-char - c-byte-order-mark +// [26] b-char ::= b-line-feed | b-carriage-return +// Including s-white (for some reason, examples doesn't match specs in this aspect) +// ns-char ::= c-printable - b-line-feed - b-carriage-return - c-byte-order-mark +function isNsCharOrWhitespace(c) { + return isPrintable$1(c) + && c !== CHAR_BOM + // - b-char + && c !== CHAR_CARRIAGE_RETURN$1 + && c !== CHAR_LINE_FEED$1; +} + +// [127] ns-plain-safe(c) ::= c = flow-out ⇒ ns-plain-safe-out +// c = flow-in ⇒ ns-plain-safe-in +// c = block-key ⇒ ns-plain-safe-out +// c = flow-key ⇒ ns-plain-safe-in +// [128] ns-plain-safe-out ::= ns-char +// [129] ns-plain-safe-in ::= ns-char - c-flow-indicator +// [130] ns-plain-char(c) ::= ( ns-plain-safe(c) - “:” - “#” ) +// | ( /* An ns-char preceding */ “#” ) +// | ( “:” /* Followed by an ns-plain-safe(c) */ ) +function isPlainSafe$1(c, prev, inblock) { + var cIsNsCharOrWhitespace = isNsCharOrWhitespace(c); + var cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace$1(c); + return ( + // ns-plain-safe + inblock ? // c = flow-in + cIsNsCharOrWhitespace + : cIsNsCharOrWhitespace + // - c-flow-indicator + && c !== CHAR_COMMA$3 + && c !== CHAR_LEFT_SQUARE_BRACKET$3 + && c !== CHAR_RIGHT_SQUARE_BRACKET$3 + && c !== CHAR_LEFT_CURLY_BRACKET$1 + && c !== CHAR_RIGHT_CURLY_BRACKET$1 + ) + // ns-plain-char + && c !== CHAR_SHARP$1 // false on '#' + && !(prev === CHAR_COLON$1 && !cIsNsChar) // false on ': ' + || (isNsCharOrWhitespace(prev) && !isWhitespace$1(prev) && c === CHAR_SHARP$1) // change to true on '[^ ]#' + || (prev === CHAR_COLON$1 && cIsNsChar); // change to true on ':[^ ]' +} + +// Simplified test for values allowed as the first character in plain style. +function isPlainSafeFirst$1(c) { + // Uses a subset of ns-char - c-indicator + // where ns-char = nb-char - s-white. + // No support of ( ( “?” | “:” | “-” ) /* Followed by an ns-plain-safe(c)) */ ) part + return isPrintable$1(c) && c !== CHAR_BOM + && !isWhitespace$1(c) // - s-white + // - (c-indicator ::= + // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}” + && c !== CHAR_MINUS$1 + && c !== CHAR_QUESTION$1 + && c !== CHAR_COLON$1 + && c !== CHAR_COMMA$3 + && c !== CHAR_LEFT_SQUARE_BRACKET$3 + && c !== CHAR_RIGHT_SQUARE_BRACKET$3 + && c !== CHAR_LEFT_CURLY_BRACKET$1 + && c !== CHAR_RIGHT_CURLY_BRACKET$1 + // | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “"” + && c !== CHAR_SHARP$1 + && c !== CHAR_AMPERSAND$1 + && c !== CHAR_ASTERISK$2 + && c !== CHAR_EXCLAMATION$1 + && c !== CHAR_VERTICAL_LINE$1 + && c !== CHAR_EQUALS$1 + && c !== CHAR_GREATER_THAN$1 + && c !== CHAR_SINGLE_QUOTE$2 + && c !== CHAR_DOUBLE_QUOTE$2 + // | “%” | “@” | “`”) + && c !== CHAR_PERCENT$1 + && c !== CHAR_COMMERCIAL_AT$1 + && c !== CHAR_GRAVE_ACCENT$1; +} + +// Simplified test for values allowed as the last character in plain style. +function isPlainSafeLast(c) { + // just not whitespace or colon, it will be checked to be plain character later + return !isWhitespace$1(c) && c !== CHAR_COLON$1; +} + +// Same as 'string'.codePointAt(pos), but works in older browsers. +function codePointAt(string, pos) { + var first = string.charCodeAt(pos), second; + if (first >= 0xD800 && first <= 0xDBFF && pos + 1 < string.length) { + second = string.charCodeAt(pos + 1); + if (second >= 0xDC00 && second <= 0xDFFF) { + // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000; + } + } + return first; +} + +// Determines whether block indentation indicator is required. +function needIndentIndicator$1(string) { + var leadingSpaceRe = /^\n* /; + return leadingSpaceRe.test(string); +} + +var STYLE_PLAIN$1 = 1, + STYLE_SINGLE$1 = 2, + STYLE_LITERAL$1 = 3, + STYLE_FOLDED$1 = 4, + STYLE_DOUBLE$1 = 5; + +// Determines which scalar styles are possible and returns the preferred style. +// lineWidth = -1 => no limit. +// Pre-conditions: str.length > 0. +// Post-conditions: +// STYLE_PLAIN or STYLE_SINGLE => no \n are in the string. +// STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1). +// STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1). +function chooseScalarStyle$1(string, singleLineOnly, indentPerLevel, lineWidth, + testAmbiguousType, quotingType, forceQuotes, inblock) { + + var i; + var char = 0; + var prevChar = null; + var hasLineBreak = false; + var hasFoldableLine = false; // only checked if shouldTrackWidth + var shouldTrackWidth = lineWidth !== -1; + var previousLineBreak = -1; // count the first line correctly + var plain = isPlainSafeFirst$1(codePointAt(string, 0)) + && isPlainSafeLast(codePointAt(string, string.length - 1)); + + if (singleLineOnly || forceQuotes) { + // Case: no block styles. + // Check for disallowed characters to rule out plain and single. + for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) { + char = codePointAt(string, i); + if (!isPrintable$1(char)) { + return STYLE_DOUBLE$1; + } + plain = plain && isPlainSafe$1(char, prevChar, inblock); + prevChar = char; + } + } else { + // Case: block styles permitted. + for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) { + char = codePointAt(string, i); + if (char === CHAR_LINE_FEED$1) { + hasLineBreak = true; + // Check if any line can be folded. + if (shouldTrackWidth) { + hasFoldableLine = hasFoldableLine || + // Foldable line = too long, and not more-indented. + (i - previousLineBreak - 1 > lineWidth && + string[previousLineBreak + 1] !== ' '); + previousLineBreak = i; + } + } else if (!isPrintable$1(char)) { + return STYLE_DOUBLE$1; + } + plain = plain && isPlainSafe$1(char, prevChar, inblock); + prevChar = char; + } + // in case the end is missing a \n + hasFoldableLine = hasFoldableLine || (shouldTrackWidth && + (i - previousLineBreak - 1 > lineWidth && + string[previousLineBreak + 1] !== ' ')); + } + // Although every style can represent \n without escaping, prefer block styles + // for multiline, since they're more readable and they don't add empty lines. + // Also prefer folding a super-long line. + if (!hasLineBreak && !hasFoldableLine) { + // Strings interpretable as another type have to be quoted; + // e.g. the string 'true' vs. the boolean true. + if (plain && !forceQuotes && !testAmbiguousType(string)) { + return STYLE_PLAIN$1; + } + return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE$1 : STYLE_SINGLE$1; + } + // Edge case: block indentation indicator can only have one digit. + if (indentPerLevel > 9 && needIndentIndicator$1(string)) { + return STYLE_DOUBLE$1; + } + // At this point we know block styles are valid. + // Prefer literal style unless we want to fold. + if (!forceQuotes) { + return hasFoldableLine ? STYLE_FOLDED$1 : STYLE_LITERAL$1; + } + return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE$1 : STYLE_SINGLE$1; +} + +// Note: line breaking/folding is implemented for only the folded style. +// NB. We drop the last trailing newline (if any) of a returned block scalar +// since the dumper adds its own newline. This always works: +// • No ending newline => unaffected; already using strip "-" chomping. +// • Ending newline => removed then restored. +// Importantly, this keeps the "+" chomp indicator from gaining an extra line. +function writeScalar$1(state, string, level, iskey, inblock) { + state.dump = (function () { + if (string.length === 0) { + return state.quotingType === QUOTING_TYPE_DOUBLE ? '""' : "''"; + } + if (!state.noCompatMode) { + if (DEPRECATED_BOOLEANS_SYNTAX$1.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) { + return state.quotingType === QUOTING_TYPE_DOUBLE ? ('"' + string + '"') : ("'" + string + "'"); + } + } + + var indent = state.indent * Math.max(1, level); // no 0-indent scalars + // As indentation gets deeper, let the width decrease monotonically + // to the lower bound min(state.lineWidth, 40). + // Note that this implies + // state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound. + // state.lineWidth > 40 + state.indent: width decreases until the lower bound. + // This behaves better than a constant minimum width which disallows narrower options, + // or an indent threshold which causes the width to suddenly increase. + var lineWidth = state.lineWidth === -1 + ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent); + + // Without knowing if keys are implicit/explicit, assume implicit for safety. + var singleLineOnly = iskey + // No block styles in flow mode. + || (state.flowLevel > -1 && level >= state.flowLevel); + function testAmbiguity(string) { + return testImplicitResolving$1(state, string); + } + + switch (chooseScalarStyle$1(string, singleLineOnly, state.indent, lineWidth, + testAmbiguity, state.quotingType, state.forceQuotes && !iskey, inblock)) { + + case STYLE_PLAIN$1: + return string; + case STYLE_SINGLE$1: + return "'" + string.replace(/'/g, "''") + "'"; + case STYLE_LITERAL$1: + return '|' + blockHeader$1(string, state.indent) + + dropEndingNewline$1(indentString$1(string, indent)); + case STYLE_FOLDED$1: + return '>' + blockHeader$1(string, state.indent) + + dropEndingNewline$1(indentString$1(foldString$1(string, lineWidth), indent)); + case STYLE_DOUBLE$1: + return '"' + escapeString$1(string) + '"'; + default: + throw new exception$1('impossible error: invalid scalar style'); + } + }()); +} + +// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9. +function blockHeader$1(string, indentPerLevel) { + var indentIndicator = needIndentIndicator$1(string) ? String(indentPerLevel) : ''; + + // note the special case: the string '\n' counts as a "trailing" empty line. + var clip = string[string.length - 1] === '\n'; + var keep = clip && (string[string.length - 2] === '\n' || string === '\n'); + var chomp = keep ? '+' : (clip ? '' : '-'); + + return indentIndicator + chomp + '\n'; +} + +// (See the note for writeScalar.) +function dropEndingNewline$1(string) { + return string[string.length - 1] === '\n' ? string.slice(0, -1) : string; +} + +// Note: a long line without a suitable break point will exceed the width limit. +// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0. +function foldString$1(string, width) { + // In folded style, $k$ consecutive newlines output as $k+1$ newlines— + // unless they're before or after a more-indented line, or at the very + // beginning or end, in which case $k$ maps to $k$. + // Therefore, parse each chunk as newline(s) followed by a content line. + var lineRe = /(\n+)([^\n]*)/g; + + // first line (possibly an empty line) + var result = (function () { + var nextLF = string.indexOf('\n'); + nextLF = nextLF !== -1 ? nextLF : string.length; + lineRe.lastIndex = nextLF; + return foldLine$1(string.slice(0, nextLF), width); + }()); + // If we haven't reached the first content line yet, don't add an extra \n. + var prevMoreIndented = string[0] === '\n' || string[0] === ' '; + var moreIndented; + + // rest of the lines + var match; + while ((match = lineRe.exec(string))) { + var prefix = match[1], line = match[2]; + moreIndented = (line[0] === ' '); + result += prefix + + (!prevMoreIndented && !moreIndented && line !== '' + ? '\n' : '') + + foldLine$1(line, width); + prevMoreIndented = moreIndented; + } + + return result; +} + +// Greedy line breaking. +// Picks the longest line under the limit each time, +// otherwise settles for the shortest line over the limit. +// NB. More-indented lines *cannot* be folded, as that would add an extra \n. +function foldLine$1(line, width) { + if (line === '' || line[0] === ' ') return line; + + // Since a more-indented line adds a \n, breaks can't be followed by a space. + var breakRe = / [^ ]/g; // note: the match index will always be <= length-2. + var match; + // start is an inclusive index. end, curr, and next are exclusive. + var start = 0, end, curr = 0, next = 0; + var result = ''; + + // Invariants: 0 <= start <= length-1. + // 0 <= curr <= next <= max(0, length-2). curr - start <= width. + // Inside the loop: + // A match implies length >= 2, so curr and next are <= length-2. + while ((match = breakRe.exec(line))) { + next = match.index; + // maintain invariant: curr - start <= width + if (next - start > width) { + end = (curr > start) ? curr : next; // derive end <= length-2 + result += '\n' + line.slice(start, end); + // skip the space that was output as \n + start = end + 1; // derive start <= length-1 + } + curr = next; + } + + // By the invariants, start <= length-1, so there is something left over. + // It is either the whole string or a part starting from non-whitespace. + result += '\n'; + // Insert a break if the remainder is too long and there is a break available. + if (line.length - start > width && curr > start) { + result += line.slice(start, curr) + '\n' + line.slice(curr + 1); + } else { + result += line.slice(start); + } + + return result.slice(1); // drop extra \n joiner +} + +// Escapes a double-quoted string. +function escapeString$1(string) { + var result = ''; + var char = 0; + var escapeSeq; + + for (var i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) { + char = codePointAt(string, i); + escapeSeq = ESCAPE_SEQUENCES$1[char]; + + if (!escapeSeq && isPrintable$1(char)) { + result += string[i]; + if (char >= 0x10000) result += string[i + 1]; + } else { + result += escapeSeq || encodeHex$1(char); + } + } + + return result; +} + +function writeFlowSequence$1(state, level, object) { + var _result = '', + _tag = state.tag, + index, + length, + value; + + for (index = 0, length = object.length; index < length; index += 1) { + value = object[index]; + + if (state.replacer) { + value = state.replacer.call(object, String(index), value); + } + + // Write only valid elements, put null instead of invalid elements. + if (writeNode$1(state, level, value, false, false) || + (typeof value === 'undefined' && + writeNode$1(state, level, null, false, false))) { + + if (_result !== '') _result += ',' + (!state.condenseFlow ? ' ' : ''); + _result += state.dump; + } + } + + state.tag = _tag; + state.dump = '[' + _result + ']'; +} + +function writeBlockSequence$1(state, level, object, compact) { + var _result = '', + _tag = state.tag, + index, + length, + value; + + for (index = 0, length = object.length; index < length; index += 1) { + value = object[index]; + + if (state.replacer) { + value = state.replacer.call(object, String(index), value); + } + + // Write only valid elements, put null instead of invalid elements. + if (writeNode$1(state, level + 1, value, true, true, false, true) || + (typeof value === 'undefined' && + writeNode$1(state, level + 1, null, true, true, false, true))) { + + if (!compact || _result !== '') { + _result += generateNextLine$1(state, level); + } + + if (state.dump && CHAR_LINE_FEED$1 === state.dump.charCodeAt(0)) { + _result += '-'; + } else { + _result += '- '; + } + + _result += state.dump; + } + } + + state.tag = _tag; + state.dump = _result || '[]'; // Empty sequence if no valid values. +} + +function writeFlowMapping$1(state, level, object) { + var _result = '', + _tag = state.tag, + objectKeyList = Object.keys(object), + index, + length, + objectKey, + objectValue, + pairBuffer; + + for (index = 0, length = objectKeyList.length; index < length; index += 1) { + + pairBuffer = ''; + if (_result !== '') pairBuffer += ', '; + + if (state.condenseFlow) pairBuffer += '"'; + + objectKey = objectKeyList[index]; + objectValue = object[objectKey]; + + if (state.replacer) { + objectValue = state.replacer.call(object, objectKey, objectValue); + } + + if (!writeNode$1(state, level, objectKey, false, false)) { + continue; // Skip this pair because of invalid key; + } + + if (state.dump.length > 1024) pairBuffer += '? '; + + pairBuffer += state.dump + (state.condenseFlow ? '"' : '') + ':' + (state.condenseFlow ? '' : ' '); + + if (!writeNode$1(state, level, objectValue, false, false)) { + continue; // Skip this pair because of invalid value. + } + + pairBuffer += state.dump; + + // Both key and value are valid. + _result += pairBuffer; + } + + state.tag = _tag; + state.dump = '{' + _result + '}'; +} + +function writeBlockMapping$1(state, level, object, compact) { + var _result = '', + _tag = state.tag, + objectKeyList = Object.keys(object), + index, + length, + objectKey, + objectValue, + explicitPair, + pairBuffer; + + // Allow sorting keys so that the output file is deterministic + if (state.sortKeys === true) { + // Default sorting + objectKeyList.sort(); + } else if (typeof state.sortKeys === 'function') { + // Custom sort function + objectKeyList.sort(state.sortKeys); + } else if (state.sortKeys) { + // Something is wrong + throw new exception$1('sortKeys must be a boolean or a function'); + } + + for (index = 0, length = objectKeyList.length; index < length; index += 1) { + pairBuffer = ''; + + if (!compact || _result !== '') { + pairBuffer += generateNextLine$1(state, level); + } + + objectKey = objectKeyList[index]; + objectValue = object[objectKey]; + + if (state.replacer) { + objectValue = state.replacer.call(object, objectKey, objectValue); + } + + if (!writeNode$1(state, level + 1, objectKey, true, true, true)) { + continue; // Skip this pair because of invalid key. + } + + explicitPair = (state.tag !== null && state.tag !== '?') || + (state.dump && state.dump.length > 1024); + + if (explicitPair) { + if (state.dump && CHAR_LINE_FEED$1 === state.dump.charCodeAt(0)) { + pairBuffer += '?'; + } else { + pairBuffer += '? '; + } + } + + pairBuffer += state.dump; + + if (explicitPair) { + pairBuffer += generateNextLine$1(state, level); + } + + if (!writeNode$1(state, level + 1, objectValue, true, explicitPair)) { + continue; // Skip this pair because of invalid value. + } + + if (state.dump && CHAR_LINE_FEED$1 === state.dump.charCodeAt(0)) { + pairBuffer += ':'; + } else { + pairBuffer += ': '; + } + + pairBuffer += state.dump; + + // Both key and value are valid. + _result += pairBuffer; + } + + state.tag = _tag; + state.dump = _result || '{}'; // Empty mapping if no valid pairs. +} + +function detectType$1(state, object, explicit) { + var _result, typeList, index, length, type, style; + + typeList = explicit ? state.explicitTypes : state.implicitTypes; + + for (index = 0, length = typeList.length; index < length; index += 1) { + type = typeList[index]; + + if ((type.instanceOf || type.predicate) && + (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) && + (!type.predicate || type.predicate(object))) { + + if (explicit) { + if (type.multi && type.representName) { + state.tag = type.representName(object); + } else { + state.tag = type.tag; + } + } else { + state.tag = '?'; + } + + if (type.represent) { + style = state.styleMap[type.tag] || type.defaultStyle; + + if (_toString$5.call(type.represent) === '[object Function]') { + _result = type.represent(object, style); + } else if (_hasOwnProperty$7.call(type.represent, style)) { + _result = type.represent[style](object, style); + } else { + throw new exception$1('!<' + type.tag + '> tag resolver accepts not "' + style + '" style'); + } + + state.dump = _result; + } + + return true; + } + } + + return false; +} + +// Serializes `object` and writes it to global `result`. +// Returns true on success, or false on invalid object. +// +function writeNode$1(state, level, object, block, compact, iskey, isblockseq) { + state.tag = null; + state.dump = object; + + if (!detectType$1(state, object, false)) { + detectType$1(state, object, true); + } + + var type = _toString$5.call(state.dump); + var inblock = block; + var tagStr; + + if (block) { + block = (state.flowLevel < 0 || state.flowLevel > level); + } + + var objectOrArray = type === '[object Object]' || type === '[object Array]', + duplicateIndex, + duplicate; + + if (objectOrArray) { + duplicateIndex = state.duplicates.indexOf(object); + duplicate = duplicateIndex !== -1; + } + + if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) { + compact = false; + } + + if (duplicate && state.usedDuplicates[duplicateIndex]) { + state.dump = '*ref_' + duplicateIndex; + } else { + if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) { + state.usedDuplicates[duplicateIndex] = true; + } + if (type === '[object Object]') { + if (block && (Object.keys(state.dump).length !== 0)) { + writeBlockMapping$1(state, level, state.dump, compact); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + state.dump; + } + } else { + writeFlowMapping$1(state, level, state.dump); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + ' ' + state.dump; + } + } + } else if (type === '[object Array]') { + if (block && (state.dump.length !== 0)) { + if (state.noArrayIndent && !isblockseq && level > 0) { + writeBlockSequence$1(state, level - 1, state.dump, compact); + } else { + writeBlockSequence$1(state, level, state.dump, compact); + } + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + state.dump; + } + } else { + writeFlowSequence$1(state, level, state.dump); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + ' ' + state.dump; + } + } + } else if (type === '[object String]') { + if (state.tag !== '?') { + writeScalar$1(state, state.dump, level, iskey, inblock); + } + } else if (type === '[object Undefined]') { + return false; + } else { + if (state.skipInvalid) return false; + throw new exception$1('unacceptable kind of an object to dump ' + type); + } + + if (state.tag !== null && state.tag !== '?') { + // Need to encode all characters except those allowed by the spec: + // + // [35] ns-dec-digit ::= [#x30-#x39] /* 0-9 */ + // [36] ns-hex-digit ::= ns-dec-digit + // | [#x41-#x46] /* A-F */ | [#x61-#x66] /* a-f */ + // [37] ns-ascii-letter ::= [#x41-#x5A] /* A-Z */ | [#x61-#x7A] /* a-z */ + // [38] ns-word-char ::= ns-dec-digit | ns-ascii-letter | “-” + // [39] ns-uri-char ::= “%” ns-hex-digit ns-hex-digit | ns-word-char | “#” + // | “;” | “/” | “?” | “:” | “@” | “&” | “=” | “+” | “$” | “,” + // | “_” | “.” | “!” | “~” | “*” | “'” | “(” | “)” | “[” | “]” + // + // Also need to encode '!' because it has special meaning (end of tag prefix). + // + tagStr = encodeURI( + state.tag[0] === '!' ? state.tag.slice(1) : state.tag + ).replace(/!/g, '%21'); + + if (state.tag[0] === '!') { + tagStr = '!' + tagStr; + } else if (tagStr.slice(0, 18) === 'tag:yaml.org,2002:') { + tagStr = '!!' + tagStr.slice(18); + } else { + tagStr = '!<' + tagStr + '>'; + } + + state.dump = tagStr + ' ' + state.dump; + } + } + + return true; +} + +function getDuplicateReferences$1(object, state) { + var objects = [], + duplicatesIndexes = [], + index, + length; + + inspectNode$1(object, objects, duplicatesIndexes); + + for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) { + state.duplicates.push(objects[duplicatesIndexes[index]]); + } + state.usedDuplicates = new Array(length); +} + +function inspectNode$1(object, objects, duplicatesIndexes) { + var objectKeyList, + index, + length; + + if (object !== null && typeof object === 'object') { + index = objects.indexOf(object); + if (index !== -1) { + if (duplicatesIndexes.indexOf(index) === -1) { + duplicatesIndexes.push(index); + } + } else { + objects.push(object); + + if (Array.isArray(object)) { + for (index = 0, length = object.length; index < length; index += 1) { + inspectNode$1(object[index], objects, duplicatesIndexes); + } + } else { + objectKeyList = Object.keys(object); + + for (index = 0, length = objectKeyList.length; index < length; index += 1) { + inspectNode$1(object[objectKeyList[index]], objects, duplicatesIndexes); + } + } + } + } +} + +function dump$2(input, options) { + options = options || {}; + + var state = new State$3(options); + + if (!state.noRefs) getDuplicateReferences$1(input, state); + + var value = input; + + if (state.replacer) { + value = state.replacer.call({ '': value }, '', value); + } + + if (writeNode$1(state, 0, value, true, true)) return state.dump + '\n'; + + return ''; +} + +var dump_1$1 = dump$2; + +var dumper$1 = { + dump: dump_1$1 +}; + +function renamed(from, to) { + return function () { + throw new Error('Function yaml.' + from + ' is removed in js-yaml 4. ' + + 'Use yaml.' + to + ' instead, which is now safe by default.'); + }; +} + + +var Type$3 = type$1; +var Schema$3 = schema$2; +var FAILSAFE_SCHEMA$1 = failsafe$1; +var JSON_SCHEMA$1 = json$1; +var CORE_SCHEMA$1 = core$3; +var DEFAULT_SCHEMA$1 = _default$8; +var load$4 = loader$1.load; +var loadAll$3 = loader$1.loadAll; +var dump$3 = dumper$1.dump; +var YAMLException$3 = exception$1; + +// Removed functions from JS-YAML 3.0.x +var safeLoad$2 = renamed('safeLoad', 'load'); +var safeLoadAll$2 = renamed('safeLoadAll', 'loadAll'); +var safeDump$2 = renamed('safeDump', 'dump'); + +var jsYaml$2 = { + Type: Type$3, + Schema: Schema$3, + FAILSAFE_SCHEMA: FAILSAFE_SCHEMA$1, + JSON_SCHEMA: JSON_SCHEMA$1, + CORE_SCHEMA: CORE_SCHEMA$1, + DEFAULT_SCHEMA: DEFAULT_SCHEMA$1, + load: load$4, + loadAll: loadAll$3, + dump: dump$3, + YAMLException: YAMLException$3, + safeLoad: safeLoad$2, + safeLoadAll: safeLoadAll$2, + safeDump: safeDump$2 +}; + // Note: this is the semver.org version of the spec that it implements // Not necessarily the package version of this code. const SEMVER_SPEC_VERSION = '2.0.0'; @@ -45837,7 +49665,7 @@ function validateYAMLComments(tree, file) { unistUtilVisit(tree, "html", function visitor(node) { if (!node.value.startsWith("".length)); + const meta = jsYaml$2.load("#" + node.value.slice(0, -"-->".length)); validateMeta(node, file, meta); } catch (e) { @@ -46701,7 +50529,7 @@ var plugins$2 = [ { yes: "GitHub" }, { no: "hostname", yes: "host name" }, { yes: "JavaScript" }, - { no: "Node", yes: "Node.js" }, + { no: "Node", yes: "Node.js", ignoreNextTo: "-API" }, { yes: "Node.js" }, { no: "Node[Jj][Ss]", yes: "Node.js" }, { no: "Node\\.js's?", yes: "the Node.js" }, diff --git a/tools/node-lint-md-cli-rollup/package-lock.json b/tools/node-lint-md-cli-rollup/package-lock.json index 7abb785af84d2c..240c1e01089457 100644 --- a/tools/node-lint-md-cli-rollup/package-lock.json +++ b/tools/node-lint-md-cli-rollup/package-lock.json @@ -11,7 +11,7 @@ "remark": "^13.0.0", "remark-gfm": "^1.0.0", "remark-lint": "^8.0.0", - "remark-preset-lint-node": "^2.0.0", + "remark-preset-lint-node": "^2.0.1", "unified-args": "^8.1.0" }, "devDependencies": { @@ -2112,11 +2112,11 @@ } }, "node_modules/remark-preset-lint-node": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-preset-lint-node/-/remark-preset-lint-node-2.0.0.tgz", - "integrity": "sha512-gjJlRK+ed3rW/k+YFENGyDDfzMS2iUyuo+MQR3pQWUl7L6Yawg6OYGKjO9eVBN/1jaourq0N515O1nXq64Qm1Q==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-preset-lint-node/-/remark-preset-lint-node-2.0.1.tgz", + "integrity": "sha512-f0/cL2XiBmsLpCtpUeVxSJf1d3N5qRQD+W2GF8TXUxFntxvxM6Gm5lPGPouXsqFQ2gc92uoF8MgC1nRWVzYpzA==", "dependencies": { - "js-yaml": "^3.14.0", + "js-yaml": "^4.0.0", "remark-lint": "^8.0.0", "remark-lint-blockquote-indentation": "^2.0.0", "remark-lint-checkbox-character-style": "^3.0.0", @@ -2151,6 +2151,22 @@ "semver": "^7.3.2" } }, + "node_modules/remark-preset-lint-node/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/remark-preset-lint-node/node_modules/js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/remark-preset-lint-recommended": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-preset-lint-recommended/-/remark-preset-lint-recommended-5.0.0.tgz", @@ -4214,11 +4230,11 @@ } }, "remark-preset-lint-node": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-preset-lint-node/-/remark-preset-lint-node-2.0.0.tgz", - "integrity": "sha512-gjJlRK+ed3rW/k+YFENGyDDfzMS2iUyuo+MQR3pQWUl7L6Yawg6OYGKjO9eVBN/1jaourq0N515O1nXq64Qm1Q==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-preset-lint-node/-/remark-preset-lint-node-2.0.1.tgz", + "integrity": "sha512-f0/cL2XiBmsLpCtpUeVxSJf1d3N5qRQD+W2GF8TXUxFntxvxM6Gm5lPGPouXsqFQ2gc92uoF8MgC1nRWVzYpzA==", "requires": { - "js-yaml": "^3.14.0", + "js-yaml": "^4.0.0", "remark-lint": "^8.0.0", "remark-lint-blockquote-indentation": "^2.0.0", "remark-lint-checkbox-character-style": "^3.0.0", @@ -4251,6 +4267,21 @@ "remark-lint-unordered-list-marker-style": "^2.0.0", "remark-preset-lint-recommended": "^5.0.0", "semver": "^7.3.2" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "requires": { + "argparse": "^2.0.1" + } + } } }, "remark-preset-lint-recommended": { diff --git a/tools/node-lint-md-cli-rollup/package.json b/tools/node-lint-md-cli-rollup/package.json index 7776ad0d5dcc5b..146e5f78ec47b0 100644 --- a/tools/node-lint-md-cli-rollup/package.json +++ b/tools/node-lint-md-cli-rollup/package.json @@ -14,7 +14,7 @@ "remark": "^13.0.0", "remark-gfm": "^1.0.0", "remark-lint": "^8.0.0", - "remark-preset-lint-node": "^2.0.0", + "remark-preset-lint-node": "^2.0.1", "unified-args": "^8.1.0" }, "main": "dist/index.js", From ebf3597db18e0e4e999ca9fe5dfee0d7c710578e Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Sat, 6 Feb 2021 19:40:36 -0800 Subject: [PATCH 048/108] doc: rename N-API to Node-API Refs: https://github.com/nodejs/abi-stable-node/issues/420 PR-URL: https://github.com/nodejs/node/pull/37259 Reviewed-By: Rich Trott Reviewed-By: Gireesh Punathil --- doc/api/addons.md | 25 +-- doc/api/errors.md | 4 +- doc/api/index.md | 2 +- doc/api/n-api.md | 298 +++++++++++++++--------------- doc/guides/adding-new-napi-api.md | 14 +- doc/guides/collaborator-guide.md | 12 +- 6 files changed, 178 insertions(+), 177 deletions(-) diff --git a/doc/api/addons.md b/doc/api/addons.md index 19799233cf7584..43f24860338a68 100644 --- a/doc/api/addons.md +++ b/doc/api/addons.md @@ -7,12 +7,13 @@ _Addons_ are dynamically-linked shared objects written in C++. The [`require()`][require] function can load addons as ordinary Node.js modules. Addons provide an interface between JavaScript and C/C++ libraries. -There are three options for implementing addons: N-API, nan, or direct +There are three options for implementing addons: Node-API, nan, or direct use of internal V8, libuv and Node.js libraries. Unless there is a need for -direct access to functionality which is not exposed by N-API, use N-API. -Refer to [C/C++ addons with N-API](n-api.md) for more information on N-API. +direct access to functionality which is not exposed by Node-API, use Node-API. +Refer to [C/C++ addons with Node-API](n-api.md) for more information on +Node-API. -When not using N-API, implementing addons is complicated, +When not using Node-API, implementing addons is complicated, involving knowledge of several components and APIs: * V8: the C++ library Node.js uses to provide the @@ -245,7 +246,7 @@ changes: In order to be loaded from multiple Node.js environments, such as a main thread and a Worker thread, an add-on needs to either: -* Be an N-API addon, or +* Be an Node-API addon, or * Be declared as context-aware using `NODE_MODULE_INIT()` as described above In order to support [`Worker`][] threads, addons need to clean up any resources @@ -437,11 +438,11 @@ addon developers are recommended to use to keep compatibility between past and future releases of V8 and Node.js. See the `nan` [examples][] for an illustration of how it can be used. -## N-API +## Node-API > Stability: 2 - Stable -N-API is an API for building native addons. It is independent from +Node-API is an API for building native addons. It is independent from the underlying JavaScript runtime (e.g. V8) and is maintained as part of Node.js itself. This API will be Application Binary Interface (ABI) stable across versions of Node.js. It is intended to insulate addons from @@ -451,17 +452,17 @@ recompilation. Addons are built/packaged with the same approach/tools outlined in this document (node-gyp, etc.). The only difference is the set of APIs that are used by the native code. Instead of using the V8 or [Native Abstractions for Node.js][] APIs, the functions available -in the N-API are used. +in the Node-API are used. Creating and maintaining an addon that benefits from the ABI stability -provided by N-API carries with it certain +provided by Node-API carries with it certain [implementation considerations](n-api.md#n_api_implications_of_abi_stability). -To use N-API in the above "Hello world" example, replace the content of +To use Node-API in the above "Hello world" example, replace the content of `hello.cc` with the following. All other instructions remain the same. ```cpp -// hello.cc using N-API +// hello.cc using Node-API #include namespace demo { @@ -493,7 +494,7 @@ NAPI_MODULE(NODE_GYP_MODULE_NAME, init) ``` The functions available and how to use them are documented in -[C/C++ addons with N-API](n-api.md). +[C/C++ addons with Node-API](n-api.md). ## Addon examples diff --git a/doc/api/errors.md b/doc/api/errors.md index 411e2a4221004e..96e810d878653a 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -1823,7 +1823,7 @@ would be possible by calling a callback more than once. ### `ERR_NAPI_CONS_FUNCTION` -While using `N-API`, a constructor passed was not a function. +While using `Node-API`, a constructor passed was not a function. ### `ERR_NAPI_INVALID_DATAVIEW_ARGS` @@ -2559,7 +2559,7 @@ added: v9.0.0 removed: v10.0.0 --> -Used by the `N-API` when `Constructor.prototype` is not an object. +Used by the `Node-API` when `Constructor.prototype` is not an object. ### `ERR_NO_LONGER_SUPPORTED` diff --git a/doc/api/index.md b/doc/api/index.md index 734d7f1cf05739..a17fb4b666c7d4 100644 --- a/doc/api/index.md +++ b/doc/api/index.md @@ -14,7 +14,7 @@ * [Async hooks](async_hooks.md) * [Buffer](buffer.md) * [C++ addons](addons.md) -* [C/C++ addons with N-API](n-api.md) +* [C/C++ addons with Node-API](n-api.md) * [C++ embedder API](embedding.md) * [Child processes](child_process.md) * [Cluster](cluster.md) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 7d9d986b9bbf02..10f05bb69873bd 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -1,30 +1,29 @@ -# N-API +# Node-API > Stability: 2 - Stable -N-API (pronounced N as in the letter, followed by API) -is an API for building native Addons. It is independent from -the underlying JavaScript runtime (for example, V8) and is maintained as part of -Node.js itself. This API will be Application Binary Interface (ABI) stable -across versions of Node.js. It is intended to insulate Addons from -changes in the underlying JavaScript engine and allow modules +Node-API (formerly N-API) is an API for building native Addons. It is +independent from the underlying JavaScript runtime (for example, V8) and is +maintained as part of Node.js itself. This API will be Application Binary +Interface (ABI) stable across versions of Node.js. It is intended to insulate +addons from changes in the underlying JavaScript engine and allow modules compiled for one major version to run on later major versions of Node.js without recompilation. The [ABI Stability][] guide provides a more in-depth explanation. Addons are built/packaged with the same approach/tools outlined in the section titled [C++ Addons][]. The only difference is the set of APIs that are used by the native code. Instead of using the V8 or [Native Abstractions for Node.js][] -APIs, the functions available in the N-API are used. +APIs, the functions available in Node-API are used. -APIs exposed by N-API are generally used to create and manipulate +APIs exposed by Node-API are generally used to create and manipulate JavaScript values. Concepts and operations generally map to ideas specified in the ECMA-262 Language Specification. The APIs have the following properties: -* All N-API calls return a status code of type `napi_status`. This +* All Node-API calls return a status code of type `napi_status`. This status indicates whether the API call succeeded or failed. * The API's return value is passed via an out parameter. * All JavaScript values are abstracted behind an opaque type named @@ -33,14 +32,14 @@ properties: using `napi_get_last_error_info`. More information can be found in the error handling section [Error handling][]. -The N-API is a C API that ensures ABI stability across Node.js versions +Node-API-API is a C API that ensures ABI stability across Node.js versions and different compiler levels. A C++ API can be easier to use. To support using C++, the project maintains a C++ wrapper module called [`node-addon-api`][]. This wrapper provides an inlineable C++ API. Binaries built -with `node-addon-api` will depend on the symbols for the N-API C-based +with `node-addon-api` will depend on the symbols for the Node-API C-based functions exported by Node.js. `node-addon-api` is a more -efficient way to write code that calls N-API. Take, for example, the +efficient way to write code that calls Node-API. Take, for example, the following `node-addon-api` code. The first section shows the `node-addon-api` code and the second section shows what actually gets used in the addon. @@ -78,13 +77,13 @@ it still gets the benefits of the ABI stability provided by the C API. When using `node-addon-api` instead of the C APIs, start with the API [docs][] for `node-addon-api`. -The [N-API Resource](https://nodejs.github.io/node-addon-examples/) offers an -excellent orientation and tips for developers just getting started with N-API -and `node-addon-api`. +The [Node-API Resource](https://nodejs.github.io/node-addon-examples/) offers +an excellent orientation and tips for developers just getting started with +Node-API and `node-addon-api`. ## Implications of ABI stability -Although N-API provides an ABI stability guarantee, other parts of Node.js do +Although Node-API provides an ABI stability guarantee, other parts of Node.js do not, and any external libraries used from the addon may not. In particular, none of the following APIs provide an ABI stability guarantee across major versions: @@ -111,19 +110,19 @@ versions: ``` Thus, for an addon to remain ABI-compatible across Node.js major versions, it -must use N-API exclusively by restricting itself to using +must use Node-API exclusively by restricting itself to using ```c #include ``` and by checking, for all external libraries that it uses, that the external -library makes ABI stability guarantees similar to N-API. +library makes ABI stability guarantees similar to Node-API. ## Building Unlike modules written in JavaScript, developing and deploying Node.js -native addons using N-API requires an additional set of tools. Besides the +native addons using Node-API requires an additional set of tools. Besides the basic tools required to develop for Node.js, the native addon developer requires a toolchain that can compile C and C++ code into a binary. In addition, depending upon how the native addon is deployed, the *user* of @@ -207,15 +206,15 @@ available to the module user when the native module is installed. ## Usage -In order to use the N-API functions, include the file [`node_api.h`][] which is -located in the src directory in the node development tree: +In order to use the Node-API functions, include the file [`node_api.h`][] which +is located in the src directory in the node development tree: ```c #include ``` This will opt into the default `NAPI_VERSION` for the given release of Node.js. -In order to ensure compatibility with specific versions of N-API, the version +In order to ensure compatibility with specific versions of Node-API, the version can be specified explicitly when including the header: ```c @@ -223,10 +222,10 @@ can be specified explicitly when including the header: #include ``` -This restricts the N-API surface to just the functionality that was available in -the specified (and earlier) versions. +This restricts the Node-API surface to just the functionality that was available +in the specified (and earlier) versions. -Some of the N-API surface is experimental and requires explicit opt-in: +Some of the Node-API surface is experimental and requires explicit opt-in: ```c #define NAPI_EXPERIMENTAL @@ -236,9 +235,9 @@ Some of the N-API surface is experimental and requires explicit opt-in: In this case the entire API surface, including any experimental APIs, will be available to the module code. -## N-API version matrix +## Node-API version matrix -N-API versions are additive and versioned independently from Node.js. +Node-API versions are additive and versioned independently from Node.js. Version 4 is an extension to version 3 in that it has all of the APIs from version 3 with some additions. This means that it is not necessary to recompile for new versions of Node.js which are @@ -325,37 +324,38 @@ listed as supporting a later version. -\* N-API was experimental. +\* Node-API was experimental. -\*\* Node.js 8.0.0 included N-API as experimental. It was released as N-API -version 1 but continued to evolve until Node.js 8.6.0. The API is different in -versions prior to Node.js 8.6.0. We recommend N-API version 3 or later. +\*\* Node.js 8.0.0 included Node-API as experimental. It was released as +Node-API version 1 but continued to evolve until Node.js 8.6.0. The API is +different in versions prior to Node.js 8.6.0. We recommend Node-API version 3 or +later. -Each API documented for N-API will have a header named `added in:`, and APIs -which are stable will have the additional header `N-API version:`. +Each API documented for Node-API will have a header named `added in:`, and APIs +which are stable will have the additional header `Node-API version:`. APIs are directly usable when using a Node.js version which supports -the N-API version shown in `N-API version:` or higher. +the Node-API version shown in `Node-API version:` or higher. When using a Node.js version that does not support the -`N-API version:` listed or if there is no `N-API version:` listed, +`Node-API version:` listed or if there is no `Node-API version:` listed, then the API will only be available if `#define NAPI_EXPERIMENTAL` precedes the inclusion of `node_api.h` or `js_native_api.h`. If an API appears not to be available on a version of Node.js which is later than the one shown in `added in:` then this is most likely the reason for the apparent absence. -The N-APIs associated strictly with accessing ECMAScript features from native +The Node-APIs associated strictly with accessing ECMAScript features from native code can be found separately in `js_native_api.h` and `js_native_api_types.h`. The APIs defined in these headers are included in `node_api.h` and `node_api_types.h`. The headers are structured in this way in order to allow -implementations of N-API outside of Node.js. For those implementations the +implementations of Node-API outside of Node.js. For those implementations the Node.js specific APIs may not be applicable. The Node.js-specific parts of an addon can be separated from the code that exposes the actual functionality to the JavaScript environment so that the -latter may be used with multiple implementations of N-API. In the example below, -`addon.c` and `addon.h` refer only to `js_native_api.h`. This ensures that -`addon.c` can be reused to compile against either the Node.js implementation of -N-API or any implementation of N-API outside of Node.js. +latter may be used with multiple implementations of Node-API. In the example +below, `addon.c` and `addon.h` refer only to `js_native_api.h`. This ensures +that `addon.c` can be reused to compile against either the Node.js +implementation of Node-API or any implementation of Node-API outside of Node.js. `addon_node.c` is a separate file that contains the Node.js specific entry point to the addon and which instantiates the addon by calling into `addon.c` when the @@ -456,8 +456,8 @@ Native addons may need to allocate global state which they use during their entire life cycle such that the state must be unique to each instance of the addon. -To this end, N-API provides a way to allocate data such that its life cycle is -tied to the life cycle of the Agent. +To this end, Node-API provides a way to allocate data such that its life cycle +is tied to the life cycle of the Agent. ### napi_set_instance_data -Integral status code indicating the success or failure of a N-API call. +Integral status code indicating the success or failure of a Node-API call. Currently, the following status codes are supported. ```c @@ -578,18 +578,18 @@ typedef struct { not implemented for any VM. * `engine_error_code`: VM-specific error code. This is currently not implemented for any VM. -* `error_code`: The N-API status code that originated with the last error. +* `error_code`: The Node-API status code that originated with the last error. See the [Error handling][] section for additional information. ### napi_env -`napi_env` is used to represent a context that the underlying N-API +`napi_env` is used to represent a context that the underlying Node-API implementation can use to persist VM-specific state. This structure is passed to native functions when they're invoked, and it must be passed back when -making N-API calls. Specifically, the same `napi_env` that was passed in when +making Node-API calls. Specifically, the same `napi_env` that was passed in when the initial native function was called must be passed to any subsequent -nested N-API calls. Caching the `napi_env` for the purpose of general reuse, +nested Node-API calls. Caching the `napi_env` for the purpose of general reuse, and passing the `napi_env` between instances of the same addon running on different [`Worker`][] threads is not allowed. The `napi_env` becomes invalid when an instance of a native addon is unloaded. Notification of this event is @@ -645,14 +645,14 @@ typedef enum { } napi_threadsafe_function_call_mode; ``` -### N-API memory management types +### Node-API memory management types #### napi_handle_scope This is an abstraction used to control and modify the lifetime of objects -created within a particular scope. In general, N-API values are created within -the context of a handle scope. When a native method is called from +created within a particular scope. In general, Node-API values are created +within the context of a handle scope. When a native method is called from JavaScript, a default handle scope will exist. If the user does not explicitly -create a new handle scope, N-API values will be created in the default handle +create a new handle scope, Node-API values will be created in the default handle scope. For any invocations of code outside the execution of a native method (for instance, during a libuv callback invocation), the module is required to create a scope before invoking any functions that can result in the creation @@ -718,7 +718,7 @@ An opaque value returned by [`napi_add_async_cleanup_hook`][]. It must be passed to [`napi_remove_async_cleanup_hook`][] when the chain of asynchronous cleanup events completes. -### N-API callback types +### Node-API callback types #### napi_callback_info Function pointer type for user-provided native functions which are to be -exposed to JavaScript via N-API. Callback functions should satisfy the +exposed to JavaScript via Node-API. Callback functions should satisfy the following signature: ```c @@ -778,8 +778,8 @@ operations. Callback functions must satisfy the following signature: typedef void (*napi_async_execute_callback)(napi_env env, void* data); ``` -Implementations of this function must avoid making N-API calls that execute -JavaScript or interact with JavaScript objects. N-API calls should be in the +Implementations of this function must avoid making Node-API calls that execute +JavaScript or interact with JavaScript objects. Node-API calls should be in the `napi_async_complete_callback` instead. Do not use the `napi_env` parameter as it will likely result in execution of JavaScript. @@ -816,7 +816,7 @@ The data arriving from the secondary thread via the queue is given in the `data` parameter and the JavaScript function to call is given in the `js_callback` parameter. -N-API sets up the environment prior to calling this callback, so it is +Node-API sets up the environment prior to calling this callback, so it is sufficient to call the JavaScript function via `napi_call_function` rather than via `napi_make_callback`. @@ -838,7 +838,7 @@ typedef void (*napi_threadsafe_function_call_js)(napi_env env, * `[in] context`: The optional data with which the thread-safe function was created. * `[in] data`: Data created by the secondary thread. It is the responsibility of - the callback to convert this native data to JavaScript values (with N-API + the callback to convert this native data to JavaScript values (with Node-API functions) that can be passed as parameters when `js_callback` is invoked. This pointer is managed entirely by the threads and this callback. Thus this callback should free the data. @@ -874,12 +874,12 @@ end of which `handle` must be passed in a call to ## Error handling -N-API uses both return values and JavaScript exceptions for error handling. +Node-API uses both return values and JavaScript exceptions for error handling. The following sections explain the approach for each case. ### Return values -All of the N-API functions share the same error handling pattern. The +All of the Node-API functions share the same error handling pattern. The return type of all API functions is `napi_status`. The return value will be `napi_ok` if the request was successful and @@ -922,10 +922,10 @@ typedef struct napi_extended_error_info { * `error_message`: Textual representation of the error that occurred. * `engine_reserved`: Opaque handle reserved for engine use only. * `engine_error_code`: VM specific error code. -* `error_code`: n-api status code for the last error. +* `error_code`: Node-API status code for the last error. [`napi_get_last_error_info`][] returns the information for the last -N-API call that was made. +Node-API call that was made. Do not rely on the content or format of any of the extended information as it is not subject to SemVer and may change at any time. It is intended only for @@ -953,7 +953,7 @@ This API retrieves a `napi_extended_error_info` structure with information about the last error that occurred. The content of the `napi_extended_error_info` returned is only valid up until -an n-api function is called on the same `env`. +a Node-API function is called on the same `env`. Do not rely on the content or format of any of the extended information as it is not subject to SemVer and may change at any time. It is intended only for @@ -963,7 +963,7 @@ This API can be called even if there is a pending JavaScript exception. ### Exceptions -Any N-API function call may result in a pending JavaScript exception. This is +Any Node-API function call may result in a pending JavaScript exception. This is the case for any of the API functions, even those that may not cause the execution of JavaScript. @@ -974,10 +974,10 @@ exception is pending and no additional action is required. If the instead of simply returning immediately, [`napi_is_exception_pending`][] must be called in order to determine if an exception is pending or not. -In many cases when an N-API function is called and an exception is +In many cases when a Node-API function is called and an exception is already pending, the function will return immediately with a `napi_status` of `napi_pending_exception`. However, this is not the case -for all functions. N-API allows a subset of the functions to be +for all functions. Node-API allows a subset of the functions to be called to allow for some minimal cleanup before returning to JavaScript. In that case, `napi_status` will reflect the status for the function. It will not reflect previous pending exceptions. To avoid confusion, check @@ -988,7 +988,7 @@ When an exception is pending one of two approaches can be employed. The first approach is to do any appropriate cleanup and then return so that execution will return to JavaScript. As part of the transition back to JavaScript, the exception will be thrown at the point in the JavaScript -code where the native method was invoked. The behavior of most N-API calls +code where the native method was invoked. The behavior of most Node-API calls is unspecified while an exception is pending, and many will simply return `napi_pending_exception`, so do as little as possible and then return to JavaScript where the exception can be handled. @@ -1021,7 +1021,7 @@ generated internally. The goal is for applications to use these error codes for all error checking. The associated error messages will remain, but will only be meant to be used for logging and display with the expectation that the message can change without -SemVer applying. In order to support this model with N-API, both +SemVer applying. In order to support this model with Node-API, both in internal functionality and for module specific functionality (as its good practice), the `throw_` and `create_` functions take an optional code parameter which is the string for the code @@ -1293,7 +1293,7 @@ This API can be called even if there is a pending JavaScript exception. ## Object lifetime management -As N-API calls are made, handles to objects in the heap for the underlying +As Node-API calls are made, handles to objects in the heap for the underlying VM may be returned as `napi_values`. These handles must hold the objects 'live' until they are no longer required by the native code, otherwise the objects could be collected before the native code was @@ -1307,7 +1307,7 @@ held live for the lifespan of the native method call. In many cases, however, it is necessary that the handles remain valid for either a shorter or longer lifespan than that of the native method. -The sections which follow describe the N-API functions that can be used +The sections which follow describe the Node-API functions that can be used to change the handle lifespan from the default. ### Making handle lifespan shorter than that of the native method @@ -1331,13 +1331,13 @@ substantial resources. In addition, even though the native code could only use the most recent handle, all of the associated objects would also be kept alive since they all share the same scope. -To handle this case, N-API provides the ability to establish a new 'scope' to +To handle this case, Node-API provides the ability to establish a new 'scope' to which newly created handles will be associated. Once those handles are no longer required, the scope can be 'closed' and any handles associated with the scope are invalidated. The methods available to open/close scopes are [`napi_open_handle_scope`][] and [`napi_close_handle_scope`][]. -N-API only supports a single nested hierarchy of scopes. There is only one +Node-API only supports a single nested hierarchy of scopes. There is only one active scope at any time, and all new handles will be associated with that scope while it is active. Scopes must be closed in the reverse order from which they are opened. In addition, all scopes created within a native method @@ -1368,8 +1368,8 @@ for (int i = 0; i < 1000000; i++) { ``` When nesting scopes, there are cases where a handle from an -inner scope needs to live beyond the lifespan of that scope. N-API supports an -'escapable scope' in order to support this case. An escapable scope +inner scope needs to live beyond the lifespan of that scope. Node-API supports +an 'escapable scope' in order to support this case. An escapable scope allows one handle to be 'promoted' so that it 'escapes' the current scope and the lifespan of the handle changes from the current scope to that of the outer scope. @@ -1502,7 +1502,7 @@ described in the earlier section. The lifespan of a normal handle is managed by scopes and all scopes must be closed before the end of a native method. -N-API provides methods to create persistent references to an object. +Node-API provides methods to create persistent references to an object. Each persistent reference has an associated count with a value of 0 or higher. The count determines if the reference will keep the corresponding object live. References with a count of 0 do not @@ -1646,7 +1646,7 @@ While a Node.js process typically releases all its resources when exiting, embedders of Node.js, or future Worker support, may require addons to register clean-up hooks that will be run once the current Node.js instance exits. -N-API provides functions for registering and un-registering such callbacks. +Node-API provides functions for registering and un-registering such callbacks. When those callbacks are run, all resources that are being held by the addon should be freed up. @@ -1770,7 +1770,7 @@ This must be called on any `napi_async_cleanup_hook_handle` value obtained from [`napi_add_async_cleanup_hook`][]. ## Module registration -N-API modules are registered in a manner similar to other modules +Node-API modules are registered in a manner similar to other modules except that instead of using the `NODE_MODULE` macro the following is used: @@ -1778,7 +1778,7 @@ is used: NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) ``` -The next difference is the signature for the `Init` method. For a N-API +The next difference is the signature for the `Init` method. For a Node-API module it is as follows: ```c @@ -1788,8 +1788,8 @@ napi_value Init(napi_env env, napi_value exports); The return value from `Init` is treated as the `exports` object for the module. The `Init` method is passed an empty object via the `exports` parameter as a convenience. If `Init` returns `NULL`, the parameter passed as `exports` is -exported by the module. N-API modules cannot modify the `module` object but can -specify anything as the `exports` property of the module. +exported by the module. Node-API modules cannot modify the `module` object but +can specify anything as the `exports` property of the module. To add the method `hello` as a function so that it can be called as a method provided by the addon: @@ -1871,7 +1871,7 @@ NAPI_MODULE_INIT() { } ``` -All N-API addons are context-aware, meaning they may be loaded multiple +All Node-API addons are context-aware, meaning they may be loaded multiple times. There are a few design considerations when declaring such a module. The documentation on [context-aware addons][] provides more details. @@ -1885,19 +1885,19 @@ For more details on building addon modules in general, refer to the existing API. ## Working with JavaScript values -N-API exposes a set of APIs to create all types of JavaScript values. +Node-API exposes a set of APIs to create all types of JavaScript values. Some of these types are documented under [Section 6][] of the [ECMAScript Language Specification][]. Fundamentally, these APIs are used to do one of the following: 1. Create a new JavaScript object -2. Convert from a primitive C type to an N-API value -3. Convert from N-API value to a primitive C type +2. Convert from a primitive C type to a Node-API value +3. Convert from Node-API value to a primitive C type 4. Get global instances including `undefined` and `null` -N-API values are represented by the type `napi_value`. -Any N-API call that requires a JavaScript value takes in a `napi_value`. +Node-API values are represented by the type `napi_value`. +Any Node-API call that requires a JavaScript value takes in a `napi_value`. In some cases, the API does check the type of the `napi_value` up-front. However, for better performance, it's better for the caller to make sure that the `napi_value` in question is of the JavaScript type expected by the API. @@ -2028,12 +2028,12 @@ napiVersion: 1 napi_status napi_create_array(napi_env env, napi_value* result) ``` -* `[in] env`: The environment that the N-API call is invoked under. +* `[in] env`: The environment that the Node-API call is invoked under. * `[out] result`: A `napi_value` representing a JavaScript `Array`. Returns `napi_ok` if the API succeeded. -This API returns an N-API value corresponding to a JavaScript `Array` type. +This API returns a Node-API value corresponding to a JavaScript `Array` type. JavaScript arrays are described in [Section 22.1][] of the ECMAScript Language Specification. @@ -2055,7 +2055,7 @@ napi_status napi_create_array_with_length(napi_env env, Returns `napi_ok` if the API succeeded. -This API returns an N-API value corresponding to a JavaScript `Array` type. +This API returns a Node-API value corresponding to a JavaScript `Array` type. The `Array`'s length property is set to the passed-in length parameter. However, the underlying buffer is not guaranteed to be pre-allocated by the VM when the array is created. That behavior is left to the underlying VM @@ -2086,7 +2086,7 @@ napi_status napi_create_arraybuffer(napi_env env, Returns `napi_ok` if the API succeeded. -This API returns an N-API value corresponding to a JavaScript `ArrayBuffer`. +This API returns a Node-API value corresponding to a JavaScript `ArrayBuffer`. `ArrayBuffer`s are used to represent fixed-length binary data buffers. They are normally used as a backing-buffer for `TypedArray` objects. The `ArrayBuffer` allocated will have an underlying byte buffer whose size is @@ -2245,7 +2245,7 @@ napi_create_external_arraybuffer(napi_env env, Returns `napi_ok` if the API succeeded. -This API returns an N-API value corresponding to a JavaScript `ArrayBuffer`. +This API returns a Node-API value corresponding to a JavaScript `ArrayBuffer`. The underlying byte buffer of the `ArrayBuffer` is externally allocated and managed. The caller must ensure that the byte buffer remains valid until the finalize callback is called. @@ -2418,7 +2418,7 @@ raised. JavaScript `DataView` objects are described in [Section 24.3][] of the ECMAScript Language Specification. -### Functions to convert from C types to N-API +### Functions to convert from C types to Node-API #### napi_create_int32 +[![Build Status](https://secure.travis-ci.org/tim-kos/node-retry.png?branch=master)](http://travis-ci.org/tim-kos/node-retry "Check this project's build status on TravisCI") +[![codecov](https://codecov.io/gh/tim-kos/node-retry/branch/master/graph/badge.svg)](https://codecov.io/gh/tim-kos/node-retry) + + +# retry + +Abstraction for exponential and custom retry strategies for failed operations. + +## Installation + + npm install retry + +## Current Status + +This module has been tested and is ready to be used. + +## Tutorial + +The example below will retry a potentially failing `dns.resolve` operation +`10` times using an exponential backoff strategy. With the default settings, this +means the last attempt is made after `17 minutes and 3 seconds`. + +``` javascript +var dns = require('dns'); +var retry = require('retry'); + +function faultTolerantResolve(address, cb) { + var operation = retry.operation(); + + operation.attempt(function(currentAttempt) { + dns.resolve(address, function(err, addresses) { + if (operation.retry(err)) { + return; + } + + cb(err ? operation.mainError() : null, addresses); + }); + }); +} + +faultTolerantResolve('nodejs.org', function(err, addresses) { + console.log(err, addresses); +}); +``` + +Of course you can also configure the factors that go into the exponential +backoff. See the API documentation below for all available settings. +currentAttempt is an int representing the number of attempts so far. + +``` javascript +var operation = retry.operation({ + retries: 5, + factor: 3, + minTimeout: 1 * 1000, + maxTimeout: 60 * 1000, + randomize: true, +}); +``` + +## API + +### retry.operation([options]) + +Creates a new `RetryOperation` object. `options` is the same as `retry.timeouts()`'s `options`, with two additions: + +* `forever`: Whether to retry forever, defaults to `false`. +* `unref`: Whether to [unref](https://nodejs.org/api/timers.html#timers_unref) the setTimeout's, defaults to `false`. +* `maxRetryTime`: The maximum time (in milliseconds) that the retried operation is allowed to run. Default is `Infinity`. + +### retry.timeouts([options]) + +Returns an array of timeouts. All time `options` and return values are in +milliseconds. If `options` is an array, a copy of that array is returned. + +`options` is a JS object that can contain any of the following keys: + +* `retries`: The maximum amount of times to retry the operation. Default is `10`. Seting this to `1` means `do it once, then retry it once`. +* `factor`: The exponential factor to use. Default is `2`. +* `minTimeout`: The number of milliseconds before starting the first retry. Default is `1000`. +* `maxTimeout`: The maximum number of milliseconds between two retries. Default is `Infinity`. +* `randomize`: Randomizes the timeouts by multiplying with a factor between `1` to `2`. Default is `false`. + +The formula used to calculate the individual timeouts is: + +``` +Math.min(random * minTimeout * Math.pow(factor, attempt), maxTimeout) +``` + +Have a look at [this article][article] for a better explanation of approach. + +If you want to tune your `factor` / `times` settings to attempt the last retry +after a certain amount of time, you can use wolfram alpha. For example in order +to tune for `10` attempts in `5 minutes`, you can use this equation: + +![screenshot](https://github.com/tim-kos/node-retry/raw/master/equation.gif) + +Explaining the various values from left to right: + +* `k = 0 ... 9`: The `retries` value (10) +* `1000`: The `minTimeout` value in ms (1000) +* `x^k`: No need to change this, `x` will be your resulting factor +* `5 * 60 * 1000`: The desired total amount of time for retrying in ms (5 minutes) + +To make this a little easier for you, use wolfram alpha to do the calculations: + + + +[article]: http://dthain.blogspot.com/2009/02/exponential-backoff-in-distributed.html + +### retry.createTimeout(attempt, opts) + +Returns a new `timeout` (integer in milliseconds) based on the given parameters. + +`attempt` is an integer representing for which retry the timeout should be calculated. If your retry operation was executed 4 times you had one attempt and 3 retries. If you then want to calculate a new timeout, you should set `attempt` to 4 (attempts are zero-indexed). + +`opts` can include `factor`, `minTimeout`, `randomize` (boolean) and `maxTimeout`. They are documented above. + +`retry.createTimeout()` is used internally by `retry.timeouts()` and is public for you to be able to create your own timeouts for reinserting an item, see [issue #13](https://github.com/tim-kos/node-retry/issues/13). + +### retry.wrap(obj, [options], [methodNames]) + +Wrap all functions of the `obj` with retry. Optionally you can pass operation options and +an array of method names which need to be wrapped. + +``` +retry.wrap(obj) + +retry.wrap(obj, ['method1', 'method2']) + +retry.wrap(obj, {retries: 3}) + +retry.wrap(obj, {retries: 3}, ['method1', 'method2']) +``` +The `options` object can take any options that the usual call to `retry.operation` can take. + +### new RetryOperation(timeouts, [options]) + +Creates a new `RetryOperation` where `timeouts` is an array where each value is +a timeout given in milliseconds. + +Available options: +* `forever`: Whether to retry forever, defaults to `false`. +* `unref`: Wether to [unref](https://nodejs.org/api/timers.html#timers_unref) the setTimeout's, defaults to `false`. + +If `forever` is true, the following changes happen: +* `RetryOperation.errors()` will only output an array of one item: the last error. +* `RetryOperation` will repeatedly use the `timeouts` array. Once all of its timeouts have been used up, it restarts with the first timeout, then uses the second and so on. + +#### retryOperation.errors() + +Returns an array of all errors that have been passed to `retryOperation.retry()` so far. The +returning array has the errors ordered chronologically based on when they were passed to +`retryOperation.retry()`, which means the first passed error is at index zero and the last is +at the last index. + +#### retryOperation.mainError() + +A reference to the error object that occured most frequently. Errors are +compared using the `error.message` property. + +If multiple error messages occured the same amount of time, the last error +object with that message is returned. + +If no errors occured so far, the value is `null`. + +#### retryOperation.attempt(fn, timeoutOps) + +Defines the function `fn` that is to be retried and executes it for the first +time right away. The `fn` function can receive an optional `currentAttempt` callback that represents the number of attempts to execute `fn` so far. + +Optionally defines `timeoutOps` which is an object having a property `timeout` in miliseconds and a property `cb` callback function. +Whenever your retry operation takes longer than `timeout` to execute, the timeout callback function `cb` is called. + + +#### retryOperation.try(fn) + +This is an alias for `retryOperation.attempt(fn)`. This is deprecated. Please use `retryOperation.attempt(fn)` instead. + +#### retryOperation.start(fn) + +This is an alias for `retryOperation.attempt(fn)`. This is deprecated. Please use `retryOperation.attempt(fn)` instead. + +#### retryOperation.retry(error) + +Returns `false` when no `error` value is given, or the maximum amount of retries +has been reached. + +Otherwise it returns `true`, and retries the operation after the timeout for +the current attempt number. + +#### retryOperation.stop() + +Allows you to stop the operation being retried. Useful for aborting the operation on a fatal error etc. + +#### retryOperation.reset() + +Resets the internal state of the operation object, so that you can call `attempt()` again as if this was a new operation object. + +#### retryOperation.attempts() + +Returns an int representing the number of attempts it took to call `fn` before it was successful. + +## License + +retry is licensed under the MIT license. + + +# Changelog + +0.10.0 Adding `stop` functionality, thanks to @maxnachlinger. + +0.9.0 Adding `unref` functionality, thanks to @satazor. + +0.8.0 Implementing retry.wrap. + +0.7.0 Some bug fixes and made retry.createTimeout() public. Fixed issues [#10](https://github.com/tim-kos/node-retry/issues/10), [#12](https://github.com/tim-kos/node-retry/issues/12), and [#13](https://github.com/tim-kos/node-retry/issues/13). + +0.6.0 Introduced optional timeOps parameter for the attempt() function which is an object having a property timeout in milliseconds and a property cb callback function. Whenever your retry operation takes longer than timeout to execute, the timeout callback function cb is called. + +0.5.0 Some minor refactoring. + +0.4.0 Changed retryOperation.try() to retryOperation.attempt(). Deprecated the aliases start() and try() for it. + +0.3.0 Added retryOperation.start() which is an alias for retryOperation.try(). + +0.2.0 Added attempts() function and parameter to retryOperation.try() representing the number of attempts it took to call fn(). diff --git a/deps/npm/node_modules/pacote/node_modules/retry/equation.gif b/deps/npm/node_modules/pacote/node_modules/retry/equation.gif new file mode 100644 index 0000000000000000000000000000000000000000..97107237ba19f51997d8d76135bc7d1486d856f0 GIT binary patch literal 1209 zcmV;q1V;NuNk%w1VXpu&0M!5h000001ONyK2nY-a5D*X$6c88~7#JKFARr(hBp@j$ zDJd)|F)%SPG%-0iIXOHzK|n!4L_tbON=i&hQczM-RZ?16T3TINVqs!pWnyY+YHDq2 zb8&NXb#r@pdwYF*gMovCg@cQUi;Inml#!H_m6V*BoSdDUq@kpwrKGH?tgNoAw6e6c zwzR#vy}iD@#lpqK#>LIb&CSlu)za0~*45tH-rnBc=Hlk&=H~9|?(XjH_VV`j_V)k! z|NsC0EC2ui0IvWs000L6z@KnPEENVOfMTEH9c0Z7p9z3<`87kr4n!IH|Ew$buF^Tr6-3^@midQKv4UFk?fCD@~8E z@HgbfvLPrU7IV4gfp|8%C^H$l;qq zLJ;`y;|7BS2YlpEz->xcBQ#7@yHNtNkOmwQ1ek!X@sGzuLXR#jx2fyLw;309jQGe6 zL`?+$umPZ&50}J^BQGxGIN%{G2=u5hqw|pm*t2Ul0ssMk0vb%GI^lz~c)})l{~Qc?h2kCMJmBf=4KTfq+A}mV<6G&6wD3KiFu51s1j8f&fS0 zFaiqI41q&$@ZBIIl0*neBoe|cd1H+<3Zdf>DJ(#i62j@_f)Fj-_2my?IyGjQMd%>G z07WXH-J3lkxMd6n7?DE>JIL@P5d*{^#0>(>vA~&p4RL3ldlu2^8P z!OlGQ%z<|`+iWomtGr?~EJ7!(^wLZ>?ex=7N4-QZ)=BNMGD+xg!3P&;Y_%-ZByj;I zEWG$NFy8zC&JhLd@WT!ToDGaV{P^?c4^0Iv_b4i{ghbnK$GtZyTzMtL-DCey_TZ>w XwprD$S>S;MUNdg_<(OxVL=XTw-hl|W literal 0 HcmV?d00001 diff --git a/deps/npm/node_modules/pacote/node_modules/retry/example/dns.js b/deps/npm/node_modules/pacote/node_modules/retry/example/dns.js new file mode 100644 index 00000000000000..446729b6f9af6b --- /dev/null +++ b/deps/npm/node_modules/pacote/node_modules/retry/example/dns.js @@ -0,0 +1,31 @@ +var dns = require('dns'); +var retry = require('../lib/retry'); + +function faultTolerantResolve(address, cb) { + var opts = { + retries: 2, + factor: 2, + minTimeout: 1 * 1000, + maxTimeout: 2 * 1000, + randomize: true + }; + var operation = retry.operation(opts); + + operation.attempt(function(currentAttempt) { + dns.resolve(address, function(err, addresses) { + if (operation.retry(err)) { + return; + } + + cb(operation.mainError(), operation.errors(), addresses); + }); + }); +} + +faultTolerantResolve('nodejs.org', function(err, errors, addresses) { + console.warn('err:'); + console.log(err); + + console.warn('addresses:'); + console.log(addresses); +}); \ No newline at end of file diff --git a/deps/npm/node_modules/pacote/node_modules/retry/example/stop.js b/deps/npm/node_modules/pacote/node_modules/retry/example/stop.js new file mode 100644 index 00000000000000..e1ceafeebafc51 --- /dev/null +++ b/deps/npm/node_modules/pacote/node_modules/retry/example/stop.js @@ -0,0 +1,40 @@ +var retry = require('../lib/retry'); + +function attemptAsyncOperation(someInput, cb) { + var opts = { + retries: 2, + factor: 2, + minTimeout: 1 * 1000, + maxTimeout: 2 * 1000, + randomize: true + }; + var operation = retry.operation(opts); + + operation.attempt(function(currentAttempt) { + failingAsyncOperation(someInput, function(err, result) { + + if (err && err.message === 'A fatal error') { + operation.stop(); + return cb(err); + } + + if (operation.retry(err)) { + return; + } + + cb(operation.mainError(), operation.errors(), result); + }); + }); +} + +attemptAsyncOperation('test input', function(err, errors, result) { + console.warn('err:'); + console.log(err); + + console.warn('result:'); + console.log(result); +}); + +function failingAsyncOperation(input, cb) { + return setImmediate(cb.bind(null, new Error('A fatal error'))); +} diff --git a/deps/npm/node_modules/pacote/node_modules/retry/index.js b/deps/npm/node_modules/pacote/node_modules/retry/index.js new file mode 100644 index 00000000000000..ee62f3a112c28b --- /dev/null +++ b/deps/npm/node_modules/pacote/node_modules/retry/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/retry'); \ No newline at end of file diff --git a/deps/npm/node_modules/pacote/node_modules/retry/lib/retry.js b/deps/npm/node_modules/pacote/node_modules/retry/lib/retry.js new file mode 100644 index 00000000000000..dcb57680727948 --- /dev/null +++ b/deps/npm/node_modules/pacote/node_modules/retry/lib/retry.js @@ -0,0 +1,100 @@ +var RetryOperation = require('./retry_operation'); + +exports.operation = function(options) { + var timeouts = exports.timeouts(options); + return new RetryOperation(timeouts, { + forever: options && options.forever, + unref: options && options.unref, + maxRetryTime: options && options.maxRetryTime + }); +}; + +exports.timeouts = function(options) { + if (options instanceof Array) { + return [].concat(options); + } + + var opts = { + retries: 10, + factor: 2, + minTimeout: 1 * 1000, + maxTimeout: Infinity, + randomize: false + }; + for (var key in options) { + opts[key] = options[key]; + } + + if (opts.minTimeout > opts.maxTimeout) { + throw new Error('minTimeout is greater than maxTimeout'); + } + + var timeouts = []; + for (var i = 0; i < opts.retries; i++) { + timeouts.push(this.createTimeout(i, opts)); + } + + if (options && options.forever && !timeouts.length) { + timeouts.push(this.createTimeout(i, opts)); + } + + // sort the array numerically ascending + timeouts.sort(function(a,b) { + return a - b; + }); + + return timeouts; +}; + +exports.createTimeout = function(attempt, opts) { + var random = (opts.randomize) + ? (Math.random() + 1) + : 1; + + var timeout = Math.round(random * opts.minTimeout * Math.pow(opts.factor, attempt)); + timeout = Math.min(timeout, opts.maxTimeout); + + return timeout; +}; + +exports.wrap = function(obj, options, methods) { + if (options instanceof Array) { + methods = options; + options = null; + } + + if (!methods) { + methods = []; + for (var key in obj) { + if (typeof obj[key] === 'function') { + methods.push(key); + } + } + } + + for (var i = 0; i < methods.length; i++) { + var method = methods[i]; + var original = obj[method]; + + obj[method] = function retryWrapper(original) { + var op = exports.operation(options); + var args = Array.prototype.slice.call(arguments, 1); + var callback = args.pop(); + + args.push(function(err) { + if (op.retry(err)) { + return; + } + if (err) { + arguments[0] = op.mainError(); + } + callback.apply(this, arguments); + }); + + op.attempt(function() { + original.apply(obj, args); + }); + }.bind(obj, original); + obj[method].options = options; + } +}; diff --git a/deps/npm/node_modules/pacote/node_modules/retry/lib/retry_operation.js b/deps/npm/node_modules/pacote/node_modules/retry/lib/retry_operation.js new file mode 100644 index 00000000000000..1e564696fe7e07 --- /dev/null +++ b/deps/npm/node_modules/pacote/node_modules/retry/lib/retry_operation.js @@ -0,0 +1,158 @@ +function RetryOperation(timeouts, options) { + // Compatibility for the old (timeouts, retryForever) signature + if (typeof options === 'boolean') { + options = { forever: options }; + } + + this._originalTimeouts = JSON.parse(JSON.stringify(timeouts)); + this._timeouts = timeouts; + this._options = options || {}; + this._maxRetryTime = options && options.maxRetryTime || Infinity; + this._fn = null; + this._errors = []; + this._attempts = 1; + this._operationTimeout = null; + this._operationTimeoutCb = null; + this._timeout = null; + this._operationStart = null; + + if (this._options.forever) { + this._cachedTimeouts = this._timeouts.slice(0); + } +} +module.exports = RetryOperation; + +RetryOperation.prototype.reset = function() { + this._attempts = 1; + this._timeouts = this._originalTimeouts; +} + +RetryOperation.prototype.stop = function() { + if (this._timeout) { + clearTimeout(this._timeout); + } + + this._timeouts = []; + this._cachedTimeouts = null; +}; + +RetryOperation.prototype.retry = function(err) { + if (this._timeout) { + clearTimeout(this._timeout); + } + + if (!err) { + return false; + } + var currentTime = new Date().getTime(); + if (err && currentTime - this._operationStart >= this._maxRetryTime) { + this._errors.unshift(new Error('RetryOperation timeout occurred')); + return false; + } + + this._errors.push(err); + + var timeout = this._timeouts.shift(); + if (timeout === undefined) { + if (this._cachedTimeouts) { + // retry forever, only keep last error + this._errors.splice(this._errors.length - 1, this._errors.length); + this._timeouts = this._cachedTimeouts.slice(0); + timeout = this._timeouts.shift(); + } else { + return false; + } + } + + var self = this; + var timer = setTimeout(function() { + self._attempts++; + + if (self._operationTimeoutCb) { + self._timeout = setTimeout(function() { + self._operationTimeoutCb(self._attempts); + }, self._operationTimeout); + + if (self._options.unref) { + self._timeout.unref(); + } + } + + self._fn(self._attempts); + }, timeout); + + if (this._options.unref) { + timer.unref(); + } + + return true; +}; + +RetryOperation.prototype.attempt = function(fn, timeoutOps) { + this._fn = fn; + + if (timeoutOps) { + if (timeoutOps.timeout) { + this._operationTimeout = timeoutOps.timeout; + } + if (timeoutOps.cb) { + this._operationTimeoutCb = timeoutOps.cb; + } + } + + var self = this; + if (this._operationTimeoutCb) { + this._timeout = setTimeout(function() { + self._operationTimeoutCb(); + }, self._operationTimeout); + } + + this._operationStart = new Date().getTime(); + + this._fn(this._attempts); +}; + +RetryOperation.prototype.try = function(fn) { + console.log('Using RetryOperation.try() is deprecated'); + this.attempt(fn); +}; + +RetryOperation.prototype.start = function(fn) { + console.log('Using RetryOperation.start() is deprecated'); + this.attempt(fn); +}; + +RetryOperation.prototype.start = RetryOperation.prototype.try; + +RetryOperation.prototype.errors = function() { + return this._errors; +}; + +RetryOperation.prototype.attempts = function() { + return this._attempts; +}; + +RetryOperation.prototype.mainError = function() { + if (this._errors.length === 0) { + return null; + } + + var counts = {}; + var mainError = null; + var mainErrorCount = 0; + + for (var i = 0; i < this._errors.length; i++) { + var error = this._errors[i]; + var message = error.message; + var count = (counts[message] || 0) + 1; + + counts[message] = count; + + if (count >= mainErrorCount) { + mainError = error; + mainErrorCount = count; + } + } + + return mainError; +}; diff --git a/deps/npm/node_modules/pacote/node_modules/retry/package.json b/deps/npm/node_modules/pacote/node_modules/retry/package.json new file mode 100644 index 00000000000000..73c7259707aeef --- /dev/null +++ b/deps/npm/node_modules/pacote/node_modules/retry/package.json @@ -0,0 +1,32 @@ +{ + "author": "Tim Koschützki (http://debuggable.com/)", + "name": "retry", + "description": "Abstraction for exponential and custom retry strategies for failed operations.", + "license": "MIT", + "version": "0.12.0", + "homepage": "https://github.com/tim-kos/node-retry", + "repository": { + "type": "git", + "url": "git://github.com/tim-kos/node-retry.git" + }, + "directories": { + "lib": "./lib" + }, + "main": "index", + "engines": { + "node": ">= 4" + }, + "dependencies": {}, + "devDependencies": { + "fake": "0.2.0", + "istanbul": "^0.4.5", + "tape": "^4.8.0" + }, + "scripts": { + "test": "./node_modules/.bin/istanbul cover ./node_modules/tape/bin/tape ./test/integration/*.js", + "release:major": "env SEMANTIC=major npm run release", + "release:minor": "env SEMANTIC=minor npm run release", + "release:patch": "env SEMANTIC=patch npm run release", + "release": "npm version ${SEMANTIC:-patch} -m \"Release %s\" && git push && git push --tags && npm publish" + } +} diff --git a/deps/npm/node_modules/pacote/node_modules/retry/test/common.js b/deps/npm/node_modules/pacote/node_modules/retry/test/common.js new file mode 100644 index 00000000000000..224720696ebac8 --- /dev/null +++ b/deps/npm/node_modules/pacote/node_modules/retry/test/common.js @@ -0,0 +1,10 @@ +var common = module.exports; +var path = require('path'); + +var rootDir = path.join(__dirname, '..'); +common.dir = { + lib: rootDir + '/lib' +}; + +common.assert = require('assert'); +common.fake = require('fake'); \ No newline at end of file diff --git a/deps/npm/node_modules/pacote/node_modules/retry/test/integration/test-forever.js b/deps/npm/node_modules/pacote/node_modules/retry/test/integration/test-forever.js new file mode 100644 index 00000000000000..b41307cb529f12 --- /dev/null +++ b/deps/npm/node_modules/pacote/node_modules/retry/test/integration/test-forever.js @@ -0,0 +1,24 @@ +var common = require('../common'); +var assert = common.assert; +var retry = require(common.dir.lib + '/retry'); + +(function testForeverUsesFirstTimeout() { + var operation = retry.operation({ + retries: 0, + minTimeout: 100, + maxTimeout: 100, + forever: true + }); + + operation.attempt(function(numAttempt) { + console.log('>numAttempt', numAttempt); + var err = new Error("foo"); + if (numAttempt == 10) { + operation.stop(); + } + + if (operation.retry(err)) { + return; + } + }); +})(); diff --git a/deps/npm/node_modules/pacote/node_modules/retry/test/integration/test-retry-operation.js b/deps/npm/node_modules/pacote/node_modules/retry/test/integration/test-retry-operation.js new file mode 100644 index 00000000000000..e351bb683ed449 --- /dev/null +++ b/deps/npm/node_modules/pacote/node_modules/retry/test/integration/test-retry-operation.js @@ -0,0 +1,258 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var retry = require(common.dir.lib + '/retry'); + +(function testReset() { + var error = new Error('some error'); + var operation = retry.operation([1, 2, 3]); + var attempts = 0; + + var finalCallback = fake.callback('finalCallback'); + fake.expectAnytime(finalCallback); + + var expectedFinishes = 1; + var finishes = 0; + + var fn = function() { + operation.attempt(function(currentAttempt) { + attempts++; + assert.equal(currentAttempt, attempts); + if (operation.retry(error)) { + return; + } + + finishes++ + assert.equal(expectedFinishes, finishes); + assert.strictEqual(attempts, 4); + assert.strictEqual(operation.attempts(), attempts); + assert.strictEqual(operation.mainError(), error); + + if (finishes < 2) { + attempts = 0; + expectedFinishes++; + operation.reset(); + fn() + } else { + finalCallback(); + } + }); + }; + + fn(); +})(); + +(function testErrors() { + var operation = retry.operation(); + + var error = new Error('some error'); + var error2 = new Error('some other error'); + operation._errors.push(error); + operation._errors.push(error2); + + assert.deepEqual(operation.errors(), [error, error2]); +})(); + +(function testMainErrorReturnsMostFrequentError() { + var operation = retry.operation(); + var error = new Error('some error'); + var error2 = new Error('some other error'); + + operation._errors.push(error); + operation._errors.push(error2); + operation._errors.push(error); + + assert.strictEqual(operation.mainError(), error); +})(); + +(function testMainErrorReturnsLastErrorOnEqualCount() { + var operation = retry.operation(); + var error = new Error('some error'); + var error2 = new Error('some other error'); + + operation._errors.push(error); + operation._errors.push(error2); + + assert.strictEqual(operation.mainError(), error2); +})(); + +(function testAttempt() { + var operation = retry.operation(); + var fn = new Function(); + + var timeoutOpts = { + timeout: 1, + cb: function() {} + }; + operation.attempt(fn, timeoutOpts); + + assert.strictEqual(fn, operation._fn); + assert.strictEqual(timeoutOpts.timeout, operation._operationTimeout); + assert.strictEqual(timeoutOpts.cb, operation._operationTimeoutCb); +})(); + +(function testRetry() { + var error = new Error('some error'); + var operation = retry.operation([1, 2, 3]); + var attempts = 0; + + var finalCallback = fake.callback('finalCallback'); + fake.expectAnytime(finalCallback); + + var fn = function() { + operation.attempt(function(currentAttempt) { + attempts++; + assert.equal(currentAttempt, attempts); + if (operation.retry(error)) { + return; + } + + assert.strictEqual(attempts, 4); + assert.strictEqual(operation.attempts(), attempts); + assert.strictEqual(operation.mainError(), error); + finalCallback(); + }); + }; + + fn(); +})(); + +(function testRetryForever() { + var error = new Error('some error'); + var operation = retry.operation({ retries: 3, forever: true }); + var attempts = 0; + + var finalCallback = fake.callback('finalCallback'); + fake.expectAnytime(finalCallback); + + var fn = function() { + operation.attempt(function(currentAttempt) { + attempts++; + assert.equal(currentAttempt, attempts); + if (attempts !== 6 && operation.retry(error)) { + return; + } + + assert.strictEqual(attempts, 6); + assert.strictEqual(operation.attempts(), attempts); + assert.strictEqual(operation.mainError(), error); + finalCallback(); + }); + }; + + fn(); +})(); + +(function testRetryForeverNoRetries() { + var error = new Error('some error'); + var delay = 50 + var operation = retry.operation({ + retries: null, + forever: true, + minTimeout: delay, + maxTimeout: delay + }); + + var attempts = 0; + var startTime = new Date().getTime(); + + var finalCallback = fake.callback('finalCallback'); + fake.expectAnytime(finalCallback); + + var fn = function() { + operation.attempt(function(currentAttempt) { + attempts++; + assert.equal(currentAttempt, attempts); + if (attempts !== 4 && operation.retry(error)) { + return; + } + + var endTime = new Date().getTime(); + var minTime = startTime + (delay * 3); + var maxTime = minTime + 20 // add a little headroom for code execution time + assert(endTime >= minTime) + assert(endTime < maxTime) + assert.strictEqual(attempts, 4); + assert.strictEqual(operation.attempts(), attempts); + assert.strictEqual(operation.mainError(), error); + finalCallback(); + }); + }; + + fn(); +})(); + +(function testStop() { + var error = new Error('some error'); + var operation = retry.operation([1, 2, 3]); + var attempts = 0; + + var finalCallback = fake.callback('finalCallback'); + fake.expectAnytime(finalCallback); + + var fn = function() { + operation.attempt(function(currentAttempt) { + attempts++; + assert.equal(currentAttempt, attempts); + + if (attempts === 2) { + operation.stop(); + + assert.strictEqual(attempts, 2); + assert.strictEqual(operation.attempts(), attempts); + assert.strictEqual(operation.mainError(), error); + finalCallback(); + } + + if (operation.retry(error)) { + return; + } + }); + }; + + fn(); +})(); + +(function testMaxRetryTime() { + var error = new Error('some error'); + var maxRetryTime = 30; + var operation = retry.operation({ + minTimeout: 1, + maxRetryTime: maxRetryTime + }); + var attempts = 0; + + var finalCallback = fake.callback('finalCallback'); + fake.expectAnytime(finalCallback); + + var longAsyncFunction = function (wait, callback){ + setTimeout(callback, wait); + }; + + var fn = function() { + var startTime = new Date().getTime(); + operation.attempt(function(currentAttempt) { + attempts++; + assert.equal(currentAttempt, attempts); + + if (attempts !== 2) { + if (operation.retry(error)) { + return; + } + } else { + var curTime = new Date().getTime(); + longAsyncFunction(maxRetryTime - (curTime - startTime - 1), function(){ + if (operation.retry(error)) { + assert.fail('timeout should be occurred'); + return; + } + + assert.strictEqual(operation.mainError(), error); + finalCallback(); + }); + } + }); + }; + + fn(); +})(); diff --git a/deps/npm/node_modules/pacote/node_modules/retry/test/integration/test-retry-wrap.js b/deps/npm/node_modules/pacote/node_modules/retry/test/integration/test-retry-wrap.js new file mode 100644 index 00000000000000..3d2b6bfa6436d2 --- /dev/null +++ b/deps/npm/node_modules/pacote/node_modules/retry/test/integration/test-retry-wrap.js @@ -0,0 +1,101 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var retry = require(common.dir.lib + '/retry'); + +function getLib() { + return { + fn1: function() {}, + fn2: function() {}, + fn3: function() {} + }; +} + +(function wrapAll() { + var lib = getLib(); + retry.wrap(lib); + assert.equal(lib.fn1.name, 'bound retryWrapper'); + assert.equal(lib.fn2.name, 'bound retryWrapper'); + assert.equal(lib.fn3.name, 'bound retryWrapper'); +}()); + +(function wrapAllPassOptions() { + var lib = getLib(); + retry.wrap(lib, {retries: 2}); + assert.equal(lib.fn1.name, 'bound retryWrapper'); + assert.equal(lib.fn2.name, 'bound retryWrapper'); + assert.equal(lib.fn3.name, 'bound retryWrapper'); + assert.equal(lib.fn1.options.retries, 2); + assert.equal(lib.fn2.options.retries, 2); + assert.equal(lib.fn3.options.retries, 2); +}()); + +(function wrapDefined() { + var lib = getLib(); + retry.wrap(lib, ['fn2', 'fn3']); + assert.notEqual(lib.fn1.name, 'bound retryWrapper'); + assert.equal(lib.fn2.name, 'bound retryWrapper'); + assert.equal(lib.fn3.name, 'bound retryWrapper'); +}()); + +(function wrapDefinedAndPassOptions() { + var lib = getLib(); + retry.wrap(lib, {retries: 2}, ['fn2', 'fn3']); + assert.notEqual(lib.fn1.name, 'bound retryWrapper'); + assert.equal(lib.fn2.name, 'bound retryWrapper'); + assert.equal(lib.fn3.name, 'bound retryWrapper'); + assert.equal(lib.fn2.options.retries, 2); + assert.equal(lib.fn3.options.retries, 2); +}()); + +(function runWrappedWithoutError() { + var callbackCalled; + var lib = {method: function(a, b, callback) { + assert.equal(a, 1); + assert.equal(b, 2); + assert.equal(typeof callback, 'function'); + callback(); + }}; + retry.wrap(lib); + lib.method(1, 2, function() { + callbackCalled = true; + }); + assert.ok(callbackCalled); +}()); + +(function runWrappedSeveralWithoutError() { + var callbacksCalled = 0; + var lib = { + fn1: function (a, callback) { + assert.equal(a, 1); + assert.equal(typeof callback, 'function'); + callback(); + }, + fn2: function (a, callback) { + assert.equal(a, 2); + assert.equal(typeof callback, 'function'); + callback(); + } + }; + retry.wrap(lib, {}, ['fn1', 'fn2']); + lib.fn1(1, function() { + callbacksCalled++; + }); + lib.fn2(2, function() { + callbacksCalled++; + }); + assert.equal(callbacksCalled, 2); +}()); + +(function runWrappedWithError() { + var callbackCalled; + var lib = {method: function(callback) { + callback(new Error('Some error')); + }}; + retry.wrap(lib, {retries: 1}); + lib.method(function(err) { + callbackCalled = true; + assert.ok(err instanceof Error); + }); + assert.ok(!callbackCalled); +}()); diff --git a/deps/npm/node_modules/pacote/node_modules/retry/test/integration/test-timeouts.js b/deps/npm/node_modules/pacote/node_modules/retry/test/integration/test-timeouts.js new file mode 100644 index 00000000000000..7206b0fb0b01d0 --- /dev/null +++ b/deps/npm/node_modules/pacote/node_modules/retry/test/integration/test-timeouts.js @@ -0,0 +1,69 @@ +var common = require('../common'); +var assert = common.assert; +var retry = require(common.dir.lib + '/retry'); + +(function testDefaultValues() { + var timeouts = retry.timeouts(); + + assert.equal(timeouts.length, 10); + assert.equal(timeouts[0], 1000); + assert.equal(timeouts[1], 2000); + assert.equal(timeouts[2], 4000); +})(); + +(function testDefaultValuesWithRandomize() { + var minTimeout = 5000; + var timeouts = retry.timeouts({ + minTimeout: minTimeout, + randomize: true + }); + + assert.equal(timeouts.length, 10); + assert.ok(timeouts[0] > minTimeout); + assert.ok(timeouts[1] > timeouts[0]); + assert.ok(timeouts[2] > timeouts[1]); +})(); + +(function testPassedTimeoutsAreUsed() { + var timeoutsArray = [1000, 2000, 3000]; + var timeouts = retry.timeouts(timeoutsArray); + assert.deepEqual(timeouts, timeoutsArray); + assert.notStrictEqual(timeouts, timeoutsArray); +})(); + +(function testTimeoutsAreWithinBoundaries() { + var minTimeout = 1000; + var maxTimeout = 10000; + var timeouts = retry.timeouts({ + minTimeout: minTimeout, + maxTimeout: maxTimeout + }); + for (var i = 0; i < timeouts; i++) { + assert.ok(timeouts[i] >= minTimeout); + assert.ok(timeouts[i] <= maxTimeout); + } +})(); + +(function testTimeoutsAreIncremental() { + var timeouts = retry.timeouts(); + var lastTimeout = timeouts[0]; + for (var i = 0; i < timeouts; i++) { + assert.ok(timeouts[i] > lastTimeout); + lastTimeout = timeouts[i]; + } +})(); + +(function testTimeoutsAreIncrementalForFactorsLessThanOne() { + var timeouts = retry.timeouts({ + retries: 3, + factor: 0.5 + }); + + var expected = [250, 500, 1000]; + assert.deepEqual(expected, timeouts); +})(); + +(function testRetries() { + var timeouts = retry.timeouts({retries: 2}); + assert.strictEqual(timeouts.length, 2); +})(); diff --git a/deps/npm/node_modules/pacote/package.json b/deps/npm/node_modules/pacote/package.json index 959cb1ec488314..8c25e68330bdcc 100644 --- a/deps/npm/node_modules/pacote/package.json +++ b/deps/npm/node_modules/pacote/package.json @@ -1,6 +1,6 @@ { "name": "pacote", - "version": "11.2.4", + "version": "11.2.6", "description": "JavaScript package downloader", "author": "Isaac Z. Schlueter (https://izs.me)", "bin": { @@ -25,7 +25,7 @@ "mutate-fs": "^2.1.1", "npm-registry-mock": "^1.3.1", "require-inject": "^1.4.4", - "tap": "^14.10.8" + "tap": "^14.11.0" }, "files": [ "lib/**/*.js" @@ -37,9 +37,9 @@ ], "dependencies": { "@npmcli/git": "^2.0.1", - "@npmcli/installed-package-contents": "^1.0.5", + "@npmcli/installed-package-contents": "^1.0.6", "@npmcli/promise-spawn": "^1.2.0", - "@npmcli/run-script": "^1.3.0", + "@npmcli/run-script": "^1.8.2", "cacache": "^15.0.5", "chownr": "^2.0.0", "fs-minipass": "^2.1.0", @@ -50,10 +50,10 @@ "npm-packlist": "^2.1.4", "npm-pick-manifest": "^6.0.0", "npm-registry-fetch": "^9.0.0", - "promise-retry": "^1.1.1", - "read-package-json-fast": "^1.1.3", + "promise-retry": "^2.0.1", + "read-package-json-fast": "^2.0.1", "rimraf": "^3.0.2", - "ssri": "^8.0.0", + "ssri": "^8.0.1", "tar": "^6.1.0" }, "engines": { diff --git a/deps/npm/node_modules/read-package-json-fast/index.js b/deps/npm/node_modules/read-package-json-fast/index.js index bfef5d6abcacc0..cf373029ddf686 100644 --- a/deps/npm/node_modules/read-package-json-fast/index.js +++ b/deps/npm/node_modules/read-package-json-fast/index.js @@ -13,7 +13,7 @@ const normalizePackageBin = require('npm-normalize-package-bin') const normalize = data => { add_id(data) fixBundled(data) - foldinOptionalDeps(data) + pruneRepeatedOptionals(data) fixScripts(data) fixFunding(data) normalizePackageBin(data) @@ -28,14 +28,20 @@ const add_id = data => { return data } -const foldinOptionalDeps = data => { +// it was once common practice to list deps both in optionalDependencies +// and in dependencies, to support npm versions that did not know abbout +// optionalDependencies. This is no longer a relevant need, so duplicating +// the deps in two places is unnecessary and excessive. +const pruneRepeatedOptionals = data => { const od = data.optionalDependencies + const dd = data.dependencies || {} if (od && typeof od === 'object') { - data.dependencies = data.dependencies || {} - for (const [name, spec] of Object.entries(od)) { - data.dependencies[name] = spec + for (const name of Object.keys(od)) { + delete dd[name] } } + if (Object.keys(dd).length === 0) + delete data.dependencies return data } diff --git a/deps/npm/node_modules/read-package-json-fast/package.json b/deps/npm/node_modules/read-package-json-fast/package.json index a59a3b2e86e9bc..aa5f5d87007b86 100644 --- a/deps/npm/node_modules/read-package-json-fast/package.json +++ b/deps/npm/node_modules/read-package-json-fast/package.json @@ -1,6 +1,6 @@ { "name": "read-package-json-fast", - "version": "1.2.1", + "version": "2.0.1", "description": "Like read-package-json, but faster", "author": "Isaac Z. Schlueter (https://izs.me)", "license": "ISC", @@ -11,6 +11,9 @@ "postversion": "npm publish", "postpublish": "git push origin --follow-tags" }, + "engines": { + "node": ">=10" + }, "tap": { "check-coverage": true }, diff --git a/deps/npm/package.json b/deps/npm/package.json index 2eecfdbfc04569..8f88726ad1e04e 100644 --- a/deps/npm/package.json +++ b/deps/npm/package.json @@ -1,5 +1,5 @@ { - "version": "7.5.2", + "version": "7.5.3", "name": "npm", "description": "a package manager for JavaScript", "keywords": [ @@ -42,10 +42,11 @@ "./package.json": "./package.json" }, "dependencies": { - "@npmcli/arborist": "^2.1.1", + "@npmcli/arborist": "^2.2.1", "@npmcli/ci-detect": "^1.2.0", "@npmcli/config": "^1.2.9", - "@npmcli/run-script": "^1.8.1", + "@npmcli/installed-package-contents": "^1.0.7", + "@npmcli/run-script": "^1.8.2", "abbrev": "~1.1.1", "ansicolors": "~0.3.2", "ansistyles": "~0.1.3", @@ -58,10 +59,10 @@ "cli-table3": "^0.6.0", "columnify": "~1.5.4", "glob": "^7.1.4", - "graceful-fs": "^4.2.3", + "graceful-fs": "^4.2.5", "hosted-git-info": "^3.0.8", "ini": "^2.0.0", - "init-package-json": "^2.0.1", + "init-package-json": "^2.0.2", "is-cidr": "^4.0.2", "json-parse-even-better-errors": "^2.3.1", "leven": "^3.1.0", @@ -74,7 +75,7 @@ "libnpmpublish": "^4.0.0", "libnpmsearch": "^3.1.0", "libnpmteam": "^2.0.2", - "libnpmversion": "^1.0.7", + "libnpmversion": "^1.0.8", "make-fetch-happen": "^8.0.13", "minipass": "^3.1.3", "minipass-pipeline": "^1.2.4", @@ -91,12 +92,12 @@ "npm-user-validate": "^1.0.1", "npmlog": "~4.1.2", "opener": "^1.5.2", - "pacote": "^11.2.3", + "pacote": "^11.2.6", "parse-conflict-json": "^1.1.1", "qrcode-terminal": "^0.12.0", "read": "~1.0.7", "read-package-json": "^3.0.0", - "read-package-json-fast": "^1.2.1", + "read-package-json-fast": "^2.0.1", "readdir-scoped-modules": "^1.1.0", "rimraf": "^3.0.2", "semver": "^7.3.4", @@ -181,7 +182,7 @@ ], "devDependencies": { "cmark-gfm": "^0.8.5", - "eslint": "^7.18.0", + "eslint": "^7.19.0", "eslint-plugin-import": "^2.22.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.2.1", diff --git a/deps/npm/scripts/install.sh b/deps/npm/scripts/install.sh index 4458de87faefbe..8c0ba3de72f12c 100755 --- a/deps/npm/scripts/install.sh +++ b/deps/npm/scripts/install.sh @@ -18,7 +18,7 @@ if [ "x$0" = "xsh" ]; then # which is a bit cuter. But on others, &1 is already closed, # so catting to another script file won't do anything. # Follow Location: headers, and fail on errors - curl -f -L -s https://www.npmjs.org/install.sh > npm-install-$$.sh + curl -q -f -L -s https://www.npmjs.org/install.sh > npm-install-$$.sh ret=$? if [ $ret -eq 0 ]; then (exit 0) @@ -134,7 +134,7 @@ fi # need to echo "" after, because Posix sed doesn't treat EOF # as an implied end of line. -url=`(curl -SsL https://registry.npmjs.org/npm/$t; echo "") \ +url=`(curl -qSsL https://registry.npmjs.org/npm/$t; echo "") \ | sed -e 's/^.*tarball":"//' \ | sed -e 's/".*$//'` @@ -142,7 +142,7 @@ ret=$? if [ "x$url" = "x" ]; then ret=125 # try without the -e arg to sed. - url=`(curl -SsL https://registry.npmjs.org/npm/$t; echo "") \ + url=`(curl -qSsL https://registry.npmjs.org/npm/$t; echo "") \ | sed 's/^.*tarball":"//' \ | sed 's/".*$//'` ret=$? @@ -159,7 +159,7 @@ fi echo "fetching: $url" >&2 cd "$TMP" \ - && curl -SsL -o npm.tgz "$url" \ + && curl -qSsL -o npm.tgz "$url" \ && $tar -xzf npm.tgz \ && cd "$TMP"/package \ && echo "removing existing npm" \ diff --git a/deps/npm/tap-snapshots/test-lib-utils-open-url.js-TAP.test.js b/deps/npm/tap-snapshots/test-lib-utils-open-url.js-TAP.test.js new file mode 100644 index 00000000000000..8c8159ebcfc04c --- /dev/null +++ b/deps/npm/tap-snapshots/test-lib-utils-open-url.js-TAP.test.js @@ -0,0 +1,25 @@ +/* IMPORTANT + * This snapshot file is auto-generated, but designed for humans. + * It should be checked into source control and tracked carefully. + * Re-generate by setting TAP_SNAPSHOT=1 and running tests. + * Make sure to inspect the output below. Do not ignore changes! + */ +'use strict' +exports[`test/lib/utils/open-url.js TAP prints where to go when browser is disabled > printed expected message 1`] = ` +npm home: + https://www.npmjs.com + +` + +exports[`test/lib/utils/open-url.js TAP prints where to go when browser is disabled and json is enabled > printed expected message 1`] = ` +{ + "title": "npm home", + "url": "https://www.npmjs.com" +} +` + +exports[`test/lib/utils/open-url.js TAP prints where to go when given browser does not exist > printed expected message 1`] = ` +npm home: + https://www.npmjs.com + +` diff --git a/deps/npm/test/lib/help.js b/deps/npm/test/lib/help.js index 17018acc61620e..40a0354210b92e 100644 --- a/deps/npm/test/lib/help.js +++ b/deps/npm/test/lib/help.js @@ -55,12 +55,13 @@ const glob = (p, cb) => { let spawnBin = null let spawnArgs = null +let spawnCode = 0 const spawn = (bin, args) => { spawnBin = bin spawnArgs = args const spawnEmitter = new EventEmitter() process.nextTick(() => { - spawnEmitter.emit('close', 0) + spawnEmitter.emit('exit', spawnCode) }) return spawnEmitter } @@ -76,7 +77,9 @@ const help = requireInject('../../lib/help.js', { '../../lib/utils/npm-usage.js': npmUsage, '../../lib/utils/open-url.js': openUrl, '../../lib/utils/output.js': output, - '../../lib/utils/spawn.js': spawn, + child_process: { + spawn, + }, glob, }) @@ -339,6 +342,29 @@ test('npm help ?(un)star', t => { }) }) +test('npm help - woman viewer propagates errors', t => { + npmConfig.viewer = 'woman' + spawnCode = 1 + globResult = [ + '/root/man/man1/npm-star.1', + '/root/man/man1/npm-unstar.1', + ] + t.teardown(() => { + npmConfig.viewer = undefined + spawnCode = 0 + globResult = globDefaults + spawnBin = null + spawnArgs = null + }) + + return help(['?(un)star'], (err) => { + t.match(err, /help process exited with code: 1/, 'received the correct error') + t.equal(spawnBin, 'emacsclient', 'maps woman to emacs correctly') + t.strictSame(spawnArgs, ['-e', `(woman-find-file '/root/man/man1/npm-unstar.1')`], 'passes the correct arguments') + t.end() + }) +}) + test('npm help un*', t => { globResult = [ '/root/man/man1/npm-unstar.1', @@ -360,3 +386,25 @@ test('npm help un*', t => { t.end() }) }) + +test('npm help - man viewer propagates errors', t => { + spawnCode = 1 + globResult = [ + '/root/man/man1/npm-unstar.1', + '/root/man/man1/npm-uninstall.1', + '/root/man/man1/npm-unpublish.1', + ] + t.teardown(() => { + spawnCode = 0 + globResult = globDefaults + spawnBin = null + spawnArgs = null + }) + + return help(['un*'], (err) => { + t.match(err, /help process exited with code: 1/, 'received correct error') + t.equal(spawnBin, 'man', 'calls man by default') + t.strictSame(spawnArgs, ['1', 'npm-unstar'], 'passes the correct arguments') + t.end() + }) +}) diff --git a/deps/npm/test/lib/publish.js b/deps/npm/test/lib/publish.js index f0ce0b966533c0..6d5cebf5406988 100644 --- a/deps/npm/test/lib/publish.js +++ b/deps/npm/test/lib/publish.js @@ -4,19 +4,40 @@ const requireInject = require('require-inject') // mock config const {defaults} = require('../../lib/utils/config.js') const credentials = { - token: 'asdfasdf', - alwaysAuth: false, + 'https://unauthed.registry': { + email: 'me@example.com', + }, + 'https://scope.specific.registry': { + token: 'some.registry.token', + alwaysAuth: false, + }, + 'https://some.registry': { + token: 'some.registry.token', + alwaysAuth: false, + }, + 'https://registry.npmjs.org/': { + token: 'npmjs.registry.token', + alwaysAuth: false, + }, } const config = { list: [defaults], - getCredentialsByURI: () => credentials, } + +const registryCredentials = (t, registry) => { + return (uri) => { + t.same(uri, registry, 'gets credentials for expected registry') + return credentials[uri] + } +} + const fs = require('fs') t.test('should publish with libnpmpublish, respecting publishConfig', (t) => { - t.plan(5) + t.plan(6) - const publishConfig = { registry: 'https://some.registry' } + const registry = 'https://some.registry' + const publishConfig = { registry } const testDir = t.testdir({ 'package.json': JSON.stringify({ name: 'my-cool-pkg', @@ -30,9 +51,12 @@ t.test('should publish with libnpmpublish, respecting publishConfig', (t) => { flatOptions: { json: true, defaultTag: 'latest', - registry: 'https://registry.npmjs.org', + registry, + }, + config: { + ...config, + getCredentialsByURI: registryCredentials(t, registry), }, - config, }, '../../lib/utils/tar.js': { getContents: () => ({ @@ -71,8 +95,9 @@ t.test('should publish with libnpmpublish, respecting publishConfig', (t) => { }) t.test('re-loads publishConfig if added during script process', (t) => { - t.plan(5) - const publishConfig = { registry: 'https://some.registry' } + t.plan(6) + const registry = 'https://some.registry' + const publishConfig = { registry } const testDir = t.testdir({ 'package.json': JSON.stringify({ name: 'my-cool-pkg', @@ -87,7 +112,10 @@ t.test('re-loads publishConfig if added during script process', (t) => { defaultTag: 'latest', registry: 'https://registry.npmjs.org/', }, - config, + config: { + ...config, + getCredentialsByURI: registryCredentials(t, registry), + }, }, '../../lib/utils/tar.js': { getContents: () => ({ @@ -112,7 +140,7 @@ t.test('re-loads publishConfig if added during script process', (t) => { t.match(manifest, { name: 'my-cool-pkg', version: '1.0.0' }, 'gets manifest') t.isa(tarData, Buffer, 'tarData is a buffer') t.ok(opts, 'gets opts object') - t.same(opts.registry, publishConfig.registry, 'publishConfig is passed through') + t.same(opts.registry, registry, 'publishConfig is passed through') }, }, }) @@ -124,9 +152,10 @@ t.test('re-loads publishConfig if added during script process', (t) => { }) }) -t.test('should not log if silent', (t) => { +t.test('should not log if silent (dry run)', (t) => { t.plan(2) + const registry = 'https://registry.npmjs.org' const testDir = t.testdir({ 'package.json': JSON.stringify({ name: 'my-cool-pkg', @@ -140,9 +169,14 @@ t.test('should not log if silent', (t) => { json: false, defaultTag: 'latest', dryRun: true, - registry: 'https://registry.npmjs.org/', + registry, + }, + config: { + ...config, + getCredentialsByURI: () => { + throw new Error('should not call getCredentialsByURI in dry run') + }, }, - config, }, '../../lib/utils/tar.js': { getContents: () => ({}), @@ -164,7 +198,7 @@ t.test('should not log if silent', (t) => { libnpmpack: async () => '', libnpmpublish: { publish: (manifest, tarData, opts) => { - throw new Error('should not call libnpmpublish!') + throw new Error('should not call libnpmpublish in dry run') }, }, }) @@ -176,8 +210,10 @@ t.test('should not log if silent', (t) => { }) }) -t.test('should log tarball contents', (t) => { +t.test('should log tarball contents (dry run)', (t) => { t.plan(3) + + const registry = 'https://registry.npmjs.org' const testDir = t.testdir({ 'package.json': JSON.stringify({ name: 'my-cool-pkg', @@ -191,12 +227,12 @@ t.test('should log tarball contents', (t) => { json: false, defaultTag: 'latest', dryRun: true, - registry: 'https://registry.npmjs.org/', + registry, }, config: { ...config, getCredentialsByURI: () => { - throw new Error('should not call getCredentialsByURI!') + throw new Error('should not call getCredentialsByURI in dry run') }}, }, '../../lib/utils/tar.js': { @@ -216,7 +252,7 @@ t.test('should log tarball contents', (t) => { libnpmpack: async () => '', libnpmpublish: { publish: () => { - throw new Error('should not call libnpmpublish!') + throw new Error('should not call libnpmpublish in dry run') }, }, }) @@ -246,12 +282,15 @@ t.test('shows usage with wrong set of arguments', (t) => { t.test('throws when invalid tag', (t) => { t.plan(1) + + const registry = 'https://registry.npmjs.org' + const publish = requireInject('../../lib/publish.js', { '../../lib/npm.js': { flatOptions: { json: false, defaultTag: '0.0.13', - registry: 'https://registry.npmjs.org/', + registry, }, config, }, @@ -265,7 +304,9 @@ t.test('throws when invalid tag', (t) => { }) t.test('can publish a tarball', t => { - t.plan(3) + t.plan(4) + + const registry = 'https://registry.npmjs.org/' const testDir = t.testdir({ package: { 'package.json': JSON.stringify({ @@ -291,9 +332,12 @@ t.test('can publish a tarball', t => { flatOptions: { json: true, defaultTag: 'latest', - registry: 'https://registry.npmjs.org/', + registry, + }, + config: { + ...config, + getCredentialsByURI: registryCredentials(t, registry), }, - config, }, '../../lib/utils/tar.js': { getContents: () => ({ @@ -323,39 +367,25 @@ t.test('can publish a tarball', t => { }) }) -t.test('throw if no registry', async t => { - t.plan(1) - const publish = requireInject('../../lib/publish.js', { - '../../lib/npm.js': { - flatOptions: { - json: false, - registry: null, - }, - config, - }, - }) - - return publish([], (err) => { - t.match(err, { - message: 'No registry specified.', - code: 'ENOREGISTRY', - }, 'throws when registry unset') - }) -}) - t.test('throw if not logged in', async t => { - t.plan(1) + t.plan(2) + const registry = 'https://unauthed.registry' + const publish = requireInject('../../lib/publish.js', { + '../../lib/utils/tar.js': { + getContents: () => ({ + id: 'someid', + }), + logTar: () => {}, + }, '../../lib/npm.js': { flatOptions: { json: false, - registry: 'https://registry.npmjs.org/', + registry, }, config: { ...config, - getCredentialsByURI: () => ({ - email: 'me@example.com', - }), + getCredentialsByURI: registryCredentials(t, registry), }, }, }) @@ -369,9 +399,10 @@ t.test('throw if not logged in', async t => { }) t.test('read registry only from publishConfig', t => { - t.plan(3) + t.plan(4) - const publishConfig = { registry: 'https://some.registry' } + const registry = 'https://some.registry' + const publishConfig = { registry } const testDir = t.testdir({ 'package.json': JSON.stringify({ name: 'my-cool-pkg', @@ -385,7 +416,10 @@ t.test('read registry only from publishConfig', t => { flatOptions: { json: false, }, - config, + config: { + ...config, + getCredentialsByURI: registryCredentials(t, registry), + }, }, '../../lib/utils/tar.js': { getContents: () => ({ @@ -397,7 +431,7 @@ t.test('read registry only from publishConfig', t => { libnpmpublish: { publish: (manifest, tarData, opts) => { t.match(manifest, { name: 'my-cool-pkg', version: '1.0.0' }, 'gets manifest') - t.same(opts.registry, publishConfig.registry, 'publishConfig is passed through') + t.same(opts.registry, registry, 'publishConfig is passed through') }, }, }) @@ -408,3 +442,44 @@ t.test('read registry only from publishConfig', t => { t.pass('got to callback') }) }) + +t.test('should check auth for scope specific registry', t => { + const testDir = t.testdir({ + 'package.json': JSON.stringify({ + name: '@npm/my-cool-pkg', + version: '1.0.0', + }, null, 2), + }) + + const registry = 'https://scope.specific.registry' + const publish = requireInject('../../lib/publish.js', { + '../../lib/npm.js': { + flatOptions: { + json: false, + '@npm:registry': registry, + }, + config: { + ...config, + getCredentialsByURI: registryCredentials(t, registry), + }, + }, + '../../lib/utils/tar.js': { + getContents: () => ({ + id: 'someid', + }), + logTar: () => {}, + }, + '../../lib/utils/output.js': () => {}, + '../../lib/utils/otplease.js': (opts, fn) => { + return Promise.resolve().then(() => fn(opts)) + }, + libnpmpublish: { + publish: () => '', + }, + }) + return publish([testDir], (er) => { + if (er) + throw er + t.pass('got to callback') + }) +}) diff --git a/deps/npm/test/lib/utils/open-url.js b/deps/npm/test/lib/utils/open-url.js new file mode 100644 index 00000000000000..ce1783dadcd7bb --- /dev/null +++ b/deps/npm/test/lib/utils/open-url.js @@ -0,0 +1,165 @@ +const { test } = require('tap') +const requireInject = require('require-inject') + +const npm = { + _config: { + json: false, + browser: true, + }, + config: { + get: (k) => npm._config[k], + set: (k, v) => { + npm._config[k] = v + }, + }, +} + +const OUTPUT = [] +const output = (...args) => OUTPUT.push(args) + +let openerUrl = null +let openerOpts = null +let openerResult = null +const opener = (url, opts, cb) => { + openerUrl = url + openerOpts = opts + return cb(openerResult) +} + +const openUrl = requireInject('../../../lib/utils/open-url.js', { + '../../../lib/npm.js': npm, + '../../../lib/utils/output.js': output, + opener, +}) + +test('opens a url', (t) => { + t.teardown(() => { + openerUrl = null + openerOpts = null + OUTPUT.length = 0 + }) + openUrl('https://www.npmjs.com', 'npm home', (err) => { + if (err) + throw err + + t.equal(openerUrl, 'https://www.npmjs.com', 'opened the given url') + t.same(openerOpts, { command: null }, 'passed command as null (the default)') + t.same(OUTPUT, [], 'printed no output') + t.done() + }) +}) + +test('returns error for non-https and non-file url', (t) => { + t.teardown(() => { + openerUrl = null + openerOpts = null + OUTPUT.length = 0 + }) + openUrl('ftp://www.npmjs.com', 'npm home', (err) => { + t.match(err, /Invalid URL/, 'got the correct error') + t.equal(openerUrl, null, 'did not open') + t.same(openerOpts, null, 'did not open') + t.same(OUTPUT, [], 'printed no output') + t.done() + }) +}) + +test('returns error for non-parseable url', (t) => { + t.teardown(() => { + openerUrl = null + openerOpts = null + OUTPUT.length = 0 + }) + openUrl('git+ssh://user@host:repo.git', 'npm home', (err) => { + t.match(err, /Invalid URL/, 'got the correct error') + t.equal(openerUrl, null, 'did not open') + t.same(openerOpts, null, 'did not open') + t.same(OUTPUT, [], 'printed no output') + t.done() + }) +}) + +test('opens a url with the given browser', (t) => { + npm.config.set('browser', 'chrome') + t.teardown(() => { + openerUrl = null + openerOpts = null + OUTPUT.length = 0 + npm.config.set('browser', true) + }) + openUrl('https://www.npmjs.com', 'npm home', (err) => { + if (err) + throw err + + t.equal(openerUrl, 'https://www.npmjs.com', 'opened the given url') + t.same(openerOpts, { command: 'chrome' }, 'passed the given browser as command') + t.same(OUTPUT, [], 'printed no output') + t.done() + }) +}) + +test('prints where to go when browser is disabled', (t) => { + npm.config.set('browser', false) + t.teardown(() => { + openerUrl = null + openerOpts = null + OUTPUT.length = 0 + npm.config.set('browser', true) + }) + openUrl('https://www.npmjs.com', 'npm home', (err) => { + if (err) + throw err + + t.equal(openerUrl, null, 'did not open') + t.same(openerOpts, null, 'did not open') + t.equal(OUTPUT.length, 1, 'got one logged message') + t.equal(OUTPUT[0].length, 1, 'logged message had one value') + t.matchSnapshot(OUTPUT[0][0], 'printed expected message') + t.done() + }) +}) + +test('prints where to go when browser is disabled and json is enabled', (t) => { + npm.config.set('browser', false) + npm.config.set('json', true) + t.teardown(() => { + openerUrl = null + openerOpts = null + OUTPUT.length = 0 + npm.config.set('browser', true) + npm.config.set('json', false) + }) + openUrl('https://www.npmjs.com', 'npm home', (err) => { + if (err) + throw err + + t.equal(openerUrl, null, 'did not open') + t.same(openerOpts, null, 'did not open') + t.equal(OUTPUT.length, 1, 'got one logged message') + t.equal(OUTPUT[0].length, 1, 'logged message had one value') + t.matchSnapshot(OUTPUT[0][0], 'printed expected message') + t.done() + }) +}) + +test('prints where to go when given browser does not exist', (t) => { + npm.config.set('browser', 'firefox') + openerResult = Object.assign(new Error('failed'), { code: 'ENOENT' }) + t.teardown(() => { + openerUrl = null + openerOpts = null + OUTPUT.length = 0 + npm.config.set('browser', true) + }) + openUrl('https://www.npmjs.com', 'npm home', (err) => { + if (err) + throw err + + t.equal(openerUrl, 'https://www.npmjs.com', 'tried to open the correct url') + t.same(openerOpts, { command: 'firefox' }, 'tried to use the correct browser') + t.equal(OUTPUT.length, 1, 'got one logged message') + t.equal(OUTPUT[0].length, 1, 'logged message had one value') + t.matchSnapshot(OUTPUT[0][0], 'printed expected message') + t.done() + }) +}) diff --git a/deps/npm/test/lib/utils/otplease.js b/deps/npm/test/lib/utils/otplease.js new file mode 100644 index 00000000000000..048856b4857707 --- /dev/null +++ b/deps/npm/test/lib/utils/otplease.js @@ -0,0 +1,94 @@ +const { test } = require('tap') +const requireInject = require('require-inject') + +const readUserInfo = { + otp: async () => '1234', +} + +const otplease = requireInject('../../../lib/utils/otplease.js', { + '../../../lib/utils/read-user-info.js': readUserInfo, +}) + +test('prompts for otp for EOTP', async (t) => { + const stdinTTY = process.stdin.isTTY + const stdoutTTY = process.stdout.isTTY + process.stdin.isTTY = true + process.stdout.isTTY = true + t.teardown(() => { + process.stdin.isTTY = stdinTTY + process.stdout.isTTY = stdoutTTY + }) + + let runs = 0 + const fn = async (opts) => { + if (++runs === 1) + throw Object.assign(new Error('nope'), { code: 'EOTP' }) + + t.equal(opts.some, 'prop', 'carried original options') + t.equal(opts.otp, '1234', 'received the otp') + t.done() + } + + await otplease({ some: 'prop' }, fn) +}) + +test('prompts for otp for 401', async (t) => { + const stdinTTY = process.stdin.isTTY + const stdoutTTY = process.stdout.isTTY + process.stdin.isTTY = true + process.stdout.isTTY = true + t.teardown(() => { + process.stdin.isTTY = stdinTTY + process.stdout.isTTY = stdoutTTY + }) + + let runs = 0 + const fn = async (opts) => { + if (++runs === 1) { + throw Object.assign(new Error('nope'), { + code: 'E401', + body: 'one-time pass required', + }) + } + + t.equal(opts.some, 'prop', 'carried original options') + t.equal(opts.otp, '1234', 'received the otp') + t.done() + } + + await otplease({ some: 'prop' }, fn) +}) + +test('does not prompt for non-otp errors', async (t) => { + const stdinTTY = process.stdin.isTTY + const stdoutTTY = process.stdout.isTTY + process.stdin.isTTY = true + process.stdout.isTTY = true + t.teardown(() => { + process.stdin.isTTY = stdinTTY + process.stdout.isTTY = stdoutTTY + }) + + const fn = async (opts) => { + throw new Error('nope') + } + + t.rejects(otplease({ some: 'prop' }, fn), { message: 'nope' }, 'rejects with the original error') +}) + +test('does not prompt if stdin or stdout is not a tty', async (t) => { + const stdinTTY = process.stdin.isTTY + const stdoutTTY = process.stdout.isTTY + process.stdin.isTTY = false + process.stdout.isTTY = false + t.teardown(() => { + process.stdin.isTTY = stdinTTY + process.stdout.isTTY = stdoutTTY + }) + + const fn = async (opts) => { + throw Object.assign(new Error('nope'), { code: 'EOTP' }) + } + + t.rejects(otplease({ some: 'prop' }, fn), { message: 'nope' }, 'rejects with the original error') +}) diff --git a/deps/npm/test/lib/utils/pulse-till-done.js b/deps/npm/test/lib/utils/pulse-till-done.js new file mode 100644 index 00000000000000..16c2d521dad082 --- /dev/null +++ b/deps/npm/test/lib/utils/pulse-till-done.js @@ -0,0 +1,35 @@ +const { test } = require('tap') +const requireInject = require('require-inject') + +let pulseStarted = null +const npmlog = { + gauge: { + pulse: () => { + if (pulseStarted) + pulseStarted() + }, + }, +} + +const pulseTillDone = requireInject('../../../lib/utils/pulse-till-done.js', { + npmlog, +}) + +test('pulses (with promise)', async (t) => { + t.teardown(() => { + pulseStarted = null + }) + + let resolver + const promise = new Promise(resolve => { + resolver = resolve + }) + + const result = pulseTillDone.withPromise(promise) + // wait until the gauge has fired at least once + await new Promise(resolve => { + pulseStarted = resolve + }) + resolver('value') + t.resolveMatch(result, 'value', 'returned the resolved promise') +}) diff --git a/deps/npm/test/lib/utils/read-user-info.js b/deps/npm/test/lib/utils/read-user-info.js new file mode 100644 index 00000000000000..99d85d66c4feb6 --- /dev/null +++ b/deps/npm/test/lib/utils/read-user-info.js @@ -0,0 +1,116 @@ +const { test } = require('tap') +const requireInject = require('require-inject') + +let readOpts = null +let readResult = null +const read = (opts, cb) => { + readOpts = opts + return cb(null, readResult) +} + +const npmlog = { + clearProgress: () => {}, + showProgress: () => {}, +} + +const npmUserValidate = { + username: (username) => { + if (username === 'invalid') + return new Error('invalid username') + + return null + }, + email: (email) => { + if (email.startsWith('invalid')) + return new Error('invalid email') + + return null + }, +} + +const readUserInfo = requireInject('../../../lib/utils/read-user-info.js', { + read, + npmlog, + 'npm-user-validate': npmUserValidate, +}) + +test('otp', async (t) => { + readResult = '1234' + t.teardown(() => { + readResult = null + readOpts = null + }) + const result = await readUserInfo.otp() + t.equal(result, '1234', 'received the otp') +}) + +test('password', async (t) => { + readResult = 'password' + t.teardown(() => { + readResult = null + readOpts = null + }) + const result = await readUserInfo.password() + t.equal(result, 'password', 'received the password') + t.match(readOpts, { + silent: true, + }, 'got the correct options') +}) + +test('username', async (t) => { + readResult = 'username' + t.teardown(() => { + readResult = null + readOpts = null + }) + const result = await readUserInfo.username() + t.equal(result, 'username', 'received the username') +}) + +test('username - invalid warns and retries', async (t) => { + readResult = 'invalid' + t.teardown(() => { + readResult = null + readOpts = null + }) + + let logMsg + const log = { + warn: (msg) => logMsg = msg, + } + const pResult = readUserInfo.username(null, null, { log }) + // have to swap it to a valid username after execution starts + // or it will loop forever + readResult = 'valid' + const result = await pResult + t.equal(result, 'valid', 'received the username') + t.equal(logMsg, 'invalid username') +}) + +test('email', async (t) => { + readResult = 'foo@bar.baz' + t.teardown(() => { + readResult = null + readOpts = null + }) + const result = await readUserInfo.email() + t.equal(result, 'foo@bar.baz', 'received the email') +}) + +test('email - invalid warns and retries', async (t) => { + readResult = 'invalid@bar.baz' + t.teardown(() => { + readResult = null + readOpts = null + }) + + let logMsg + const log = { + warn: (msg) => logMsg = msg, + } + const pResult = readUserInfo.email(null, null, { log }) + readResult = 'foo@bar.baz' + const result = await pResult + t.equal(result, 'foo@bar.baz', 'received the email') + t.equal(logMsg, 'invalid email') +}) From 85bed2ec266170d1b6c66256132a070ba598f609 Mon Sep 17 00:00:00 2001 From: marsonya Date: Sun, 7 Feb 2021 11:35:20 +0530 Subject: [PATCH 061/108] doc: fix misnamed SHASUMS256.txt name in README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/37260 Reviewed-By: Richard Lau Reviewed-By: Darshan Sen Reviewed-By: Luigi Pinca Reviewed-By: Myles Borins Reviewed-By: Beth Griggs Reviewed-By: Rich Trott Reviewed-By: Tobias Nießen --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4539df2d5172af..ea02f292daa224 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ $ grep node-vx.y.z.tar.gz SHASUMS256.txt | sha256sum -c - For Current and LTS, the GPG detached signature of `SHASUMS256.txt` is in `SHASUMS256.txt.sig`. You can use it with `gpg` to verify the integrity of -`SHASUM256.txt`. You will first need to import +`SHASUMS256.txt`. You will first need to import [the GPG keys of individuals authorized to create releases](#release-keys). To import the keys: From e28ea89b1a400582c128099af2d97c1770facce0 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Sat, 6 Feb 2021 23:07:35 +0100 Subject: [PATCH 062/108] crypto: fix subtle.importKey JWK OKP public key import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/37255 Reviewed-By: Rich Trott Reviewed-By: Tobias Nießen --- lib/internal/crypto/ec.js | 2 +- test/parallel/test-webcrypto-x25519-x448.js | 33 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/internal/crypto/ec.js b/lib/internal/crypto/ec.js index 88079707367b5d..24ccac8c38e059 100644 --- a/lib/internal/crypto/ec.js +++ b/lib/internal/crypto/ec.js @@ -303,7 +303,7 @@ async function ecImportKey( keyObject = createECRawKey( namedCurve, Buffer.from( - isPublic ? keyData.k : keyData.d, + isPublic ? keyData.x : keyData.d, 'base64'), isPublic); break; diff --git a/test/parallel/test-webcrypto-x25519-x448.js b/test/parallel/test-webcrypto-x25519-x448.js index 947948406306c6..322c6b7b013b21 100644 --- a/test/parallel/test-webcrypto-x25519-x448.js +++ b/test/parallel/test-webcrypto-x25519-x448.js @@ -244,3 +244,36 @@ assert.rejects( { message: /Unsupported named curves for ECDH/ }); + +{ + // Private JWK import + subtle.importKey( + 'jwk', + { + crv: 'X25519', + d: '8CE-XY7cvbR-Pu7mILHq8YZ4hLGAA2-RD01he5q2wUA', + x: '42IbTo34ZYANub5o42547vB6OxdEd44ztwZewoRch0Q', + kty: 'OKP' + }, + { + name: 'ECDH', + namedCurve: 'NODE-X25519' + }, + true, + ['deriveBits']).then(common.mustCall()); + + // Public JWK import + subtle.importKey( + 'jwk', + { + crv: 'X25519', + x: '42IbTo34ZYANub5o42547vB6OxdEd44ztwZewoRch0Q', + kty: 'OKP' + }, + { + name: 'ECDH', + namedCurve: 'NODE-X25519' + }, + true, + []).then(common.mustCall()); +} From 42cc33cc484166b7940ef7c54476dcc0a71f906c Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Thu, 7 Jan 2021 08:21:37 +0100 Subject: [PATCH 063/108] src: add mutex to ManagedEVPPKey class This commit introduces a mutex field on the ManagedEVPPKey class intended to be used when multiple threads require access to an OpenSSL EVP_PKEY object. The motivation for this came from the work being done to upgrade Node.js to OpenSSL 3.0. OpenSSL objects, like EVP_PKEY, are not thread safe (see refs for details). In versions prior to OpenSSL 3.0 this was not noticeable and did not cause any issues (like incorrect logic or crashes), but with OpenSSL 3.0 this does cause issues if access to an EVP_PKEY instance is required from multiple threads without locking. In OpenSSL 3.0 when the evp_pkey_downgrade function is called, which downgrades an EVP_PKEY instance to a legacy version, it will clear all the fields of EVP_PKEY struct except the lock (#13374). But this also means that keymgmt and keydata will also be cleared, which other parts of the code base depends on, and those calls will either fail to export the key (returning null) or crash due to a segment fault. This same code works with OpenSSL 1.1.1 without locking and I think this is because there is no downgrade being done in OpenSSL 1.1.1. But even so, as far as I can tell there are no guarantees that these object are thread safe in 1.1.1 either and should be protected with a lock. PR-URL: https://github.com/nodejs/node/pull/36825 Refs: https://github.com/openssl/openssl/pull/13374 Refs: https://github.com/openssl/openssl/pull/13374 Refs: https://github.com/openssl/openssl/issues/2165) Refs: https://www.openssl.org/blog/blog/2017/02/21/threads Reviewed-By: James M Snell --- src/crypto/crypto_dsa.cc | 7 ++++--- src/crypto/crypto_ec.cc | 20 ++++++++++++-------- src/crypto/crypto_keys.cc | 18 +++++++++++++++--- src/crypto/crypto_keys.h | 2 ++ src/crypto/crypto_rsa.cc | 23 +++++++++++++---------- src/crypto/crypto_sig.cc | 24 +++++++++++++----------- 6 files changed, 59 insertions(+), 35 deletions(-) diff --git a/src/crypto/crypto_dsa.cc b/src/crypto/crypto_dsa.cc index 970ab5cf5f048b..c4016dc07c6743 100644 --- a/src/crypto/crypto_dsa.cc +++ b/src/crypto/crypto_dsa.cc @@ -133,11 +133,12 @@ Maybe GetDsaKeyDetail( const BIGNUM* p; // Modulus length const BIGNUM* q; // Divisor length - ManagedEVPPKey pkey = key->GetAsymmetricKey(); - int type = EVP_PKEY_id(pkey.get()); + ManagedEVPPKey m_pkey = key->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); + int type = EVP_PKEY_id(m_pkey.get()); CHECK(type == EVP_PKEY_DSA); - DSA* dsa = EVP_PKEY_get0_DSA(pkey.get()); + DSA* dsa = EVP_PKEY_get0_DSA(m_pkey.get()); CHECK_NOT_NULL(dsa); DSA_get0_pqg(dsa, &p, &q, nullptr); diff --git a/src/crypto/crypto_ec.cc b/src/crypto/crypto_ec.cc index 1dd3b317633cdd..ec8b7a864d9d18 100644 --- a/src/crypto/crypto_ec.cc +++ b/src/crypto/crypto_ec.cc @@ -601,9 +601,11 @@ WebCryptoKeyExportStatus EC_Raw_Export( KeyObjectData* key_data, const ECKeyExportConfig& params, ByteSource* out) { - CHECK(key_data->GetAsymmetricKey()); + ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey(); + CHECK(m_pkey); + Mutex::ScopedLock lock(*m_pkey.mutex()); - EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_data->GetAsymmetricKey().get()); + EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(m_pkey.get()); unsigned char* data; size_t len = 0; @@ -688,10 +690,11 @@ Maybe ExportJWKEcKey( Environment* env, std::shared_ptr key, Local target) { - ManagedEVPPKey pkey = key->GetAsymmetricKey(); - CHECK_EQ(EVP_PKEY_id(pkey.get()), EVP_PKEY_EC); + ManagedEVPPKey m_pkey = key->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); + CHECK_EQ(EVP_PKEY_id(m_pkey.get()), EVP_PKEY_EC); - EC_KEY* ec = EVP_PKEY_get0_EC_KEY(pkey.get()); + EC_KEY* ec = EVP_PKEY_get0_EC_KEY(m_pkey.get()); CHECK_NOT_NULL(ec); const EC_POINT* pub = EC_KEY_get0_public_key(ec); @@ -893,10 +896,11 @@ Maybe GetEcKeyDetail( Environment* env, std::shared_ptr key, Local target) { - ManagedEVPPKey pkey = key->GetAsymmetricKey(); - CHECK_EQ(EVP_PKEY_id(pkey.get()), EVP_PKEY_EC); + ManagedEVPPKey m_pkey = key->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); + CHECK_EQ(EVP_PKEY_id(m_pkey.get()), EVP_PKEY_EC); - EC_KEY* ec = EVP_PKEY_get0_EC_KEY(pkey.get()); + EC_KEY* ec = EVP_PKEY_get0_EC_KEY(m_pkey.get()); CHECK_NOT_NULL(ec); const EC_GROUP* group = EC_KEY_get0_group(ec); diff --git a/src/crypto/crypto_keys.cc b/src/crypto/crypto_keys.cc index 891e65dcbc2933..07004b78bac954 100644 --- a/src/crypto/crypto_keys.cc +++ b/src/crypto/crypto_keys.cc @@ -552,7 +552,8 @@ Maybe GetAsymmetricKeyDetail( } } // namespace -ManagedEVPPKey::ManagedEVPPKey(EVPKeyPointer&& pkey) : pkey_(std::move(pkey)) {} +ManagedEVPPKey::ManagedEVPPKey(EVPKeyPointer&& pkey) : pkey_(std::move(pkey)), + mutex_(std::make_shared()) {} ManagedEVPPKey::ManagedEVPPKey(const ManagedEVPPKey& that) { *this = that; @@ -564,6 +565,8 @@ ManagedEVPPKey& ManagedEVPPKey::operator=(const ManagedEVPPKey& that) { if (pkey_) EVP_PKEY_up_ref(pkey_.get()); + mutex_ = that.mutex_; + return *this; } @@ -575,6 +578,10 @@ EVP_PKEY* ManagedEVPPKey::get() const { return pkey_.get(); } +Mutex* ManagedEVPPKey::mutex() const { + return mutex_.get(); +} + void ManagedEVPPKey::MemoryInfo(MemoryTracker* tracker) const { tracker->TrackFieldWithSize("pkey", !pkey_ ? 0 : kSizeOf_EVP_PKEY + @@ -1326,8 +1333,10 @@ WebCryptoKeyExportStatus PKEY_SPKI_Export( KeyObjectData* key_data, ByteSource* out) { CHECK_EQ(key_data->GetKeyType(), kKeyTypePublic); + ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); BIOPointer bio(BIO_new(BIO_s_mem())); - if (!i2d_PUBKEY_bio(bio.get(), key_data->GetAsymmetricKey().get())) + if (!i2d_PUBKEY_bio(bio.get(), m_pkey.get())) return WebCryptoKeyExportStatus::FAILED; *out = ByteSource::FromBIO(bio); @@ -1338,8 +1347,11 @@ WebCryptoKeyExportStatus PKEY_PKCS8_Export( KeyObjectData* key_data, ByteSource* out) { CHECK_EQ(key_data->GetKeyType(), kKeyTypePrivate); + ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); + BIOPointer bio(BIO_new(BIO_s_mem())); - PKCS8Pointer p8inf(EVP_PKEY2PKCS8(key_data->GetAsymmetricKey().get())); + PKCS8Pointer p8inf(EVP_PKEY2PKCS8(m_pkey.get())); if (!i2d_PKCS8_PRIV_KEY_INFO_bio(bio.get(), p8inf.get())) return WebCryptoKeyExportStatus::FAILED; diff --git a/src/crypto/crypto_keys.h b/src/crypto/crypto_keys.h index 64bf45a1dba0ed..5f9fcc8510a781 100644 --- a/src/crypto/crypto_keys.h +++ b/src/crypto/crypto_keys.h @@ -81,6 +81,7 @@ class ManagedEVPPKey : public MemoryRetainer { operator bool() const; EVP_PKEY* get() const; + Mutex* mutex() const; void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(ManagedEVPPKey) @@ -127,6 +128,7 @@ class ManagedEVPPKey : public MemoryRetainer { size_t size_of_public_key() const; EVPKeyPointer pkey_; + std::shared_ptr mutex_; }; // Objects of this class can safely be shared among threads. diff --git a/src/crypto/crypto_rsa.cc b/src/crypto/crypto_rsa.cc index 971b184b0c53f5..741e1885e2659c 100644 --- a/src/crypto/crypto_rsa.cc +++ b/src/crypto/crypto_rsa.cc @@ -191,9 +191,10 @@ WebCryptoCipherStatus RSA_Cipher( const ByteSource& in, ByteSource* out) { CHECK_NE(key_data->GetKeyType(), kKeyTypeSecret); + ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); - EVPKeyCtxPointer ctx( - EVP_PKEY_CTX_new(key_data->GetAsymmetricKey().get(), nullptr)); + EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(m_pkey.get(), nullptr)); if (!ctx || init(ctx.get()) <= 0) return WebCryptoCipherStatus::FAILED; @@ -363,17 +364,18 @@ Maybe ExportJWKRsaKey( Environment* env, std::shared_ptr key, Local target) { - ManagedEVPPKey pkey = key->GetAsymmetricKey(); - int type = EVP_PKEY_id(pkey.get()); + ManagedEVPPKey m_pkey = key->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); + int type = EVP_PKEY_id(m_pkey.get()); CHECK(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA_PSS); // TODO(tniessen): Remove the "else" branch once we drop support for OpenSSL // versions older than 1.1.1e via FIPS / dynamic linking. RSA* rsa; if (OpenSSL_version_num() >= 0x1010105fL) { - rsa = EVP_PKEY_get0_RSA(pkey.get()); + rsa = EVP_PKEY_get0_RSA(m_pkey.get()); } else { - rsa = static_cast(EVP_PKEY_get0(pkey.get())); + rsa = static_cast(EVP_PKEY_get0(m_pkey.get())); } CHECK_NOT_NULL(rsa); @@ -511,17 +513,18 @@ Maybe GetRsaKeyDetail( const BIGNUM* e; // Public Exponent const BIGNUM* n; // Modulus - ManagedEVPPKey pkey = key->GetAsymmetricKey(); - int type = EVP_PKEY_id(pkey.get()); + ManagedEVPPKey m_pkey = key->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); + int type = EVP_PKEY_id(m_pkey.get()); CHECK(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA_PSS); // TODO(tniessen): Remove the "else" branch once we drop support for OpenSSL // versions older than 1.1.1e via FIPS / dynamic linking. RSA* rsa; if (OpenSSL_version_num() >= 0x1010105fL) { - rsa = EVP_PKEY_get0_RSA(pkey.get()); + rsa = EVP_PKEY_get0_RSA(m_pkey.get()); } else { - rsa = static_cast(EVP_PKEY_get0(pkey.get())); + rsa = static_cast(EVP_PKEY_get0(m_pkey.get())); } CHECK_NOT_NULL(rsa); diff --git a/src/crypto/crypto_sig.cc b/src/crypto/crypto_sig.cc index b0d97ade6c8bd1..dc03ca0d633348 100644 --- a/src/crypto/crypto_sig.cc +++ b/src/crypto/crypto_sig.cc @@ -96,9 +96,9 @@ AllocatedBuffer Node_SignFinal(Environment* env, return AllocatedBuffer(); } -int GetDefaultSignPadding(const ManagedEVPPKey& key) { - return EVP_PKEY_id(key.get()) == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING : - RSA_PKCS1_PADDING; +int GetDefaultSignPadding(const ManagedEVPPKey& m_pkey) { + return EVP_PKEY_id(m_pkey.get()) == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING : + RSA_PKCS1_PADDING; } unsigned int GetBytesOfRS(const ManagedEVPPKey& pkey) { @@ -752,11 +752,11 @@ Maybe SignTraits::AdditionalConfig( } // If this is an EC key (assuming ECDSA) we need to convert the // the signature from WebCrypto format into DER format... - if (EVP_PKEY_id(params->key->GetAsymmetricKey().get()) == EVP_PKEY_EC) { + ManagedEVPPKey m_pkey = params->key->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); + if (EVP_PKEY_id(m_pkey.get()) == EVP_PKEY_EC) { params->signature = - ConvertFromWebCryptoSignature( - params->key->GetAsymmetricKey(), - signature.ToByteSource()); + ConvertFromWebCryptoSignature(m_pkey, signature.ToByteSource()); } else { params->signature = mode == kCryptoJobAsync ? signature.ToCopy() @@ -774,6 +774,8 @@ bool SignTraits::DeriveBits( EVPMDPointer context(EVP_MD_CTX_new()); EVP_PKEY_CTX* ctx = nullptr; + ManagedEVPPKey m_pkey = params.key->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); switch (params.mode) { case SignConfiguration::kSign: CHECK_EQ(params.key->GetKeyType(), kKeyTypePrivate); @@ -782,7 +784,7 @@ bool SignTraits::DeriveBits( &ctx, params.digest, nullptr, - params.key->GetAsymmetricKey().get())) { + m_pkey.get())) { return false; } break; @@ -793,7 +795,7 @@ bool SignTraits::DeriveBits( &ctx, params.digest, nullptr, - params.key->GetAsymmetricKey().get())) { + m_pkey.get())) { return false; } break; @@ -801,13 +803,13 @@ bool SignTraits::DeriveBits( int padding = params.flags & SignConfiguration::kHasPadding ? params.padding - : GetDefaultSignPadding(params.key->GetAsymmetricKey()); + : GetDefaultSignPadding(m_pkey); Maybe salt_length = params.flags & SignConfiguration::kHasSaltLength ? Just(params.salt_length) : Nothing(); if (!ApplyRSAOptions( - params.key->GetAsymmetricKey(), + m_pkey, ctx, padding, salt_length)) { From 061939d2f6fbc86ee854481dbfa0aa762a2f591f Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Tue, 2 Feb 2021 23:07:34 -0800 Subject: [PATCH 064/108] node-api: allow retrieval of add-on file name Unlike JS-only modules, native add-ons are always associated with a dynamic shared object from which they are loaded. Being able to retrieve its absolute path is important to native-only add-ons, i.e. add-ons that are not themselves being loaded from a JS-only module located in the same package as the native add-on itself. Currently, the file name is obtained at environment construction time from the JS `module.filename`. Nevertheless, the presence of `module` is not required, because the file name could also be passed in via a private property added onto `exports` from the `process.dlopen` binding. As an attempt at future-proofing, the file name is provided as a URL, i.e. prefixed with the `file://` protocol. Fixes: https://github.com/nodejs/node-addon-api/issues/449 PR-URL: https://github.com/nodejs/node/pull/37195 Co-authored-by: Michael Dawson Reviewed-By: Michael Dawson --- doc/api/n-api.md | 25 +++++++++++++ src/env.h | 1 + src/node_api.cc | 45 ++++++++++++++++++++--- src/node_api.h | 3 ++ test/node-api/test_general/test.js | 7 +++- test/node-api/test_general/test_general.c | 13 +++++++ 6 files changed, 87 insertions(+), 7 deletions(-) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 10f05bb69873bd..eb1c2782642995 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -5954,6 +5954,31 @@ idempotent. This API may only be called from the main thread. +## Miscellaneous utilities + +## node_api_get_module_file_name + + + +> Stability: 1 - Experimental + +```c +NAPI_EXTERN napi_status +node_api_get_module_file_name(napi_env env, const char** result); + +``` + +* `[in] env`: The environment that the API is invoked under. +* `[out] result`: A URL containing the absolute path of the + location from which the add-on was loaded. For a file on the local + file system it will start with `file://`. The string is null-terminated and + owned by `env` and must thus not be modified or freed. + +`result` may be an empty string if the add-on loading process fails to establish +the add-on's file name during loading. + [ABI Stability]: https://nodejs.org/en/docs/guides/abi-stability/ [AppVeyor]: https://www.appveyor.com [C++ Addons]: addons.md diff --git a/src/env.h b/src/env.h index f2fc681f56ed69..9e4e11e105632f 100644 --- a/src/env.h +++ b/src/env.h @@ -253,6 +253,7 @@ constexpr size_t kFsStatsBufferLength = V(fd_string, "fd") \ V(fields_string, "fields") \ V(file_string, "file") \ + V(filename_string, "filename") \ V(fingerprint256_string, "fingerprint256") \ V(fingerprint_string, "fingerprint") \ V(flags_string, "flags") \ diff --git a/src/node_api.cc b/src/node_api.cc index f1a5265b6a7234..8dbf48d466dfe1 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -15,8 +15,9 @@ #include struct node_napi_env__ : public napi_env__ { - explicit node_napi_env__(v8::Local context): - napi_env__(context) { + explicit node_napi_env__(v8::Local context, + const std::string& module_filename): + napi_env__(context), filename(module_filename) { CHECK_NOT_NULL(node_env()); } @@ -46,6 +47,10 @@ struct node_napi_env__ : public napi_env__ { }); }); } + + const char* GetFilename() const { return filename.c_str(); } + + std::string filename; }; typedef node_napi_env__* node_napi_env; @@ -87,10 +92,11 @@ class BufferFinalizer : private Finalizer { }; }; -static inline napi_env NewEnv(v8::Local context) { +static inline napi_env +NewEnv(v8::Local context, const std::string& module_filename) { node_napi_env result; - result = new node_napi_env__(context); + result = new node_napi_env__(context, module_filename); // TODO(addaleax): There was previously code that tried to delete the // napi_env when its v8::Context was garbage collected; // However, as long as N-API addons using this napi_env are in place, @@ -552,16 +558,35 @@ void napi_module_register_by_symbol(v8::Local exports, v8::Local module, v8::Local context, napi_addon_register_func init) { + node::Environment* node_env = node::Environment::GetCurrent(context); + std::string module_filename = ""; if (init == nullptr) { - node::Environment* node_env = node::Environment::GetCurrent(context); CHECK_NOT_NULL(node_env); node_env->ThrowError( "Module has no declared entry point."); return; } + // We set `env->filename` from `module.filename` here, but we could just as + // easily add a private property to `exports` in `process.dlopen`, which + // receives the file name from JS, and retrieve *that* here. Thus, we are not + // endorsing commonjs here by making use of `module.filename`. + v8::Local filename_js; + v8::Local modobj; + if (module->ToObject(context).ToLocal(&modobj) && + modobj->Get(context, node_env->filename_string()).ToLocal(&filename_js) && + filename_js->IsString()) { + node::Utf8Value filename(node_env->isolate(), filename_js); // Cast + + // Turn the absolute path into a URL. Currently the absolute path is always + // a file system path. + // TODO(gabrielschulhof): Pass the `filename` through unchanged if/when we + // receive it as a URL already. + module_filename = std::string("file://") + (*filename); + } + // Create a new napi_env for this specific module. - napi_env env = v8impl::NewEnv(context); + napi_env env = v8impl::NewEnv(context, module_filename); napi_value _exports; env->CallIntoModule([&](napi_env env) { @@ -1257,3 +1282,11 @@ napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func) { CHECK_NOT_NULL(func); return reinterpret_cast(func)->Ref(); } + +napi_status node_api_get_module_file_name(napi_env env, const char** result) { + CHECK_ENV(env); + CHECK_ARG(env, result); + + *result = static_cast(env)->GetFilename(); + return napi_clear_last_error(env); +} diff --git a/src/node_api.h b/src/node_api.h index 786988e296b8b2..e7be240cdccd38 100644 --- a/src/node_api.h +++ b/src/node_api.h @@ -261,6 +261,9 @@ NAPI_EXTERN napi_status napi_add_async_cleanup_hook( NAPI_EXTERN napi_status napi_remove_async_cleanup_hook( napi_async_cleanup_hook_handle remove_handle); +NAPI_EXTERN napi_status +node_api_get_module_file_name(napi_env env, const char** result); + #endif // NAPI_EXPERIMENTAL EXTERN_C_END diff --git a/test/node-api/test_general/test.js b/test/node-api/test_general/test.js index 108d51a1e11ac9..dd409f010a3ada 100644 --- a/test/node-api/test_general/test.js +++ b/test/node-api/test_general/test.js @@ -1,9 +1,14 @@ 'use strict'; const common = require('../../common'); -const test_general = require(`./build/${common.buildType}/test_general`); +const filename = require.resolve(`./build/${common.buildType}/test_general`); +const test_general = require(filename); const assert = require('assert'); +// TODO(gabrielschulhof): This test may need updating if/when the filename +// becomes a full-fledged URL. +assert.strictEqual(test_general.filename, `file://${filename}`); + const [ major, minor, patch, release ] = test_general.testGetNodeVersion(); assert.strictEqual(process.version.split('-')[0], `v${major}.${minor}.${patch}`); diff --git a/test/node-api/test_general/test_general.c b/test/node-api/test_general/test_general.c index a7b7c34047c717..d430e2df4f3520 100644 --- a/test/node-api/test_general/test_general.c +++ b/test/node-api/test_general/test_general.c @@ -1,3 +1,4 @@ +#define NAPI_EXPERIMENTAL #include #include #include "../../js-native-api/common.h" @@ -20,9 +21,21 @@ static napi_value testGetNodeVersion(napi_env env, napi_callback_info info) { return result; } +static napi_value GetFilename(napi_env env, napi_callback_info info) { + const char* filename; + napi_value result; + + NODE_API_CALL(env, node_api_get_module_file_name(env, &filename)); + NODE_API_CALL(env, + napi_create_string_utf8(env, filename, NAPI_AUTO_LENGTH, &result)); + + return result; +} + static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { DECLARE_NODE_API_PROPERTY("testGetNodeVersion", testGetNodeVersion), + DECLARE_NODE_API_GETTER("filename", GetFilename), }; NODE_API_CALL(env, napi_define_properties( From d63ac28a9a7b415f68899b7f6870ea47824ff3d9 Mon Sep 17 00:00:00 2001 From: Qingyu Deng Date: Tue, 9 Feb 2021 06:28:42 +0800 Subject: [PATCH 065/108] http: explain the unused argument in IncomingMessage._read PR-URL: https://github.com/nodejs/node/pull/37275 Reviewed-By: Antoine du Hamel Reviewed-By: Darshan Sen Reviewed-By: Matteo Collina --- lib/_http_incoming.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/_http_incoming.js b/lib/_http_incoming.js index e166177e0d4947..18121830b5048b 100644 --- a/lib/_http_incoming.js +++ b/lib/_http_incoming.js @@ -152,7 +152,10 @@ IncomingMessage.prototype.setTimeout = function setTimeout(msecs, callback) { return this; }; - +// Argument n cannot be factored out due to the overhead of +// argument adaptor frame creation inside V8 in case that number of actual +// arguments is different from expected arguments. +// Ref: https://bugs.chromium.org/p/v8/issues/detail?id=10201 IncomingMessage.prototype._read = function _read(n) { if (!this._consuming) { this._readableState.readingMore = false; From f5d1bf9d0eddc429d6eedc1661867eaa20d29b0e Mon Sep 17 00:00:00 2001 From: Qingyu Deng Date: Wed, 10 Feb 2021 13:10:36 +0800 Subject: [PATCH 066/108] http: explain the possibilty of refactor unused argument PR-URL: https://github.com/nodejs/node/pull/37275 Reviewed-By: Antoine du Hamel Reviewed-By: Darshan Sen Reviewed-By: Matteo Collina --- lib/_http_incoming.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/_http_incoming.js b/lib/_http_incoming.js index 18121830b5048b..2e440e3f1b1992 100644 --- a/lib/_http_incoming.js +++ b/lib/_http_incoming.js @@ -156,6 +156,10 @@ IncomingMessage.prototype.setTimeout = function setTimeout(msecs, callback) { // argument adaptor frame creation inside V8 in case that number of actual // arguments is different from expected arguments. // Ref: https://bugs.chromium.org/p/v8/issues/detail?id=10201 +// NOTE: Argument adapt frame issue might be solved in V8 engine v8.9. +// Refactoring `n` out might be possible when V8 is upgraded to that +// version. +// Ref: https://v8.dev/blog/v8-release-89 IncomingMessage.prototype._read = function _read(n) { if (!this._consuming) { this._readableState.readingMore = false; From e28fa6c3fc199edbd138aede9f96f27876c7a054 Mon Sep 17 00:00:00 2001 From: Darshan Sen Date: Mon, 1 Feb 2021 19:30:04 +0530 Subject: [PATCH 067/108] src: fix return type of method in string_search.h `Vector::forward()` is supposed to return a `bool`. PR-URL: https://github.com/nodejs/node/pull/37167 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Rich Trott --- src/string_search.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string_search.h b/src/string_search.h index 3648bc015ab229..cd9ef320a81112 100644 --- a/src/string_search.h +++ b/src/string_search.h @@ -32,7 +32,7 @@ class Vector { // Returns true if the Vector is front-to-back, false if back-to-front. // In the latter case, v[0] corresponds to the *end* of the memory range. - size_t forward() const { return is_forward_; } + bool forward() const { return is_forward_; } // Access individual vector elements - checks bounds in debug mode. T& operator[](size_t index) const { From 3464c9f007a8b1b180bee70831dec487cb63b074 Mon Sep 17 00:00:00 2001 From: Benjamin Gruenbaum Date: Sun, 7 Feb 2021 14:25:35 +0200 Subject: [PATCH 068/108] doc: discourage error event PR-URL: https://github.com/nodejs/node/pull/37264 Refs: https://github.com/nodejs/node/pull/37237 Reviewed-By: Anna Henningsen Reviewed-By: Matteo Collina Reviewed-By: Rich Trott --- doc/api/events.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/doc/api/events.md b/doc/api/events.md index 571f2893a741de..cd2d7fc6137945 100644 --- a/doc/api/events.md +++ b/doc/api/events.md @@ -1247,12 +1247,21 @@ target.addEventListener('foo', handler4, { once: true }); ### `EventTarget` error handling When a registered event listener throws (or returns a Promise that rejects), -by default the error is forwarded to the `process.on('error')` event -on `process.nextTick()`. Throwing within an event listener will *not* stop -the other registered handlers from being invoked. +by default the error is treated as an uncaught exception on +`process.nextTick()`. This means uncaught exceptions in `EventTarget`s will +terminate the Node.js process by default. -The `EventTarget` does not implement any special default handling for -`'error'` type events. +Throwing within an event listener will *not* stop the other registered handlers +from being invoked. + +The `EventTarget` does not implement any special default handling for `'error'` +type events like `EventEmitter`. + +Currently errors are first forwarded to the `process.on('error')` event +before reaching `process.on('uncaughtException')`. This behavior is +deprecated and will change in a future release to align `EventTarget` with +other Node.js APIs. Any code relying on the `process.on('error')` event should +be aligned with the new behavior. ### Class: `Event` -For most `fs` module functions, the `path` or `filename` argument may be passed -as a WHATWG [`URL`][] object. Only [`URL`][] objects using the `file:` protocol -are supported. -```js -const fs = require('fs'); -const fileUrl = new URL('file:///tmp/hello'); +The `fs/promises` API provides asynchronous file system methods that return +promises. -fs.readFileSync(fileUrl); -``` +The promise APIs use the underlying Node.js threadpool to perform file +system operations off the event loop thread. These operations are not +synchronized or threadsafe. Care must be taken when performing multiple +concurrent modifications on the same file or data corruption may occur. -`file:` URLs are always absolute paths. +### Class: `FileHandle` + -Using WHATWG [`URL`][] objects might introduce platform-specific behaviors. +A {FileHandle} object is an object wrapper for a numeric file descriptor. -On Windows, `file:` URLs with a host name convert to UNC paths, while `file:` -URLs with drive letters convert to local absolute paths. `file:` URLs without a -host name nor a drive letter will result in a throw: +Instances of the {FileHandle} object are created by the `fsPromises.open()` +method. -```js -// On Windows : +All {FileHandle} objects are {EventEmitter}s. -// - WHATWG file URLs with hostname convert to UNC path -// file://hostname/p/a/t/h/file => \\hostname\p\a\t\h\file -fs.readFileSync(new URL('file://hostname/p/a/t/h/file')); +If a {FileHandle} is not closed using the `filehandle.close()` method, it will +try to automatically close the file descriptor and emit a process warning, +helping to prevent memory leaks. Please do not rely on this behavior because +it can be unreliable and the file may not be closed. Instead, always explicitly +close {FileHandle}s. Node.js may change this behavior in the future. -// - WHATWG file URLs with drive letters convert to absolute path -// file:///C:/tmp/hello => C:\tmp\hello -fs.readFileSync(new URL('file:///C:/tmp/hello')); +#### Event: `'close'` + -// - WHATWG file URLs without hostname must have a drive letters -fs.readFileSync(new URL('file:///notdriveletter/p/a/t/h/file')); -fs.readFileSync(new URL('file:///c/p/a/t/h/file')); -// TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must be absolute -``` +The `'close'` event is emitted when the {FileHandle} has been closed and can no +longer be used. -`file:` URLs with drive letters must use `:` as a separator just after -the drive letter. Using another separator will result in a throw. +#### `filehandle.appendFile(data[, options])` + -On all other platforms, `file:` URLs with a host name are unsupported and will -result in a throw: +* `data` {string|Buffer|TypedArray|DataView} +* `options` {Object|string} + * `encoding` {string|null} **Default:** `'utf8'` +* Returns: {Promise} Fulfills with `undefined` upon success. -```js -// On other platforms: +Alias of [`filehandle.writeFile()`][]. -// - WHATWG file URLs with hostname are unsupported -// file://hostname/p/a/t/h/file => throw! -fs.readFileSync(new URL('file://hostname/p/a/t/h/file')); -// TypeError [ERR_INVALID_FILE_URL_PATH]: must be absolute +When operating on file handles, the mode cannot be changed from what it was set +to with [`fsPromises.open()`][]. Therefore, this is equivalent to +[`filehandle.writeFile()`][]. -// - WHATWG file URLs convert to absolute path -// file:///tmp/hello => /tmp/hello -fs.readFileSync(new URL('file:///tmp/hello')); -``` +#### `filehandle.chmod(mode)` + -A `file:` URL having encoded slash characters will result in a throw on all -platforms: +* `mode` {integer} the file mode bit mask. +* Returns: {Promise} Fulfills with `undefined` upon success. -```js -// On Windows -fs.readFileSync(new URL('file:///C:/p/a/t/h/%2F')); -fs.readFileSync(new URL('file:///C:/p/a/t/h/%2f')); -/* TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must not include encoded -\ or / characters */ +Modifies the permissions on the file. See chmod(2). -// On POSIX -fs.readFileSync(new URL('file:///p/a/t/h/%2F')); -fs.readFileSync(new URL('file:///p/a/t/h/%2f')); -/* TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must not include encoded -/ characters */ -``` +#### `filehandle.chown(uid, gid)` + -On Windows, `file:` URLs having encoded backslash will result in a throw: +* `uid` {integer} The file's new owner's user id. +* `gid` {integer} The file's new group's group id. +* Returns: {Promise} Fulfills with `undefined` upon success. -```js -// On Windows -fs.readFileSync(new URL('file:///C:/path/%5C')); -fs.readFileSync(new URL('file:///C:/path/%5c')); -/* TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must not include encoded -\ or / characters */ -``` +Changes the ownership of the file. A wrapper for chown(2). -## File descriptors +#### `filehandle.close()` + -On POSIX systems, for every process, the kernel maintains a table of currently -open files and resources. Each open file is assigned a simple numeric -identifier called a *file descriptor*. At the system-level, all file system -operations use these file descriptors to identify and track each specific -file. Windows systems use a different but conceptually similar mechanism for -tracking resources. To simplify things for users, Node.js abstracts away the -specific differences between operating systems and assigns all open files a -numeric file descriptor. +* Returns: {Promise} Fulfills with `undefined` upon success. -The `fs.open()` method is used to allocate a new file descriptor. Once -allocated, the file descriptor may be used to read data from, write data to, -or request information about the file. +Closes the file handle after waiting for any pending operation on the handle to +complete. -```js -fs.open('/open/some/file.txt', 'r', (err, fd) => { - if (err) throw err; - fs.fstat(fd, (err, stat) => { - if (err) throw err; - // use stat +```js esm +import { open } from 'fs/promises'; - // always close the file descriptor! - fs.close(fd, (err) => { - if (err) throw err; - }); - }); -}); +let filehandle; +try { + filehandle = await open('thefile.txt', 'r'); +} finally { + await filehandle?.close(); +} ``` -Most operating systems limit the number of file descriptors that may be open -at any given time so it is critical to close the descriptor when operations -are completed. Failure to do so will result in a memory leak that will -eventually cause an application to crash. - -## Threadpool usage - -All file system APIs except `fs.FSWatcher()` and those that are explicitly -synchronous use libuv's threadpool, which can have surprising and negative -performance implications for some applications. See the -[`UV_THREADPOOL_SIZE`][] documentation for more information. - -## Class: `fs.Dir` +#### `filehandle.datasync()` -A class representing a directory stream. - -Created by [`fs.opendir()`][], [`fs.opendirSync()`][], or -[`fsPromises.opendir()`][]. +* Returns: {Promise} Fulfills with `undefined` upon success. -```js -const fs = require('fs'); +Forces all currently queued I/O operations associated with the file to the +operating system's synchronized I/O completion state. Refer to the POSIX +fdatasync(2) documentation for details. -async function print(path) { - const dir = await fs.promises.opendir(path); - for await (const dirent of dir) { - console.log(dirent.name); - } -} -print('./').catch(console.error); -``` +Unlike `filehandle.sync` this method does not flush modified metadata. -### `dir.close()` +#### `filehandle.fd` -* Returns: {Promise} - -Asynchronously close the directory's underlying resource handle. -Subsequent reads will result in errors. - -A `Promise` is returned that will be fulfilled after the resource has been -closed. +* {number} The numeric file descriptor managed by the {FileHandle} object. -### `dir.close(callback)` +#### `filehandle.read(buffer, offset, length, position)` -* `callback` {Function} - * `err` {Error} +* `buffer` {Buffer|Uint8Array} A buffer that will be filled with the file + data read. +* `offset` {integer} The location in the buffer at which to start filling. + **Default:** `0` +* `length` {integer} The number of bytes to read. **Default:** `buffer.length` +* `position` {integer} The location where to begin reading data from the + file. If `null`, data will be read from the current file position, and + the position will be updated. If `position` is an integer, the current + file position will remain unchanged. +* Returns: {Promise} Fulfills upon success with an object with two properties: + * `bytesRead` {integer} The number of bytes read + * `buffer` {Buffer|Uint8Array} A reference to the passed in `buffer` argument. -Asynchronously close the directory's underlying resource handle. -Subsequent reads will result in errors. +Reads data from the file and stores that in the given buffer. -The `callback` will be called after the resource handle has been closed. +If the file is not modified concurrently, the end-of-file is reached when the +number of bytes read is zero. -### `dir.closeSync()` +#### `filehandle.read(options)` +* `options` {Object} + * `buffer` {Buffer|Uint8Array} A buffer that will be filled with the file + data read. **Default:** `Buffer.alloc(16384)` + * `offset` {integer} The location in the buffer at which to start filling. + **Default:** `0` + * `length` {integer} The number of bytes to read. **Default:** `buffer.length` + * `position` {integer} The location where to begin reading data from the + file. If `null`, data will be read from the current file position, and + the position will be updated. If `position` is an integer, the current + file position will remain unchanged. **Default:**: `null` +* Returns: {Promise} Fulfills upon success with an object with two properties: + * `bytesRead` {integer} The number of bytes read + * `buffer` {Buffer|Uint8Array} A reference to the passed in `buffer` + argument. + +Reads data from the file and stores that in the given buffer. -Synchronously close the directory's underlying resource handle. -Subsequent reads will result in errors. +If the file is not modified concurrently, the end-of-file is reached when the +number of bytes read is zero. -### `dir.path` +#### `filehandle.readFile(options)` -* {string} - -The read-only path of this directory as was provided to [`fs.opendir()`][], -[`fs.opendirSync()`][], or [`fsPromises.opendir()`][]. - -### `dir.read()` - +* `options` {Object|string} + * `encoding` {string|null} **Default:** `null` + * `signal` {AbortSignal} allows aborting an in-progress readFile +* Returns: {Promise} Fulfills upon a successful read with the contents of the + file. If no encoding is specified (using `options.encoding`), the data is + returned as a {Buffer} object. Otherwise, the data will be a string. -* Returns: {Promise} containing {fs.Dirent|null} +Asynchronously reads the entire contents of a file. -Asynchronously read the next directory entry via readdir(3) as an -[`fs.Dirent`][]. +If `options` is a string, then it specifies the `encoding`. -After the read is completed, a `Promise` is returned that will be fulfilled -with an [`fs.Dirent`][], or `null` if there are no more directory entries to -read. +The {FileHandle} has to support reading. -Directory entries returned by this function are in no particular order as -provided by the operating system's underlying directory mechanisms. -Entries added or removed while iterating over the directory might not be -included in the iteration results. +If one or more `filehandle.read()` calls are made on a file handle and then a +`filehandle.readFile()` call is made, the data will be read from the current +position till the end of the file. It doesn't always read from the beginning +of the file. -### `dir.read(callback)` +#### `filehandle.readv(buffers[, position])` -* `callback` {Function} - * `err` {Error} - * `dirent` {fs.Dirent|null} - -Asynchronously read the next directory entry via readdir(3) as an -[`fs.Dirent`][]. - -After the read is completed, the `callback` will be called with an -[`fs.Dirent`][], or `null` if there are no more directory entries to read. +* `buffers` {Buffer[]|TypedArray[]|DataView[]} +* `position` {integer} The offset from the beginning of the file where the data + should be read from. If `position` is not a `number`, the data will be read + from the current position. +* Returns: {Promise} Fulfills upon success an object containing two properties: + * `bytesRead` {integer} the number of bytes read + * `buffers` {Buffer[]|TypedArray[]|DataView[]} property containing + a reference to the `buffers` input. -Directory entries returned by this function are in no particular order as -provided by the operating system's underlying directory mechanisms. -Entries added or removed while iterating over the directory might not be -included in the iteration results. +Read from a file and write to an array of {ArrayBufferView}s -### `dir.readSync()` +#### `filehandle.stat([options])` -* Returns: {fs.Dirent|null} +* `options` {Object} + * `bigint` {boolean} Whether the numeric values in the returned + {fs.Stats} object should be `bigint`. **Default:** `false`. +* Returns: {Promise} Fulfills with an {fs.Stats} for the file. -Synchronously read the next directory entry via readdir(3) as an -[`fs.Dirent`][]. +#### `filehandle.sync()` + -If there are no more directory entries to read, `null` will be returned. +* Returns: {Promise} Fufills with `undefined` upon success. -Directory entries returned by this function are in no particular order as -provided by the operating system's underlying directory mechanisms. -Entries added or removed while iterating over the directory might not be -included in the iteration results. +Request that all data for the open file descriptor is flushed to the storage +device. The specific implementation is operating system and device specific. +Refer to the POSIX fsync(2) documentation for more detail. -### `dir[Symbol.asyncIterator]()` +#### `filehandle.truncate(len)` -* Returns: {AsyncIterator} of {fs.Dirent} - -Asynchronously iterates over the directory via readdir(3) until all entries have -been read. +* `len` {integer} **Default:** `0` +* Returns: {Promise} Fulfills with `undefined` upo nsuccess. -Entries returned by the async iterator are always an [`fs.Dirent`][]. -The `null` case from `dir.read()` is handled internally. +Truncates the file. -See [`fs.Dir`][] for an example. +If the file was larger than `len` bytes, only the first `len` bytes will be +retained in the file. -Directory entries returned by this iterator are in no particular order as -provided by the operating system's underlying directory mechanisms. -Entries added or removed while iterating over the directory might not be -included in the iteration results. +The following example retains only the first four bytes of the file: -## Class: `fs.Dirent` - +```js esm +import { open } from 'fs/promises'; -A representation of a directory entry, which can be a file or a subdirectory -within the directory, as returned by reading from an [`fs.Dir`][]. The -directory entry is a combination of the file name and file type pairs. +let filehandle = null; +try { + filehandle = await open('temp.txt', 'r+'); + await filehandle.truncate(4); +} finally { + filehandle?.close(); +} +``` -Additionally, when [`fs.readdir()`][] or [`fs.readdirSync()`][] is called with -the `withFileTypes` option set to `true`, the resulting array is filled with -`fs.Dirent` objects, rather than strings or `Buffers`. +If the file previously was shorter than `len` bytes, it is extended, and the +extended part is filled with null bytes (`'\0'`): -### `dirent.isBlockDevice()` +#### `filehandle.utimes(atime, mtime)` -* Returns: {boolean} +* `atime` {number|string|Date} +* `mtime` {number|string|Date} +* Returns: {Promise} + +Change the file system timestamps of the object referenced by the {FileHandle} +then resolves the promise with no arguments upon success. -Returns `true` if the `fs.Dirent` object describes a block device. +This function does not work on AIX versions before 7.1, it will reject the +promise with an error using code `UV_ENOSYS`. -### `dirent.isCharacterDevice()` +#### `filehandle.write(buffer[, offset[, length[, position]]])` -* Returns: {boolean} +* `buffer` {Buffer|Uint8Array|string|Object} +* `offset` {integer} The start position from within `buffer` where the data + to write begins. +* `length` {integer} The number of bytes from `buffer` to write. +* `position` {integer} The offset from the beginning of the file where the + data from `buffer` should be written. If `position` is not a `number`, + the data will be written at the current position. See the POSIX pwrite(2) + documentation for more detail. +* Returns: {Promise} -Returns `true` if the `fs.Dirent` object describes a character device. +Write `buffer` to the file. -### `dirent.isDirectory()` - +The promise is resolved with an object containing two properties: -* Returns: {boolean} +* `bytesWritten` {integer} the number of bytes written +* `buffer` {Buffer|Uint8Array|string|Object} a reference to the `buffer` + written. -Returns `true` if the `fs.Dirent` object describes a file system -directory. +It is unsafe to use `filehandle.write()` multiple times on the same file +without waiting for the promise to be resolved (or rejected). For this +scenario, use [`fs.createWriteStream()`][]. + +On Linux, positional writes do not work when the file is opened in append mode. +The kernel ignores the position argument and always appends the data to +the end of the file. -### `dirent.isFIFO()` +#### `filehandle.write(string[, position[, encoding]])` -* Returns: {boolean} +* `string` {string|Object} +* `position` {integer} The offset from the beginning of the file where the + data from `string` should be written. If `position` is not a `number` the + data will be written at the current position. See the POSIX pwrite(2) + documentation for more detail. +* `encoding` {string} The expected string encoding. **Default:** `'utf8'` +* Returns: {Promise} -Returns `true` if the `fs.Dirent` object describes a first-in-first-out -(FIFO) pipe. +Write `string` to the file. If `string` is not a string, or an object with an +own `toString` function property, the promise is rejected with an error. -### `dirent.isFile()` - +The promise is resolved with an object containing two properties: -* Returns: {boolean} +* `bytesWritten` {integer} the number of bytes written +* `buffer` {string|Object} a reference to the `string` written. -Returns `true` if the `fs.Dirent` object describes a regular file. +It is unsafe to use `filehandle.write()` multiple times on the same file +without waiting for the promise to be resolved (or rejected). For this +scenario, use [`fs.createWriteStream()`][]. + +On Linux, positional writes do not work when the file is opened in append mode. +The kernel ignores the position argument and always appends the data to +the end of the file. -### `dirent.isSocket()` +#### `filehandle.writeFile(data, options)` -* Returns: {boolean} +* `data` {string|Buffer|Uint8Array|Object} +* `options` {Object|string} + * `encoding` {string|null} The expected character encoding when `data` is a + string. **Default:** `'utf8'` +* Returns: {Promise} -Returns `true` if the `fs.Dirent` object describes a socket. +Asynchronously writes data to a file, replacing the file if it already exists. +`data` can be a string, a buffer, or an object with an own `toString` function +property. The promise is resolved with no arguments upon success. -### `dirent.isSymbolicLink()` - +If `options` is a string, then it specifies the `encoding`. -* Returns: {boolean} +The {FileHandle} has to support writing. -Returns `true` if the `fs.Dirent` object describes a symbolic link. +It is unsafe to use `filehandle.writeFile()` multiple times on the same file +without waiting for the promise to be resolved (or rejected). + +If one or more `filehandle.write()` calls are made on a file handle and then a +`filehandle.writeFile()` call is made, the data will be written from the +current position till the end of the file. It doesn't always write from the +beginning of the file. -### `dirent.name` +#### `filehandle.writev(buffers[, position])` -* {string|Buffer} +* `buffers` {Buffer[]|TypedArray[]|DataView[]} +* `position` {integer} The offset from the beginning of the file where the + data from `buffers` should be written. If `position` is not a `number`, + the data will be written at the current position. +* Returns: {Promise} -The file name that this `fs.Dirent` object refers to. The type of this -value is determined by the `options.encoding` passed to [`fs.readdir()`][] or -[`fs.readdirSync()`][]. +Write an array of {ArrayBufferView}s to the file. -## Class: `fs.FSWatcher` - +The promise is resolved with an object containing a two properties: -* Extends {EventEmitter} +* `bytesWritten` {integer} the number of bytes written +* `buffers` {Buffer[]|TypedArray[]|DataView[]} a reference to the `buffers` + input. -A successful call to [`fs.watch()`][] method will return a new `fs.FSWatcher` -object. +It is unsafe to call `writev()` multiple times on the same file without waiting +for the promise to be resolved (or rejected). -All `fs.FSWatcher` objects emit a `'change'` event whenever a specific watched -file is modified. +On Linux, positional writes don't work when the file is opened in append mode. +The kernel ignores the position argument and always appends the data to +the end of the file. -### Event: `'change'` +### `fsPromises.access(path[, mode])` -* `eventType` {string} The type of change event that has occurred -* `filename` {string|Buffer} The filename that changed (if relevant/available) +* `path` {string|Buffer|URL} +* `mode` {integer} **Default:** `fs.constants.F_OK` +* Returns: {Promise} Fulfills with `undefined` upon success. -Emitted when something changes in a watched directory or file. -See more details in [`fs.watch()`][]. +Tests a user's permissions for the file or directory specified by `path`. +The `mode` argument is an optional integer that specifies the accessibility +checks to be performed. Check [File access constants][] for possible values +of `mode`. It is possible to create a mask consisting of the bitwise OR of +two or more values (e.g. `fs.constants.W_OK | fs.constants.R_OK`). -The `filename` argument may not be provided depending on operating system -support. If `filename` is provided, it will be provided as a `Buffer` if -`fs.watch()` is called with its `encoding` option set to `'buffer'`, otherwise -`filename` will be a UTF-8 string. +If the accessibility check is successful, the promise is resolved with no +value. If any of the accessibility checks fail, the promise is rejected +with an {Error} object. The following example checks if the file +`/etc/passwd` can be read and written by the current process. -```js -// Example when handled through fs.watch() listener -fs.watch('./tmp', { encoding: 'buffer' }, (eventType, filename) => { - if (filename) { - console.log(filename); - // Prints: - } -}); +```js esm +import { access } from 'fs/promises'; +import { constants } from 'fs'; + +try { + await access('/etc/passwd', constants.R_OK | constants.W_OK); + console.log('can access'); +} catch { + console.error('cannot access'); +} ``` -### Event: `'close'` +Using `fsPromises.access()` to check for the accessibility of a file before +calling `fsPromises.open()` is not recommended. Doing so introduces a race +condition, since other processes may change the file's state between the two +calls. Instead, user code should open/read/write the file directly and handle +the error raised if the file is not accessible. + +### `fsPromises.appendFile(path, data[, options])` -Emitted when the watcher stops watching for changes. The closed -`fs.FSWatcher` object is no longer usable in the event handler. +* `path` {string|Buffer|URL|FileHandle} filename or {FileHandle} +* `data` {string|Buffer} +* `options` {Object|string} + * `encoding` {string|null} **Default:** `'utf8'` + * `mode` {integer} **Default:** `0o666` + * `flag` {string} See [support of file system `flags`][]. **Default:** `'a'`. +* Returns: {Promise} Fulfills with `undefined` upon success. -### Event: `'error'` - +Asynchronously append data to a file, creating the file if it does not yet +exist. `data` can be a string or a {Buffer}. -* `error` {Error} +If `options` is a string, then it specifies the `encoding`. -Emitted when an error occurs while watching the file. The errored -`fs.FSWatcher` object is no longer usable in the event handler. +The `path` may be specified as a {FileHandle} that has been opened +for appending (using `fsPromises.open()`). -### `watcher.close()` +### `fsPromises.chmod(path, mode)` -Stop watching for changes on the given `fs.FSWatcher`. Once stopped, the -`fs.FSWatcher` object is no longer usable. +* `path` {string|Buffer|URL} +* `mode` {string|integer} +* Returns: {Promise} Fulfills with `undefined` upon success. + +Changes the permissions of a file. -### `watcher.ref()` +### `fsPromises.chown(path, uid, gid)` -* Returns: {fs.FSWatcher} - -When called, requests that the Node.js event loop *not* exit so long as the -`FSWatcher` is active. Calling `watcher.ref()` multiple times will have -no effect. +* `path` {string|Buffer|URL} +* `uid` {integer} +* `gid` {integer} +* Returns: {Promise} Fulfills with `undefined` upon success. -By default, all `FSWatcher` objects are "ref'ed", making it normally -unnecessary to call `watcher.ref()` unless `watcher.unref()` had been -called previously. +Changes the ownership of a file. -### `watcher.unref()` +### `fsPromises.copyFile(src, dest[, mode])` -* Returns: {fs.FSWatcher} +* `src` {string|Buffer|URL} source filename to copy +* `dest` {string|Buffer|URL} destination filename of the copy operation +* `mode` {integer} Optional modifiers that specify the behavior of the copy + operation. It is possible to create a mask consisting of the bitwise OR of + two or more values (e.g. + `fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE`) + **Default:** `0`. + * `fs.constants.COPYFILE_EXCL`: The copy operation will fail if `dest` + already exists. + * `fs.constants.COPYFILE_FICLONE`: The copy operation will attempt to create + a copy-on-write reflink. If the platform does not support copy-on-write, + then a fallback copy mechanism is used. + * `fs.constants.COPYFILE_FICLONE_FORCE`: The copy operation will attempt to + create a copy-on-write reflink. If the platform does not support + copy-on-write, then the operation will fail. +* Returns: {Promise} Fulfills with `undefined` upon success. -When called, the active `FSWatcher` object will not require the Node.js -event loop to remain active. If there is no other activity keeping the -event loop running, the process may exit before the `FSWatcher` object's -callback is invoked. Calling `watcher.unref()` multiple times will have -no effect. +Asynchronously copies `src` to `dest`. By default, `dest` is overwritten if it +already exists. -## Class: `fs.StatWatcher` - +No guarantees are made about the atomicity of the copy operation. If an +error occurs after the destination file has been opened for writing, an attempt +will be made to remove the destination. -* Extends {EventEmitter} +```js esm +import { constants } from 'fs'; +import { copyFile } from 'fs/promises'; -A successful call to `fs.watchFile()` method will return a new `fs.StatWatcher` -object. +try { + await copyFile('source.txt', 'destination.txt'); + console.log('source.txt was copied to destination.txt'); +} catch { + console.log('The file could not be copied'); +} + +// By using COPYFILE_EXCL, the operation will fail if destination.txt exists. +try { + await copyFile('source.txt', 'destination.txt', constants.COPYFILE_EXCL); + console.log('source.txt was copied to destination.txt'); +} catch { + console.log('The file could not be copied'); +} +``` -### `watcher.ref()` +### `fsPromises.lchmod(path, mode)` -* Returns: {fs.StatWatcher} +* `path` {string|Buffer|URL} +* `mode` {integer} +* Returns: {Promise} Fulfills with `undefined` upon success. -When called, requests that the Node.js event loop *not* exit so long as the -`StatWatcher` is active. Calling `watcher.ref()` multiple times will have -no effect. +Changes the permissions on a symbolic link. -By default, all `StatWatcher` objects are "ref'ed", making it normally -unnecessary to call `watcher.ref()` unless `watcher.unref()` had been -called previously. +This method is only implemented on macOS. -### `watcher.unref()` +### `fsPromises.lchown(path, uid, gid)` -* Returns: {fs.StatWatcher} +* `path` {string|Buffer|URL} +* `uid` {integer} +* `gid` {integer} +* Returns: {Promise} Fulfills with `undefined` upon success. -When called, the active `StatWatcher` object will not require the Node.js -event loop to remain active. If there is no other activity keeping the -event loop running, the process may exit before the `StatWatcher` object's -callback is invoked. Calling `watcher.unref()` multiple times will have -no effect. +Changes the ownership on a symbolic link. -## Class: `fs.ReadStream` +### `fsPromises.lutimes(path, atime, mtime)` -* Extends: {stream.Readable} +* `path` {string|Buffer|URL} +* `atime` {number|string|Date} +* `mtime` {number|string|Date} +* Returns: {Promise} Fulfills with `undefined` upon success. -Instances of `fs.ReadStream` are created and returned using the -[`fs.createReadStream()`][] function. +Changes the access and modification times of a file in the same way as +[`fsPromises.utimes()`][], with the difference that if the path refers to a +symbolic link, then the link is not dereferenced: instead, the timestamps of +the symbolic link itself are changed. -### Event: `'close'` +### `fsPromises.link(existingPath, newPath)` -Emitted when the `fs.ReadStream`'s underlying file descriptor has been closed. +* `existingPath` {string|Buffer|URL} +* `newPath` {string|Buffer|URL} +* Returns: {Promise} Fulfills with `undefined` upon success. + +Creates a new link from the `existingPath` to the `newPath`. See the POSIX +link(2) documentation for more detail. -### Event: `'open'` +### `fsPromises.lstat(path[, options])` -* `fd` {integer} Integer file descriptor used by the `ReadStream`. +* `path` {string|Buffer|URL} +* `options` {Object} + * `bigint` {boolean} Whether the numeric values in the returned + {fs.Stats} object should be `bigint`. **Default:** `false`. +* Returns: {Promise} Fulfills with the {fs.Stats} object for the given + symbolic link `path`. -Emitted when the `fs.ReadStream`'s file descriptor has been opened. +Equivalent to `fsPromises.stats()` when `path` refers to a symbolic link. +Refer to the POSIX lstat(2) document for more detail. -### Event: `'ready'` +### `fsPromises.mkdir(path[, options])` -Emitted when the `fs.ReadStream` is ready to be used. +* `path` {string|Buffer|URL} +* `options` {Object|integer} + * `recursive` {boolean} **Default:** `false` + * `mode` {string|integer} Not supported on Windows. **Default:** `0o777`. +* Returns: {Promise} Upon success, fulfills with `undefined` if `recursive` + is `false`, or the first directory path created if `recursive` is `true`. -Fires immediately after `'open'`. +Asynchronously creates a directory. + +The optional `options` argument can be an integer specifying `mode` (permission +and sticky bits), or an object with a `mode` property and a `recursive` +property indicating whether parent directories should be created. Calling +`fsPromises.mkdir()` when `path` is a directory that exists results in a +rejection only when `recursive` is false. -### `readStream.bytesRead` +### `fsPromises.mkdtemp(prefix[, options])` -* {number} +* `prefix` {string} +* `options` {string|Object} + * `encoding` {string} **Default:** `'utf8'` +* Returns: {Promise} Fulfills with a string containing the filesystem path + of the newly created temporary directory. -The number of bytes that have been read so far. +Creates a unique temporary directory. A unique directory name is generated by +appending six random characters to the end of the provided `prefix`. Due to +platform inconsistencies, avoid trailing `X` characters in `prefix`. Some +platforms, notably the BSDs, can return more than six random characters, and +replace trailing `X` characters in `prefix` with random characters. -### `readStream.path` - +The optional `options` argument can be a string specifying an encoding, or an +object with an `encoding` property specifying the character encoding to use. -* {string|Buffer} +```js esm +import { mkdtemp } from 'fs/promises'; -The path to the file the stream is reading from as specified in the first -argument to `fs.createReadStream()`. If `path` is passed as a string, then -`readStream.path` will be a string. If `path` is passed as a `Buffer`, then -`readStream.path` will be a `Buffer`. +try { + await mkdtemp(path.join(os.tmpdir(), 'foo-')); +} catch (err) { + console.error(err); +} +``` + +The `fsPromises.mkdtemp()` method will append the six randomly selected +characters directly to the `prefix` string. For instance, given a directory +`/tmp`, if the intention is to create a temporary directory *within* `/tmp`, the +`prefix` must end with a trailing platform-specific path separator +(`require('path').sep`). -### `readStream.pending` +### `fsPromises.open(path, flags[, mode])` -* {boolean} +* `path` {string|Buffer|URL} +* `flags` {string|number} See [support of file system `flags`][]. + **Default:** `'r'`. +* `mode` {string|integer} Sets the file mode (permission and sticky bits) + if the file is created. **Default:** `0o666` (readable and writable) +* Returns: {Promise} Fullfils with a {FileHandle} object. -This property is `true` if the underlying file has not been opened yet, -i.e. before the `'ready'` event is emitted. +Opens a {FileHandle}. -## Class: `fs.Stats` +Refer to the POSIX open(2) documentation for more detail. + +Some characters (`< > : " / \ | ? *`) are reserved under Windows as documented +by [Naming Files, Paths, and Namespaces][]. Under NTFS, if the filename contains +a colon, Node.js will open a file system stream, as described by +[this MSDN page][MSDN-Using-Streams]. + +### `fsPromises.opendir(path[, options])` -A `fs.Stats` object provides information about a file. +* `path` {string|Buffer|URL} +* `options` {Object} + * `encoding` {string|null} **Default:** `'utf8'` + * `bufferSize` {number} Number of directory entries that are buffered + internally when reading from the directory. Higher values lead to better + performance but higher memory usage. **Default:** `32` +* Returns: {Promise} Fulfills with an {fs.Dir}. -Objects returned from [`fs.stat()`][], [`fs.lstat()`][] and [`fs.fstat()`][] and -their synchronous counterparts are of this type. -If `bigint` in the `options` passed to those methods is true, the numeric values -will be `bigint` instead of `number`, and the object will contain additional -nanosecond-precision properties suffixed with `Ns`. +Asynchronously open a directory for iterative scanning. See the POSIX +opendir(3) documentation for more detail. -```console -Stats { - dev: 2114, - ino: 48064969, - mode: 33188, - nlink: 1, - uid: 85, - gid: 100, - rdev: 0, - size: 527, - blksize: 4096, - blocks: 8, - atimeMs: 1318289051000.1, - mtimeMs: 1318289051000.1, - ctimeMs: 1318289051000.1, - birthtimeMs: 1318289051000.1, - atime: Mon, 10 Oct 2011 23:24:11 GMT, - mtime: Mon, 10 Oct 2011 23:24:11 GMT, - ctime: Mon, 10 Oct 2011 23:24:11 GMT, - birthtime: Mon, 10 Oct 2011 23:24:11 GMT } -``` +Creates an {fs.Dir}, which contains all further functions for reading from +and cleaning up the directory. -`bigint` version: +The `encoding` option sets the encoding for the `path` while opening the +directory and subsequent read operations. -```console -BigIntStats { - dev: 2114n, - ino: 48064969n, - mode: 33188n, - nlink: 1n, - uid: 85n, - gid: 100n, - rdev: 0n, - size: 527n, - blksize: 4096n, - blocks: 8n, - atimeMs: 1318289051000n, - mtimeMs: 1318289051000n, - ctimeMs: 1318289051000n, - birthtimeMs: 1318289051000n, - atimeNs: 1318289051000000000n, - mtimeNs: 1318289051000000000n, - ctimeNs: 1318289051000000000n, - birthtimeNs: 1318289051000000000n, - atime: Mon, 10 Oct 2011 23:24:11 GMT, - mtime: Mon, 10 Oct 2011 23:24:11 GMT, - ctime: Mon, 10 Oct 2011 23:24:11 GMT, - birthtime: Mon, 10 Oct 2011 23:24:11 GMT } +Example using async iteration: + +```js esm +import { opendir } from 'fs/promises'; + +try { + const dir = await opendir('./'); + for await (const dirent of dir) + console.log(dirent.name); +} catch (err) { + console.error(err); +} ``` -### `stats.isBlockDevice()` +### `fsPromises.readdir(path[, options])` -* Returns: {boolean} +* `path` {string|Buffer|URL} +* `options` {string|Object} + * `encoding` {string} **Default:** `'utf8'` + * `withFileTypes` {boolean} **Default:** `false` +* Returns: {Promise} Fulfills with an array of the names of the files in + the directory excluding `'.'` and `'..'`. -Returns `true` if the `fs.Stats` object describes a block device. +Reads the contents of a directory. -### `stats.isCharacterDevice()` - +The optional `options` argument can be a string specifying an encoding, or an +object with an `encoding` property specifying the character encoding to use for +the filenames. If the `encoding` is set to `'buffer'`, the filenames returned +will be passed as {Buffer} objects. -* Returns: {boolean} +If `options.withFileTypes` is set to `true`, the resolved array will contain +{fs.Dirent} objects. -Returns `true` if the `fs.Stats` object describes a character device. +```js esm +import { readdir } from 'fs/promises'; -### `stats.isDirectory()` - - -* Returns: {boolean} - -Returns `true` if the `fs.Stats` object describes a file system directory. - -If the `fs.Stats` object was obtained from [`fs.lstat()`][], this method will -always return `false`. This is because [`fs.lstat()`][] returns information -about a symbolic link itself and not the path it resolves to. - -### `stats.isFIFO()` - - -* Returns: {boolean} - -Returns `true` if the `fs.Stats` object describes a first-in-first-out (FIFO) -pipe. - -### `stats.isFile()` - - -* Returns: {boolean} - -Returns `true` if the `fs.Stats` object describes a regular file. - -### `stats.isSocket()` - - -* Returns: {boolean} - -Returns `true` if the `fs.Stats` object describes a socket. +try { + const files = await readdir(path); + for await (const file of files) + console.log(file); +} catch (err) { + console.error(err); +} +``` -### `stats.isSymbolicLink()` +### `fsPromises.readFile(path[, options])` -* Returns: {boolean} - -Returns `true` if the `fs.Stats` object describes a symbolic link. - -This method is only valid when using [`fs.lstat()`][]. - -### `stats.dev` - -* {number|bigint} - -The numeric identifier of the device containing the file. - -### `stats.ino` - -* {number|bigint} - -The file system specific "Inode" number for the file. - -### `stats.mode` - -* {number|bigint} - -A bit-field describing the file type and mode. - -### `stats.nlink` +* `path` {string|Buffer|URL|FileHandle} filename or `FileHandle` +* `options` {Object|string} + * `encoding` {string|null} **Default:** `null` + * `flag` {string} See [support of file system `flags`][]. **Default:** `'r'`. + * `signal` {AbortSignal} allows aborting an in-progress readFile +* Returns: {Promise} Fulfills with the contents of the file. -* {number|bigint} +Asynchronously reads the entire contents of a file. -The number of hard-links that exist for the file. +If no encoding is specified (using `options.encoding`), the data is returned +as a {Buffer} object. Otherwise, the data will be a string. -### `stats.uid` +If `options` is a string, then it specifies the encoding. -* {number|bigint} +When the `path` is a directory, the behavior of `fsPromises.readFile()` is +platform-specific. On macOS, Linux, and Windows, the promise will be rejected +with an error. On FreeBSD, a representation of the directory's contents will be +returned. -The numeric user identifier of the user that owns the file (POSIX). +It is possible to abort an ongoing `readFile` using an {AbortSignal}. If a +request is aborted the promise returned is rejected with an `AbortError`: -### `stats.gid` +```js esm +import { readFile } from 'fs/promises'; -* {number|bigint} +try { + const controller = new AbortController(); + const signal = controller.signal; + readFile(fileName, { signal }); -The numeric group identifier of the group that owns the file (POSIX). + // Abort the request + controller.abort(); +} catch (err) { + console.error(err); +} +``` -### `stats.rdev` +Aborting an ongoing request does not abort individual operating +system requests but rather the internal buffering `fs.readFile` performs. -* {number|bigint} +Any specified {FileHandle} has to support reading. -A numeric device identifier if the file represents a device. +### `fsPromises.readlink(path[, options])` + -### `stats.size` +* `path` {string|Buffer|URL} +* `options` {string|Object} + * `encoding` {string} **Default:** `'utf8'` +* Returns: {Promise} Fulfills with the `linkString` upon success. -* {number|bigint} +Reads the contents of the symbolic link refered to by `path`. See the POSIX +readlink(2) documentation for more etail. The promise is resolved with the +`linkString` upon success. -The size of the file in bytes. +The optional `options` argument can be a string specifying an encoding, or an +object with an `encoding` property specifying the character encoding to use for +the link path returned. If the `encoding` is set to `'buffer'`, the link path +returned will be passed as a {Buffer} object. -### `stats.blksize` +### `fsPromises.realpath(path[, options])` + -* {number|bigint} +* `path` {string|Buffer|URL} +* `options` {string|Object} + * `encoding` {string} **Default:** `'utf8'` +* Returns: {Promise} Fulfills with the resolved path upon success. -The file system block size for i/o operations. +Determines the actual location of `path` using the same semantics as the +`fs.realpath.native()` function. -### `stats.blocks` +Only paths that can be converted to UTF8 strings are supported. -* {number|bigint} +The optional `options` argument can be a string specifying an encoding, or an +object with an `encoding` property specifying the character encoding to use for +the path. If the `encoding` is set to `'buffer'`, the path returned will be +passed as a {Buffer} object. -The number of blocks allocated for this file. +On Linux, when Node.js is linked against musl libc, the procfs file system must +be mounted on `/proc` in order for this function to work. Glibc does not have +this restriction. -### `stats.atimeMs` +### `fsPromises.rename(oldPath, newPath)` -* {number|bigint} +* `oldPath` {string|Buffer|URL} +* `newPath` {string|Buffer|URL} +* Returns: {Promise} Fulfills with `undefined` upon success. -The timestamp indicating the last time this file was accessed expressed in -milliseconds since the POSIX Epoch. +Renames `oldPath` to `newPath`. -### `stats.mtimeMs` +### `fsPromises.rmdir(path[, options])` -* {number|bigint} - -The timestamp indicating the last time this file was modified expressed in -milliseconds since the POSIX Epoch. +* `path` {string|Buffer|URL} +* `options` {Object} + * `maxRetries` {integer} If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or + `EPERM` error is encountered, Node.js retries the operation with a linear + backoff wait of `retryDelay` milliseconds longer on each try. This option + represents the number of retries. This option is ignored if the `recursive` + option is not `true`. **Default:** `0`. + * `recursive` {boolean} If `true`, perform a recursive directory removal. In + recursive mode, errors are not reported if `path` does not exist, and + operations are retried on failure. **Default:** `false`. + * `retryDelay` {integer} The amount of time in milliseconds to wait between + retries. This option is ignored if the `recursive` option is not `true`. + **Default:** `100`. +* Returns: {Promise} Fulfills with `undefined` upon success. -### `stats.ctimeMs` - +Removes the directory identified by `path`. -* {number|bigint} +Using `fsPromises.rmdir()` on a file (not a directory) results in the +promise being rejected with an `ENOENT` error on Windows and an `ENOTDIR` +error on POSIX. -The timestamp indicating the last time the file status was changed expressed -in milliseconds since the POSIX Epoch. +Setting `recursive` to `true` results in behavior similar to the Unix command +`rm -rf`: an error will not be raised for paths that do not exist, and paths +that represent files will be deleted. The permissive behavior of the +`recursive` option is deprecated, `ENOTDIR` and `ENOENT` will be thrown in +the future. -### `stats.birthtimeMs` +### `fsPromises.rm(path[, options])` -* {number|bigint} +* `path` {string|Buffer|URL} +* `options` {Object} + * `force` {boolean} When `true`, exceptions will be ignored if `path` does + not exist. **Default:** `false`. + * `maxRetries` {integer} If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or + `EPERM` error is encountered, Node.js will retry the operation with a linear + backoff wait of `retryDelay` milliseconds longer on each try. This option + represents the number of retries. This option is ignored if the `recursive` + option is not `true`. **Default:** `0`. + * `recursive` {boolean} If `true`, perform a recursive directory removal. In + recursive mode operations are retried on failure. **Default:** `false`. + * `retryDelay` {integer} The amount of time in milliseconds to wait between + retries. This option is ignored if the `recursive` option is not `true`. + **Default:** `100`. +* Returns: {Promise} Fulfills with `undefined` upon success. -The timestamp indicating the creation time of this file expressed in -milliseconds since the POSIX Epoch. +Removes files and directories (modeled on the standard POSIX `rm` utility). -### `stats.atimeNs` +### `fsPromises.stat(path[, options])` -* {bigint} - -Only present when `bigint: true` is passed into the method that generates -the object. -The timestamp indicating the last time this file was accessed expressed in -nanoseconds since the POSIX Epoch. +* `path` {string|Buffer|URL} +* `options` {Object} + * `bigint` {boolean} Whether the numeric values in the returned + {fs.Stats} object should be `bigint`. **Default:** `false`. +* Returns: {Promise} Fulfills with the {fs.Stats} object for the + given `path`. -### `stats.mtimeNs` +### `fsPromises.symlink(target, path[, type])` -* {bigint} +* `target` {string|Buffer|URL} +* `path` {string|Buffer|URL} +* `type` {string} **Default:** `'file'` +* Returns: {Promise} Fulfills with `undefined` upon success. -Only present when `bigint: true` is passed into the method that generates -the object. -The timestamp indicating the last time this file was modified expressed in -nanoseconds since the POSIX Epoch. +Creates a symbolic link. -### `stats.ctimeNs` +The `type` argument is only used on Windows platforms and can be one of `'dir'`, +`'file'`, or `'junction'`. Windows junction points require the destination path +to be absolute. When using `'junction'`, the `target` argument will +automatically be normalized to absolute path. + +### `fsPromises.truncate(path[, len])` -* {bigint} +* `path` {string|Buffer|URL} +* `len` {integer} **Default:** `0` +* Returns: {Promise} Fulfills with `undefined` upon success. -Only present when `bigint: true` is passed into the method that generates -the object. -The timestamp indicating the last time the file status was changed expressed -in nanoseconds since the POSIX Epoch. +Truncates (shortens or extends the length) of the content at `path` to `len` +bytes. -### `stats.birthtimeNs` +### `fsPromises.unlink(path)` -* {bigint} +* `path` {string|Buffer|URL} +* Returns: {Promise} Fulfills with `undefined` upon success. -Only present when `bigint: true` is passed into the method that generates -the object. -The timestamp indicating the creation time of this file expressed in -nanoseconds since the POSIX Epoch. +If `path` refers to a symbolic link, then the link is removed without affecting +the file or directory to which that link refers. If the `path` refers to a file +path that is not a symbolic link, the file is deleted. See the POSIX unlink(2) +documentation for more detail. -### `stats.atime` +### `fsPromises.utimes(path, atime, mtime)` -* {Date} +* `path` {string|Buffer|URL} +* `atime` {number|string|Date} +* `mtime` {number|string|Date} +* Returns: {Promise} Fulfills with `undefined` upon success. -The timestamp indicating the last time this file was accessed. - -### `stats.mtime` - - -* {Date} - -The timestamp indicating the last time this file was modified. - -### `stats.ctime` - - -* {Date} - -The timestamp indicating the last time the file status was changed. - -### `stats.birthtime` - - -* {Date} - -The timestamp indicating the creation time of this file. - -### Stat time values - -The `atimeMs`, `mtimeMs`, `ctimeMs`, `birthtimeMs` properties are -numeric values that hold the corresponding times in milliseconds. Their -precision is platform specific. When `bigint: true` is passed into the -method that generates the object, the properties will be [bigints][], -otherwise they will be [numbers][MDN-Number]. - -The `atimeNs`, `mtimeNs`, `ctimeNs`, `birthtimeNs` properties are -[bigints][] that hold the corresponding times in nanoseconds. They are -only present when `bigint: true` is passed into the method that generates -the object. Their precision is platform specific. - -`atime`, `mtime`, `ctime`, and `birthtime` are -[`Date`][MDN-Date] object alternate representations of the various times. The -`Date` and number values are not connected. Assigning a new number value, or -mutating the `Date` value, will not be reflected in the corresponding alternate -representation. - -The times in the stat object have the following semantics: - -* `atime` "Access Time": Time when file data last accessed. Changed - by the mknod(2), utimes(2), and read(2) system calls. -* `mtime` "Modified Time": Time when file data last modified. - Changed by the mknod(2), utimes(2), and write(2) system calls. -* `ctime` "Change Time": Time when file status was last changed - (inode data modification). Changed by the chmod(2), chown(2), - link(2), mknod(2), rename(2), unlink(2), utimes(2), - read(2), and write(2) system calls. -* `birthtime` "Birth Time": Time of file creation. Set once when the - file is created. On filesystems where birthtime is not available, - this field may instead hold either the `ctime` or - `1970-01-01T00:00Z` (ie, Unix epoch timestamp `0`). This value may be greater - than `atime` or `mtime` in this case. On Darwin and other FreeBSD variants, - also set if the `atime` is explicitly set to an earlier value than the current - `birthtime` using the utimes(2) system call. - -Prior to Node.js 0.12, the `ctime` held the `birthtime` on Windows systems. As -of 0.12, `ctime` is not "creation time", and on Unix systems, it never was. - -## Class: `fs.WriteStream` - +Change the file system timestamps of the object referenced by `path`. -* Extends {stream.Writable} +The `atime` and `mtime` arguments follow these rules: -Instances of `fs.WriteStream` are created and returned using the -[`fs.createWriteStream()`][] function. +* Values can be either numbers representing Unix epoch time, `Date`s, or a + numeric string like `'123456789.0'`. +* If the value can not be converted to a number, or is `NaN`, `Infinity` or + `-Infinity`, an `Error` will be thrown. -### Event: `'close'` +### `fsPromises.writeFile(file, data[, options])` -Emitted when the `WriteStream`'s underlying file descriptor has been closed. +* `file` {string|Buffer|URL|FileHandle} filename or `FileHandle` +* `data` {string|Buffer|Uint8Array|Object} +* `options` {Object|string} + * `encoding` {string|null} **Default:** `'utf8'` + * `mode` {integer} **Default:** `0o666` + * `flag` {string} See [support of file system `flags`][]. **Default:** `'w'`. + * `signal` {AbortSignal} allows aborting an in-progress writeFile +* Returns: {Promise} Fulfills with `undefined` upon success. -### Event: `'open'` - +Asynchronously writes data to a file, replacing the file if it already exists. +`data` can be a string, a {Buffer}, or an object with an own `toString` function +property. -* `fd` {integer} Integer file descriptor used by the `WriteStream`. +The `encoding` option is ignored if `data` is a buffer. -Emitted when the `WriteStream`'s file is opened. +If `options` is a string, then it specifies the encoding. -### Event: `'ready'` - +Any specified {FileHandle} has to support writing. -Emitted when the `fs.WriteStream` is ready to be used. +It is unsafe to use `fsPromises.writeFile()` multiple times on the same file +without waiting for the promise to be settled. -Fires immediately after `'open'`. +Similarly to `fsPromises.readFile` - `fsPromises.writeFile` is a convenience +method that performs multiple `write` calls internally to write the buffer +passed to it. For performance sensitive code consider using +[`fs.createWriteStream()`][]. -### `writeStream.bytesWritten` - +It is possible to use an {AbortSignal} to cancel an `fsPromises.writeFile()`. +Cancelation is "best effort", and some amount of data is likely still +to be written. -The number of bytes written so far. Does not include data that is still queued -for writing. +```js esm +import { writeFile } from 'fs/promises'; -### `writeStream.path` - +try { + const controller = new AbortController(); + const { signal } = controller; + const data = new Uint8Array(Buffer.from('Hello Node.js')); + writeFile('message.txt', data, { signal }); + controller.abort(); +} catch (err) { + // When a request is aborted - err is an AbortError + console.error(err); +} +``` -The path to the file the stream is writing to as specified in the first -argument to [`fs.createWriteStream()`][]. If `path` is passed as a string, then -`writeStream.path` will be a string. If `path` is passed as a `Buffer`, then -`writeStream.path` will be a `Buffer`. +Aborting an ongoing request does not abort individual operating +system requests but rather the internal buffering `fs.writeFile` performs. -### `writeStream.pending` - +## Callback API -* {boolean} +The callback APIs perform all operations asynchronously, without blocking the +event loop, then invoke a callback function upon completion or error. -This property is `true` if the underlying file has not been opened yet, -i.e. before the `'ready'` event is emitted. +The callback APIs use the underlying Node.js threadpool to perform file +system operations off the event loop thread. These operations are not +synchronized or threadsafe. Care must be taken when performing multiple +concurrent modifications on the same file or data corruption may occur. -## `fs.access(path[, mode], callback)` +### `fs.access(path[, mode], callback)` - -* `path` {string|Buffer|URL} -* `mode` {integer} **Default:** `fs.constants.F_OK` - -Synchronously tests a user's permissions for the file or directory specified -by `path`. The `mode` argument is an optional integer that specifies the -accessibility checks to be performed. Check [File access constants][] for -possible values of `mode`. It is possible to create a mask consisting of -the bitwise OR of two or more values -(e.g. `fs.constants.W_OK | fs.constants.R_OK`). - -If any of the accessibility checks fail, an `Error` will be thrown. Otherwise, -the method will return `undefined`. - -```js -try { - fs.accessSync('etc/passwd', fs.constants.R_OK | fs.constants.W_OK); - console.log('can read/write'); -} catch (err) { - console.error('no access!'); -} -``` - -## `fs.appendFile(path, data[, options], callback)` +### `fs.appendFile(path, data[, options], callback)` -* `path` {string|Buffer|URL|number} filename or file descriptor -* `data` {string|Buffer} -* `options` {Object|string} - * `encoding` {string|null} **Default:** `'utf8'` - * `mode` {integer} **Default:** `0o666` - * `flag` {string} See [support of file system `flags`][]. **Default:** `'a'`. - -Synchronously append data to a file, creating the file if it does not yet -exist. `data` can be a string or a [`Buffer`][]. +* `path` {string|Buffer|URL} +* `mode` {string|integer} +* `callback` {Function} + * `err` {Error} -```js -try { - fs.appendFileSync('message.txt', 'data to append'); - console.log('The "data to append" was appended to file!'); -} catch (err) { - /* Handle the error */ -} -``` +Asynchronously changes the permissions of a file. No arguments other than a +possible exception are given to the completion callback. -If `options` is a string, then it specifies the encoding: +See the POSIX chmod(2) documentation for more detail. -```js -fs.appendFileSync('message.txt', 'data to append', 'utf8'); -``` +```js esm +import { chmod } from 'fs'; -The `path` may be specified as a numeric file descriptor that has been opened -for appending (using `fs.open()` or `fs.openSync()`). The file descriptor will -not be closed automatically. - -```js -let fd; - -try { - fd = fs.openSync('message.txt', 'a'); - fs.appendFileSync(fd, 'data to append', 'utf8'); -} catch (err) { - /* Handle the error */ -} finally { - if (fd !== undefined) - fs.closeSync(fd); -} -``` - -## `fs.chmod(path, mode, callback)` - - -* `path` {string|Buffer|URL} -* `mode` {string|integer} -* `callback` {Function} - * `err` {Error} - -Asynchronously changes the permissions of a file. No arguments other than a -possible exception are given to the completion callback. - -See also: chmod(2). - -```js -fs.chmod('my_file.txt', 0o775, (err) => { +chmod('my_file.txt', 0o775, (err) => { if (err) throw err; console.log('The permissions for file "my_file.txt" have been changed!'); }); ``` -### File modes +#### File modes The `mode` argument used in both the `fs.chmod()` and `fs.chmodSync()` methods is a numeric bitmask created using a logical OR of the following @@ -1542,25 +1617,7 @@ Caveats: on Windows only the write permission can be changed, and the distinction among the permissions of group, owner or others is not implemented. -## `fs.chmodSync(path, mode)` - - -* `path` {string|Buffer|URL} -* `mode` {string|integer} - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.chmod()`][]. - -See also: chmod(2). - -## `fs.chown(path, uid, gid, callback)` +### `fs.chown(path, uid, gid, callback)` - -* `path` {string|Buffer|URL} -* `uid` {integer} -* `gid` {integer} - -Synchronously changes owner and group of a file. Returns `undefined`. -This is the synchronous version of [`fs.chown()`][]. +See the POSIX chown(2) documentation for more detail. -See also: chown(2). - -## `fs.close(fd[, callback])` +### `fs.close(fd[, callback])` - -* `fd` {integer} - -Synchronous close(2). Returns `undefined`. - -Calling `fs.closeSync()` on any file descriptor (`fd`) that is currently in use -through any other `fs` operation may lead to undefined behavior. - -## `fs.constants` +See the POSIX close(2) documentation for more detail. -* {Object} - -Returns an object containing commonly used constants for file system -operations. The specific constants currently defined are described in -[FS constants][]. - -## `fs.copyFile(src, dest[, mode], callback)` +### `fs.copyFile(src, dest[, mode], callback)` - -* `src` {string|Buffer|URL} source filename to copy -* `dest` {string|Buffer|URL} destination filename of the copy operation -* `mode` {integer} modifiers for copy operation. **Default:** `0`. - -Synchronously copies `src` to `dest`. By default, `dest` is overwritten if it -already exists. Returns `undefined`. Node.js makes no guarantees about the -atomicity of the copy operation. If an error occurs after the destination file -has been opened for writing, Node.js will attempt to remove the destination. - -`mode` is an optional integer that specifies the behavior -of the copy operation. It is possible to create a mask consisting of the bitwise -OR of two or more values (e.g. -`fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE`). - -* `fs.constants.COPYFILE_EXCL`: The copy operation will fail if `dest` already - exists. -* `fs.constants.COPYFILE_FICLONE`: The copy operation will attempt to create a - copy-on-write reflink. If the platform does not support copy-on-write, then a - fallback copy mechanism is used. -* `fs.constants.COPYFILE_FICLONE_FORCE`: The copy operation will attempt to - create a copy-on-write reflink. If the platform does not support - copy-on-write, then the operation will fail. - -```js -const fs = require('fs'); -const { COPYFILE_EXCL } = fs.constants; - -// destination.txt will be created or overwritten by default. -fs.copyFileSync('source.txt', 'destination.txt'); -console.log('source.txt was copied to destination.txt'); +copyFile('source.txt', 'destination.txt', callback); // By using COPYFILE_EXCL, the operation will fail if destination.txt exists. -fs.copyFileSync('source.txt', 'destination.txt', COPYFILE_EXCL); +copyFile('source.txt', 'destination.txt', constants.COPYFILE_EXCL, callback); ``` -## `fs.createReadStream(path[, options])` +### `fs.createReadStream(path[, options])` - -* `path` {string|Buffer|URL} -* Returns: {boolean} - -Returns `true` if the path exists, `false` otherwise. - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.exists()`][]. - -`fs.exists()` is deprecated, but `fs.existsSync()` is not. The `callback` -parameter to `fs.exists()` accepts parameters that are inconsistent with other -Node.js callbacks. `fs.existsSync()` does not use a callback. - -```js -if (fs.existsSync('/etc/passwd')) { - console.log('The path exists.'); -} -``` - -## `fs.fchmod(fd, mode, callback)` +### `fs.fchmod(fd, mode, callback)` - -* `fd` {integer} -* `mode` {string|integer} - -Synchronous fchmod(2). Returns `undefined`. +See the POSIX fchmod(2) documentation for more detail. -## `fs.fchown(fd, uid, gid, callback)` +### `fs.fchown(fd, uid, gid, callback)` - -* `fd` {integer} -* `uid` {integer} -* `gid` {integer} +Sets the owner of the file. No arguments other than a possible exception are +given to the completion callback. -Synchronous fchown(2). Returns `undefined`. +See the POSIX fchown(2) documentation for more detail. -## `fs.fdatasync(fd, callback)` +### `fs.fdatasync(fd, callback)` - -* `fd` {integer} - -Synchronous fdatasync(2). Returns `undefined`. +Forces all currently queued I/O operations associated with the file to the +operating system's synchronized I/O completion state. Refer to the POSIX +fdatasync(2) documentation for details. No arguments other than a possible +exception are given to the completion callback. -## `fs.fstat(fd[, options], callback)` +### `fs.fstat(fd[, options], callback)` - -* `fd` {integer} -* `options` {Object} - * `bigint` {boolean} Whether the numeric values in the returned - [`fs.Stats`][] object should be `bigint`. **Default:** `false`. -* Returns: {fs.Stats} +Invokes the callback with the {fs.Stats} for the file descriptor. -Synchronous fstat(2). +See the POSIX fstat(2) documentation for more detail. -## `fs.fsync(fd, callback)` +### `fs.fsync(fd, callback)` - -* `fd` {integer} - -Synchronous fsync(2). Returns `undefined`. +Request that all data for the open file descriptor is flushed to the storage +device. The specific implementation is operating system and device specific. +Refer to the POSIX fsync(2) documentation for more detail. No arguments other +than a possible exception are given to the completion callback. -## `fs.ftruncate(fd[, len], callback)` +### `fs.ftruncate(fd[, len], callback)` - -* `fd` {integer} -* `len` {integer} **Default:** `0` - -Returns `undefined`. - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.ftruncate()`][]. - -## `fs.futimes(fd, atime, mtime, callback)` +### `fs.futimes(fd, atime, mtime, callback)` - -* `fd` {integer} -* `atime` {number|string|Date} -* `mtime` {number|string|Date} - -Synchronous version of [`fs.futimes()`][]. Returns `undefined`. - -## `fs.lchmod(path, mode, callback)` +### `fs.lchmod(path, mode, callback)` +Changes the permissions on a symbolic link. No arguments other than a possible +exception are given to the completion callback. -* `path` {string|Buffer|URL} -* `mode` {integer} +This method is only implemented on macOS. -Synchronous lchmod(2). Returns `undefined`. +See the POSIX lchmod(2) documentation for more detail. -## `fs.lchown(path, uid, gid, callback)` +### `fs.lchown(path, uid, gid, callback)` - -* `path` {string|Buffer|URL} -* `uid` {integer} -* `gid` {integer} +Set the owner of the symbolic link. No arguments other than a possible +exception are given to the completion callback. -Synchronous lchown(2). Returns `undefined`. +See the POSIX lchown(2) documentation for more detail. -## `fs.lutimes(path, atime, mtime, callback)` +### `fs.lutimes(path, atime, mtime, callback)` - -* `path` {string|Buffer|URL} -* `atime` {number|string|Date} -* `mtime` {number|string|Date} - -Change the file system timestamps of the symbolic link referenced by `path`. -Returns `undefined`, or throws an exception when parameters are incorrect or -the operation fails. This is the synchronous version of [`fs.lutimes()`][]. - -## `fs.link(existingPath, newPath, callback)` +### `fs.link(existingPath, newPath, callback)` - -* `existingPath` {string|Buffer|URL} -* `newPath` {string|Buffer|URL} +Creates a new link from the `existingPath` to the `newPath`. See the POSIX +link(2) documentation for more detail. No arguments other than a possible +exception are given to the completion callback. -Synchronous link(2). Returns `undefined`. - -## `fs.lstat(path[, options], callback)` +### `fs.lstat(path[, options], callback)` - -* `path` {string|Buffer|URL} -* `options` {Object} - * `bigint` {boolean} Whether the numeric values in the returned - [`fs.Stats`][] object should be `bigint`. **Default:** `false`. - * `throwIfNoEntry` {boolean} Whether an exception will be thrown - if no file system entry exists, rather than returning `undefined`. - **Default:** `true`. -* Returns: {fs.Stats} +Retrieves the {fs.Stats} for the symbolic link refered to by the path. +The callback gets two arguments `(err, stats)` where `stats` is a {`fs.Stats} +object. `lstat()` is identical to `stat()`, except that if `path` is a symbolic +link, then the link itself is stat-ed, not the file that it refers to. -Synchronous lstat(2). +See the POSIX lstat(2) documentation for more details. -## `fs.mkdir(path[, options], callback)` +### `fs.mkdir(path[, options], callback)` - -* `path` {string|Buffer|URL} -* `options` {Object|integer} - * `recursive` {boolean} **Default:** `false` - * `mode` {string|integer} Not supported on Windows. **Default:** `0o777`. -* Returns: {string|undefined} - -Synchronously creates a directory. Returns `undefined`, or if `recursive` is -`true`, the first directory path created. -This is the synchronous version of [`fs.mkdir()`][]. - -See also: mkdir(2). +See the POSIX mkdir(2) documentation for more details. -## `fs.mkdtemp(prefix[, options], callback)` +### `fs.mkdtemp(prefix[, options], callback)` - -* `prefix` {string} -* `options` {string|Object} - * `encoding` {string} **Default:** `'utf8'` -* Returns: {string} - -Returns the created directory path. - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.mkdtemp()`][]. - -The optional `options` argument can be a string specifying an encoding, or an -object with an `encoding` property specifying the character encoding to use. - -## `fs.open(path[, flags[, mode]], callback)` +### `fs.open(path[, flags[, mode]], callback)` - -* `path` {string|Buffer|URL} -* `options` {Object} - * `encoding` {string|null} **Default:** `'utf8'` - * `bufferSize` {number} Number of directory entries that are buffered - internally when reading from the directory. Higher values lead to better - performance but higher memory usage. **Default:** `32` -* Returns: {fs.Dir} - -Synchronously open a directory. See opendir(3). +Asynchronously open a directory. See the POSIX opendir(3) documentation for +more details. -Creates an [`fs.Dir`][], which contains all further functions for reading from +Creates an {fs.Dir}, which contains all further functions for reading from and cleaning up the directory. The `encoding` option sets the encoding for the `path` while opening the directory and subsequent read operations. -## `fs.openSync(path[, flags, mode])` - - -* `path` {string|Buffer|URL} -* `flags` {string|number} **Default:** `'r'`. - See [support of file system `flags`][]. -* `mode` {string|integer} **Default:** `0o666` -* Returns: {number} - -Returns an integer representing the file descriptor. - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.open()`][]. - -## `fs.read(fd, buffer, offset, length, position, callback)` +### `fs.read(fd, buffer, offset, length, position, callback)` * `fd` {integer} -* `buffer` {Buffer|TypedArray|DataView} -* `offset` {integer} -* `length` {integer} -* `position` {integer|bigint} +* `buffer` {Buffer|TypedArray|DataView} The buffer that the data will be + written to. +* `offset` {integer} The position in `buffer` to write the data to. +* `length` {integer} The number of bytes to read. +* `position` {integer|bigint} Specifies where to begin reading from in the + file. If `position` is `null` or `-1 `, data will be read from the current + file position, and the file position will be updated. If `position` is an + integer, the file position will be unchanged. * `callback` {Function} * `err` {Error} * `bytesRead` {integer} @@ -2942,26 +2670,15 @@ changes: Read data from the file specified by `fd`. -`buffer` is the buffer that the data (read from the fd) will be written to. - -`offset` is the offset in the buffer to start writing at. - -`length` is an integer specifying the number of bytes to read. - -`position` is an argument specifying where to begin reading from in the file. -If `position` is `null`, data will be read from the current file position, -and the file position will be updated. -If `position` is an integer, the file position will remain unchanged. - The callback is given the three arguments, `(err, bytesRead, buffer)`. If the file is not modified concurrently, the end-of-file is reached when the number of bytes read is zero. If this method is invoked as its [`util.promisify()`][]ed version, it returns -a `Promise` for an `Object` with `bytesRead` and `buffer` properties. +a promise for an `Object` with `bytesRead` and `buffer` properties. -## `fs.read(fd, [options,] callback)` +### `fs.read(fd, [options,] callback)` - -* `path` {string|Buffer|URL} -* `options` {string|Object} - * `encoding` {string} **Default:** `'utf8'` - * `withFileTypes` {boolean} **Default:** `false` -* Returns: {string[]|Buffer[]|fs.Dirent[]} - -Synchronous readdir(3). - -The optional `options` argument can be a string specifying an encoding, or an -object with an `encoding` property specifying the character encoding to use for -the filenames returned. If the `encoding` is set to `'buffer'`, -the filenames returned will be passed as `Buffer` objects. - -If `options.withFileTypes` is set to `true`, the result will contain -[`fs.Dirent`][] objects. +{fs.Dirent} objects. -## `fs.readFile(path[, options], callback)` +### `fs.readFile(path[, options], callback)` - -* `path` {string|Buffer|URL|integer} filename or file descriptor -* `options` {Object|string} - * `encoding` {string|null} **Default:** `null` - * `flag` {string} See [support of file system `flags`][]. **Default:** `'r'`. -* Returns: {string|Buffer} - -Returns the contents of the `path`. - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.readFile()`][]. - -If the `encoding` option is specified then this function returns a -string. Otherwise it returns a buffer. - -Similar to [`fs.readFile()`][], when the path is a directory, the behavior of -`fs.readFileSync()` is platform-specific. - -```js -// macOS, Linux, and Windows -fs.readFileSync(''); -// => [Error: EISDIR: illegal operation on a directory, read ] - -// FreeBSD -fs.readFileSync(''); // => -``` - -## `fs.readlink(path[, options], callback)` - - -* `path` {string|Buffer|URL} -* `options` {string|Object} - * `encoding` {string} **Default:** `'utf8'` -* Returns: {string|Buffer} +Reads the contents of the symbolic link refered to by `path`. The callback gets +two arguments `(err, linkString)`. -Synchronous readlink(2). Returns the symbolic link's string value. +See the POSIX readlink(2) documentation for more details. The optional `options` argument can be a string specifying an encoding, or an object with an `encoding` property specifying the character encoding to use for -the link path returned. If the `encoding` is set to `'buffer'`, -the link path returned will be passed as a `Buffer` object. - -## `fs.readSync(fd, buffer, offset, length, position)` - - -* `fd` {integer} -* `buffer` {Buffer|TypedArray|DataView} -* `offset` {integer} -* `length` {integer} -* `position` {integer|bigint} -* Returns: {number} - -Returns the number of `bytesRead`. - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.read()`][]. - -## `fs.readSync(fd, buffer, [options])` - - -* `fd` {integer} -* `buffer` {Buffer|TypedArray|DataView} -* `options` {Object} - * `offset` {integer} **Default:** `0` - * `length` {integer} **Default:** `buffer.length` - * `position` {integer|bigint} **Default:** `null` -* Returns: {number} - -Returns the number of `bytesRead`. - -Similar to the above `fs.readSync` function, this version takes an optional `options` object. -If no `options` object is specified, it will default with the above values. - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.read()`][]. +the link path passed to the callback. If the `encoding` is set to `'buffer'`, +the link path returned will be passed as a {Buffer} object. -## `fs.readv(fd, buffers[, position], callback)` +### `fs.readv(fd, buffers[, position], callback)` - -* `fd` {integer} -* `buffers` {ArrayBufferView[]} -* `position` {integer} -* Returns: {number} The number of bytes read. - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.readv()`][]. +a promise for an `Object` with `bytesRead` and `buffers` properties. -## `fs.realpath(path[, options], callback)` +### `fs.realpath(path[, options], callback)` @@ -3461,66 +3031,13 @@ Only paths that can be converted to UTF8 strings are supported. The optional `options` argument can be a string specifying an encoding, or an object with an `encoding` property specifying the character encoding to use for the path passed to the callback. If the `encoding` is set to `'buffer'`, -the path returned will be passed as a `Buffer` object. - -On Linux, when Node.js is linked against musl libc, the procfs file system must -be mounted on `/proc` in order for this function to work. Glibc does not have -this restriction. - -## `fs.realpathSync(path[, options])` - - -* `path` {string|Buffer|URL} -* `options` {string|Object} - * `encoding` {string} **Default:** `'utf8'` -* Returns: {string|Buffer} - -Returns the resolved pathname. - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.realpath()`][]. - -## `fs.realpathSync.native(path[, options])` - - -* `path` {string|Buffer|URL} -* `options` {string|Object} - * `encoding` {string} **Default:** `'utf8'` -* Returns: {string|Buffer} - -Synchronous realpath(3). - -Only paths that can be converted to UTF8 strings are supported. - -The optional `options` argument can be a string specifying an encoding, or an -object with an `encoding` property specifying the character encoding to use for -the path returned. If the `encoding` is set to `'buffer'`, -the path returned will be passed as a `Buffer` object. +the path returned will be passed as a {Buffer} object. On Linux, when Node.js is linked against musl libc, the procfs file system must be mounted on `/proc` in order for this function to work. Glibc does not have this restriction. -## `fs.rename(oldPath, newPath, callback)` +### `fs.rename(oldPath, newPath, callback)` - -* `oldPath` {string|Buffer|URL} -* `newPath` {string|Buffer|URL} - -Synchronous rename(2). Returns `undefined`. - -## `fs.rmdir(path[, options], callback)` +### `fs.rmdir(path[, options], callback)` - -* `path` {string|Buffer|URL} -* `options` {Object} - * `maxRetries` {integer} If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or - `EPERM` error is encountered, Node.js retries the operation with a linear - backoff wait of `retryDelay` milliseconds longer on each try. This option - represents the number of retries. This option is ignored if the `recursive` - option is not `true`. **Default:** `0`. - * `recursive` {boolean} If `true`, perform a recursive directory removal. In - recursive mode, errors are not reported if `path` does not exist, and - operations are retried on failure. **Default:** `false`. - * `retryDelay` {integer} The amount of time in milliseconds to wait between - retries. This option is ignored if the `recursive` option is not `true`. - **Default:** `100`. - -Synchronous rmdir(2). Returns `undefined`. - -Using `fs.rmdirSync()` on a file (not a directory) results in an `ENOENT` error -on Windows and an `ENOTDIR` error on POSIX. - -Setting `recursive` to `true` results in behavior similar to the Unix command -`rm -rf`: an error will not be raised for paths that do not exist, and paths -that represent files will be deleted. The permissive behavior of the -`recursive` option is deprecated, `ENOTDIR` and `ENOENT` will be thrown in -the future. - -## `fs.rm(path[, options], callback)` +### `fs.rm(path[, options], callback)` @@ -3708,61 +3163,38 @@ Asynchronously removes files and directories (modeled on the standard POSIX `rm` utility). No arguments other than a possible exception are given to the completion callback. -## `fs.rmSync(path[, options])` +### `fs.stat(path[, options], callback)` - -* `path` {string|Buffer|URL} -* `options` {Object} - * `force` {boolean} When `true`, exceptions will be ignored if `path` does - not exist. **Default:** `false`. - * `maxRetries` {integer} If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or - `EPERM` error is encountered, Node.js will retry the operation with a linear - backoff wait of `retryDelay` milliseconds longer on each try. This option - represents the number of retries. This option is ignored if the `recursive` - option is not `true`. **Default:** `0`. - * `recursive` {boolean} If `true`, perform a recursive directory removal. In - recursive mode operations are retried on failure. **Default:** `false`. - * `retryDelay` {integer} The amount of time in milliseconds to wait between - retries. This option is ignored if the `recursive` option is not `true`. - **Default:** `100`. - -Synchronously removes files and directories (modeled on the standard POSIX `rm` -utility). Returns `undefined`. - -## `fs.stat(path[, options], callback)` - * `path` {string|Buffer|URL} * `options` {Object} * `bigint` {boolean} Whether the numeric values in the returned - [`fs.Stats`][] object should be `bigint`. **Default:** `false`. + {fs.Stats} object should be `bigint`. **Default:** `false`. * `callback` {Function} * `err` {Error} * `stats` {fs.Stats} Asynchronous stat(2). The callback gets two arguments `(err, stats)` where -`stats` is an [`fs.Stats`][] object. +`stats` is an {fs.Stats} object. In case of an error, the `err.code` will be one of [Common System Errors][]. @@ -3784,13 +3216,13 @@ For example, given the following directory structure: The next program will check for the stats of the given paths: -```js -const fs = require('fs'); +```js esm +import { stat } from 'fs'; const pathsToCheck = ['./txtDir', './txtDir/file.txt']; for (let i = 0; i < pathsToCheck.length; i++) { - fs.stat(pathsToCheck[i], function(err, stats) { + stat(pathsToCheck[i], (err, stats) => { console.log(stats.isDirectory()); console.log(stats); }); @@ -3844,36 +3276,7 @@ Stats { } ``` -## `fs.statSync(path[, options])` - - -* `path` {string|Buffer|URL} -* `options` {Object} - * `bigint` {boolean} Whether the numeric values in the returned - [`fs.Stats`][] object should be `bigint`. **Default:** `false`. - * `throwIfNoEntry` {boolean} Whether an exception will be thrown - if no file system entry exists, rather than returning `undefined`. - **Default:** `true`. -* Returns: {fs.Stats} - -Synchronous stat(2). - -## `fs.symlink(target, path[, type], callback)` +### `fs.symlink(target, path[, type], callback)` - -* `target` {string|Buffer|URL} -* `path` {string|Buffer|URL} -* `type` {string} - -Returns `undefined`. - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.symlink()`][]. - -## `fs.truncate(path[, len], callback)` +### `fs.truncate(path[, len], callback)` - -* `path` {string|Buffer|URL} -* `len` {integer} **Default:** `0` - -Synchronous truncate(2). Returns `undefined`. A file descriptor can also be -passed as the first argument. In this case, `fs.ftruncateSync()` is called. - -Passing a file descriptor is deprecated and may result in an error being thrown -in the future. +See the POSIX truncate(2) documentation for more details. -## `fs.unlink(path, callback)` +### `fs.unlink(path, callback)` - -* `path` {string|Buffer|URL} - -Synchronous unlink(2). Returns `undefined`. +See the POSIX unlink(2) documentation for more details. -## `fs.unwatchFile(filename[, listener])` +### `fs.unwatchFile(filename[, listener])` @@ -4057,7 +3414,7 @@ Using [`fs.watch()`][] is more efficient than `fs.watchFile()` and `fs.unwatchFile()`. `fs.watch()` should be used instead of `fs.watchFile()` and `fs.unwatchFile()` when possible. -## `fs.utimes(path, atime, mtime, callback)` +### `fs.utimes(path, atime, mtime, callback)` - -* `path` {string|Buffer|URL} -* `atime` {number|string|Date} -* `mtime` {number|string|Date} - -Returns `undefined`. - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.utimes()`][]. - -## `fs.watch(filename[, options][, listener])` +### `fs.watch(filename[, options][, listener])` @@ -4191,7 +3521,7 @@ when the option is used on a platform that does not support it. On Windows, no events will be emitted if the watched directory is moved or renamed. An `EPERM` error is reported when the watched directory is deleted. -#### Availability +##### Availability @@ -4216,7 +3546,7 @@ when using virtualization software such as Vagrant or Docker. It is still possible to use `fs.watchFile()`, which uses stat polling, but this method is slower and less reliable. -#### Inodes +##### Inodes @@ -4230,7 +3560,7 @@ AIX files retain the same inode for the lifetime of a file. Saving and closing a watched file on AIX will result in two notifications (one for adding new content, and one for truncation). -#### Filename argument +##### Filename argument @@ -4239,8 +3569,9 @@ macOS, Windows, and AIX. Even on supported platforms, `filename` is not always guaranteed to be provided. Therefore, don't assume that `filename` argument is always provided in the callback, and have some fallback logic if it is `null`. -```js -fs.watch('somedir', (eventType, filename) => { +```js esm +import { watch } from 'fs'; +watch('somedir', (eventType, filename) => { console.log(`event type is: ${eventType}`); if (filename) { console.log(`filename provided: ${filename}`); @@ -4250,7 +3581,7 @@ fs.watch('somedir', (eventType, filename) => { }); ``` -## `fs.watchFile(filename[, options], listener)` +### `fs.watchFile(filename[, options], listener)` - -* `file` {string|Buffer|URL|integer} filename or file descriptor -* `data` {string|Buffer|TypedArray|DataView|Object} -* `options` {Object|string} - * `encoding` {string|null} **Default:** `'utf8'` - * `mode` {integer} **Default:** `0o666` - * `flag` {string} See [support of file system `flags`][]. **Default:** `'w'`. - -Returns `undefined`. - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.writeFile()`][]. - -## `fs.writeSync(fd, buffer[, offset[, length[, position]]])` - - -* `fd` {integer} -* `buffer` {Buffer|TypedArray|DataView|string|Object} -* `offset` {integer} -* `length` {integer} -* `position` {integer} -* Returns: {number} The number of bytes written. - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.write(fd, buffer...)`][]. - -## `fs.writeSync(fd, string[, position[, encoding]])` - - -* `fd` {integer} -* `string` {string|Object} -* `position` {integer} -* `encoding` {string} -* Returns: {number} The number of bytes written. - -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.write(fd, string...)`][]. - -## `fs.writev(fd, buffers[, position], callback)` +### `fs.writev(fd, buffers[, position], callback)` @@ -4688,7 +3933,7 @@ at the current position. The callback will be given three arguments: `err`, `bytesWritten`, and `buffers`. `bytesWritten` is how many bytes were written from `buffers`. -If this method is [`util.promisify()`][]ed, it returns a `Promise` for an +If this method is [`util.promisify()`][]ed, it returns a promise for an `Object` with `bytesWritten` and `buffers` properties. It is unsafe to use `fs.writev()` multiple times on the same file without @@ -4698,247 +3943,269 @@ On Linux, positional writes don't work when the file is opened in append mode. The kernel ignores the position argument and always appends the data to the end of the file. -## `fs.writevSync(fd, buffers[, position])` - +## Synchronous API -* `fd` {integer} -* `buffers` {ArrayBufferView[]} -* `position` {integer} -* Returns: {number} The number of bytes written. +The synchronous APIs perform all operations synchronously, blocking the +event loop until the operation completes or fails. -For detailed information, see the documentation of the asynchronous version of -this API: [`fs.writev()`][]. - -## `fs` Promises API +### `fs.accessSync(path[, mode])` - -The `fs.promises` API provides an alternative set of asynchronous file system -methods that return `Promise` objects rather than using callbacks. The -API is accessible via `require('fs').promises` or `require('fs/promises')`. - -### Class: `FileHandle` - -A `FileHandle` object is a wrapper for a numeric file descriptor. -Instances of `FileHandle` are distinct from numeric file descriptors -in that they provide an object oriented API for working with files. - -If a `FileHandle` is not closed using the -`filehandle.close()` method, it might automatically close the file descriptor -and will emit a process warning, thereby helping to prevent memory leaks. -Please do not rely on this behavior because it is unreliable and -the file may not be closed. Instead, always explicitly close `FileHandle`s. -Node.js may change this behavior in the future. +* `path` {string|Buffer|URL} +* `mode` {integer} **Default:** `fs.constants.F_OK` -Instances of the `FileHandle` object are created internally by the -`fsPromises.open()` method. +Synchronously tests a user's permissions for the file or directory specified +by `path`. The `mode` argument is an optional integer that specifies the +accessibility checks to be performed. Check [File access constants][] for +possible values of `mode`. It is possible to create a mask consisting of +the bitwise OR of two or more values +(e.g. `fs.constants.W_OK | fs.constants.R_OK`). -Unlike the callback-based API (`fs.fstat()`, `fs.fchown()`, `fs.fchmod()`, and -so on), a numeric file descriptor is not used by the promise-based API. Instead, -the promise-based API uses the `FileHandle` class in order to help avoid -accidental leaking of unclosed file descriptors after a `Promise` is fulfilled -or rejected. +If any of the accessibility checks fail, an `Error` will be thrown. Otherwise, +the method will return `undefined`. -#### Event: `'close'` - +```js esm +import { accessSync, constants } from 'fs'; -The `'close'` event is emitted when the `FileHandle` and any of its underlying -resources (a file descriptor, for example) have been closed. +try { + accessSync('etc/passwd', constants.R_OK | constants.W_OK); + console.log('can read/write'); +} catch (err) { + console.error('no access!'); +} +``` -#### `filehandle.appendFile(data, options)` +### `fs.appendFileSync(path, data[, options])` +* `path` {string|Buffer|URL|number} filename or file descriptor * `data` {string|Buffer} * `options` {Object|string} * `encoding` {string|null} **Default:** `'utf8'` -* Returns: {Promise} + * `mode` {integer} **Default:** `0o666` + * `flag` {string} See [support of file system `flags`][]. **Default:** `'a'`. -Alias of [`filehandle.writeFile()`][]. +Synchronously append data to a file, creating the file if it does not yet +exist. `data` can be a string or a {Buffer}. -When operating on file handles, the mode cannot be changed from what it was set -to with [`fsPromises.open()`][]. Therefore, this is equivalent to -[`filehandle.writeFile()`][]. +```js esm +import { appendFileSync } from 'fs'; -#### `filehandle.chmod(mode)` +try { + appendFileSync('message.txt', 'data to append'); + console.log('The "data to append" was appended to file!'); +} catch (err) { + /* Handle the error */ +} +``` + +If `options` is a string, then it specifies the encoding: + +```js esm +import { appendFileSync } from 'fs'; + +appendFileSync('message.txt', 'data to append', 'utf8'); +``` + +The `path` may be specified as a numeric file descriptor that has been opened +for appending (using `fs.open()` or `fs.openSync()`). The file descriptor will +not be closed automatically. + +```js esm +import { openSync, closeSync, appendFileSync } from 'fs'; + +let fd; + +try { + fd = openSync('message.txt', 'a'); + appendFileSync(fd, 'data to append', 'utf8'); +} catch (err) { + /* Handle the error */ +} finally { + if (fd !== undefined) + closeSync(fd); +} +``` + +### `fs.chmodSync(path, mode)` -* `mode` {integer} -* Returns: {Promise} +* `path` {string|Buffer|URL} +* `mode` {string|integer} + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.chmod()`][]. -Modifies the permissions on the file. The `Promise` is fulfilled with no -arguments upon success. +See the POSIX chmod(2) documentation for more detail. -#### `filehandle.chown(uid, gid)` +### `fs.chownSync(path, uid, gid)` +* `path` {string|Buffer|URL} * `uid` {integer} * `gid` {integer} -* Returns: {Promise} -Changes the ownership of the file then fulfills the `Promise` with no arguments -upon success. +Synchronously changes owner and group of a file. Returns `undefined`. +This is the synchronous version of [`fs.chown()`][]. -#### `filehandle.close()` +See the POSIX chown(2) documentation for more detail. + +### `fs.closeSync(fd)` -* Returns: {Promise} A `Promise` that will be fulfilled once the underlying - file descriptor is closed, or will be rejected if an error occurs while - closing. +* `fd` {integer} -Closes the file handle after waiting for any pending operation on the handle to -complete. +Closes the file descriptor. Returns `undefined`. -```js -const fsPromises = require('fs').promises; -async function openAndClose() { - let filehandle; - try { - filehandle = await fsPromises.open('thefile.txt', 'r'); - } finally { - if (filehandle !== undefined) - await filehandle.close(); - } -} -``` +Calling `fs.closeSync()` on any file descriptor (`fd`) that is currently in use +through any other `fs` operation may lead to undefined behavior. -#### `filehandle.datasync()` +See the POSIX close(2) documentation for more detail. + +### `fs.copyFileSync(src, dest[, mode])` -* Returns: {Promise} +* `src` {string|Buffer|URL} source filename to copy +* `dest` {string|Buffer|URL} destination filename of the copy operation +* `mode` {integer} modifiers for copy operation. **Default:** `0`. -Asynchronous fdatasync(2). The `Promise` is fulfilled with no arguments upon -success. +Synchronously copies `src` to `dest`. By default, `dest` is overwritten if it +already exists. Returns `undefined`. Node.js makes no guarantees about the +atomicity of the copy operation. If an error occurs after the destination file +has been opened for writing, Node.js will attempt to remove the destination. -#### `filehandle.fd` - +`mode` is an optional integer that specifies the behavior +of the copy operation. It is possible to create a mask consisting of the bitwise +OR of two or more values (e.g. +`fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE`). + +* `fs.constants.COPYFILE_EXCL`: The copy operation will fail if `dest` already + exists. +* `fs.constants.COPYFILE_FICLONE`: The copy operation will attempt to create a + copy-on-write reflink. If the platform does not support copy-on-write, then a + fallback copy mechanism is used. +* `fs.constants.COPYFILE_FICLONE_FORCE`: The copy operation will attempt to + create a copy-on-write reflink. If the platform does not support + copy-on-write, then the operation will fail. -* {number} The numeric file descriptor managed by the `FileHandle` object. +```js esm +import { copyFileSync, constants } from 'fs'; -#### `filehandle.read(buffer, offset, length, position)` - +// destination.txt will be created or overwritten by default. +copyFileSync('source.txt', 'destination.txt'); +console.log('source.txt was copied to destination.txt'); -* `buffer` {Buffer|Uint8Array} -* `offset` {integer} -* `length` {integer} -* `position` {integer} -* Returns: {Promise} +// By using COPYFILE_EXCL, the operation will fail if destination.txt exists. +copyFileSync('source.txt', 'destination.txt', constants.COPYFILE_EXCL); +``` -Read data from the file. +### `fs.existsSync(path)` + -`buffer` is the buffer that the data will be written to. +* `path` {string|Buffer|URL} +* Returns: {boolean} -`offset` is the offset in the buffer to start writing at. +Returns `true` if the path exists, `false` otherwise. -`length` is an integer specifying the number of bytes to read. +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.exists()`][]. -`position` is an argument specifying where to begin reading from in the file. -If `position` is `null`, data will be read from the current file position, -and the file position will be updated. -If `position` is an integer, the file position will remain unchanged. +`fs.exists()` is deprecated, but `fs.existsSync()` is not. The `callback` +parameter to `fs.exists()` accepts parameters that are inconsistent with other +Node.js callbacks. `fs.existsSync()` does not use a callback. -Following successful read, the `Promise` is fulfilled with an object with a -`bytesRead` property specifying the number of bytes read, and a `buffer` -property that is a reference to the passed in `buffer` argument. +```js esm +import { existsSync } from 'fs'; -If the file is not modified concurrently, the end-of-file is reached when the -number of bytes read is zero. +if (existsSync('/etc/passwd')) + console.log('The path exists.'); +``` -#### `filehandle.read(options)` +### `fs.fchmodSync(fd, mode)` -* `options` {Object} - * `buffer` {Buffer|Uint8Array} **Default:** `Buffer.alloc(16384)` - * `offset` {integer} **Default:** `0` - * `length` {integer} **Default:** `buffer.length` - * `position` {integer} **Default:** `null` -* Returns: {Promise} -#### `filehandle.readFile(options)` - +* `fd` {integer} +* `mode` {string|integer} -* `options` {Object|string} - * `encoding` {string|null} **Default:** `null` - * `signal` {AbortSignal} allows aborting an in-progress readFile -* Returns: {Promise} +Sets the permissions on the file. Returns `undefined`. -Asynchronously reads the entire contents of a file. +See the POSIX fchmod(2) documentation for more detail. -The `Promise` is fulfilled with the contents of the file. If no encoding is -specified (using `options.encoding`), the data is returned as a `Buffer` -object. Otherwise, the data will be a string. +### `fs.fchownSync(fd, uid, gid)` + -If `options` is a string, then it specifies the encoding. +* `fd` {integer} +* `uid` {integer} The file's new owner's user id. +* `gid` {integer} The file's new group's group id. -The `FileHandle` has to support reading. +Sets the owner of the file. Returns `undefined`. -If one or more `filehandle.read()` calls are made on a file handle and then a -`filehandle.readFile()` call is made, the data will be read from the current -position till the end of the file. It doesn't always read from the beginning -of the file. +See the POSIX fchown(2) documentation for more detail. -#### `filehandle.readv(buffers[, position])` +### `fs.fdatasyncSync(fd)` -* `buffers` {ArrayBufferView[]} -* `position` {integer} -* Returns: {Promise} - -Read from a file and write to an array of `ArrayBufferView`s - -The `Promise` is fulfilled with an object containing a `bytesRead` property -identifying the number of bytes read, and a `buffers` property containing -a reference to the `buffers` input. +* `fd` {integer} -`position` is the offset from the beginning of the file where this data -should be read from. If `typeof position !== 'number'`, the data will be read -from the current position. +Forces all currently queued I/O operations associated with the file to the +operating system's synchronized I/O completion state. Refer to the POSIX +fdatasync(2) documentation for details. Returns `undefined`. -#### `filehandle.stat([options])` +### `fs.fstatSync(fd[, options])` +* `fd` {integer} * `options` {Object} * `bigint` {boolean} Whether the numeric values in the returned - [`fs.Stats`][] object should be `bigint`. **Default:** `false`. -* Returns: {Promise} + {fs.Stats} object should be `bigint`. **Default:** `false`. +* Returns: {fs.Stats} -Retrieves the [`fs.Stats`][] for the file. +Retrieves the {fs.Stats} for the file descriptor. -#### `filehandle.sync()` +See the POSIX fstat(2) documentation for more detail. + +### `fs.fsyncSync(fd)` -* Returns: {Promise} +* `fd` {integer} -Asynchronous fsync(2). The `Promise` is fulflled with no arguments upon -success. +Request that all data for the open file descriptor is flushed to the storage +device. The specific implementation is operating system and device specific. +Refer to the POSIX fsync(2) documentation for more detail. Returns `undefined`. -#### `filehandle.truncate(len)` +### `fs.ftruncateSync(fd[, len])` +* `fd` {integer} +* `len` {integer} **Default:** `0` + +Truncates the file descriptor. Returns `undefined`. + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.ftruncate()`][]. + +### `fs.futimesSync(fd, atime, mtime)` + + +* `fd` {integer} +* `atime` {number|string|Date} +* `mtime` {number|string|Date} + +Synchronous version of [`fs.futimes()`][]. Returns `undefined`. + +### `fs.lchmodSync(path, mode)` + + +* `path` {string|Buffer|URL} +* `mode` {integer} + +Changes the permissions on a symbolic link. Returns `undefined`. + +This method is only implemented on macOS. + +See the POSIX lchmod(2) documentation for more detail. + +### `fs.lchownSync(path, uid, gid)` + + +* `path` {string|Buffer|URL} +* `uid` {integer} The file's new owner's user id. +* `gid` {integer} The file's new group's group id. + +Set the owner for the path. Returns `undefined`. + +See the POSIX lchown(2) documentation for more details. + +### `fs.lutimesSync(path, atime, mtime)` + + +* `path` {string|Buffer|URL} +* `atime` {number|string|Date} +* `mtime` {number|string|Date} + +Change the file system timestamps of the symbolic link referenced by `path`. +Returns `undefined`, or throws an exception when parameters are incorrect or +the operation fails. This is the synchronous version of [`fs.lutimes()`][]. + +### `fs.linkSync(existingPath, newPath)` + + +* `existingPath` {string|Buffer|URL} +* `newPath` {string|Buffer|URL} + +Creates a new link from the `existingPath` to the `newPath`. See the POSIX +link(2) documentation for more detail. Returns `undefined`. + +### `fs.lstatSync(path[, options])` + + +* `path` {string|Buffer|URL} +* `options` {Object} + * `bigint` {boolean} Whether the numeric values in the returned + {fs.Stats} object should be `bigint`. **Default:** `false`. + * `throwIfNoEntry` {boolean} Whether an exception will be thrown + if no file system entry exists, rather than returning `undefined`. + **Default:** `true`. +* Returns: {fs.Stats} + +Retrieves the {fs.Stats} for the symbolic link refered to by `path`. + +See the POSIX lstat(2) documentation for more details. + +### `fs.mkdirSync(path[, options])` + + +* `path` {string|Buffer|URL} +* `options` {Object|integer} + * `recursive` {boolean} **Default:** `false` + * `mode` {string|integer} Not supported on Windows. **Default:** `0o777`. +* Returns: {string|undefined} + +Synchronously creates a directory. Returns `undefined`, or if `recursive` is +`true`, the first directory path created. +This is the synchronous version of [`fs.mkdir()`][]. + +See the POSIX mkdir(2) documentation for more details. + +### `fs.mkdtempSync(prefix[, options])` + + +* `prefix` {string} +* `options` {string|Object} + * `encoding` {string} **Default:** `'utf8'` +* Returns: {string} + +Returns the created directory path. + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.mkdtemp()`][]. + +The optional `options` argument can be a string specifying an encoding, or an +object with an `encoding` property specifying the character encoding to use. + +### `fs.opendirSync(path[, options])` + + +* `path` {string|Buffer|URL} +* `options` {Object} + * `encoding` {string|null} **Default:** `'utf8'` + * `bufferSize` {number} Number of directory entries that are buffered + internally when reading from the directory. Higher values lead to better + performance but higher memory usage. **Default:** `32` +* Returns: {fs.Dir} + +Synchronously open a directory. See opendir(3). + +Creates an {fs.Dir}, which contains all further functions for reading from +and cleaning up the directory. + +The `encoding` option sets the encoding for the `path` while opening the +directory and subsequent read operations. + +### `fs.openSync(path[, flags, mode])` + + +* `path` {string|Buffer|URL} +* `flags` {string|number} **Default:** `'r'`. + See [support of file system `flags`][]. +* `mode` {string|integer} **Default:** `0o666` +* Returns: {number} + +Returns an integer representing the file descriptor. + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.open()`][]. + +### `fs.readdirSync(path[, options])` + + +* `path` {string|Buffer|URL} +* `options` {string|Object} + * `encoding` {string} **Default:** `'utf8'` + * `withFileTypes` {boolean} **Default:** `false` +* Returns: {string[]|Buffer[]|fs.Dirent[]} + +Reads the contents of the director. + +See the POSIX readdir(3) documentation for more details. + +The optional `options` argument can be a string specifying an encoding, or an +object with an `encoding` property specifying the character encoding to use for +the filenames returned. If the `encoding` is set to `'buffer'`, +the filenames returned will be passed as {Buffer} objects. + +If `options.withFileTypes` is set to `true`, the result will contain +{fs.Dirent} objects. + +### `fs.readFileSync(path[, options])` + + +* `path` {string|Buffer|URL|integer} filename or file descriptor +* `options` {Object|string} + * `encoding` {string|null} **Default:** `null` + * `flag` {string} See [support of file system `flags`][]. **Default:** `'r'`. +* Returns: {string|Buffer} + +Returns the contents of the `path`. + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.readFile()`][]. + +If the `encoding` option is specified then this function returns a +string. Otherwise it returns a buffer. + +Similar to [`fs.readFile()`][], when the path is a directory, the behavior of +`fs.readFileSync()` is platform-specific. + +```js esm +import { readFileSync } from 'fs'; + +// macOS, Linux, and Windows +readFileSync(''); +// => [Error: EISDIR: illegal operation on a directory, read ] + +// FreeBSD +readFileSync(''); // => +``` + +### `fs.readlinkSync(path[, options])` + + +* `path` {string|Buffer|URL} +* `options` {string|Object} + * `encoding` {string} **Default:** `'utf8'` +* Returns: {string|Buffer} + +Returns the symbolic link's string value. + +See the POSIX readlink(2) documentation for more details. + +The optional `options` argument can be a string specifying an encoding, or an +object with an `encoding` property specifying the character encoding to use for +the link path returned. If the `encoding` is set to `'buffer'`, +the link path returned will be passed as a {Buffer} object. + +### `fs.readSync(fd, buffer, offset, length, position)` + + +* `fd` {integer} +* `buffer` {Buffer|TypedArray|DataView} +* `offset` {integer} +* `length` {integer} +* `position` {integer|bigint} +* Returns: {number} + +Returns the number of `bytesRead`. + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.read()`][]. + +### `fs.readSync(fd, buffer, [options])` + + +* `fd` {integer} +* `buffer` {Buffer|TypedArray|DataView} +* `options` {Object} + * `offset` {integer} **Default:** `0` + * `length` {integer} **Default:** `buffer.length` + * `position` {integer|bigint} **Default:** `null` +* Returns: {number} + +Returns the number of `bytesRead`. + +Similar to the above `fs.readSync` function, this version takes an optional `options` object. +If no `options` object is specified, it will default with the above values. + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.read()`][]. + +### `fs.readvSync(fd, buffers[, position])` + + +* `fd` {integer} +* `buffers` {ArrayBufferView[]} +* `position` {integer} +* Returns: {number} The number of bytes read. + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.readv()`][]. + +### `fs.realpathSync(path[, options])` + + +* `path` {string|Buffer|URL} +* `options` {string|Object} + * `encoding` {string} **Default:** `'utf8'` +* Returns: {string|Buffer} + +Returns the resolved pathname. + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.realpath()`][]. + +### `fs.realpathSync.native(path[, options])` + + +* `path` {string|Buffer|URL} +* `options` {string|Object} + * `encoding` {string} **Default:** `'utf8'` +* Returns: {string|Buffer} + +Synchronous realpath(3). + +Only paths that can be converted to UTF8 strings are supported. + +The optional `options` argument can be a string specifying an encoding, or an +object with an `encoding` property specifying the character encoding to use for +the path returned. If the `encoding` is set to `'buffer'`, +the path returned will be passed as a {Buffer} object. + +On Linux, when Node.js is linked against musl libc, the procfs file system must +be mounted on `/proc` in order for this function to work. Glibc does not have +this restriction. + +### `fs.renameSync(oldPath, newPath)` + + +* `oldPath` {string|Buffer|URL} +* `newPath` {string|Buffer|URL} + +Renames the file from `oldPath` to `newPath`. Returns `undefined`. + +See the POSIX rename(2) documentation for more details. + +### `fs.rmdirSync(path[, options])` + + +* `path` {string|Buffer|URL} +* `options` {Object} + * `maxRetries` {integer} If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or + `EPERM` error is encountered, Node.js retries the operation with a linear + backoff wait of `retryDelay` milliseconds longer on each try. This option + represents the number of retries. This option is ignored if the `recursive` + option is not `true`. **Default:** `0`. + * `recursive` {boolean} If `true`, perform a recursive directory removal. In + recursive mode, errors are not reported if `path` does not exist, and + operations are retried on failure. **Default:** `false`. + * `retryDelay` {integer} The amount of time in milliseconds to wait between + retries. This option is ignored if the `recursive` option is not `true`. + **Default:** `100`. + +Synchronous rmdir(2). Returns `undefined`. + +Using `fs.rmdirSync()` on a file (not a directory) results in an `ENOENT` error +on Windows and an `ENOTDIR` error on POSIX. + +Setting `recursive` to `true` results in behavior similar to the Unix command +`rm -rf`: an error will not be raised for paths that do not exist, and paths +that represent files will be deleted. The permissive behavior of the +`recursive` option is deprecated, `ENOTDIR` and `ENOENT` will be thrown in +the future. + +### `fs.rmSync(path[, options])` + + +* `path` {string|Buffer|URL} +* `options` {Object} + * `force` {boolean} When `true`, exceptions will be ignored if `path` does + not exist. **Default:** `false`. + * `maxRetries` {integer} If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or + `EPERM` error is encountered, Node.js will retry the operation with a linear + backoff wait of `retryDelay` milliseconds longer on each try. This option + represents the number of retries. This option is ignored if the `recursive` + option is not `true`. **Default:** `0`. + * `recursive` {boolean} If `true`, perform a recursive directory removal. In + recursive mode operations are retried on failure. **Default:** `false`. + * `retryDelay` {integer} The amount of time in milliseconds to wait between + retries. This option is ignored if the `recursive` option is not `true`. + **Default:** `100`. + +Synchronously removes files and directories (modeled on the standard POSIX `rm` +utility). Returns `undefined`. + +### `fs.statSync(path[, options])` + + +* `path` {string|Buffer|URL} +* `options` {Object} + * `bigint` {boolean} Whether the numeric values in the returned + {fs.Stats} object should be `bigint`. **Default:** `false`. + * `throwIfNoEntry` {boolean} Whether an exception will be thrown + if no file system entry exists, rather than returning `undefined`. + **Default:** `true`. +* Returns: {fs.Stats} + +Retrieves the {fs.Stats} for the path. + +### `fs.symlinkSync(target, path[, type])` + + +* `target` {string|Buffer|URL} +* `path` {string|Buffer|URL} +* `type` {string} + +Returns `undefined`. + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.symlink()`][]. + +### `fs.truncateSync(path[, len])` + + +* `path` {string|Buffer|URL} * `len` {integer} **Default:** `0` -* Returns: {Promise} -Truncates the file then fulfills the `Promise` with no arguments upon success. +Truncates the file. Returns `undefined`. A file descriptor can also be +passed as the first argument. In this case, `fs.ftruncateSync()` is called. + +Passing a file descriptor is deprecated and may result in an error being thrown +in the future. + +### `fs.unlinkSync(path)` + + +* `path` {string|Buffer|URL} + +Synchronous unlink(2). Returns `undefined`. + +### `fs.utimesSync(path, atime, mtime)` + + +* `path` {string|Buffer|URL} +* `atime` {number|string|Date} +* `mtime` {number|string|Date} + +Returns `undefined`. + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.utimes()`][]. + +### `fs.writeFileSync(file, data[, options])` + + +* `file` {string|Buffer|URL|integer} filename or file descriptor +* `data` {string|Buffer|TypedArray|DataView|Object} +* `options` {Object|string} + * `encoding` {string|null} **Default:** `'utf8'` + * `mode` {integer} **Default:** `0o666` + * `flag` {string} See [support of file system `flags`][]. **Default:** `'w'`. + +Returns `undefined`. + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.writeFile()`][]. + +### `fs.writeSync(fd, buffer[, offset[, length[, position]]])` + + +* `fd` {integer} +* `buffer` {Buffer|TypedArray|DataView|string|Object} +* `offset` {integer} +* `length` {integer} +* `position` {integer} +* Returns: {number} The number of bytes written. + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.write(fd, buffer...)`][]. + +### `fs.writeSync(fd, string[, position[, encoding]])` + -If the file was larger than `len` bytes, only the first `len` bytes will be -retained in the file. +* `fd` {integer} +* `string` {string|Object} +* `position` {integer} +* `encoding` {string} +* Returns: {number} The number of bytes written. -For example, the following program retains only the first four bytes of the -file: +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.write(fd, string...)`][]. -```js -const fs = require('fs'); -const fsPromises = fs.promises; +### `fs.writevSync(fd, buffers[, position])` + -console.log(fs.readFileSync('temp.txt', 'utf8')); -// Prints: Node.js +* `fd` {integer} +* `buffers` {ArrayBufferView[]} +* `position` {integer} +* Returns: {number} The number of bytes written. -async function doTruncate() { - let filehandle = null; - try { - filehandle = await fsPromises.open('temp.txt', 'r+'); - await filehandle.truncate(4); - } finally { - if (filehandle) { - // Close the file if it is opened. - await filehandle.close(); - } - } - console.log(fs.readFileSync('temp.txt', 'utf8')); // Prints: Node -} +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.writev()`][]. -doTruncate().catch(console.error); -``` +## Common Objects -If the file previously was shorter than `len` bytes, it is extended, and the -extended part is filled with null bytes (`'\0'`): +The common objects are shared by all of the file system API variants +(promise, callback, and synchronous). -```js -const fs = require('fs'); -const fsPromises = fs.promises; +### Class: `fs.Dir` + -console.log(fs.readFileSync('temp.txt', 'utf8')); -// Prints: Node.js +A class representing a directory stream. -async function doTruncate() { - let filehandle = null; - try { - filehandle = await fsPromises.open('temp.txt', 'r+'); - await filehandle.truncate(10); - } finally { - if (filehandle) { - // Close the file if it is opened. - await filehandle.close(); - } - } - console.log(fs.readFileSync('temp.txt', 'utf8')); // Prints Node.js\0\0\0 +Created by [`fs.opendir()`][], [`fs.opendirSync()`][], or +[`fsPromises.opendir()`][]. + +```js esm +import { opendir } from 'fs/promises'; + +try { + const dir = await opendir('./'); + for await (const dirent of dir) + console.log(dirent.name); +} catch (err) { + console.error(err); } +``` + +#### `dir.close()` + + +* Returns: {Promise} + +Asynchronously close the directory's underlying resource handle. +Subsequent reads will result in errors. + +A promise is returned that will be resolved after the resource has been +closed. + +#### `dir.close(callback)` + + +* `callback` {Function} + * `err` {Error} + +Asynchronously close the directory's underlying resource handle. +Subsequent reads will result in errors. + +The `callback` will be called after the resource handle has been closed. + +#### `dir.closeSync()` + + +Synchronously close the directory's underlying resource handle. +Subsequent reads will result in errors. + +#### `dir.path` + + +* {string} + +The read-only path of this directory as was provided to [`fs.opendir()`][], +[`fs.opendirSync()`][], or [`fsPromises.opendir()`][]. + +#### `dir.read()` + + +* Returns: {Promise} containing {fs.Dirent|null} + +Asynchronously read the next directory entry via readdir(3) as an +{fs.Dirent}. + +A promise is returned that will be resolved with an {fs.Dirent}, or `null` +if there are no more directory entries to read. + +Directory entries returned by this function are in no particular order as +provided by the operating system's underlying directory mechanisms. +Entries added or removed while iterating over the directory might not be +included in the iteration results. + +#### `dir.read(callback)` + + +* `callback` {Function} + * `err` {Error} + * `dirent` {fs.Dirent|null} + +Asynchronously read the next directory entry via readdir(3) as an +{fs.Dirent}. + +After the read is completed, the `callback` will be called with an +{fs.Dirent}, or `null` if there are no more directory entries to read. + +Directory entries returned by this function are in no particular order as +provided by the operating system's underlying directory mechanisms. +Entries added or removed while iterating over the directory might not be +included in the iteration results. + +#### `dir.readSync()` + + +* Returns: {fs.Dirent|null} + +Synchronously read the next directory entry as an {fs.Dirent}. See the +POSIX readdir(3) documentation for more detail. + +If there are no more directory entries to read, `null` will be returned. + +Directory entries returned by this function are in no particular order as +provided by the operating system's underlying directory mechanisms. +Entries added or removed while iterating over the directory might not be +included in the iteration results. + +#### `dir[Symbol.asyncIterator]()` + + +* Returns: {AsyncIterator} of {fs.Dirent} + +Asynchronously iterates over the directory until all entries have +been read. Refer to the POSIX readdir(3) documentation for more detail. + +Entries returned by the async iterator are always an {fs.Dirent}. +The `null` case from `dir.read()` is handled internally. + +See {fs.Dir} for an example. + +Directory entries returned by this iterator are in no particular order as +provided by the operating system's underlying directory mechanisms. +Entries added or removed while iterating over the directory might not be +included in the iteration results. + +### Class: `fs.Dirent` + + +A representation of a directory entry, which can be a file or a subdirectory +within the directory, as returned by reading from an {fs.Dir}. The +directory entry is a combination of the file name and file type pairs. + +Additionally, when [`fs.readdir()`][] or [`fs.readdirSync()`][] is called with +the `withFileTypes` option set to `true`, the resulting array is filled with +{fs.Dirent} objects, rather than strings or {Buffer}s. + +#### `dirent.isBlockDevice()` + + +* Returns: {boolean} + +Returns `true` if the {fs.Dirent} object describes a block device. + +#### `dirent.isCharacterDevice()` + + +* Returns: {boolean} + +Returns `true` if the {fs.Dirent} object describes a character device. + +#### `dirent.isDirectory()` + + +* Returns: {boolean} + +Returns `true` if the {fs.Dirent} object describes a file system +directory. + +#### `dirent.isFIFO()` + + +* Returns: {boolean} + +Returns `true` if the {fs.Dirent} object describes a first-in-first-out +(FIFO) pipe. + +#### `dirent.isFile()` + + +* Returns: {boolean} + +Returns `true` if the {fs.Dirent} object describes a regular file. + +#### `dirent.isSocket()` + + +* Returns: {boolean} + +Returns `true` if the {fs.Dirent} object describes a socket. + +#### `dirent.isSymbolicLink()` + + +* Returns: {boolean} + +Returns `true` if the {fs.Dirent} object describes a symbolic link. + +#### `dirent.name` + + +* {string|Buffer} + +The file name that this {fs.Dirent} object refers to. The type of this +value is determined by the `options.encoding` passed to [`fs.readdir()`][] or +[`fs.readdirSync()`][]. + +### Class: `fs.FSWatcher` + + +* Extends {EventEmitter} + +A successful call to [`fs.watch()`][] method will return a new {fs.FSWatcher} +object. + +All {fs.FSWatcher} objects emit a `'change'` event whenever a specific watched +file is modified. + +#### Event: `'change'` + + +* `eventType` {string} The type of change event that has occurred +* `filename` {string|Buffer} The filename that changed (if relevant/available) + +Emitted when something changes in a watched directory or file. +See more details in [`fs.watch()`][]. + +The `filename` argument may not be provided depending on operating system +support. If `filename` is provided, it will be provided as a {Buffer} if +`fs.watch()` is called with its `encoding` option set to `'buffer'`, otherwise +`filename` will be a UTF-8 string. -doTruncate().catch(console.error); +```js esm +import { watch } from 'fs'; +// Example when handled through fs.watch() listener +watch('./tmp', { encoding: 'buffer' }, (eventType, filename) => { + if (filename) { + console.log(filename); + // Prints: + } +}); ``` -The last three bytes are null bytes (`'\0'`), to compensate the over-truncation. - -#### `filehandle.utimes(atime, mtime)` +#### Event: `'close'` -* `atime` {number|string|Date} -* `mtime` {number|string|Date} -* Returns: {Promise} +Emitted when the watcher stops watching for changes. The closed +{fs.FSWatcher} object is no longer usable in the event handler. + +#### Event: `'error'` + -Change the file system timestamps of the object referenced by the `FileHandle` -then fulfills the `Promise` with no arguments upon success. +* `error` {Error} -This function does not work on AIX versions before 7.1, it will reject the -`Promise` with an error using code `UV_ENOSYS`. +Emitted when an error occurs while watching the file. The errored +{fs.FSWatcher} object is no longer usable in the event handler. -#### `filehandle.write(buffer[, offset[, length[, position]]])` +#### `watcher.close()` -* `buffer` {Buffer|Uint8Array|string|Object} -* `offset` {integer} -* `length` {integer} -* `position` {integer} -* Returns: {Promise} +Stop watching for changes on the given {fs.FSWatcher}. Once stopped, the +{fs.FSWatcher} object is no longer usable. -Write `buffer` to the file. +#### `watcher.ref()` + -The `Promise` is fulfilled with an object containing a `bytesWritten` property -identifying the number of bytes written, and a `buffer` property containing -a reference to the `buffer` written. +* Returns: {fs.FSWatcher} -`offset` determines the part of the buffer to be written, and `length` is -an integer specifying the number of bytes to write. +When called, requests that the Node.js event loop *not* exit so long as the +{fs.FSWatcher} is active. Calling `watcher.ref()` multiple times will have +no effect. -`position` refers to the offset from the beginning of the file where this data -should be written. If `typeof position !== 'number'`, the data will be written -at the current position. See pwrite(2). +By default, all {fs.FSWatcher} objects are "ref'ed", making it normally +unnecessary to call `watcher.ref()` unless `watcher.unref()` had been +called previously. -It is unsafe to use `filehandle.write()` multiple times on the same file -without waiting for the `Promise` to be fulfilled (or rejected). For this -scenario, use [`fs.createWriteStream()`][]. +#### `watcher.unref()` + -On Linux, positional writes do not work when the file is opened in append mode. -The kernel ignores the position argument and always appends the data to -the end of the file. +* Returns: {fs.FSWatcher} -#### `filehandle.write(string[, position[, encoding]])` +When called, the active {fs.FSWatcher} object will not require the Node.js +event loop to remain active. If there is no other activity keeping the +event loop running, the process may exit before the {fs.FSWatcher} object's +callback is invoked. Calling `watcher.unref()` multiple times will have +no effect. + +### Class: `fs.StatWatcher` -* `string` {string|Object} -* `position` {integer} -* `encoding` {string} **Default:** `'utf8'` -* Returns: {Promise} - -Write `string` to the file. If `string` is not a string, or an -object with an own `toString` function property, then an exception is thrown. +* Extends {EventEmitter} -The `Promise` is fulfilled with an object containing a `bytesWritten` property -identifying the number of bytes written, and a `buffer` property containing -a reference to the `string` written. +A successful call to `fs.watchFile()` method will return a new {fs.StatWatcher} +object. -`position` refers to the offset from the beginning of the file where this data -should be written. If the type of `position` is not a `number` the data -will be written at the current position. See pwrite(2). +#### `watcher.ref()` + -`encoding` is the expected string encoding. +* Returns: {fs.StatWatcher} -It is unsafe to use `filehandle.write()` multiple times on the same file -without waiting for the `Promise` to be fulfilled (or rejected). For this -scenario, use [`fs.createWriteStream()`][]. +When called, requests that the Node.js event loop *not* exit so long as the +{fs.StatWatcher} is active. Calling `watcher.ref()` multiple times will have +no effect. -On Linux, positional writes do not work when the file is opened in append mode. -The kernel ignores the position argument and always appends the data to -the end of the file. +By default, all {fs.StatWatcher} objects are "ref'ed", making it normally +unnecessary to call `watcher.ref()` unless `watcher.unref()` had been +called previously. -#### `filehandle.writeFile(data, options)` +#### `watcher.unref()` -* `data` {string|Buffer|Uint8Array|Object} -* `options` {Object|string} - * `encoding` {string|null} **Default:** `'utf8'` -* Returns: {Promise} +* Returns: {fs.StatWatcher} -Asynchronously writes data to a file, replacing the file if it already exists. -`data` can be a string, a buffer, or an object with an own `toString` function -property. The `Promise` is fulfilled with no arguments upon success. +When called, the active {fs.StatWatcher} object will not require the Node.js +event loop to remain active. If there is no other activity keeping the +event loop running, the process may exit before the {fs.StatWatcher} object's +callback is invoked. Calling `watcher.unref()` multiple times will have +no effect. -The `encoding` option is ignored if `data` is a buffer. +### Class: `fs.ReadStream` + -If `options` is a string, then it specifies the encoding. +* Extends: {stream.Readable} -The `FileHandle` has to support writing. +Instances of {fs.ReadStream} are created and returned using the +[`fs.createReadStream()`][] function. -It is unsafe to use `filehandle.writeFile()` multiple times on the same file -without waiting for the `Promise` to be fulfilled (or rejected). +#### Event: `'close'` + -If one or more `filehandle.write()` calls are made on a file handle and then a -`filehandle.writeFile()` call is made, the data will be written from the -current position till the end of the file. It doesn't always write from the -beginning of the file. +Emitted when the {fs.ReadStream}'s underlying file descriptor has been closed. -#### `filehandle.writev(buffers[, position])` +#### Event: `'open'` -* `buffers` {ArrayBufferView[]} -* `position` {integer} -* Returns: {Promise} - -Write an array of `ArrayBufferView`s to the file. +* `fd` {integer} Integer file descriptor used by the {fs.ReadStream}. -The `Promise` is fulfilled with an object containing a `bytesWritten` property -identifying the number of bytes written, and a `buffers` property containing -a reference to the `buffers` input. +Emitted when the {fs.ReadStream}'s file descriptor has been opened. -`position` is the offset from the beginning of the file where this data -should be written. If `typeof position !== 'number'`, the data will be written -at the current position. +#### Event: `'ready'` + -It is unsafe to call `writev()` multiple times on the same file without waiting -for the previous operation to complete. +Emitted when the {fs.ReadStream} is ready to be used. -On Linux, positional writes don't work when the file is opened in append mode. -The kernel ignores the position argument and always appends the data to -the end of the file. +Fires immediately after `'open'`. -### `fsPromises.access(path[, mode])` +#### `readStream.bytesRead` -* `path` {string|Buffer|URL} -* `mode` {integer} **Default:** `fs.constants.F_OK` -* Returns: {Promise} +* {number} -Tests a user's permissions for the file or directory specified by `path`. -The `mode` argument is an optional integer that specifies the accessibility -checks to be performed. Check [File access constants][] for possible values -of `mode`. It is possible to create a mask consisting of the bitwise OR of -two or more values (e.g. `fs.constants.W_OK | fs.constants.R_OK`). +The number of bytes that have been read so far. -If the accessibility check is successful, the `Promise` is fulfilled with no -value. If any of the accessibility checks fail, the `Promise` is rejected -with an `Error` object. The following example checks if the file -`/etc/passwd` can be read and written by the current process. +#### `readStream.path` + -```js -const fs = require('fs'); -const fsPromises = fs.promises; +* {string|Buffer} -fsPromises.access('/etc/passwd', fs.constants.R_OK | fs.constants.W_OK) - .then(() => console.log('can access')) - .catch(() => console.error('cannot access')); -``` +The path to the file the stream is reading from as specified in the first +argument to `fs.createReadStream()`. If `path` is passed as a string, then +`readStream.path` will be a string. If `path` is passed as a {Buffer}, then +`readStream.path` will be a {Buffer}. -Using `fsPromises.access()` to check for the accessibility of a file before -calling `fsPromises.open()` is not recommended. Doing so introduces a race -condition, since other processes may change the file's state between the two -calls. Instead, user code should open/read/write the file directly and handle -the error raised if the file is not accessible. +#### `readStream.pending` + -### `fsPromises.appendFile(path, data[, options])` +* {boolean} + +This property is `true` if the underlying file has not been opened yet, +i.e. before the `'ready'` event is emitted. + +### Class: `fs.Stats` -* `path` {string|Buffer|URL|FileHandle} filename or `FileHandle` -* `data` {string|Buffer} -* `options` {Object|string} - * `encoding` {string|null} **Default:** `'utf8'` - * `mode` {integer} **Default:** `0o666` - * `flag` {string} See [support of file system `flags`][]. **Default:** `'a'`. -* Returns: {Promise} +A {fs.Stats} object provides information about a file. -Asynchronously append data to a file, creating the file if it does not yet -exist. `data` can be a string or a [`Buffer`][]. The `Promise` will be -fulfilled with no arguments upon success. +Objects returned from [`fs.stat()`][], [`fs.lstat()`][] and [`fs.fstat()`][] and +their synchronous counterparts are of this type. +If `bigint` in the `options` passed to those methods is true, the numeric values +will be `bigint` instead of `number`, and the object will contain additional +nanosecond-precision properties suffixed with `Ns`. -If `options` is a string, then it specifies the encoding. +```console +Stats { + dev: 2114, + ino: 48064969, + mode: 33188, + nlink: 1, + uid: 85, + gid: 100, + rdev: 0, + size: 527, + blksize: 4096, + blocks: 8, + atimeMs: 1318289051000.1, + mtimeMs: 1318289051000.1, + ctimeMs: 1318289051000.1, + birthtimeMs: 1318289051000.1, + atime: Mon, 10 Oct 2011 23:24:11 GMT, + mtime: Mon, 10 Oct 2011 23:24:11 GMT, + ctime: Mon, 10 Oct 2011 23:24:11 GMT, + birthtime: Mon, 10 Oct 2011 23:24:11 GMT } +``` -The `path` may be specified as a `FileHandle` that has been opened -for appending (using `fsPromises.open()`). +`bigint` version: + +```console +BigIntStats { + dev: 2114n, + ino: 48064969n, + mode: 33188n, + nlink: 1n, + uid: 85n, + gid: 100n, + rdev: 0n, + size: 527n, + blksize: 4096n, + blocks: 8n, + atimeMs: 1318289051000n, + mtimeMs: 1318289051000n, + ctimeMs: 1318289051000n, + birthtimeMs: 1318289051000n, + atimeNs: 1318289051000000000n, + mtimeNs: 1318289051000000000n, + ctimeNs: 1318289051000000000n, + birthtimeNs: 1318289051000000000n, + atime: Mon, 10 Oct 2011 23:24:11 GMT, + mtime: Mon, 10 Oct 2011 23:24:11 GMT, + ctime: Mon, 10 Oct 2011 23:24:11 GMT, + birthtime: Mon, 10 Oct 2011 23:24:11 GMT } +``` -### `fsPromises.chmod(path, mode)` +#### `stats.isBlockDevice()` -* `path` {string|Buffer|URL} -* `mode` {string|integer} -* Returns: {Promise} +* Returns: {boolean} -Changes the permissions of a file then fulfills the `Promise` with no -arguments upon succces. +Returns `true` if the {fs.Stats} object describes a block device. -### `fsPromises.chown(path, uid, gid)` +#### `stats.isCharacterDevice()` -* `path` {string|Buffer|URL} -* `uid` {integer} -* `gid` {integer} -* Returns: {Promise} +* Returns: {boolean} -Changes the ownership of a file then fulfills the `Promise` with no arguments -upon success. +Returns `true` if the {fs.Stats} object describes a character device. -### `fsPromises.copyFile(src, dest[, mode])` +#### `stats.isDirectory()` -* `src` {string|Buffer|URL} source filename to copy -* `dest` {string|Buffer|URL} destination filename of the copy operation -* `mode` {integer} modifiers for copy operation. **Default:** `0`. -* Returns: {Promise} - -Asynchronously copies `src` to `dest`. By default, `dest` is overwritten if it -already exists. The `Promise` will be fulfilled with no arguments upon success. - -Node.js makes no guarantees about the atomicity of the copy operation. If an -error occurs after the destination file has been opened for writing, Node.js -will attempt to remove the destination. - -`mode` is an optional integer that specifies the behavior -of the copy operation. It is possible to create a mask consisting of the bitwise -OR of two or more values (e.g. -`fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE`). - -* `fs.constants.COPYFILE_EXCL`: The copy operation will fail if `dest` already - exists. -* `fs.constants.COPYFILE_FICLONE`: The copy operation will attempt to create a - copy-on-write reflink. If the platform does not support copy-on-write, then a - fallback copy mechanism is used. -* `fs.constants.COPYFILE_FICLONE_FORCE`: The copy operation will attempt to - create a copy-on-write reflink. If the platform does not support - copy-on-write, then the operation will fail. - -```js -const { - promises: fsPromises, - constants: { - COPYFILE_EXCL - } -} = require('fs'); +* Returns: {boolean} -// destination.txt will be created or overwritten by default. -fsPromises.copyFile('source.txt', 'destination.txt') - .then(() => console.log('source.txt was copied to destination.txt')) - .catch(() => console.log('The file could not be copied')); +Returns `true` if the {fs.Stats} object describes a file system directory. -// By using COPYFILE_EXCL, the operation will fail if destination.txt exists. -fsPromises.copyFile('source.txt', 'destination.txt', COPYFILE_EXCL) - .then(() => console.log('source.txt was copied to destination.txt')) - .catch(() => console.log('The file could not be copied')); -``` +If the {fs.Stats} object was obtained from [`fs.lstat()`][], this method will +always return `false`. This is because [`fs.lstat()`][] returns information +about a symbolic link itself and not the path it resolves to. -### `fsPromises.lchmod(path, mode)` +#### `stats.isFIFO()` -* `path` {string|Buffer|URL} -* `mode` {integer} -* Returns: {Promise} +* Returns: {boolean} -Changes the permissions on a symbolic link then fulfills the `Promise` with -no arguments upon success. This method is only implemented on macOS. +Returns `true` if the {fs.Stats} object describes a first-in-first-out (FIFO) +pipe. -### `fsPromises.lchown(path, uid, gid)` +#### `stats.isFile()` -* `path` {string|Buffer|URL} -* `uid` {integer} -* `gid` {integer} -* Returns: {Promise} +* Returns: {boolean} -Changes the ownership on a symbolic link then fulfills the `Promise` with -no arguments upon success. +Returns `true` if the {fs.Stats} object describes a regular file. -### `fsPromises.lutimes(path, atime, mtime)` +#### `stats.isSocket()` -* `path` {string|Buffer|URL} -* `atime` {number|string|Date} -* `mtime` {number|string|Date} -* Returns: {Promise} - -Changes the access and modification times of a file in the same way as -[`fsPromises.utimes()`][], with the difference that if the path refers to a -symbolic link, then the link is not dereferenced: instead, the timestamps of -the symbolic link itself are changed. +* Returns: {boolean} -Upon success, the `Promise` is fulfilled without arguments. +Returns `true` if the {fs.Stats} object describes a socket. -### `fsPromises.link(existingPath, newPath)` +#### `stats.isSymbolicLink()` -* `existingPath` {string|Buffer|URL} -* `newPath` {string|Buffer|URL} -* Returns: {Promise} - -Asynchronous link(2). The `Promise` is fulfilled with no arguments upon success. - -### `fsPromises.lstat(path[, options])` - +* Returns: {boolean} -* `path` {string|Buffer|URL} -* `options` {Object} - * `bigint` {boolean} Whether the numeric values in the returned - [`fs.Stats`][] object should be `bigint`. **Default:** `false`. -* Returns: {Promise} +Returns `true` if the {fs.Stats} object describes a symbolic link. -Asynchronous lstat(2). The `Promise` is fulfilled with the [`fs.Stats`][] -object for the given symbolic link `path`. +This method is only valid when using [`fs.lstat()`][]. -### `fsPromises.mkdir(path[, options])` - +#### `stats.dev` -* `path` {string|Buffer|URL} -* `options` {Object|integer} - * `recursive` {boolean} **Default:** `false` - * `mode` {string|integer} Not supported on Windows. **Default:** `0o777`. -* Returns: {Promise} +* {number|bigint} -Asynchronously creates a directory then fulfills the `Promise` with either no -arguments, or the first directory path created if `recursive` is `true`. +The numeric identifier of the device containing the file. -The optional `options` argument can be an integer specifying `mode` (permission -and sticky bits), or an object with a `mode` property and a `recursive` -property indicating whether parent directories should be created. Calling -`fsPromises.mkdir()` when `path` is a directory that exists results in a -rejection only when `recursive` is false. +#### `stats.ino` -### `fsPromises.mkdtemp(prefix[, options])` - +* {number|bigint} -* `prefix` {string} -* `options` {string|Object} - * `encoding` {string} **Default:** `'utf8'` -* Returns: {Promise} +The file system specific "Inode" number for the file. -Creates a unique temporary directory and fulfills the `Promise` with the -created directory path. A unique directory name is generated by appending six -random characters to the end of the provided `prefix`. Due to platform -inconsistencies, avoid trailing `X` characters in `prefix`. Some platforms, -notably the BSDs, can return more than six random characters, and replace -trailing `X` characters in `prefix` with random characters. +#### `stats.mode` -The optional `options` argument can be a string specifying an encoding, or an -object with an `encoding` property specifying the character encoding to use. +* {number|bigint} -```js -fsPromises.mkdtemp(path.join(os.tmpdir(), 'foo-')) - .catch(console.error); -``` +A bit-field describing the file type and mode. -The `fsPromises.mkdtemp()` method will append the six randomly selected -characters directly to the `prefix` string. For instance, given a directory -`/tmp`, if the intention is to create a temporary directory *within* `/tmp`, the -`prefix` must end with a trailing platform-specific path separator -(`require('path').sep`). +#### `stats.nlink` -### `fsPromises.open(path, flags[, mode])` - +* {number|bigint} -* `path` {string|Buffer|URL} -* `flags` {string|number} See [support of file system `flags`][]. - **Default:** `'r'`. -* `mode` {string|integer} **Default:** `0o666` (readable and writable) -* Returns: {Promise} +The number of hard-links that exist for the file. -Asynchronous file open that returns a `Promise` that, when fulfilled, yields a -`FileHandle` object. See open(2). +#### `stats.uid` -`mode` sets the file mode (permission and sticky bits), but only if the file was -created. +* {number|bigint} -Some characters (`< > : " / \ | ? *`) are reserved under Windows as documented -by [Naming Files, Paths, and Namespaces][]. Under NTFS, if the filename contains -a colon, Node.js will open a file system stream, as described by -[this MSDN page][MSDN-Using-Streams]. +The numeric user identifier of the user that owns the file (POSIX). -### `fsPromises.opendir(path[, options])` - +#### `stats.gid` -* `path` {string|Buffer|URL} -* `options` {Object} - * `encoding` {string|null} **Default:** `'utf8'` - * `bufferSize` {number} Number of directory entries that are buffered - internally when reading from the directory. Higher values lead to better - performance but higher memory usage. **Default:** `32` -* Returns: {Promise} containing {fs.Dir} +* {number|bigint} -Asynchronously open a directory. See opendir(3). +The numeric group identifier of the group that owns the file (POSIX). -Creates an [`fs.Dir`][], which contains all further functions for reading from -and cleaning up the directory. +#### `stats.rdev` -The `encoding` option sets the encoding for the `path` while opening the -directory and subsequent read operations. +* {number|bigint} -Example using async iteration: +A numeric device identifier if the file represents a device. -```js -const fs = require('fs'); +#### `stats.size` -async function print(path) { - const dir = await fs.promises.opendir(path); - for await (const dirent of dir) { - console.log(dirent.name); - } -} -print('./').catch(console.error); -``` +* {number|bigint} -### `fsPromises.readdir(path[, options])` - +The size of the file in bytes. -* `path` {string|Buffer|URL} -* `options` {string|Object} - * `encoding` {string} **Default:** `'utf8'` - * `withFileTypes` {boolean} **Default:** `false` -* Returns: {Promise} +#### `stats.blksize` -Reads the contents of a directory then fulfills the `Promise` with an array -of the names of the files in the directory excluding `'.'` and `'..'`. +* {number|bigint} -The optional `options` argument can be a string specifying an encoding, or an -object with an `encoding` property specifying the character encoding to use for -the filenames. If the `encoding` is set to `'buffer'`, the filenames returned -will be passed as `Buffer` objects. +The file system block size for i/o operations. -If `options.withFileTypes` is set to `true`, the array will contain -[`fs.Dirent`][] objects. +#### `stats.blocks` -```js -const fs = require('fs'); +* {number|bigint} -async function print(path) { - const files = await fs.promises.readdir(path); - for (const file of files) { - console.log(file); - } -} -print('./').catch(console.error); -``` +The number of blocks allocated for this file. -### `fsPromises.readFile(path[, options])` +#### `stats.atimeMs` -* `path` {string|Buffer|URL|FileHandle} filename or `FileHandle` -* `options` {Object|string} - * `encoding` {string|null} **Default:** `null` - * `flag` {string} See [support of file system `flags`][]. **Default:** `'r'`. - * `signal` {AbortSignal} allows aborting an in-progress readFile -* Returns: {Promise} - -Asynchronously reads the entire contents of a file. +* {number|bigint} -The `Promise` is fulfilled with the contents of the file. If no encoding is -specified (using `options.encoding`), the data is returned as a `Buffer` -object. Otherwise, the data will be a string. +The timestamp indicating the last time this file was accessed expressed in +milliseconds since the POSIX Epoch. -If `options` is a string, then it specifies the encoding. +#### `stats.mtimeMs` + -When the `path` is a directory, the behavior of `fsPromises.readFile()` is -platform-specific. On macOS, Linux, and Windows, the promise will be rejected -with an error. On FreeBSD, a representation of the directory's contents will be -returned. +* {number|bigint} -It is possible to abort an ongoing `readFile` using an `AbortSignal`. If a -request is aborted the promise returned is rejected with an `AbortError`: +The timestamp indicating the last time this file was modified expressed in +milliseconds since the POSIX Epoch. -```js -const controller = new AbortController(); -const signal = controller.signal; -readFile(fileName, { signal }).then((file) => { /* ... */ }); -// Abort the request -controller.abort(); -``` +#### `stats.ctimeMs` + -Aborting an ongoing request does not abort individual operating -system requests but rather the internal buffering `fs.readFile` performs. +* {number|bigint} -Any specified `FileHandle` has to support reading. +The timestamp indicating the last time the file status was changed expressed +in milliseconds since the POSIX Epoch. -### `fsPromises.readlink(path[, options])` +#### `stats.birthtimeMs` -* `path` {string|Buffer|URL} -* `options` {string|Object} - * `encoding` {string} **Default:** `'utf8'` -* Returns: {Promise} - -Asynchronous readlink(2). The `Promise` is fulfilled with the `linkString` upon -success. +* {number|bigint} -The optional `options` argument can be a string specifying an encoding, or an -object with an `encoding` property specifying the character encoding to use for -the link path returned. If the `encoding` is set to `'buffer'`, the link path -returned will be passed as a `Buffer` object. +The timestamp indicating the creation time of this file expressed in +milliseconds since the POSIX Epoch. -### `fsPromises.realpath(path[, options])` +#### `stats.atimeNs` -* `path` {string|Buffer|URL} -* `options` {string|Object} - * `encoding` {string} **Default:** `'utf8'` -* Returns: {Promise} +* {bigint} -Determines the actual location of `path` using the same semantics as the -`fs.realpath.native()` function then fulfills the `Promise` with the resolved -path. +Only present when `bigint: true` is passed into the method that generates +the object. +The timestamp indicating the last time this file was accessed expressed in +nanoseconds since the POSIX Epoch. -Only paths that can be converted to UTF8 strings are supported. +#### `stats.mtimeNs` + -The optional `options` argument can be a string specifying an encoding, or an -object with an `encoding` property specifying the character encoding to use for -the path. If the `encoding` is set to `'buffer'`, the path returned will be -passed as a `Buffer` object. +* {bigint} -On Linux, when Node.js is linked against musl libc, the procfs file system must -be mounted on `/proc` in order for this function to work. Glibc does not have -this restriction. +Only present when `bigint: true` is passed into the method that generates +the object. +The timestamp indicating the last time this file was modified expressed in +nanoseconds since the POSIX Epoch. -### `fsPromises.rename(oldPath, newPath)` +#### `stats.ctimeNs` -* `oldPath` {string|Buffer|URL} -* `newPath` {string|Buffer|URL} -* Returns: {Promise} +* {bigint} -Renames `oldPath` to `newPath` and fulfills the `Promise` with no arguments -upon success. +Only present when `bigint: true` is passed into the method that generates +the object. +The timestamp indicating the last time the file status was changed expressed +in nanoseconds since the POSIX Epoch. -### `fsPromises.rmdir(path[, options])` +#### `stats.birthtimeNs` -* `path` {string|Buffer|URL} -* `options` {Object} - * `maxRetries` {integer} If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or - `EPERM` error is encountered, Node.js retries the operation with a linear - backoff wait of `retryDelay` milliseconds longer on each try. This option - represents the number of retries. This option is ignored if the `recursive` - option is not `true`. **Default:** `0`. - * `recursive` {boolean} If `true`, perform a recursive directory removal. In - recursive mode, errors are not reported if `path` does not exist, and - operations are retried on failure. **Default:** `false`. - * `retryDelay` {integer} The amount of time in milliseconds to wait between - retries. This option is ignored if the `recursive` option is not `true`. - **Default:** `100`. -* Returns: {Promise} +* {bigint} -Removes the directory identified by `path` then fulfills the `Promise` with -no arguments upon success. +Only present when `bigint: true` is passed into the method that generates +the object. +The timestamp indicating the creation time of this file expressed in +nanoseconds since the POSIX Epoch. -Using `fsPromises.rmdir()` on a file (not a directory) results in the -`Promise` being rejected with an `ENOENT` error on Windows and an `ENOTDIR` -error on POSIX. +#### `stats.atime` + -Setting `recursive` to `true` results in behavior similar to the Unix command -`rm -rf`: an error will not be raised for paths that do not exist, and paths -that represent files will be deleted. The permissive behavior of the -`recursive` option is deprecated, `ENOTDIR` and `ENOENT` will be thrown in -the future. +* {Date} -### `fsPromises.rm(path[, options])` +The timestamp indicating the last time this file was accessed. + +#### `stats.mtime` -* `path` {string|Buffer|URL} -* `options` {Object} - * `force` {boolean} When `true`, exceptions will be ignored if `path` does - not exist. **Default:** `false`. - * `maxRetries` {integer} If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or - `EPERM` error is encountered, Node.js will retry the operation with a linear - backoff wait of `retryDelay` milliseconds longer on each try. This option - represents the number of retries. This option is ignored if the `recursive` - option is not `true`. **Default:** `0`. - * `recursive` {boolean} If `true`, perform a recursive directory removal. In - recursive mode operations are retried on failure. **Default:** `false`. - * `retryDelay` {integer} The amount of time in milliseconds to wait between - retries. This option is ignored if the `recursive` option is not `true`. - **Default:** `100`. +* {Date} -Removes files and directories (modeled on the standard POSIX `rm` utility). -Fulfills the `Promise` with no arguments on success. +The timestamp indicating the last time this file was modified. -### `fsPromises.stat(path[, options])` +#### `stats.ctime` -* `path` {string|Buffer|URL} -* `options` {Object} - * `bigint` {boolean} Whether the numeric values in the returned - [`fs.Stats`][] object should be `bigint`. **Default:** `false`. -* Returns: {Promise} +* {Date} -The `Promise` is fulfilled with the [`fs.Stats`][] object for the given `path`. +The timestamp indicating the last time the file status was changed. -### `fsPromises.symlink(target, path[, type])` +#### `stats.birthtime` -* `target` {string|Buffer|URL} -* `path` {string|Buffer|URL} -* `type` {string} **Default:** `'file'` -* Returns: {Promise} +* {Date} -Creates a symbolic link then fulfills the `Promise` with no arguments upon -success. +The timestamp indicating the creation time of this file. -The `type` argument is only used on Windows platforms and can be one of `'dir'`, -`'file'`, or `'junction'`. Windows junction points require the destination path -to be absolute. When using `'junction'`, the `target` argument will -automatically be normalized to absolute path. +#### Stat time values -### `fsPromises.truncate(path[, len])` - +The `atimeMs`, `mtimeMs`, `ctimeMs`, `birthtimeMs` properties are +numeric values that hold the corresponding times in milliseconds. Their +precision is platform specific. When `bigint: true` is passed into the +method that generates the object, the properties will be [bigints][], +otherwise they will be [numbers][MDN-Number]. -* `path` {string|Buffer|URL} -* `len` {integer} **Default:** `0` -* Returns: {Promise} +The `atimeNs`, `mtimeNs`, `ctimeNs`, `birthtimeNs` properties are +[bigints][] that hold the corresponding times in nanoseconds. They are +only present when `bigint: true` is passed into the method that generates +the object. Their precision is platform specific. -Truncates the `path` then fulfills the `Promise` with no arguments upon -success. The `path` *must* be a string or `Buffer`. +`atime`, `mtime`, `ctime`, and `birthtime` are +[`Date`][MDN-Date] object alternate representations of the various times. The +`Date` and number values are not connected. Assigning a new number value, or +mutating the `Date` value, will not be reflected in the corresponding alternate +representation. -### `fsPromises.unlink(path)` - +The times in the stat object have the following semantics: -* `path` {string|Buffer|URL} -* Returns: {Promise} +* `atime` "Access Time": Time when file data last accessed. Changed + by the mknod(2), utimes(2), and read(2) system calls. +* `mtime` "Modified Time": Time when file data last modified. + Changed by the mknod(2), utimes(2), and write(2) system calls. +* `ctime` "Change Time": Time when file status was last changed + (inode data modification). Changed by the chmod(2), chown(2), + link(2), mknod(2), rename(2), unlink(2), utimes(2), + read(2), and write(2) system calls. +* `birthtime` "Birth Time": Time of file creation. Set once when the + file is created. On filesystems where birthtime is not available, + this field may instead hold either the `ctime` or + `1970-01-01T00:00Z` (ie, Unix epoch timestamp `0`). This value may be greater + than `atime` or `mtime` in this case. On Darwin and other FreeBSD variants, + also set if the `atime` is explicitly set to an earlier value than the current + `birthtime` using the utimes(2) system call. -Asynchronous unlink(2). The `Promise` is fulfilled with no arguments upon -success. +Prior to Node.js 0.12, the `ctime` held the `birthtime` on Windows systems. As +of 0.12, `ctime` is not "creation time", and on Unix systems, it never was. -### `fsPromises.utimes(path, atime, mtime)` +### Class: `fs.WriteStream` -* `path` {string|Buffer|URL} -* `atime` {number|string|Date} -* `mtime` {number|string|Date} -* Returns: {Promise} +* Extends {stream.Writable} -Change the file system timestamps of the object referenced by `path` then -fulfills the `Promise` with no arguments upon success. +Instances of {fs.WriteStream} are created and returned using the +[`fs.createWriteStream()`][] function. -The `atime` and `mtime` arguments follow these rules: +#### Event: `'close'` + -* Values can be either numbers representing Unix epoch time, `Date`s, or a - numeric string like `'123456789.0'`. -* If the value can not be converted to a number, or is `NaN`, `Infinity` or - `-Infinity`, an `Error` will be thrown. +Emitted when the {fs.WriteStream}'s underlying file descriptor has been closed. -### `fsPromises.writeFile(file, data[, options])` +#### Event: `'open'` -* `file` {string|Buffer|URL|FileHandle} filename or `FileHandle` -* `data` {string|Buffer|Uint8Array|Object} -* `options` {Object|string} - * `encoding` {string|null} **Default:** `'utf8'` - * `mode` {integer} **Default:** `0o666` - * `flag` {string} See [support of file system `flags`][]. **Default:** `'w'`. - * `signal` {AbortSignal} allows aborting an in-progress writeFile -* Returns: {Promise} +* `fd` {integer} Integer file descriptor used by the {fs.WriteStream}. -Asynchronously writes data to a file, replacing the file if it already exists. -`data` can be a string, a buffer, or an object with an own `toString` function -property. The `Promise` is fulfilled with no arguments upon success. +Emitted when the {fs.WriteStream}'s file is opened. -The `encoding` option is ignored if `data` is a buffer. +#### Event: `'ready'` + -If `options` is a string, then it specifies the encoding. +Emitted when the {fs.WriteStream} is ready to be used. -Any specified `FileHandle` has to support writing. +Fires immediately after `'open'`. -It is unsafe to use `fsPromises.writeFile()` multiple times on the same file -without waiting for the `Promise` to be fulfilled (or rejected). +#### `writeStream.bytesWritten` + -Similarly to `fsPromises.readFile` - `fsPromises.writeFile` is a convenience -method that performs multiple `write` calls internally to write the buffer -passed to it. For performance sensitive code consider using -[`fs.createWriteStream()`][]. +The number of bytes written so far. Does not include data that is still queued +for writing. -It is possible to use an {AbortSignal} to cancel an `fsPromises.writeFile()`. -Cancelation is "best effort", and some amount of data is likely still -to be written. +#### `writeStream.path` + -```js -const controller = new AbortController(); -const { signal } = controller; -const data = new Uint8Array(Buffer.from('Hello Node.js')); -(async () => { - try { - await fs.writeFile('message.txt', data, { signal }); - } catch (err) { - // When a request is aborted - err is an AbortError - } -})(); -// When the request should be aborted -controller.abort(); -``` +The path to the file the stream is writing to as specified in the first +argument to [`fs.createWriteStream()`][]. If `path` is passed as a string, then +`writeStream.path` will be a string. If `path` is passed as a {Buffer}, then +`writeStream.path` will be a {Buffer}. -Aborting an ongoing request does not abort individual operating -system requests but rather the internal buffering `fs.writeFile` performs. +#### `writeStream.pending` + + +* {boolean} + +This property is `true` if the underlying file has not been opened yet, +i.e. before the `'ready'` event is emitted. -## FS constants +### `fs.constants` + +* {Object} + +Returns an object containing commonly used constants for file system +operations. + +#### FS constants The following constants are exported by `fs.constants`. @@ -5889,21 +5872,21 @@ To use more than one constant, use the bitwise OR `|` operator. Example: -```js -const fs = require('fs'); +```js esm +import { open, constants } from 'fs'; const { O_RDWR, O_CREAT, O_EXCL -} = fs.constants; +} = constants; -fs.open('/path/to/my/file', O_RDWR | O_CREAT | O_EXCL, (err, fd) => { +open('/path/to/my/file', O_RDWR | O_CREAT | O_EXCL, (err, fd) => { // ... }); ``` -### File access constants +##### File access constants The following constants are meant for use with [`fs.access()`][]. @@ -5935,7 +5918,7 @@ The following constants are meant for use with [`fs.access()`][]. -### File copy constants +##### File copy constants The following constants are meant for use with [`fs.copyFile()`][]. @@ -5963,7 +5946,7 @@ The following constants are meant for use with [`fs.copyFile()`][]. -### File open constants +##### File open constants The following constants are meant for use with `fs.open()`. @@ -6057,9 +6040,9 @@ The following constants are meant for use with `fs.open()`. -### File type constants +##### File type constants -The following constants are meant for use with the [`fs.Stats`][] object's +The following constants are meant for use with the {fs.Stats} object's `mode` property for determining a file's type. @@ -6101,9 +6084,9 @@ The following constants are meant for use with the [`fs.Stats`][] object's
-### File mode constants +##### File mode constants -The following constants are meant for use with the [`fs.Stats`][] object's +The following constants are meant for use with the {fs.Stats} object's `mode` property for determining the access permissions for a file. @@ -6161,7 +6144,323 @@ The following constants are meant for use with the [`fs.Stats`][] object's
-## File system flags +## Notes + +### Ordering of callback and promise-based operations + +Because they are executed asynchronously by the underlying thread pool, +there is no guaranteed ordering when using either the callback or +promise-based methods. + +For example, the following is prone to error because the `fs.stat()` +operation might complete before the `fs.rename()` operation: + +```js +fs.rename('/tmp/hello', '/tmp/world', (err) => { + if (err) throw err; + console.log('renamed complete'); +}); +fs.stat('/tmp/world', (err, stats) => { + if (err) throw err; + console.log(`stats: ${JSON.stringify(stats)}`); +}); +``` + +It is important to correctly order the operations by awaiting the results +of one before invoking the other: + +```js esm +// Using ESM syntax +import { rename, stat } from 'fs/promises'; + +const from = '/tmp/hello'; +const to = '/tmp/world'; + +try { + await rename(from, to); + const stats = await stat(to); + console.log(`stats: ${JSON.stringify(stats)}`); +} catch (error) { + console.error('there was an error:', error.message); +} +``` + +```js cjs +// Using CommonJS syntax +const { rename, stat } = require('fs/promises'); + +(async function(from, to) { + try { + await rename(from, to); + const stats = await stat(to); + console.log(`stats: ${JSON.stringify(stats)}`); + } catch (error) { + console.error('there was an error:', error.message); + } +})('/tmp/hello', '/tmp/world'); +``` + +Or, when using the callback APIs, move the `fs.stat()` call into the callback +of the `fs.rename()` operation: + +```js esm +import { rename, stat } from 'fs'; + +rename('/tmp/hello', '/tmp/world', (err) => { + if (err) throw err; + stat('/tmp/world', (err, stats) => { + if (err) throw err; + console.log(`stats: ${JSON.stringify(stats)}`); + }); +}); +``` + +```js cjs +const { rename, stat } = require('fs/promises'); + +rename('/tmp/hello', '/tmp/world', (err) => { + if (err) throw err; + stat('/tmp/world', (err, stats) => { + if (err) throw err; + console.log(`stats: ${JSON.stringify(stats)}`); + }); +}); +``` + +### File paths + +Most `fs` operations accept file paths that may be specified in the form of +a string, a {Buffer}, or a {URL} object using the `file:` protocol. + +#### String paths + +String form paths are interpreted as UTF-8 character sequences identifying +the absolute or relative filename. Relative paths will be resolved relative +to the current working directory as determined by calling `process.cwd()`. + +Example using an absolute path on POSIX: + +```js esm +import { open } from 'fs/promises'; + +let fd; +try { + fd = await open('/open/some/file.txt', 'r'); + // Do something with the file +} finally { + await fd.close(); +} +``` + +Example using a relative path on POSIX (relative to `process.cwd()`): + +```js esm +import { open } from 'fs/promises'; + +let fd; +try { + fd = await open('file.txt', 'r'); + // Do something with the file +} finally { + await fd.close(); +} +``` + +#### File URL paths + +For most `fs` module functions, the `path` or `filename` argument may be passed +as a {URL} object using the `file:` protocol. + +```js esm +import { readFileSync } from 'fs'; + +readFileSync(new URL('file:///tmp/hello')); +``` + +`file:` URLs are always absolute paths. + +##### Platform-specific considerations + +On Windows, `file:` {URL}s with a host name convert to UNC paths, while `file:` +{URL}s with drive letters convert to local absolute paths. `file:` {URL}s +without a host name nor a drive letter will result in an error: + +```js esm +import { readFileSync } from 'fs'; +// On Windows : + +// - WHATWG file URLs with hostname convert to UNC path +// file://hostname/p/a/t/h/file => \\hostname\p\a\t\h\file +readFileSync(new URL('file://hostname/p/a/t/h/file')); + +// - WHATWG file URLs with drive letters convert to absolute path +// file:///C:/tmp/hello => C:\tmp\hello +readFileSync(new URL('file:///C:/tmp/hello')); + +// - WHATWG file URLs without hostname must have a drive letters +readFileSync(new URL('file:///notdriveletter/p/a/t/h/file')); +readFileSync(new URL('file:///c/p/a/t/h/file')); +// TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must be absolute +``` + +`file:` {URL}s with drive letters must use `:` as a separator just after +the drive letter. Using another separator will result in an error. + +On all other platforms, `file:` {URL}s with a host name are unsupported and +will result in an error: + +```js esm +import { readFileSync } from 'fs'; +// On other platforms: + +// - WHATWG file URLs with hostname are unsupported +// file://hostname/p/a/t/h/file => throw! +readFileSync(new URL('file://hostname/p/a/t/h/file')); +// TypeError [ERR_INVALID_FILE_URL_PATH]: must be absolute + +// - WHATWG file URLs convert to absolute path +// file:///tmp/hello => /tmp/hello +readFileSync(new URL('file:///tmp/hello')); +``` + +A `file:` {URL} having encoded slash characters will result in an error on all +platforms: + +```js esm +import { readFileSync } from 'fs'; + +// On Windows +readFileSync(new URL('file:///C:/p/a/t/h/%2F')); +readFileSync(new URL('file:///C:/p/a/t/h/%2f')); +/* TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must not include encoded +\ or / characters */ + +// On POSIX +readFileSync(new URL('file:///p/a/t/h/%2F')); +readFileSync(new URL('file:///p/a/t/h/%2f')); +/* TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must not include encoded +/ characters */ +``` + +On Windows, `file:` {URL}s having encoded backslash will result in an error: + +```js esm +import { readFileSync } from 'fs'; + +// On Windows +readFileSync(new URL('file:///C:/path/%5C')); +readFileSync(new URL('file:///C:/path/%5c')); +/* TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must not include encoded +\ or / characters */ +``` + +#### Buffer paths + +Paths specified using a {Buffer} are useful primarily on certain POSIX +operating systems that treat file paths as opaque byte sequences. On such +systems, it is possible for a single file path to contain sub-sequences that +use multiple character encodings. As with string paths, {Buffer} paths may +be relative or absolute: + +Example using an absolute path on POSIX: + +```js esm +import { open } from 'fs/promises'; + +let fd; +try { + fd = await open(Buffer.from('/open/some/file.txt'), 'r'); + // Do something with the file +} finally { + await fd.close(); +} +``` + +#### Per-drive working directories on Windows + +On Windows, Node.js follows the concept of per-drive working directory. This +behavior can be observed when using a drive path without a backslash. For +example `fs.readdirSync('C:\\')` can potentially return a different result than +`fs.readdirSync('C:')`. For more information, see +[this MSDN page][MSDN-Rel-Path]. + +### File descriptors + +On POSIX systems, for every process, the kernel maintains a table of currently +open files and resources. Each open file is assigned a simple numeric +identifier called a *file descriptor*. At the system-level, all file system +operations use these file descriptors to identify and track each specific +file. Windows systems use a different but conceptually similar mechanism for +tracking resources. To simplify things for users, Node.js abstracts away the +differences between operating systems and assigns all open files a numeric file +descriptor. + +The callback-based `fs.open()`, and synchronous `fs.openSync()` methods open a +file and allocate a new file descriptor. Once allocated, the file descriptor may +be used to read data from, write data to, or request information about the file. + +Operating systems limit the number of file descriptors that may be open +at any given time so it is critical to close the descriptor when operations +are completed. Failure to do so will result in a memory leak that will +eventually cause an application to crash. + +```js esm +import { open, close, fstat } from 'fs'; + +function closeFd(fd) { + close(fd, (err) => { + if (err) throw err; + }); +} + +open('/open/some/file.txt', 'r', (err, fd) => { + if (err) throw err; + try { + fstat(fd, (err, stat) => { + if (err) { + closeFd(fd); + throw err; + } + + // use stat + + closeFd(fd); + }); + } catch (err) { + closeFd(fd); + throw err; + } +}); +``` + +The promise-based APIs use a {FileHandle} object in place of the numeric +file descriptor. These objects are better managed by the system to ensure +that resources are not leaked. However, it is still required that they are +closed when operations are completed: + +```js esm +import { open } from 'fs/promises'; + +let file; +try { + file = await open('/open/some/file.txt', 'r'); + const stat = await file.stat(); + // use stat +} finally { + await file.close(); +} +``` + +### Threadpool usage + +All callback and promise-based file system APIs ( with the exception of +`fs.FSWatcher()`) use libuv's threadpool. This can have surprising and negative +performance implications for some applications. See the +[`UV_THREADPOOL_SIZE`][] documentation for more information. + +### File system flags The following flags are available wherever the `flag` option takes a string. @@ -6253,7 +6552,6 @@ the file contents. [#25741]: https://github.com/nodejs/node/issues/25741 [Caveats]: #fs_caveats [Common System Errors]: errors.md#errors_common_system_errors -[FS constants]: #fs_fs_constants_1 [File access constants]: #fs_file_access_constants [MDN-Date]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date [MDN-Number]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type @@ -6264,20 +6562,12 @@ the file contents. [Writable Stream]: stream.md#stream_class_stream_writable [`AHAFS`]: https://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/ [`Buffer.byteLength`]: buffer.md#buffer_static_method_buffer_bytelength_string_encoding -[`Buffer`]: buffer.md#buffer_buffer [`FSEvents`]: https://developer.apple.com/documentation/coreservices/file_system_events [`Number.MAX_SAFE_INTEGER`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER [`ReadDirectoryChangesW`]: https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-readdirectorychangesw -[`ReadStream`]: #fs_class_fs_readstream -[`URL`]: url.md#url_the_whatwg_url_api [`UV_THREADPOOL_SIZE`]: cli.md#cli_uv_threadpool_size_size -[`WriteStream`]: #fs_class_fs_writestream [`event ports`]: https://illumos.org/man/port_create [`filehandle.writeFile()`]: #fs_filehandle_writefile_data_options -[`fs.Dir`]: #fs_class_fs_dir -[`fs.Dirent`]: #fs_class_fs_dirent -[`fs.FSWatcher`]: #fs_class_fs_fswatcher -[`fs.Stats`]: #fs_class_fs_stats [`fs.access()`]: #fs_fs_access_path_mode_callback [`fs.chmod()`]: #fs_fs_chmod_path_mode_callback [`fs.chown()`]: #fs_fs_chown_path_uid_gid_callback @@ -6316,8 +6606,6 @@ the file contents. [`fsPromises.utimes()`]: #fs_fspromises_utimes_path_atime_mtime [`inotify(7)`]: https://man7.org/linux/man-pages/man7/inotify.7.html [`kqueue(2)`]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2 -[`net.Socket`]: net.md#net_class_net_socket -[`stat()`]: fs.md#fs_fs_stat_path_options_callback [`util.promisify()`]: util.md#util_util_promisify_original [bigints]: https://tc39.github.io/proposal-bigint [chcp]: https://ss64.com/nt/chcp.html From d96a97a2b9b14a4f5475129fbfe495588798f36a Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Tue, 9 Feb 2021 13:23:39 -0800 Subject: [PATCH 072/108] module: make synthetic module evaluation steps return a Promise to support top level await MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Top level await expects that all module script evaluation returns a Promise. As such, update ModuleWrap::SyntheticModuleEvaluationStepsCallback to return a resolved Promise now that V8 has enabled top-level await by default. Unfortunately I don't have a spec reference that I can point to here because the Built-in modules proposal isn't yet updated for top level await. The corresponding change for Blink is https://chromium-review.googlesource.com/c/chromium/src/+/2568823. This will allow a workaround for Node in this V8 bugfix to be removed: https://chromium-review.googlesource.com/c/v8/v8/+/2673794. Fixes: https://github.com/nodejs/node/issues/37299 PR-URL: https://github.com/nodejs/node/pull/37300 Reviewed-By: Gus Caplan Reviewed-By: Michaël Zasso --- src/module_wrap.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/module_wrap.cc b/src/module_wrap.cc index 0ac36d4aa6373f..4885e65f9c5d47 100644 --- a/src/module_wrap.cc +++ b/src/module_wrap.cc @@ -665,7 +665,14 @@ MaybeLocal ModuleWrap::SyntheticModuleEvaluationStepsCallback( try_catch.ReThrow(); return MaybeLocal(); } - return Undefined(isolate); + + Local resolver; + if (!Promise::Resolver::New(context).ToLocal(&resolver)) { + return MaybeLocal(); + } + + resolver->Resolve(context, Undefined(isolate)).ToChecked(); + return resolver->GetPromise(); } void ModuleWrap::SetSyntheticExport(const FunctionCallbackInfo& args) { From 1ff375beb3fac33e673153b7064647b6cbc00326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Sun, 7 Feb 2021 17:18:16 +0100 Subject: [PATCH 073/108] tools: avoid pending deprecation in doc generator `unist-util-find` depends on `lodash.iteratee` which uses `process.binding()`. Let's remove this dependency which is used in one place to do a very simple thing. PR-URL: https://github.com/nodejs/node/pull/37267 Reviewed-By: Rich Trott Reviewed-By: Antoine du Hamel Reviewed-By: Richard Lau Reviewed-By: Luigi Pinca Reviewed-By: Darshan Sen --- tools/doc/html.js | 9 +++- tools/doc/package-lock.json | 83 ------------------------------------- tools/doc/package.json | 1 - 3 files changed, 7 insertions(+), 86 deletions(-) diff --git a/tools/doc/html.js b/tools/doc/html.js index 6eb3484052bc69..07a3e5ef405403 100644 --- a/tools/doc/html.js +++ b/tools/doc/html.js @@ -24,7 +24,6 @@ const common = require('./common.js'); const fs = require('fs'); const unified = require('unified'); -const find = require('unist-util-find'); const visit = require('unist-util-visit'); const markdown = require('remark-parse'); const gfm = require('remark-gfm'); @@ -97,7 +96,13 @@ function toHTML({ input, content, filename, nodeVersion, versions }) { // Set the section name based on the first header. Default to 'Index'. function firstHeader() { return (tree, file) => { - const heading = find(tree, { type: 'heading' }); + let heading; + visit(tree, (node) => { + if (node.type === 'heading') { + heading = node; + return false; + } + }); if (heading && heading.children.length) { const recursiveTextContent = (node) => diff --git a/tools/doc/package-lock.json b/tools/doc/package-lock.json index e93d935aece6c1..586e90b4bb62ad 100644 --- a/tools/doc/package-lock.json +++ b/tools/doc/package-lock.json @@ -21,7 +21,6 @@ "remark-rehype": "8.0.0", "to-vfile": "6.1.0", "unified": "9.2.0", - "unist-util-find": "^1.0.2", "unist-util-select": "3.0.4", "unist-util-visit": "2.0.3" }, @@ -441,12 +440,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/lodash.iteratee": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.iteratee/-/lodash.iteratee-4.7.0.tgz", - "integrity": "sha1-vkF32yiajMw8CZDx2ya1si/BVUw=", - "dev": true - }, "node_modules/longest-streak": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", @@ -958,40 +951,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-find": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unist-util-find/-/unist-util-find-1.0.2.tgz", - "integrity": "sha512-ft06UDYzqi9o9RmGP0sZWI/zvLLQiBW2/MD+rW6mDqbOWDcmknGX9orQPspfuGRYWr8eSJAmfsBcvOpfGRJseA==", - "dev": true, - "dependencies": { - "lodash.iteratee": "^4.5.0", - "unist-util-visit": "^1.1.0" - } - }, - "node_modules/unist-util-find/node_modules/unist-util-is": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", - "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", - "dev": true - }, - "node_modules/unist-util-find/node_modules/unist-util-visit": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", - "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", - "dev": true, - "dependencies": { - "unist-util-visit-parents": "^2.0.0" - } - }, - "node_modules/unist-util-find/node_modules/unist-util-visit-parents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", - "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", - "dev": true, - "dependencies": { - "unist-util-is": "^3.0.0" - } - }, "node_modules/unist-util-generated": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", @@ -1442,12 +1401,6 @@ "argparse": "^2.0.1" } }, - "lodash.iteratee": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.iteratee/-/lodash.iteratee-4.7.0.tgz", - "integrity": "sha1-vkF32yiajMw8CZDx2ya1si/BVUw=", - "dev": true - }, "longest-streak": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", @@ -1815,42 +1768,6 @@ "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==", "dev": true }, - "unist-util-find": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unist-util-find/-/unist-util-find-1.0.2.tgz", - "integrity": "sha512-ft06UDYzqi9o9RmGP0sZWI/zvLLQiBW2/MD+rW6mDqbOWDcmknGX9orQPspfuGRYWr8eSJAmfsBcvOpfGRJseA==", - "dev": true, - "requires": { - "lodash.iteratee": "^4.5.0", - "unist-util-visit": "^1.1.0" - }, - "dependencies": { - "unist-util-is": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", - "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", - "dev": true - }, - "unist-util-visit": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", - "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", - "dev": true, - "requires": { - "unist-util-visit-parents": "^2.0.0" - } - }, - "unist-util-visit-parents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", - "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", - "dev": true, - "requires": { - "unist-util-is": "^3.0.0" - } - } - } - }, "unist-util-generated": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", diff --git a/tools/doc/package.json b/tools/doc/package.json index d13ac4f30e8feb..441249f3282887 100644 --- a/tools/doc/package.json +++ b/tools/doc/package.json @@ -17,7 +17,6 @@ "remark-rehype": "8.0.0", "to-vfile": "6.1.0", "unified": "9.2.0", - "unist-util-find": "^1.0.2", "unist-util-select": "3.0.4", "unist-util-visit": "2.0.3" }, From 848718445713fee026edc3d9a389f7b7273fe5e2 Mon Sep 17 00:00:00 2001 From: Nitzan Uziely Date: Sun, 7 Feb 2021 01:52:14 +0200 Subject: [PATCH 074/108] child_process: fix bad abort signal leak Move abort signal validation to before spawn is executed so that the file is not leaked. PR-URL: https://github.com/nodejs/node/pull/37257 Reviewed-By: Benjamin Gruenbaum Reviewed-By: Luigi Pinca --- lib/child_process.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/child_process.js b/lib/child_process.js index 74699a16834c30..4325caa9496eb1 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -758,11 +758,14 @@ function spawnWithSignal(file, args, options) { const opts = options && typeof options === 'object' && ('signal' in options) ? { ...options, signal: undefined } : options; - const child = spawn(file, args, opts); - if (options && options.signal) { + if (options?.signal) { // Validate signal, if present validateAbortSignal(options.signal, 'options.signal'); + } + const child = spawn(file, args, opts); + + if (options && options.signal) { function kill() { if (child._handle) { child._handle.kill(options.killSignal || 'SIGTERM'); From 15804e0b3f953b184b21f6136efa4e4a80082c84 Mon Sep 17 00:00:00 2001 From: bcoe Date: Sat, 6 Feb 2021 11:11:35 -0800 Subject: [PATCH 075/108] errors: align source-map stacks with spec Reformat stack traces when --enable-source-maps flag is set to format more likely to fit https://github.com/tc39/proposal-error-stacks PR-URL: https://github.com/nodejs/node/pull/37252 Reviewed-By: Rich Trott Reviewed-By: Ian Sutherland Reviewed-By: Gus Caplan Reviewed-By: Zeyu Yang Reviewed-By: Benjamin Gruenbaum Reviewed-By: Joyee Cheung --- .../source_map/prepare_stack_trace.js | 25 ++++++++++++------- .../message/source_map_enclosing_function.out | 15 ++++------- .../source_map_reference_error_tabs.out | 6 ++--- test/message/source_map_throw_catch.out | 6 ++--- test/message/source_map_throw_first_tick.out | 6 ++--- test/message/source_map_throw_icu.out | 6 ++--- .../source_map_throw_set_immediate.out | 6 ++--- test/parallel/test-source-map-enable.js | 20 +++++++-------- 8 files changed, 41 insertions(+), 49 deletions(-) diff --git a/lib/internal/source_map/prepare_stack_trace.js b/lib/internal/source_map/prepare_stack_trace.js index c32f9780c2fb3f..6b8d4e566ff1b1 100644 --- a/lib/internal/source_map/prepare_stack_trace.js +++ b/lib/internal/source_map/prepare_stack_trace.js @@ -51,8 +51,7 @@ const prepareStackTrace = (globalThis, error, trace) => { let lastSourceMap; let lastFileName; const preparedTrace = ArrayPrototypeJoin(ArrayPrototypeMap(trace, (t, i) => { - let str = i !== 0 ? '\n at ' : ''; - str = `${str}${t}`; + const str = i !== 0 ? '\n at ' : ''; try { // A stack trace will often have several call sites in a row within the // same file, cache the source map and file content accordingly: @@ -81,21 +80,29 @@ const prepareStackTrace = (globalThis, error, trace) => { originalColumn ); } - // Show both original and transpiled stack trace information: - const prefix = (name && name !== t.getFunctionName()) ? - `\n -> at ${name}` : - '\n ->'; + // Construct call site name based on: v8.dev/docs/stack-trace-api: + const fnName = t.getFunctionName() ?? t.getMethodName(); + const originalName = `${t.getTypeName() !== 'global' ? + `${t.getTypeName()}.` : ''}${fnName ? fnName : ''}`; + // The original call site may have a different symbol name + // associated with it, use it: + const prefix = (name && name !== originalName) ? + `${name}` : + `${originalName ? originalName : ''}`; + const hasName = !!(name || originalName); const originalSourceNoScheme = StringPrototypeStartsWith(originalSource, 'file://') ? fileURLToPath(originalSource) : originalSource; - str += `${prefix} (${originalSourceNoScheme}:${originalLine + 1}:` + - `${originalColumn + 1})`; + // Replace the transpiled call site with the original: + return `${str}${prefix}${hasName ? ' (' : ''}` + + `${originalSourceNoScheme}:${originalLine + 1}:` + + `${originalColumn + 1}${hasName ? ')' : ''}`; } } } catch (err) { debug(err.stack); } - return str; + return `${str}${t}`; }), ''); return `${errorSource}${errorString}\n at ${preparedTrace}`; }; diff --git a/test/message/source_map_enclosing_function.out b/test/message/source_map_enclosing_function.out index 4cb969dc38bf38..3eb76ecbbef31c 100644 --- a/test/message/source_map_enclosing_function.out +++ b/test/message/source_map_enclosing_function.out @@ -3,16 +3,11 @@ ^ Error: an error! - at functionD (*enclosing-call-site-min.js:1:156) - -> (*enclosing-call-site.js:16:17) - at functionC (*enclosing-call-site-min.js:1:97) - -> (*enclosing-call-site.js:10:3) - at functionB (*enclosing-call-site-min.js:1:60) - -> (*enclosing-call-site.js:6:3) - at functionA (*enclosing-call-site-min.js:1:26) - -> (*enclosing-call-site.js:2:3) - at Object. (*enclosing-call-site-min.js:1:199) - -> (*enclosing-call-site.js:24:3) + at functionD (*enclosing-call-site.js:16:17) + at functionC (*enclosing-call-site.js:10:3) + at functionB (*enclosing-call-site.js:6:3) + at functionA (*enclosing-call-site.js:2:3) + at Object. (*enclosing-call-site.js:24:3) at Module._compile (node:internal/modules/cjs/loader:*) at Object.Module._extensions..js (node:internal/modules/cjs/loader:*) at Module.load (node:internal/modules/cjs/loader:*) diff --git a/test/message/source_map_reference_error_tabs.out b/test/message/source_map_reference_error_tabs.out index e0adcbc442aeef..bce1b5f8911d4b 100644 --- a/test/message/source_map_reference_error_tabs.out +++ b/test/message/source_map_reference_error_tabs.out @@ -3,10 +3,8 @@ ^ ReferenceError: alert is not defined - at Object. (*tabs.coffee:39:5) - -> *tabs.coffee:26:2* - at Object. (*tabs.coffee:53:4) - -> *tabs.coffee:1:14* + at *tabs.coffee:26:2* + at *tabs.coffee:1:14* at Module._compile (node:internal/modules/cjs/loader:* at Object.Module._extensions..js (node:internal/modules/cjs/loader:* at Module.load (node:internal/modules/cjs/loader:* diff --git a/test/message/source_map_throw_catch.out b/test/message/source_map_throw_catch.out index 893e75f92bbf5c..95bba5eee3e9dc 100644 --- a/test/message/source_map_throw_catch.out +++ b/test/message/source_map_throw_catch.out @@ -3,10 +3,8 @@ reachable throw Error('an exception'); ^ Error: an exception - at branch (*typescript-throw.js:20:15) - -> *typescript-throw.ts:18:11* - at Object. (*typescript-throw.js:26:1) - -> *typescript-throw.ts:24:1* + at *typescript-throw.ts:18:11* + at *typescript-throw.ts:24:1* at Module._compile (node:internal/modules/cjs/loader:*) at Object.Module._extensions..js (node:internal/modules/cjs/loader:*) at Module.load (node:internal/modules/cjs/loader:*) diff --git a/test/message/source_map_throw_first_tick.out b/test/message/source_map_throw_first_tick.out index 4fc5aae55bf169..efa97a1d9f56dd 100644 --- a/test/message/source_map_throw_first_tick.out +++ b/test/message/source_map_throw_first_tick.out @@ -3,10 +3,8 @@ reachable throw Error('an exception'); ^ Error: an exception - at branch (*typescript-throw.js:20:15) - -> *typescript-throw.ts:18:11* - at Object. (*typescript-throw.js:26:1) - -> *typescript-throw.ts:24:1* + at *typescript-throw.ts:18:11* + at *typescript-throw.ts:24:1* at Module._compile (node:internal/modules/cjs/loader:*) at Object.Module._extensions..js (node:internal/modules/cjs/loader:*) at Module.load (node:internal/modules/cjs/loader:*) diff --git a/test/message/source_map_throw_icu.out b/test/message/source_map_throw_icu.out index ba5e94044cb2ed..78482d73ddf037 100644 --- a/test/message/source_map_throw_icu.out +++ b/test/message/source_map_throw_icu.out @@ -3,10 +3,8 @@ ^ Error: an error - at Object.createElement (*icu.js:5:7) - -> *icu.jsx:3:23* - at Object. (*icu.js:8:82) - -> *icu.jsx:9:5* + at *icu.jsx:3:23* + at *icu.jsx:9:5* at Module._compile (node:internal/modules/cjs/loader:* at Object.Module._extensions..js (node:internal/modules/cjs/loader:* at Module.load (node:internal/modules/cjs/loader:* diff --git a/test/message/source_map_throw_set_immediate.out b/test/message/source_map_throw_set_immediate.out index 4893b856f0fe81..c735e23cb955c5 100644 --- a/test/message/source_map_throw_set_immediate.out +++ b/test/message/source_map_throw_set_immediate.out @@ -3,8 +3,6 @@ ^ Error: goodbye - at *uglify-throw.js:1:43 - -> at Hello *uglify-throw-original.js:5:9* - at Immediate. (*uglify-throw.js:1:60) - -> *uglify-throw-original.js:9:3* + at Hello *uglify-throw-original.js:5:9* + at *uglify-throw-original.js:9:3* at processImmediate (node:internal/timers:*) diff --git a/test/parallel/test-source-map-enable.js b/test/parallel/test-source-map-enable.js index 6435aa99d2c752..9df38cba6cac91 100644 --- a/test/parallel/test-source-map-enable.js +++ b/test/parallel/test-source-map-enable.js @@ -155,11 +155,11 @@ function nextdir() { require.resolve('../fixtures/source-map/uglify-throw.js') ]); assert.strictEqual( - output.stderr.toString().match(/->.*uglify-throw-original\.js:5:9/), + output.stderr.toString().match(/.*uglify-throw-original\.js:5:9/), null ); assert.strictEqual( - output.stderr.toString().match(/->.*uglify-throw-original\.js:9:3/), + output.stderr.toString().match(/.*uglify-throw-original\.js:9:3/), null ); } @@ -172,11 +172,11 @@ function nextdir() { ]); assert.match( output.stderr.toString(), - /->.*uglify-throw-original\.js:5:9/ + /.*uglify-throw-original\.js:5:9/ ); assert.match( output.stderr.toString(), - /->.*uglify-throw-original\.js:9:3/ + /.*uglify-throw-original\.js:9:3/ ); assert.match(output.stderr.toString(), /at Hello/); } @@ -187,8 +187,8 @@ function nextdir() { '--enable-source-maps', require.resolve('../fixtures/source-map/typescript-throw.js') ]); - assert.ok(output.stderr.toString().match(/->.*typescript-throw\.ts:18:11/)); - assert.ok(output.stderr.toString().match(/->.*typescript-throw\.ts:24:1/)); + assert.ok(output.stderr.toString().match(/.*typescript-throw\.ts:18:11/)); + assert.ok(output.stderr.toString().match(/.*typescript-throw\.ts:24:1/)); } // Applies source-maps generated by babel to stack trace. @@ -198,7 +198,7 @@ function nextdir() { require.resolve('../fixtures/source-map/babel-throw.js') ]); assert.ok( - output.stderr.toString().match(/->.*babel-throw-original\.js:18:31/) + output.stderr.toString().match(/.*babel-throw-original\.js:18:31/) ); } @@ -209,10 +209,10 @@ function nextdir() { require.resolve('../fixtures/source-map/istanbul-throw.js') ]); assert.ok( - output.stderr.toString().match(/->.*istanbul-throw-original\.js:5:9/) + output.stderr.toString().match(/.*istanbul-throw-original\.js:5:9/) ); assert.ok( - output.stderr.toString().match(/->.*istanbul-throw-original\.js:9:3/) + output.stderr.toString().match(/.*istanbul-throw-original\.js:9:3/) ); } @@ -223,7 +223,7 @@ function nextdir() { require.resolve('../fixtures/source-map/babel-esm.mjs') ]); assert.ok( - output.stderr.toString().match(/->.*babel-esm-original\.mjs:9:29/) + output.stderr.toString().match(/.*babel-esm-original\.mjs:9:29/) ); } From 1fc830713851febc8f8d03aa9e66113fcc7b7128 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 4 Feb 2021 11:54:09 -0800 Subject: [PATCH 076/108] test: re-implement promises.setInterval() test robustly Fixes: https://github.com/nodejs/node/issues/37226 PR-URL: https://github.com/nodejs/node/pull/37230 Reviewed-By: Benjamin Gruenbaum --- test/parallel/test-timers-promisified.js | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/parallel/test-timers-promisified.js b/test/parallel/test-timers-promisified.js index 348f6c2ae0476d..3e68470c7dae97 100644 --- a/test/parallel/test-timers-promisified.js +++ b/test/parallel/test-timers-promisified.js @@ -348,6 +348,34 @@ process.on('multipleResolves', common.mustNotCall()); assert.strictEqual(loopCount, 5); })); } + + { + // Check that if we abort when we have some unresolved callbacks, + // we actually call them. + const controller = new AbortController(); + const { signal } = controller; + const delay = 10; + let totalIterations = 0; + const timeoutLoop = runInterval(async (iterationNumber) => { + await setTimeout(delay * 4); + if (iterationNumber <= 2) { + assert.strictEqual(signal.aborted, false); + } + if (iterationNumber === 2) { + controller.abort(); + } + if (iterationNumber > 2) { + assert.strictEqual(signal.aborted, true); + } + if (iterationNumber > totalIterations) { + totalIterations = iterationNumber; + } + }, delay, signal); + + timeoutLoop.catch(common.mustCall(() => { + assert.ok(totalIterations >= 3, `iterations was ${totalIterations} < 3`); + })); + } } { From d0f1ff53ff1ca53c525d1722729a8f85f445e186 Mon Sep 17 00:00:00 2001 From: Sajal Khandelwal Date: Sun, 7 Feb 2021 11:33:33 -0500 Subject: [PATCH 077/108] async_hooks: set unhandledRejection async context This commit now executes `process.on('unhandledRejection')` in the async execution context of the concerned `Promise`. PR-URL: https://github.com/nodejs/node/pull/37281 Reviewed-By: Anna Henningsen Reviewed-By: Benjamin Gruenbaum --- lib/internal/async_hooks.js | 2 + lib/internal/process/promises.js | 34 ++++++-- src/node_task_queue.cc | 77 ++++++++++++++++++- .../test-unhandled-rejection-context.js | 27 +++++++ test/parallel/test-bootstrap-modules.js | 1 + 5 files changed, 130 insertions(+), 11 deletions(-) create mode 100644 test/async-hooks/test-unhandled-rejection-context.js diff --git a/lib/internal/async_hooks.js b/lib/internal/async_hooks.js index f3014318071d9f..43ba749cd69946 100644 --- a/lib/internal/async_hooks.js +++ b/lib/internal/async_hooks.js @@ -573,6 +573,8 @@ module.exports = { emitBefore: emitBeforeScript, emitAfter: emitAfterScript, emitDestroy: emitDestroyScript, + pushAsyncContext, + popAsyncContext, registerDestroyHook, useDomainTrampoline, nativeHooks: { diff --git a/lib/internal/process/promises.js b/lib/internal/process/promises.js index 023f7df0360d02..c4eb9c53e242e7 100644 --- a/lib/internal/process/promises.js +++ b/lib/internal/process/promises.js @@ -24,6 +24,12 @@ const { triggerUncaughtException } = internalBinding('errors'); +const { + pushAsyncContext, + popAsyncContext, +} = require('internal/async_hooks'); +const async_hooks = require('async_hooks'); + // *Must* match Environment::TickInfo::Fields in src/env.h. const kHasRejectionToWarn = 1; @@ -116,11 +122,28 @@ function resolveError(type, promise, reason) { } function unhandledRejection(promise, reason) { + const asyncId = async_hooks.executionAsyncId(); + const triggerAsyncId = async_hooks.triggerAsyncId(); + const resource = promise; + + const emit = (reason, promise, promiseInfo) => { + try { + pushAsyncContext(asyncId, triggerAsyncId, resource); + if (promiseInfo.domain) { + return promiseInfo.domain.emit('error', reason); + } + return process.emit('unhandledRejection', reason, promise); + } finally { + popAsyncContext(asyncId); + } + }; + maybeUnhandledPromises.set(promise, { reason, uid: ++lastPromiseId, warned: false, - domain: process.domain + domain: process.domain, + emit }); // This causes the promise to be referenced at least for one tick. ArrayPrototypePush(pendingUnhandledRejections, promise); @@ -194,13 +217,8 @@ function processPromiseRejections() { continue; } promiseInfo.warned = true; - const { reason, uid } = promiseInfo; - function emit(reason, promise, promiseInfo) { - if (promiseInfo.domain) { - return promiseInfo.domain.emit('error', reason); - } - return process.emit('unhandledRejection', reason, promise); - } + const { reason, uid, emit } = promiseInfo; + switch (unhandledRejectionsMode) { case kStrictUnhandledRejections: { const err = reason instanceof Error ? diff --git a/src/node_task_queue.cc b/src/node_task_queue.cc index 0aa021fc5b27df..004eb6a6529f79 100644 --- a/src/node_task_queue.cc +++ b/src/node_task_queue.cc @@ -1,3 +1,4 @@ +#include "async_wrap.h" #include "env-inl.h" #include "node.h" #include "node_errors.h" @@ -16,11 +17,13 @@ using v8::Context; using v8::Function; using v8::FunctionCallbackInfo; using v8::Isolate; +using v8::Just; using v8::kPromiseHandlerAddedAfterReject; using v8::kPromiseRejectAfterResolved; using v8::kPromiseRejectWithNoHandler; using v8::kPromiseResolveAfterResolved; using v8::Local; +using v8::Maybe; using v8::Number; using v8::Object; using v8::Promise; @@ -28,6 +31,40 @@ using v8::PromiseRejectEvent; using v8::PromiseRejectMessage; using v8::Value; +static Maybe GetAssignedPromiseAsyncId(Environment* env, + Local promise, + Local id_symbol) { + Local maybe_async_id; + if (!promise->Get(env->context(), id_symbol).ToLocal(&maybe_async_id)) { + return v8::Just(AsyncWrap::kInvalidAsyncId); + } + return maybe_async_id->IsNumber() + ? maybe_async_id->NumberValue(env->context()) + : v8::Just(AsyncWrap::kInvalidAsyncId); +} + +static Maybe GetAssignedPromiseWrapAsyncId(Environment* env, + Local promise, + Local id_symbol) { + // This check is imperfect. If the internal field is set, it should + // be an object. If it's not, we just ignore it. Ideally v8 would + // have had GetInternalField returning a MaybeLocal but this works + // for now. + Local promiseWrap = promise->GetInternalField(0); + if (promiseWrap->IsObject()) { + Local maybe_async_id; + if (!promiseWrap.As()->Get(env->context(), id_symbol) + .ToLocal(&maybe_async_id)) { + return v8::Just(AsyncWrap::kInvalidAsyncId); + } + return maybe_async_id->IsNumber() + ? maybe_async_id->NumberValue(env->context()) + : v8::Just(AsyncWrap::kInvalidAsyncId); + } else { + return v8::Just(AsyncWrap::kInvalidAsyncId); + } +} + void PromiseRejectCallback(PromiseRejectMessage message) { static std::atomic unhandledRejections{0}; static std::atomic rejectionsHandledAfter{0}; @@ -76,12 +113,46 @@ void PromiseRejectCallback(PromiseRejectMessage message) { Local args[] = { type, promise, value }; - // V8 does not expect this callback to have a scheduled exceptions once it - // returns, so we print them out in a best effort to do something about it - // without failing silently and without crashing the process. + double async_id = AsyncWrap::kInvalidAsyncId; + double trigger_async_id = AsyncWrap::kInvalidAsyncId; TryCatchScope try_catch(env); + + if (!GetAssignedPromiseAsyncId(env, promise, env->async_id_symbol()) + .To(&async_id)) return; + if (!GetAssignedPromiseAsyncId(env, promise, env->trigger_async_id_symbol()) + .To(&trigger_async_id)) return; + + if (async_id == AsyncWrap::kInvalidAsyncId && + trigger_async_id == AsyncWrap::kInvalidAsyncId) { + // That means that promise might be a PromiseWrap, so we'll + // check there as well. + if (!GetAssignedPromiseWrapAsyncId(env, promise, env->async_id_symbol()) + .To(&async_id)) return; + if (!GetAssignedPromiseWrapAsyncId( + env, promise, env->trigger_async_id_symbol()) + .To(&trigger_async_id)) return; + } + + if (async_id != AsyncWrap::kInvalidAsyncId && + trigger_async_id != AsyncWrap::kInvalidAsyncId) { + env->async_hooks()->push_async_context( + async_id, trigger_async_id, promise); + } + USE(callback->Call( env->context(), Undefined(isolate), arraysize(args), args)); + + if (async_id != AsyncWrap::kInvalidAsyncId && + trigger_async_id != AsyncWrap::kInvalidAsyncId && + env->execution_async_id() == async_id) { + // This condition might not be true if async_hooks was enabled during + // the promise callback execution. + env->async_hooks()->pop_async_context(async_id); + } + + // V8 does not expect this callback to have a scheduled exceptions once it + // returns, so we print them out in a best effort to do something about it + // without failing silently and without crashing the process. if (try_catch.HasCaught() && !try_catch.HasTerminated()) { fprintf(stderr, "Exception in PromiseRejectCallback:\n"); PrintCaughtException(isolate, env->context(), try_catch); diff --git a/test/async-hooks/test-unhandled-rejection-context.js b/test/async-hooks/test-unhandled-rejection-context.js new file mode 100644 index 00000000000000..b70d97f99fd441 --- /dev/null +++ b/test/async-hooks/test-unhandled-rejection-context.js @@ -0,0 +1,27 @@ +'use strict'; + +const common = require('../common'); + +const assert = require('assert'); +const initHooks = require('./init-hooks'); +const async_hooks = require('async_hooks'); + +if (!common.isMainThread) + common.skip('Worker bootstrapping works differently -> different async IDs'); + +const promiseAsyncIds = []; +const hooks = initHooks({ + oninit(asyncId, type) { + if (type === 'PROMISE') { + promiseAsyncIds.push(asyncId); + } + } +}); + +hooks.enable(); +Promise.reject(); + +process.on('unhandledRejection', common.mustCall(() => { + assert.strictEqual(promiseAsyncIds.length, 1); + assert.strictEqual(async_hooks.executionAsyncId(), promiseAsyncIds[0]); +})); diff --git a/test/parallel/test-bootstrap-modules.js b/test/parallel/test-bootstrap-modules.js index 105bfb10866499..4d47de41c29f32 100644 --- a/test/parallel/test-bootstrap-modules.js +++ b/test/parallel/test-bootstrap-modules.js @@ -102,6 +102,7 @@ const expectedModules = new Set([ 'NativeModule internal/worker/io', 'NativeModule internal/worker/js_transferable', 'NativeModule internal/blob', + 'NativeModule async_hooks', 'NativeModule path', 'NativeModule stream', 'NativeModule timers', From fbcab109dea4426bdd2ec29aa61e3beeeb04d27e Mon Sep 17 00:00:00 2001 From: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> Date: Wed, 6 Jan 2021 09:20:00 +0100 Subject: [PATCH 078/108] =?UTF-8?q?url:=20move=C2=A0`URLSearchParams`=20me?= =?UTF-8?q?thod=C2=A0definitions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/36799 Reviewed-By: Antoine du Hamel Reviewed-By: Tiancheng "Timothy" Gu --- lib/internal/url.js | 480 ++++++++++++++++++++++---------------------- 1 file changed, 240 insertions(+), 240 deletions(-) diff --git a/lib/internal/url.js b/lib/internal/url.js index e48811a9c3ca61..0584fd83983c62 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -259,6 +259,246 @@ class URLSearchParams { } } +defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { + append(name, value) { + if (!this || !this[searchParams] || this[searchParams][searchParams]) { + throw new ERR_INVALID_THIS('URLSearchParams'); + } + if (arguments.length < 2) { + throw new ERR_MISSING_ARGS('name', 'value'); + } + + name = toUSVString(name); + value = toUSVString(value); + ArrayPrototypePush(this[searchParams], name, value); + update(this[context], this); + }, + + delete(name) { + if (!this || !this[searchParams] || this[searchParams][searchParams]) { + throw new ERR_INVALID_THIS('URLSearchParams'); + } + if (arguments.length < 1) { + throw new ERR_MISSING_ARGS('name'); + } + + const list = this[searchParams]; + name = toUSVString(name); + for (let i = 0; i < list.length;) { + const cur = list[i]; + if (cur === name) { + list.splice(i, 2); + } else { + i += 2; + } + } + update(this[context], this); + }, + + get(name) { + if (!this || !this[searchParams] || this[searchParams][searchParams]) { + throw new ERR_INVALID_THIS('URLSearchParams'); + } + if (arguments.length < 1) { + throw new ERR_MISSING_ARGS('name'); + } + + const list = this[searchParams]; + name = toUSVString(name); + for (let i = 0; i < list.length; i += 2) { + if (list[i] === name) { + return list[i + 1]; + } + } + return null; + }, + + getAll(name) { + if (!this || !this[searchParams] || this[searchParams][searchParams]) { + throw new ERR_INVALID_THIS('URLSearchParams'); + } + if (arguments.length < 1) { + throw new ERR_MISSING_ARGS('name'); + } + + const list = this[searchParams]; + const values = []; + name = toUSVString(name); + for (let i = 0; i < list.length; i += 2) { + if (list[i] === name) { + values.push(list[i + 1]); + } + } + return values; + }, + + has(name) { + if (!this || !this[searchParams] || this[searchParams][searchParams]) { + throw new ERR_INVALID_THIS('URLSearchParams'); + } + if (arguments.length < 1) { + throw new ERR_MISSING_ARGS('name'); + } + + const list = this[searchParams]; + name = toUSVString(name); + for (let i = 0; i < list.length; i += 2) { + if (list[i] === name) { + return true; + } + } + return false; + }, + + set(name, value) { + if (!this || !this[searchParams] || this[searchParams][searchParams]) { + throw new ERR_INVALID_THIS('URLSearchParams'); + } + if (arguments.length < 2) { + throw new ERR_MISSING_ARGS('name', 'value'); + } + + const list = this[searchParams]; + name = toUSVString(name); + value = toUSVString(value); + + // If there are any name-value pairs whose name is `name`, in `list`, set + // the value of the first such name-value pair to `value` and remove the + // others. + let found = false; + for (let i = 0; i < list.length;) { + const cur = list[i]; + if (cur === name) { + if (!found) { + list[i + 1] = value; + found = true; + i += 2; + } else { + list.splice(i, 2); + } + } else { + i += 2; + } + } + + // Otherwise, append a new name-value pair whose name is `name` and value + // is `value`, to `list`. + if (!found) { + ArrayPrototypePush(list, name, value); + } + + update(this[context], this); + }, + + sort() { + const a = this[searchParams]; + const len = a.length; + + if (len <= 2) { + // Nothing needs to be done. + } else if (len < 100) { + // 100 is found through testing. + // Simple stable in-place insertion sort + // Derived from v8/src/js/array.js + for (let i = 2; i < len; i += 2) { + const curKey = a[i]; + const curVal = a[i + 1]; + let j; + for (j = i - 2; j >= 0; j -= 2) { + if (a[j] > curKey) { + a[j + 2] = a[j]; + a[j + 3] = a[j + 1]; + } else { + break; + } + } + a[j + 2] = curKey; + a[j + 3] = curVal; + } + } else { + // Bottom-up iterative stable merge sort + const lBuffer = new Array(len); + const rBuffer = new Array(len); + for (let step = 2; step < len; step *= 2) { + for (let start = 0; start < len - 2; start += 2 * step) { + const mid = start + step; + let end = mid + step; + end = end < len ? end : len; + if (mid > end) + continue; + merge(a, start, mid, end, lBuffer, rBuffer); + } + } + } + + update(this[context], this); + }, + + // https://heycam.github.io/webidl/#es-iterators + // Define entries here rather than [Symbol.iterator] as the function name + // must be set to `entries`. + entries() { + if (!this || !this[searchParams] || this[searchParams][searchParams]) { + throw new ERR_INVALID_THIS('URLSearchParams'); + } + + return createSearchParamsIterator(this, 'key+value'); + }, + + forEach(callback, thisArg = undefined) { + if (!this || !this[searchParams] || this[searchParams][searchParams]) { + throw new ERR_INVALID_THIS('URLSearchParams'); + } + validateCallback(callback); + + let list = this[searchParams]; + + let i = 0; + while (i < list.length) { + const key = list[i]; + const value = list[i + 1]; + callback.call(thisArg, value, key, this); + // In case the URL object's `search` is updated + list = this[searchParams]; + i += 2; + } + }, + + // https://heycam.github.io/webidl/#es-iterable + keys() { + if (!this || !this[searchParams] || this[searchParams][searchParams]) { + throw new ERR_INVALID_THIS('URLSearchParams'); + } + + return createSearchParamsIterator(this, 'key'); + }, + + values() { + if (!this || !this[searchParams] || this[searchParams][searchParams]) { + throw new ERR_INVALID_THIS('URLSearchParams'); + } + + return createSearchParamsIterator(this, 'value'); + }, + + // https://heycam.github.io/webidl/#es-stringifier + // https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior + toString() { + if (!this || !this[searchParams] || this[searchParams][searchParams]) { + throw new ERR_INVALID_THIS('URLSearchParams'); + } + + return serializeParams(this[searchParams]); + } +}); + +// https://heycam.github.io/webidl/#es-iterable-entries +ObjectDefineProperty(URLSearchParams.prototype, SymbolIterator, { + writable: true, + configurable: true, + value: URLSearchParams.prototype.entries +}); + function onParseComplete(flags, protocol, username, password, host, port, path, query, fragment) { const ctx = this[context]; @@ -944,246 +1184,6 @@ function merge(out, start, mid, end, lBuffer, rBuffer) { out[o++] = rBuffer[r++]; } -defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { - append(name, value) { - if (!this || !this[searchParams] || this[searchParams][searchParams]) { - throw new ERR_INVALID_THIS('URLSearchParams'); - } - if (arguments.length < 2) { - throw new ERR_MISSING_ARGS('name', 'value'); - } - - name = toUSVString(name); - value = toUSVString(value); - ArrayPrototypePush(this[searchParams], name, value); - update(this[context], this); - }, - - delete(name) { - if (!this || !this[searchParams] || this[searchParams][searchParams]) { - throw new ERR_INVALID_THIS('URLSearchParams'); - } - if (arguments.length < 1) { - throw new ERR_MISSING_ARGS('name'); - } - - const list = this[searchParams]; - name = toUSVString(name); - for (let i = 0; i < list.length;) { - const cur = list[i]; - if (cur === name) { - list.splice(i, 2); - } else { - i += 2; - } - } - update(this[context], this); - }, - - get(name) { - if (!this || !this[searchParams] || this[searchParams][searchParams]) { - throw new ERR_INVALID_THIS('URLSearchParams'); - } - if (arguments.length < 1) { - throw new ERR_MISSING_ARGS('name'); - } - - const list = this[searchParams]; - name = toUSVString(name); - for (let i = 0; i < list.length; i += 2) { - if (list[i] === name) { - return list[i + 1]; - } - } - return null; - }, - - getAll(name) { - if (!this || !this[searchParams] || this[searchParams][searchParams]) { - throw new ERR_INVALID_THIS('URLSearchParams'); - } - if (arguments.length < 1) { - throw new ERR_MISSING_ARGS('name'); - } - - const list = this[searchParams]; - const values = []; - name = toUSVString(name); - for (let i = 0; i < list.length; i += 2) { - if (list[i] === name) { - values.push(list[i + 1]); - } - } - return values; - }, - - has(name) { - if (!this || !this[searchParams] || this[searchParams][searchParams]) { - throw new ERR_INVALID_THIS('URLSearchParams'); - } - if (arguments.length < 1) { - throw new ERR_MISSING_ARGS('name'); - } - - const list = this[searchParams]; - name = toUSVString(name); - for (let i = 0; i < list.length; i += 2) { - if (list[i] === name) { - return true; - } - } - return false; - }, - - set(name, value) { - if (!this || !this[searchParams] || this[searchParams][searchParams]) { - throw new ERR_INVALID_THIS('URLSearchParams'); - } - if (arguments.length < 2) { - throw new ERR_MISSING_ARGS('name', 'value'); - } - - const list = this[searchParams]; - name = toUSVString(name); - value = toUSVString(value); - - // If there are any name-value pairs whose name is `name`, in `list`, set - // the value of the first such name-value pair to `value` and remove the - // others. - let found = false; - for (let i = 0; i < list.length;) { - const cur = list[i]; - if (cur === name) { - if (!found) { - list[i + 1] = value; - found = true; - i += 2; - } else { - list.splice(i, 2); - } - } else { - i += 2; - } - } - - // Otherwise, append a new name-value pair whose name is `name` and value - // is `value`, to `list`. - if (!found) { - ArrayPrototypePush(list, name, value); - } - - update(this[context], this); - }, - - sort() { - const a = this[searchParams]; - const len = a.length; - - if (len <= 2) { - // Nothing needs to be done. - } else if (len < 100) { - // 100 is found through testing. - // Simple stable in-place insertion sort - // Derived from v8/src/js/array.js - for (let i = 2; i < len; i += 2) { - const curKey = a[i]; - const curVal = a[i + 1]; - let j; - for (j = i - 2; j >= 0; j -= 2) { - if (a[j] > curKey) { - a[j + 2] = a[j]; - a[j + 3] = a[j + 1]; - } else { - break; - } - } - a[j + 2] = curKey; - a[j + 3] = curVal; - } - } else { - // Bottom-up iterative stable merge sort - const lBuffer = new Array(len); - const rBuffer = new Array(len); - for (let step = 2; step < len; step *= 2) { - for (let start = 0; start < len - 2; start += 2 * step) { - const mid = start + step; - let end = mid + step; - end = end < len ? end : len; - if (mid > end) - continue; - merge(a, start, mid, end, lBuffer, rBuffer); - } - } - } - - update(this[context], this); - }, - - // https://heycam.github.io/webidl/#es-iterators - // Define entries here rather than [Symbol.iterator] as the function name - // must be set to `entries`. - entries() { - if (!this || !this[searchParams] || this[searchParams][searchParams]) { - throw new ERR_INVALID_THIS('URLSearchParams'); - } - - return createSearchParamsIterator(this, 'key+value'); - }, - - forEach(callback, thisArg = undefined) { - if (!this || !this[searchParams] || this[searchParams][searchParams]) { - throw new ERR_INVALID_THIS('URLSearchParams'); - } - validateCallback(callback); - - let list = this[searchParams]; - - let i = 0; - while (i < list.length) { - const key = list[i]; - const value = list[i + 1]; - callback.call(thisArg, value, key, this); - // In case the URL object's `search` is updated - list = this[searchParams]; - i += 2; - } - }, - - // https://heycam.github.io/webidl/#es-iterable - keys() { - if (!this || !this[searchParams] || this[searchParams][searchParams]) { - throw new ERR_INVALID_THIS('URLSearchParams'); - } - - return createSearchParamsIterator(this, 'key'); - }, - - values() { - if (!this || !this[searchParams] || this[searchParams][searchParams]) { - throw new ERR_INVALID_THIS('URLSearchParams'); - } - - return createSearchParamsIterator(this, 'value'); - }, - - // https://heycam.github.io/webidl/#es-stringifier - // https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior - toString() { - if (!this || !this[searchParams] || this[searchParams][searchParams]) { - throw new ERR_INVALID_THIS('URLSearchParams'); - } - - return serializeParams(this[searchParams]); - } -}); - -// https://heycam.github.io/webidl/#es-iterable-entries -ObjectDefineProperty(URLSearchParams.prototype, SymbolIterator, { - writable: true, - configurable: true, - value: URLSearchParams.prototype.entries -}); - // https://heycam.github.io/webidl/#dfn-default-iterator-object function createSearchParamsIterator(target, kind) { const iterator = ObjectCreate(URLSearchParamsIteratorPrototype); From 676f696a99e68fb0bc5c730e74bb5b69a5df2d60 Mon Sep 17 00:00:00 2001 From: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> Date: Tue, 5 Jan 2021 13:20:00 +0100 Subject: [PATCH 079/108] =?UTF-8?q?url:=20fix=C2=A0definitions=20of=C2=A0`?= =?UTF-8?q?URL`/`SearchParams`=C2=A0methods=20and=C2=A0accessors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes getter and setter names for the WHATWG URL classes, and fixes a few other inconsistencies with browsers implementations. Co-authored-by: Gerhard Stöbich PR-URL: https://github.com/nodejs/node/pull/36799 Reviewed-By: Antoine du Hamel Reviewed-By: Tiancheng "Timothy" Gu --- lib/internal/url.js | 620 ++++++++++---------- test/parallel/test-whatwg-url-properties.js | 100 ++++ 2 files changed, 404 insertions(+), 316 deletions(-) create mode 100644 test/parallel/test-whatwg-url-properties.js diff --git a/lib/internal/url.js b/lib/internal/url.js index 0584fd83983c62..4fd7702367e8a6 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -257,9 +257,7 @@ class URLSearchParams { } return `${this.constructor.name} {}`; } -} -defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { append(name, value) { if (!this || !this[searchParams] || this[searchParams][searchParams]) { throw new ERR_INVALID_THIS('URLSearchParams'); @@ -272,7 +270,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { value = toUSVString(value); ArrayPrototypePush(this[searchParams], name, value); update(this[context], this); - }, + } delete(name) { if (!this || !this[searchParams] || this[searchParams][searchParams]) { @@ -293,7 +291,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { } } update(this[context], this); - }, + } get(name) { if (!this || !this[searchParams] || this[searchParams][searchParams]) { @@ -311,7 +309,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { } } return null; - }, + } getAll(name) { if (!this || !this[searchParams] || this[searchParams][searchParams]) { @@ -330,7 +328,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { } } return values; - }, + } has(name) { if (!this || !this[searchParams] || this[searchParams][searchParams]) { @@ -348,7 +346,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { } } return false; - }, + } set(name, value) { if (!this || !this[searchParams] || this[searchParams][searchParams]) { @@ -388,7 +386,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { } update(this[context], this); - }, + } sort() { const a = this[searchParams]; @@ -432,7 +430,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { } update(this[context], this); - }, + } // https://heycam.github.io/webidl/#es-iterators // Define entries here rather than [Symbol.iterator] as the function name @@ -443,7 +441,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { } return createSearchParamsIterator(this, 'key+value'); - }, + } forEach(callback, thisArg = undefined) { if (!this || !this[searchParams] || this[searchParams][searchParams]) { @@ -462,7 +460,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { list = this[searchParams]; i += 2; } - }, + } // https://heycam.github.io/webidl/#es-iterable keys() { @@ -471,7 +469,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { } return createSearchParamsIterator(this, 'key'); - }, + } values() { if (!this || !this[searchParams] || this[searchParams][searchParams]) { @@ -479,7 +477,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { } return createSearchParamsIterator(this, 'value'); - }, + } // https://heycam.github.io/webidl/#es-stringifier // https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior @@ -490,13 +488,29 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { return serializeParams(this[searchParams]); } -}); +} -// https://heycam.github.io/webidl/#es-iterable-entries -ObjectDefineProperty(URLSearchParams.prototype, SymbolIterator, { - writable: true, - configurable: true, - value: URLSearchParams.prototype.entries +ObjectDefineProperties(URLSearchParams.prototype, { + append: { enumerable: true }, + delete: { enumerable: true }, + get: { enumerable: true }, + getAll: { enumerable: true }, + has: { enumerable: true }, + set: { enumerable: true }, + sort: { enumerable: true }, + entries: { enumerable: true }, + forEach: { enumerable: true }, + keys: { enumerable: true }, + values: { enumerable: true }, + toString: { enumerable: true }, + [SymbolToStringTag]: { configurable: true, value: 'URLSearchParams' }, + + // https://heycam.github.io/webidl/#es-iterable-entries + [SymbolIterator]: { + configurable: true, + writable: true, + value: URLSearchParams.prototype.entries, + }, }); function onParseComplete(flags, protocol, username, password, @@ -648,319 +662,293 @@ class URL { return `${constructor.name} ${inspect(obj, opts)}`; } -} -ObjectDefineProperties(URL.prototype, { - [kFormat]: { - enumerable: false, - configurable: false, - // eslint-disable-next-line func-name-matching - value: function format(options) { - if (options) - validateObject(options, 'options'); - - options = { - fragment: true, - unicode: false, - search: true, - auth: true, - ...options - }; - const ctx = this[context]; - // https://url.spec.whatwg.org/#url-serializing - let ret = ctx.scheme; - if (ctx.host !== null) { - ret += '//'; - const has_username = ctx.username !== ''; - const has_password = ctx.password !== ''; - if (options.auth && (has_username || has_password)) { - if (has_username) - ret += ctx.username; - if (has_password) - ret += `:${ctx.password}`; - ret += '@'; - } - ret += options.unicode ? - domainToUnicode(ctx.host) : ctx.host; - if (ctx.port !== null) - ret += `:${ctx.port}`; - } - if (this[cannotBeBase]) { - ret += ctx.path[0]; - } else { - if (ctx.host === null && ctx.path.length > 1 && ctx.path[0] === '') { - ret += '/.'; - } - if (ctx.path.length) { - ret += '/' + ArrayPrototypeJoin(ctx.path, '/'); - } - } - if (options.search && ctx.query !== null) - ret += `?${ctx.query}`; - if (options.fragment && ctx.fragment !== null) - ret += `#${ctx.fragment}`; - return ret; - } - }, - [SymbolToStringTag]: { - configurable: true, - value: 'URL' - }, - toString: { - // https://heycam.github.io/webidl/#es-stringifier - writable: true, - enumerable: true, - configurable: true, - // eslint-disable-next-line func-name-matching - value: function toString() { - return this[kFormat]({}); - } - }, - href: { - enumerable: true, - configurable: true, - get() { - return this[kFormat]({}); - }, - set(input) { - // toUSVString is not needed. - input = `${input}`; - parse(input, -1, undefined, undefined, - FunctionPrototypeBind(onParseComplete, this), onParseError); - } - }, - origin: { // readonly - enumerable: true, - configurable: true, - get() { - // Refs: https://url.spec.whatwg.org/#concept-url-origin - const ctx = this[context]; - switch (ctx.scheme) { - case 'blob:': - if (ctx.path.length > 0) { - try { - return (new URL(ctx.path[0])).origin; - } catch { - // Fall through... do nothing - } - } - return kOpaqueOrigin; - case 'ftp:': - case 'http:': - case 'https:': - case 'ws:': - case 'wss:': - return serializeTupleOrigin(ctx.scheme, ctx.host, ctx.port); + [kFormat](options) { + if (options) + validateObject(options, 'options'); + + options = { + fragment: true, + unicode: false, + search: true, + auth: true, + ...options + }; + const ctx = this[context]; + // https://url.spec.whatwg.org/#url-serializing + let ret = ctx.scheme; + if (ctx.host !== null) { + ret += '//'; + const has_username = ctx.username !== ''; + const has_password = ctx.password !== ''; + if (options.auth && (has_username || has_password)) { + if (has_username) + ret += ctx.username; + if (has_password) + ret += `:${ctx.password}`; + ret += '@'; } - return kOpaqueOrigin; - } - }, - protocol: { - enumerable: true, - configurable: true, - get() { - return this[context].scheme; - }, - set(scheme) { - // toUSVString is not needed. - scheme = `${scheme}`; - if (scheme.length === 0) - return; - const ctx = this[context]; - parse(scheme, kSchemeStart, null, ctx, - FunctionPrototypeBind(onParseProtocolComplete, this)); + ret += options.unicode ? + domainToUnicode(ctx.host) : ctx.host; + if (ctx.port !== null) + ret += `:${ctx.port}`; } - }, - username: { - enumerable: true, - configurable: true, - get() { - return this[context].username; - }, - set(username) { - // toUSVString is not needed. - username = `${username}`; - if (this[cannotHaveUsernamePasswordPort]) - return; - const ctx = this[context]; - if (username === '') { - ctx.username = ''; - ctx.flags &= ~URL_FLAGS_HAS_USERNAME; - return; + if (this[cannotBeBase]) { + ret += ctx.path[0]; + } else { + if (ctx.host === null && ctx.path.length > 1 && ctx.path[0] === '') { + ret += '/.'; } - ctx.username = encodeAuth(username); - ctx.flags |= URL_FLAGS_HAS_USERNAME; - } - }, - password: { - enumerable: true, - configurable: true, - get() { - return this[context].password; - }, - set(password) { - // toUSVString is not needed. - password = `${password}`; - if (this[cannotHaveUsernamePasswordPort]) - return; - const ctx = this[context]; - if (password === '') { - ctx.password = ''; - ctx.flags &= ~URL_FLAGS_HAS_PASSWORD; - return; + if (ctx.path.length) { + ret += '/' + ArrayPrototypeJoin(ctx.path, '/'); } - ctx.password = encodeAuth(password); - ctx.flags |= URL_FLAGS_HAS_PASSWORD; } - }, - host: { - enumerable: true, - configurable: true, - get() { - const ctx = this[context]; - let ret = ctx.host || ''; - if (ctx.port !== null) - ret += `:${ctx.port}`; - return ret; - }, - set(host) { - const ctx = this[context]; - // toUSVString is not needed. - host = `${host}`; - if (this[cannotBeBase]) { - // Cannot set the host if cannot-be-base is set - return; - } - parse(host, kHost, null, ctx, - FunctionPrototypeBind(onParseHostComplete, this)); + if (options.search && ctx.query !== null) + ret += `?${ctx.query}`; + if (options.fragment && ctx.fragment !== null) + ret += `#${ctx.fragment}`; + return ret; + } + + // https://heycam.github.io/webidl/#es-stringifier + toString() { + return this[kFormat]({}); + } + + get href() { + return this[kFormat]({}); + } + + set href(input) { + // toUSVString is not needed. + input = `${input}`; + parse(input, -1, undefined, undefined, + FunctionPrototypeBind(onParseComplete, this), onParseError); + } + + // readonly + get origin() { + // Refs: https://url.spec.whatwg.org/#concept-url-origin + const ctx = this[context]; + switch (ctx.scheme) { + case 'blob:': + if (ctx.path.length > 0) { + try { + return (new URL(ctx.path[0])).origin; + } catch { + // Fall through... do nothing + } + } + return kOpaqueOrigin; + case 'ftp:': + case 'http:': + case 'https:': + case 'ws:': + case 'wss:': + return serializeTupleOrigin(ctx.scheme, ctx.host, ctx.port); } - }, - hostname: { - enumerable: true, - configurable: true, - get() { - return this[context].host || ''; - }, - set(host) { - const ctx = this[context]; - // toUSVString is not needed. - host = `${host}`; - if (this[cannotBeBase]) { - // Cannot set the host if cannot-be-base is set - return; - } - parse(host, kHostname, null, ctx, onParseHostnameComplete.bind(this)); + return kOpaqueOrigin; + } + + get protocol() { + return this[context].scheme; + } + + set protocol(scheme) { + // toUSVString is not needed. + scheme = `${scheme}`; + if (scheme.length === 0) + return; + const ctx = this[context]; + parse(scheme, kSchemeStart, null, ctx, + FunctionPrototypeBind(onParseProtocolComplete, this)); + } + + get username() { + return this[context].username; + } + + set username(username) { + // toUSVString is not needed. + username = `${username}`; + if (this[cannotHaveUsernamePasswordPort]) + return; + const ctx = this[context]; + if (username === '') { + ctx.username = ''; + ctx.flags &= ~URL_FLAGS_HAS_USERNAME; + return; } - }, - port: { - enumerable: true, - configurable: true, - get() { - const port = this[context].port; - return port === null ? '' : String(port); - }, - set(port) { - // toUSVString is not needed. - port = `${port}`; - if (this[cannotHaveUsernamePasswordPort]) - return; - const ctx = this[context]; - if (port === '') { - ctx.port = null; - return; - } - parse(port, kPort, null, ctx, - FunctionPrototypeBind(onParsePortComplete, this)); + ctx.username = encodeAuth(username); + ctx.flags |= URL_FLAGS_HAS_USERNAME; + } + + get password() { + return this[context].password; + } + + set password(password) { + // toUSVString is not needed. + password = `${password}`; + if (this[cannotHaveUsernamePasswordPort]) + return; + const ctx = this[context]; + if (password === '') { + ctx.password = ''; + ctx.flags &= ~URL_FLAGS_HAS_PASSWORD; + return; } - }, - pathname: { - enumerable: true, - configurable: true, - get() { - const ctx = this[context]; - if (this[cannotBeBase]) - return ctx.path[0]; - if (ctx.path.length === 0) - return ''; - return `/${ArrayPrototypeJoin(ctx.path, '/')}`; - }, - set(path) { - // toUSVString is not needed. - path = `${path}`; - if (this[cannotBeBase]) - return; - parse(path, kPathStart, null, this[context], - onParsePathComplete.bind(this)); + ctx.password = encodeAuth(password); + ctx.flags |= URL_FLAGS_HAS_PASSWORD; + } + + get host() { + const ctx = this[context]; + let ret = ctx.host || ''; + if (ctx.port !== null) + ret += `:${ctx.port}`; + return ret; + } + + set host(host) { + const ctx = this[context]; + // toUSVString is not needed. + host = `${host}`; + if (this[cannotBeBase]) { + // Cannot set the host if cannot-be-base is set + return; } - }, - search: { - enumerable: true, - configurable: true, - get() { - const { query } = this[context]; - if (query === null || query === '') - return ''; - return `?${query}`; - }, - set(search) { - const ctx = this[context]; - search = toUSVString(search); - if (search === '') { - ctx.query = null; - ctx.flags &= ~URL_FLAGS_HAS_QUERY; - } else { - if (search[0] === '?') search = StringPrototypeSlice(search, 1); - ctx.query = ''; - ctx.flags |= URL_FLAGS_HAS_QUERY; - if (search) { - parse(search, kQuery, null, ctx, - FunctionPrototypeBind(onParseSearchComplete, this)); - } - } - initSearchParams(this[searchParams], search); + parse(host, kHost, null, ctx, + FunctionPrototypeBind(onParseHostComplete, this)); + } + + get hostname() { + return this[context].host || ''; + } + + set hostname(host) { + const ctx = this[context]; + // toUSVString is not needed. + host = `${host}`; + if (this[cannotBeBase]) { + // Cannot set the host if cannot-be-base is set + return; } - }, - searchParams: { // readonly - enumerable: true, - configurable: true, - get() { - return this[searchParams]; + parse(host, kHostname, null, ctx, onParseHostnameComplete.bind(this)); + } + + get port() { + const port = this[context].port; + return port === null ? '' : String(port); + } + + set port(port) { + // toUSVString is not needed. + port = `${port}`; + if (this[cannotHaveUsernamePasswordPort]) + return; + const ctx = this[context]; + if (port === '') { + ctx.port = null; + return; } - }, - hash: { - enumerable: true, - configurable: true, - get() { - const { fragment } = this[context]; - if (fragment === null || fragment === '') - return ''; - return `#${fragment}`; - }, - set(hash) { - const ctx = this[context]; - // toUSVString is not needed. - hash = `${hash}`; - if (!hash) { - ctx.fragment = null; - ctx.flags &= ~URL_FLAGS_HAS_FRAGMENT; - return; + parse(port, kPort, null, ctx, + FunctionPrototypeBind(onParsePortComplete, this)); + } + + get pathname() { + const ctx = this[context]; + if (this[cannotBeBase]) + return ctx.path[0]; + if (ctx.path.length === 0) + return ''; + return `/${ArrayPrototypeJoin(ctx.path, '/')}`; + } + + set pathname(path) { + // toUSVString is not needed. + path = `${path}`; + if (this[cannotBeBase]) + return; + parse(path, kPathStart, null, this[context], + onParsePathComplete.bind(this)); + } + + get search() { + const { query } = this[context]; + if (query === null || query === '') + return ''; + return `?${query}`; + } + + set search(search) { + const ctx = this[context]; + search = toUSVString(search); + if (search === '') { + ctx.query = null; + ctx.flags &= ~URL_FLAGS_HAS_QUERY; + } else { + if (search[0] === '?') search = StringPrototypeSlice(search, 1); + ctx.query = ''; + ctx.flags |= URL_FLAGS_HAS_QUERY; + if (search) { + parse(search, kQuery, null, ctx, + FunctionPrototypeBind(onParseSearchComplete, this)); } - if (hash[0] === '#') hash = StringPrototypeSlice(hash, 1); - ctx.fragment = ''; - ctx.flags |= URL_FLAGS_HAS_FRAGMENT; - parse(hash, kFragment, null, ctx, - FunctionPrototypeBind(onParseHashComplete, this)); } - }, - toJSON: { - writable: true, - enumerable: true, - configurable: true, - // eslint-disable-next-line func-name-matching - value: function toJSON() { - return this[kFormat]({}); + initSearchParams(this[searchParams], search); + } + + // readonly + get searchParams() { + return this[searchParams]; + } + + get hash() { + const { fragment } = this[context]; + if (fragment === null || fragment === '') + return ''; + return `#${fragment}`; + } + + set hash(hash) { + const ctx = this[context]; + // toUSVString is not needed. + hash = `${hash}`; + if (!hash) { + ctx.fragment = null; + ctx.flags &= ~URL_FLAGS_HAS_FRAGMENT; + return; } + if (hash[0] === '#') hash = StringPrototypeSlice(hash, 1); + ctx.fragment = ''; + ctx.flags |= URL_FLAGS_HAS_FRAGMENT; + parse(hash, kFragment, null, ctx, + FunctionPrototypeBind(onParseHashComplete, this)); } + + toJSON() { + return this[kFormat]({}); + } +} + +ObjectDefineProperties(URL.prototype, { + [kFormat]: { configurable: false, writable: false }, + [SymbolToStringTag]: { configurable: true, value: 'URL' }, + toString: { enumerable: true }, + href: { enumerable: true }, + origin: { enumerable: true }, + protocol: { enumerable: true }, + username: { enumerable: true }, + password: { enumerable: true }, + host: { enumerable: true }, + hostname: { enumerable: true }, + port: { enumerable: true }, + pathname: { enumerable: true }, + search: { enumerable: true }, + searchParams: { enumerable: true }, + hash: { enumerable: true }, + toJSON: { enumerable: true }, }); function update(url, params) { diff --git a/test/parallel/test-whatwg-url-properties.js b/test/parallel/test-whatwg-url-properties.js new file mode 100644 index 00000000000000..a387b0eb753e1a --- /dev/null +++ b/test/parallel/test-whatwg-url-properties.js @@ -0,0 +1,100 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { URL, URLSearchParams } = require('url'); + +[ + { name: 'toString' }, + { name: 'toJSON' }, + { name: Symbol.for('nodejs.util.inspect.custom') }, +].forEach(({ name }) => { + testMethod(URL.prototype, name); +}); + +[ + { name: 'href' }, + { name: 'protocol' }, + { name: 'username' }, + { name: 'password' }, + { name: 'host' }, + { name: 'hostname' }, + { name: 'port' }, + { name: 'pathname' }, + { name: 'search' }, + { name: 'hash' }, + { name: 'origin', readonly: true }, + { name: 'searchParams', readonly: true }, +].forEach(({ name, readonly = false }) => { + testAccessor(URL.prototype, name, readonly); +}); + +[ + { name: 'append' }, + { name: 'delete' }, + { name: 'get' }, + { name: 'getAll' }, + { name: 'has' }, + { name: 'set' }, + { name: 'sort' }, + { name: 'entries' }, + { name: 'forEach' }, + { name: 'keys' }, + { name: 'values' }, + { name: 'toString' }, + { name: Symbol.iterator, methodName: 'entries' }, + { name: Symbol.for('nodejs.util.inspect.custom') }, +].forEach(({ name, methodName }) => { + testMethod(URLSearchParams.prototype, name, methodName); +}); + +function stringifyName(name) { + if (typeof name === 'symbol') { + const { description } = name; + if (description === undefined) { + return ''; + } + return `[${description}]`; + } + + return name; +} + +function testMethod(target, name, methodName = stringifyName(name)) { + const desc = Object.getOwnPropertyDescriptor(target, name); + assert.notStrictEqual(desc, undefined); + assert.strictEqual(desc.enumerable, typeof name === 'string'); + + const { value } = desc; + assert.strictEqual(typeof value, 'function'); + assert.strictEqual(value.name, methodName); + assert.strictEqual( + Object.prototype.hasOwnProperty.call(value, 'prototype'), + false, + ); +} + +function testAccessor(target, name, readonly = false) { + const desc = Object.getOwnPropertyDescriptor(target, name); + assert.notStrictEqual(desc, undefined); + assert.strictEqual(desc.enumerable, typeof name === 'string'); + + const methodName = stringifyName(name); + const { get, set } = desc; + assert.strictEqual(typeof get, 'function'); + assert.strictEqual(get.name, `get ${methodName}`); + assert.strictEqual( + Object.prototype.hasOwnProperty.call(get, 'prototype'), + false, + ); + + if (readonly) { + assert.strictEqual(set, undefined); + } else { + assert.strictEqual(typeof set, 'function'); + assert.strictEqual(set.name, `set ${methodName}`); + assert.strictEqual( + Object.prototype.hasOwnProperty.call(set, 'prototype'), + false, + ); + } +} From a483c284f3f8b530acf0fcffc49752285c42d453 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Wed, 10 Feb 2021 11:18:23 +0100 Subject: [PATCH 080/108] tools: fix lint-pr-url message PR-URL: https://github.com/nodejs/node/pull/37304 Reviewed-By: Darshan Sen Reviewed-By: Luigi Pinca Reviewed-By: Rich Trott --- tools/lint-pr-url.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lint-pr-url.mjs b/tools/lint-pr-url.mjs index 3b491d26e389cb..0ebbfdd079671d 100755 --- a/tools/lint-pr-url.mjs +++ b/tools/lint-pr-url.mjs @@ -28,7 +28,7 @@ for await (const line of diff) { } else if (!validatePrUrl(line.match(prUrlDefinition)?.[1])) { console.warn( `::warning file=${currentFile},line=${currentLine++},col=${line.length}` + - '::pr-url doesn\'t match the actual PR URL.' + '::pr-url doesn\'t match the URL of the current PR.' ); } else if (line[0] !== '-') { // Increment line counter if line is not being deleted. From cdd2fe5651ac6f721c9b2525522cb17c9825547a Mon Sep 17 00:00:00 2001 From: marsonya Date: Thu, 11 Feb 2021 00:09:29 +0530 Subject: [PATCH 081/108] doc: fix typo in /api/dns.md PR-URL: https://github.com/nodejs/node/pull/37312 Reviewed-By: Luigi Pinca Reviewed-By: Rich Trott Reviewed-By: Zijian Liu Reviewed-By: Pooja D P Reviewed-By: Darshan Sen Reviewed-By: Harshitha K P Reviewed-By: Colin Ihrig Reviewed-By: Benjamin Gruenbaum --- doc/api/dns.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/dns.md b/doc/api/dns.md index baa8b8bfde4eb3..c85bf7124292f9 100644 --- a/doc/api/dns.md +++ b/doc/api/dns.md @@ -450,7 +450,7 @@ added: v15.0.0 Uses the DNS protocol to resolve `CAA` records for the `hostname`. The `addresses` argument passed to the `callback` function will contain an array of certification authority authorization records -available for the `hostname` (e.g. `[{critial: 0, iodef: +available for the `hostname` (e.g. `[{critical: 0, iodef: 'mailto:pki@example.com'}, {critical: 128, issue: 'pki.example.com'}]`). ## `dns.resolveMx(hostname, callback)` @@ -968,7 +968,7 @@ added: v15.0.0 Uses the DNS protocol to resolve `CAA` records for the `hostname`. On success, the `Promise` is resolved with an array of objects containing available certification authority authorization records available for the `hostname` -(e.g. `[{critial: 0, iodef: 'mailto:pki@example.com'},{critical: 128, issue: +(e.g. `[{critical: 0, iodef: 'mailto:pki@example.com'},{critical: 128, issue: 'pki.example.com'}]`). ### `dnsPromises.resolveCname(hostname)` From 804e7ae713a016a19fd81a32b9f0ed414347f69f Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Tue, 9 Feb 2021 11:42:18 +0100 Subject: [PATCH 082/108] doc: add version metadata for packages features PR-URL: https://github.com/nodejs/node/pull/37289 Reviewed-By: Guy Bedford Reviewed-By: Luigi Pinca --- doc/api/packages.md | 50 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/doc/api/packages.md b/doc/api/packages.md index 933e7816547f46..baeae2ded98e5d 100644 --- a/doc/api/packages.md +++ b/doc/api/packages.md @@ -8,7 +8,9 @@ changes: - v14.13.0 pr-url: https://github.com/nodejs/node/pull/34718 description: Add support for `"exports"` patterns. - - version: v14.6.0 + - version: + - v14.6.0 + - v12.19.0 pr-url: https://github.com/nodejs/node/pull/34117 description: Add package `"imports"` field. - version: @@ -135,6 +137,9 @@ package: `"commonjs"` package). ### `--input-type` flag + Strings passed in as an argument to `--eval` (or `-e`), or piped to `node` via `STDIN`, are treated as [ES modules][] when the `--input-type=module` flag @@ -252,6 +257,9 @@ absolute subpath of the package such as `require('/path/to/node_modules/pkg/subpath.js')` will still load `subpath.js`. ### Subpath exports + When using the [`"exports"`][] field, custom subpaths can be defined along with the main entry point by treating the main entry point as the @@ -282,6 +290,11 @@ import submodule from 'es-module-package/private-module.js'; ``` ### Subpath imports + In addition to the [`"exports"`][] field, it is possible to define internal package import maps that only apply to import specifiers from within the package @@ -319,6 +332,11 @@ The resolution rules for the imports field are otherwise analogous to the exports field. ### Subpath patterns + For packages with a small number of exports or imports, we recommend explicitly listing each exports subpath entry. But for packages that have @@ -404,6 +422,9 @@ The benefit of patterns over folder exports is that packages can always be imported by consumers without subpath file extensions being necessary. ### Exports sugar + If the `"."` export is the only export, the [`"exports"`][] field provides sugar for this case being the direct [`"exports"`][] field value. @@ -428,6 +449,17 @@ can be written: ``` ### Conditional exports + Conditional exports provide a way to map to different paths depending on certain conditions. They are supported for both CommonJS and ES module imports. @@ -526,6 +558,11 @@ the remaining conditions of the parent condition. In this way nested conditions behave analogously to nested JavaScript `if` statements. ### Resolving user conditions + When running Node.js, custom user conditions can be added with the `--conditions` flag: @@ -587,6 +624,17 @@ The above definitions may be moved to a dedicated conditions registry in due course. ### Self-referencing a package using its name + Within a package, the values defined in the package’s `package.json` [`"exports"`][] field can be referenced via the package’s name. From f253cb9303fe8fe9dd14b84c1e11c7a3d57a6e09 Mon Sep 17 00:00:00 2001 From: marsonya Date: Mon, 8 Feb 2021 00:55:51 +0530 Subject: [PATCH 083/108] doc: fix typo in buffer.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/37268 Reviewed-By: Luigi Pinca Reviewed-By: Richard Lau Reviewed-By: Antoine du Hamel Reviewed-By: Tobias Nießen Reviewed-By: Gireesh Punathil Reviewed-By: Pooja D P Reviewed-By: Darshan Sen Reviewed-By: Michael Dawson --- doc/api/buffer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/buffer.md b/doc/api/buffer.md index 5c02be9f3613a4..d3c1e43e5e29ce 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -370,7 +370,7 @@ The content-type of the `Blob`. ### `Blob` objects and `MessageChannel` Once a {Blob} object is created, it can be sent via `MessagePort` to multiple -destinations without transfering or immediately copying the data. The data +destinations without transferring or immediately copying the data. The data contained by the `Blob` is copied only when the `arrayBuffer()` or `text()` methods are called. From 85b1476f1dbc8be6116d5ba9a7683d4a0707626a Mon Sep 17 00:00:00 2001 From: marsonya Date: Tue, 9 Feb 2021 00:09:32 +0530 Subject: [PATCH 084/108] doc: fix typo in deprecations.md PR-URL: https://github.com/nodejs/node/pull/37282 Reviewed-By: Luigi Pinca Reviewed-By: Rich Trott Reviewed-By: Michael Dawson Reviewed-By: Pooja D P Reviewed-By: Darshan Sen Reviewed-By: Harshitha K P --- doc/api/deprecations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index bb8cbe63725a19..ac0f99bf4fcf95 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -2480,7 +2480,7 @@ called, not whether `'finish'` has been emitted and the underlying data is flushed. Use [`response.writableFinished`][] or [`response.writableEnded`][] -accordingly instead to avoid the ambigiuty. +accordingly instead to avoid the ambiguity. To maintain existing behaviour `response.finished` should be replaced with `response.writableEnded`. From c4faa39768d59ad9475f54e26ef49ea958dac8d5 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Sat, 30 Jan 2021 09:26:15 -0800 Subject: [PATCH 085/108] perf_hooks: introduce createHistogram Adds a new `perf_hooks.createHistogram()` API for creating histogram instances that allow user recording. Makes Histogram instances cloneable via MessagePort. This allows, for instance, an event loop delay monitor to be running on the main thread while the histogram data can be monitored actively from a worker thread. Signed-off-by: James M Snell PR-URL: https://github.com/nodejs/node/pull/37155 Reviewed-By: Matteo Collina --- doc/api/perf_hooks.md | 114 +++++--- doc/api/worker_threads.md | 12 +- lib/internal/histogram.js | 145 ++++++++-- lib/perf_hooks.js | 29 +- src/env.h | 3 +- src/histogram-inl.h | 43 +-- src/histogram.cc | 315 ++++++++++++++++++--- src/histogram.h | 149 ++++++++-- src/node.cc | 1 + src/node_http2.cc | 1 + src/node_perf.cc | 184 ++---------- src/node_perf.h | 37 +-- src/node_worker.cc | 1 + test/parallel/test-perf-hooks-histogram.js | 69 +++++ tools/doc/type-parser.js | 4 + 15 files changed, 784 insertions(+), 323 deletions(-) create mode 100644 test/parallel/test-perf-hooks-histogram.js diff --git a/doc/api/perf_hooks.md b/doc/api/perf_hooks.md index bbd8a3c1a99efb..9354c40e68f552 100644 --- a/doc/api/perf_hooks.md +++ b/doc/api/perf_hooks.md @@ -653,6 +653,22 @@ performance.mark('test'); performance.mark('meow'); ``` +## `perf_hooks.createHistogram([options])` + + +* `options` {Object} + * `min` {number|bigint} The minimum recordable value. Must be an integer + value greater than 0. **Defaults**: `1`. + * `max` {number|bigint} The maximum recordable value. Must be an integer + value greater than `min`. **Defaults**: `Number.MAX_SAFE_INTEGER`. + * `figures` {number} The number of accuracy digits. Must be a number between + `1` and `5`. **Defaults**: `3`. +* Returns {RecordableHistogram} + +Returns a {RecordableHistogram}. + ## `perf_hooks.monitorEventLoopDelay([options])` -Tracks the event loop delay at a given sampling rate. The constructor of -this class not exposed to users. - -_This property is an extension by Node.js. It is not available in Web browsers._ - -#### `histogram.disable()` - - -* Returns: {boolean} - -Disables the event loop delay sample timer. Returns `true` if the timer was -stopped, `false` if it was already stopped. - -#### `histogram.enable()` +## Class: `Histogram` -* Returns: {boolean} - -Enables the event loop delay sample timer. Returns `true` if the timer was -started, `false` if it was already started. - -#### `histogram.exceeds` +### `histogram.exceeds` @@ -728,7 +720,7 @@ added: v11.10.0 The number of times the event loop delay exceeded the maximum 1 hour event loop delay threshold. -#### `histogram.max` +### `histogram.max` @@ -737,7 +729,7 @@ added: v11.10.0 The maximum recorded event loop delay. -#### `histogram.mean` +### `histogram.mean` @@ -746,7 +738,7 @@ added: v11.10.0 The mean of the recorded event loop delays. -#### `histogram.min` +### `histogram.min` @@ -755,7 +747,7 @@ added: v11.10.0 The minimum recorded event loop delay. -#### `histogram.percentile(percentile)` +### `histogram.percentile(percentile)` @@ -765,7 +757,7 @@ added: v11.10.0 Returns the value at the given percentile. -#### `histogram.percentiles` +### `histogram.percentiles` @@ -774,14 +766,14 @@ added: v11.10.0 Returns a `Map` object detailing the accumulated percentile distribution. -#### `histogram.reset()` +### `histogram.reset()` Resets the collected histogram data. -#### `histogram.stddev` +### `histogram.stddev` @@ -790,6 +782,56 @@ added: v11.10.0 The standard deviation of the recorded event loop delays. +## Class: `IntervalHistogram extends Histogram` + +A `Histogram` that is periodically updated on a given interval. + +### `histogram.disable()` + + +* Returns: {boolean} + +Disables the update interval timer. Returns `true` if the timer was +stopped, `false` if it was already stopped. + +### `histogram.enable()` + + +* Returns: {boolean} + +Enables the update interval timer. Returns `true` if the timer was +started, `false` if it was already started. + +### Cloning an `IntervalHistogram` + +{IntervalHistogram} instances can be cloned via {MessagePort}. On the receiving +end, the histogram is cloned as a plain {Histogram} object that does not +implement the `enable()` and `disable()` methods. + +## Class: `RecordableHistogram extends Histogram` + + +### `histogram.record(val)` + + +* `val` {number|bigint} The amount to record in the histogram. + +### `histogram.recordDelta()` + + +Calculates the amount of time (in nanoseconds) that has passed since the +previous call to `recordDelta()` and records that amount in the histogram. + ## Examples ### Measuring the duration of async operations diff --git a/doc/api/worker_threads.md b/doc/api/worker_threads.md index 4c6e590c2a788b..95167da0a91666 100644 --- a/doc/api/worker_threads.md +++ b/doc/api/worker_threads.md @@ -474,6 +474,9 @@ are part of the channel. - -* `type`: {string} The intended use of the generated secret key. Currently - accepted values are `'hmac'` and `'aes'`. -* `options`: {Object} - * `length`: {number} The bit length of the key to generate. - * If `type` is `'hmac'`, the minimum is 1, and the maximum length is - 231-1. If the value is not a multiple of 8, the generated - key will be truncated to `Math.floor(length / 8)`. - * If `type` is `'aes'`, the length must be one of `128`, `192`, or `256`. -* Returns: {KeyObject} - -Synchronously generates a new random secret key of the given `length`. The -`type` will determine which validations will be performed on the `length`. - -```js -const { generateKeySync } = require('crypto'); - -const key = generateKeySync('hmac', 64); -console.log(key.export().toString('hex')); // e89..........41e -``` - ### `crypto.generateKeyPair(type, options, callback)` + +* `type`: {string} The intended use of the generated secret key. Currently + accepted values are `'hmac'` and `'aes'`. +* `options`: {Object} + * `length`: {number} The bit length of the key to generate. + * If `type` is `'hmac'`, the minimum is 1, and the maximum length is + 231-1. If the value is not a multiple of 8, the generated + key will be truncated to `Math.floor(length / 8)`. + * If `type` is `'aes'`, the length must be one of `128`, `192`, or `256`. +* Returns: {KeyObject} + +Synchronously generates a new random secret key of the given `length`. The +`type` will determine which validations will be performed on the `length`. + +```js +const { generateKeySync } = require('crypto'); + +const key = generateKeySync('hmac', 64); +console.log(key.export().toString('hex')); // e89..........41e +``` + ### `crypto.generatePrime(size[, options[, callback]])` - -* Returns: {string[]} An array with the names of the supported cipher - algorithms. - -```js -const ciphers = crypto.getCiphers(); -console.log(ciphers); // ['aes-128-cbc', 'aes-128-ccm', ...] -``` - ### `crypto.getCipherInfo(nameOrNid[, options])` + +* Returns: {string[]} An array with the names of the supported cipher + algorithms. + +```js +const ciphers = crypto.getCiphers(); +console.log(ciphers); // ['aes-128-cbc', 'aes-128-ccm', ...] +``` + ### `crypto.getCurves()` @@ -3310,7 +3310,7 @@ changes: `crypto.constants`, which may be: `crypto.constants.RSA_NO_PADDING` or `crypto.constants.RSA_PKCS1_PADDING`. * `encoding` {string} The string encoding to use when `buffer`, `key`, - or 'passphrase` are strings. + or `passphrase` are strings. * `buffer` {string|ArrayBuffer|Buffer|TypedArray|DataView} * Returns: {Buffer} A new `Buffer` with the decrypted content. @@ -3362,7 +3362,7 @@ changes: `crypto.constants.RSA_PKCS1_PADDING`, or `crypto.constants.RSA_PKCS1_OAEP_PADDING`. * `encoding` {string} The string encoding to use when `buffer`, `key`, - `oaepLabel`, or 'passphrase` are strings. + `oaepLabel`, or `passphrase` are strings. * `buffer` {string|ArrayBuffer|Buffer|TypedArray|DataView} * Returns: {Buffer} A new `Buffer` with the encrypted content. From c188466a1855793bebb9048c6de73c6fbdd203eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Mon, 8 Feb 2021 14:26:31 +0100 Subject: [PATCH 094/108] doc: fix quotes in stream docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/37269 Reviewed-By: Richard Lau Reviewed-By: Beth Griggs Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Darshan Sen Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Rich Trott --- doc/api/stream.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/stream.md b/doc/api/stream.md index 1d6b811c655fd5..1e14d3c6c29729 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -2169,7 +2169,7 @@ user programs. be written. The `chunk` will be a string if the `Writable` was created with the `decodeStrings` option set to `false` and a string was passed to `write()`. * `encoding` {string} The character encoding of the `chunk`. If `chunk` is - a `Buffer`, the `encoding` will be `'buffer`. + a `Buffer`, the `encoding` will be `'buffer'`. * `callback` {Function} A callback function (optionally with an error argument) to be invoked when processing is complete for the supplied chunks. From dd054ca37fc2c91a3a5ba34ef73c54d60539fc6d Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Tue, 9 Feb 2021 22:41:47 +0100 Subject: [PATCH 095/108] doc: optimize HTML rendering Defer rendering sections of docs until they are displayed on the user's screen. PR-URL: https://github.com/nodejs/node/pull/37301 Reviewed-By: Darshan Sen Reviewed-By: James M Snell --- doc/api_assets/style.css | 5 +++++ tools/doc/allhtml.js | 4 ++-- tools/doc/html.js | 14 +++++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/doc/api_assets/style.css b/doc/api_assets/style.css index d2e79444a93558..e1538d962e2545 100644 --- a/doc/api_assets/style.css +++ b/doc/api_assets/style.css @@ -372,6 +372,11 @@ dd + dt.pre { #apicontent { padding-top: 1rem; } + +#apicontent section { + content-visibility: auto; + contain-intrinsic-size: 1px 5000px; +} #apicontent .line { width: calc(50% - 1rem); diff --git a/tools/doc/allhtml.js b/tools/doc/allhtml.js index 93197f812e10c6..fad74e59d5cb2e 100644 --- a/tools/doc/allhtml.js +++ b/tools/doc/allhtml.js @@ -36,8 +36,8 @@ for (const link of toc.match(//g)) { contents += data.slice(0, match.index) .replace(/[\s\S]*?id="toc"[^>]*>\s*<\w+>.*?<\/\w+>\s*(
    \s*)?/, ''); - apicontent += data.slice(match.index + match[0].length) - .replace(/[\s\S]*/, '') + apicontent += '
    ' + data.slice(match.index + match[0].length) + .replace(/[\s\S]*/, '
    ') .replace(/ { return htmlFiles.includes(href) ? '/); From c160d88c9e42ab86ba6ec3c0b48b9fc9e4ee7458 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Fri, 12 Feb 2021 17:27:06 -0500 Subject: [PATCH 096/108] buffer: add @@toStringTag to Blob This commit adds the toStringTag to the Blob class to match the behavior of Chrome and Firefox. PR-URL: https://github.com/nodejs/node/pull/37336 Fixes: https://github.com/nodejs/node/issues/37337 Reviewed-By: Luigi Pinca Reviewed-By: Antoine du Hamel Reviewed-By: James M Snell --- lib/internal/blob.js | 7 +++++++ test/parallel/test-blob.js | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/lib/internal/blob.js b/lib/internal/blob.js index 82b375da783fe1..a4d89e126617fe 100644 --- a/lib/internal/blob.js +++ b/lib/internal/blob.js @@ -2,12 +2,14 @@ const { ArrayFrom, + ObjectDefineProperty, ObjectSetPrototypeOf, PromiseResolve, RegExpPrototypeTest, StringPrototypeToLowerCase, Symbol, SymbolIterator, + SymbolToStringTag, Uint8Array, } = primordials; @@ -217,6 +219,11 @@ class Blob extends JSTransferable { } } +ObjectDefineProperty(Blob.prototype, SymbolToStringTag, { + configurable: true, + value: 'Blob', +}); + InternalBlob.prototype.constructor = Blob; ObjectSetPrototypeOf( InternalBlob.prototype, diff --git a/test/parallel/test-blob.js b/test/parallel/test-blob.js index 795d4bb6fbdff5..fdcc0177279dad 100644 --- a/test/parallel/test-blob.js +++ b/test/parallel/test-blob.js @@ -184,3 +184,14 @@ assert.throws(() => new Blob(['test', 1]), { const b = new Blob(['hello'], { type: '\x01' }); assert.strictEqual(b.type, ''); } + +{ + const descriptor = + Object.getOwnPropertyDescriptor(Blob.prototype, Symbol.toStringTag); + assert.deepStrictEqual(descriptor, { + configurable: true, + enumerable: false, + value: 'Blob', + writable: false + }); +} From b2b64113b19074691084700a6a9a6b1cede93435 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Fri, 12 Feb 2021 18:39:10 -0500 Subject: [PATCH 097/108] tools: update ESLint to 7.20.0 Update ESLint to 7.20.0 PR-URL: https://github.com/nodejs/node/pull/37339 Reviewed-By: Luigi Pinca Reviewed-By: Antoine du Hamel Reviewed-By: Rich Trott --- tools/node_modules/eslint/README.md | 6 +- .../eslint/lib/cli-engine/cli-engine.js | 2 +- .../eslint/lib/init/autoconfig.js | 2 +- .../node_modules/eslint/lib/linter/linter.js | 4 +- .../eslint/lib/linter/node-event-generator.js | 6 +- .../eslint/lib/rules/no-unused-expressions.js | 13 +- .../node_modules/@babel/highlight/README.md | 2 +- .../@babel/highlight/lib/index.js | 79 +- .../@babel/highlight/package.json | 7 +- .../eslint/node_modules/esprima/package.json | 4 +- .../node_modules/esquery/dist/esquery.esm.js | 904 ++-- .../esquery/dist/esquery.esm.min.js | 2 +- .../node_modules/esquery/dist/esquery.js | 904 ++-- .../node_modules/esquery/dist/esquery.lite.js | 3995 +++++++++++++++++ .../esquery/dist/esquery.lite.min.js | 2 + .../node_modules/esquery/dist/esquery.min.js | 2 +- .../eslint/node_modules/esquery/package.json | 2 +- .../eslint/node_modules/esquery/parser.js | 472 +- .../table/node_modules/ajv/README.md | 103 +- .../table/node_modules/ajv/dist/ajv.js | 5 +- .../ajv/dist/compile/codegen/scope.js | 12 +- .../node_modules/ajv/dist/compile/context.js | 2 +- .../ajv/dist/compile/error_classes.js | 4 +- .../node_modules/ajv/dist/compile/errors.js | 30 +- .../node_modules/ajv/dist/compile/index.js | 13 +- .../node_modules/ajv/dist/compile/rules.js | 4 +- .../ajv/dist/compile/subschema.js | 8 +- .../ajv/dist/compile/timestamp.js | 29 + .../ajv/dist/compile/validate/index.js | 2 + .../ajv/dist/compile/validate/iterate.js | 3 +- .../table/node_modules/ajv/dist/core.js | 9 +- .../table/node_modules/ajv/dist/jtd.js | 44 + .../node_modules/ajv/dist/refs/jtd-schema.js | 118 + .../node_modules/ajv/dist/standalone/index.js | 24 +- .../applicator/additionalProperties.js | 10 +- .../ajv/dist/vocabularies/applicator/anyOf.js | 29 +- .../ajv/dist/vocabularies/applicator/items.js | 29 +- .../applicator/patternProperties.js | 1 - .../vocabularies/applicator/properties.js | 1 - .../vocabularies/applicator/propertyNames.js | 1 - .../ajv/dist/vocabularies/code.js | 53 +- .../ajv/dist/vocabularies/core/index.js | 1 + .../ajv/dist/vocabularies/core/ref.js | 1 - .../dist/vocabularies/jtd/discriminator.js | 38 + .../ajv/dist/vocabularies/jtd/elements.js | 22 + .../ajv/dist/vocabularies/jtd/enum.js | 41 + .../ajv/dist/vocabularies/jtd/index.js | 30 + .../ajv/dist/vocabularies/jtd/metadata.js | 25 + .../ajv/dist/vocabularies/jtd/nullable.js | 22 + .../vocabularies/jtd/optionalProperties.js | 14 + .../ajv/dist/vocabularies/jtd/properties.js | 123 + .../ajv/dist/vocabularies/jtd/ref.js | 64 + .../ajv/dist/vocabularies/jtd/type.js | 47 + .../ajv/dist/vocabularies/jtd/union.js | 11 + .../ajv/dist/vocabularies/jtd/values.js | 43 + .../unevaluated/unevaluatedProperties.js | 1 - .../ajv/dist/vocabularies/validation/index.js | 1 + .../table/node_modules/ajv/package.json | 8 +- .../eslint/node_modules/which/package.json | 2 +- tools/node_modules/eslint/package.json | 6 +- 60 files changed, 6412 insertions(+), 1030 deletions(-) create mode 100644 tools/node_modules/eslint/node_modules/esquery/dist/esquery.lite.js create mode 100644 tools/node_modules/eslint/node_modules/esquery/dist/esquery.lite.min.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/timestamp.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/jtd.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/refs/jtd-schema.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/discriminator.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/elements.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/enum.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/index.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/metadata.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/nullable.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/optionalProperties.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/properties.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/ref.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/type.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/union.js create mode 100644 tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/values.js diff --git a/tools/node_modules/eslint/README.md b/tools/node_modules/eslint/README.md index 624ad9e3adb868..92298bd955f2d8 100644 --- a/tools/node_modules/eslint/README.md +++ b/tools/node_modules/eslint/README.md @@ -280,10 +280,10 @@ The following companies, organizations, and individuals support ESLint's ongoing

    Platinum Sponsors

    -

    Automattic

    Gold Sponsors

    -

    Chrome's Web Framework & Tools Performance Fund Shopify Salesforce Airbnb Microsoft FOSS Fund Sponsorships

    Silver Sponsors

    +

    Automattic

    Gold Sponsors

    +

    Nx (by Nrwl) Chrome's Web Framework & Tools Performance Fund Shopify Salesforce Airbnb Microsoft FOSS Fund Sponsorships

    Silver Sponsors

    Retool Liftoff AMP Project

    Bronze Sponsors

    -

    Streamat The Standard Daily Writers Per Hour February 2021 calendar Buy.Fineproxy.Org Anagram Solver Bugsnag Stability Monitoring Mixpanel VPS Server Icons8: free icons, photos, illustrations, and music Discord ThemeIsle Fire Stick Tricks

    +

    Writers Per Hour March 2021 calendar Buy.Fineproxy.Org Anagram Solver Bugsnag Stability Monitoring Mixpanel VPS Server Icons8: free icons, photos, illustrations, and music Discord ThemeIsle Fire Stick Tricks

    ## Technology Sponsors diff --git a/tools/node_modules/eslint/lib/cli-engine/cli-engine.js b/tools/node_modules/eslint/lib/cli-engine/cli-engine.js index 9a414061501e2d..3fd4f5ee1e3f0e 100644 --- a/tools/node_modules/eslint/lib/cli-engine/cli-engine.js +++ b/tools/node_modules/eslint/lib/cli-engine/cli-engine.js @@ -531,7 +531,7 @@ function directoryExists(resolvedPath) { try { return fs.statSync(resolvedPath).isDirectory(); } catch (error) { - if (error && error.code === "ENOENT") { + if (error && (error.code === "ENOENT" || error.code === "ENOTDIR")) { return false; } throw error; diff --git a/tools/node_modules/eslint/lib/init/autoconfig.js b/tools/node_modules/eslint/lib/init/autoconfig.js index 0ace177aa16a42..19d016a54c18d5 100644 --- a/tools/node_modules/eslint/lib/init/autoconfig.js +++ b/tools/node_modules/eslint/lib/init/autoconfig.js @@ -85,7 +85,7 @@ class Registry { * @returns {void} */ populateFromCoreRules() { - const rulesConfig = configRule.createCoreRuleConfigs(); + const rulesConfig = configRule.createCoreRuleConfigs(/* noDeprecated = */ true); this.rules = makeRegistryItems(rulesConfig); } diff --git a/tools/node_modules/eslint/lib/linter/linter.js b/tools/node_modules/eslint/lib/linter/linter.js index 5c1a8d78aa1df0..adb5c215590251 100644 --- a/tools/node_modules/eslint/lib/linter/linter.js +++ b/tools/node_modules/eslint/lib/linter/linter.js @@ -942,7 +942,9 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser }); // only run code path analyzer if the top level node is "Program", skip otherwise - const eventGenerator = nodeQueue[0].node.type === "Program" ? new CodePathAnalyzer(new NodeEventGenerator(emitter)) : new NodeEventGenerator(emitter); + const eventGenerator = nodeQueue[0].node.type === "Program" + ? new CodePathAnalyzer(new NodeEventGenerator(emitter, { visitorKeys: sourceCode.visitorKeys, fallback: Traverser.getKeys })) + : new NodeEventGenerator(emitter, { visitorKeys: sourceCode.visitorKeys, fallback: Traverser.getKeys }); nodeQueue.forEach(traversalInfo => { currentNode = traversalInfo.node; diff --git a/tools/node_modules/eslint/lib/linter/node-event-generator.js b/tools/node_modules/eslint/lib/linter/node-event-generator.js index 6f3b2513998dcd..0b4e50fc4b71ba 100644 --- a/tools/node_modules/eslint/lib/linter/node-event-generator.js +++ b/tools/node_modules/eslint/lib/linter/node-event-generator.js @@ -208,10 +208,12 @@ class NodeEventGenerator { * An SafeEmitter which is the destination of events. This emitter must already * have registered listeners for all of the events that it needs to listen for. * (See lib/linter/safe-emitter.js for more details on `SafeEmitter`.) + * @param {ESQueryOptions} esqueryOptions `esquery` options for traversing custom nodes. * @returns {NodeEventGenerator} new instance */ - constructor(emitter) { + constructor(emitter, esqueryOptions) { this.emitter = emitter; + this.esqueryOptions = esqueryOptions; this.currentAncestry = []; this.enterSelectorsByNodeType = new Map(); this.exitSelectorsByNodeType = new Map(); @@ -250,7 +252,7 @@ class NodeEventGenerator { * @returns {void} */ applySelector(node, selector) { - if (esquery.matches(node, selector.parsedSelector, this.currentAncestry)) { + if (esquery.matches(node, selector.parsedSelector, this.currentAncestry, this.esqueryOptions)) { this.emitter.emit(selector.rawSelector, node); } } diff --git a/tools/node_modules/eslint/lib/rules/no-unused-expressions.js b/tools/node_modules/eslint/lib/rules/no-unused-expressions.js index 882a0fd1c11276..58c9b33418794b 100644 --- a/tools/node_modules/eslint/lib/rules/no-unused-expressions.js +++ b/tools/node_modules/eslint/lib/rules/no-unused-expressions.js @@ -50,6 +50,10 @@ module.exports = { allowTaggedTemplates: { type: "boolean", default: false + }, + enforceForJSX: { + type: "boolean", + default: false } }, additionalProperties: false @@ -65,7 +69,8 @@ module.exports = { const config = context.options[0] || {}, allowShortCircuit = config.allowShortCircuit || false, allowTernary = config.allowTernary || false, - allowTaggedTemplates = config.allowTaggedTemplates || false; + allowTaggedTemplates = config.allowTaggedTemplates || false, + enforceForJSX = config.enforceForJSX || false; // eslint-disable-next-line jsdoc/require-description /** @@ -140,6 +145,12 @@ module.exports = { }, FunctionExpression: alwaysTrue, Identifier: alwaysTrue, + JSXElement() { + return enforceForJSX; + }, + JSXFragment() { + return enforceForJSX; + }, Literal: alwaysTrue, LogicalExpression(node) { if (allowShortCircuit) { diff --git a/tools/node_modules/eslint/node_modules/@babel/highlight/README.md b/tools/node_modules/eslint/node_modules/@babel/highlight/README.md index 72dae6094590f3..f8887ad2ca470c 100644 --- a/tools/node_modules/eslint/node_modules/@babel/highlight/README.md +++ b/tools/node_modules/eslint/node_modules/@babel/highlight/README.md @@ -2,7 +2,7 @@ > Syntax highlight JavaScript strings for output in terminals. -See our website [@babel/highlight](https://babeljs.io/docs/en/next/babel-highlight.html) for more information. +See our website [@babel/highlight](https://babeljs.io/docs/en/babel-highlight) for more information. ## Install diff --git a/tools/node_modules/eslint/node_modules/@babel/highlight/lib/index.js b/tools/node_modules/eslint/node_modules/@babel/highlight/lib/index.js index b0d1be7f553b64..3cd2aed36a98eb 100644 --- a/tools/node_modules/eslint/node_modules/@babel/highlight/lib/index.js +++ b/tools/node_modules/eslint/node_modules/@babel/highlight/lib/index.js @@ -7,7 +7,7 @@ exports.shouldHighlight = shouldHighlight; exports.getChalk = getChalk; exports.default = highlight; -var _jsTokens = _interopRequireWildcard(require("js-tokens")); +var jsTokensNs = _interopRequireWildcard(require("js-tokens")); var _helperValidatorIdentifier = require("@babel/helper-validator-identifier"); @@ -19,11 +19,13 @@ function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } +const sometimesKeywords = new Set(["as", "async", "from", "get", "of", "set"]); + function getDefs(chalk) { return { keyword: chalk.cyan, capitalized: chalk.yellow, - jsx_tag: chalk.yellow, + jsxIdentifier: chalk.yellow, punctuator: chalk.yellow, number: chalk.magenta, string: chalk.green, @@ -34,49 +36,70 @@ function getDefs(chalk) { } const NEWLINE = /\r\n|[\n\r\u2028\u2029]/; -const JSX_TAG = /^[a-z][\w-]*$/i; const BRACKET = /^[()[\]{}]$/; - -function getTokenType(match) { - const [offset, text] = match.slice(-2); - const token = (0, _jsTokens.matchToToken)(match); - - if (token.type === "name") { - if ((0, _helperValidatorIdentifier.isKeyword)(token.value) || (0, _helperValidatorIdentifier.isReservedWord)(token.value)) { - return "keyword"; +let tokenize; +{ + const { + matchToToken + } = jsTokensNs; + const JSX_TAG = /^[a-z][\w-]*$/i; + + const getTokenType = function (token, offset, text) { + if (token.type === "name") { + if ((0, _helperValidatorIdentifier.isKeyword)(token.value) || (0, _helperValidatorIdentifier.isStrictReservedWord)(token.value, true) || sometimesKeywords.has(token.value)) { + return "keyword"; + } + + if (JSX_TAG.test(token.value) && (text[offset - 1] === "<" || text.substr(offset - 2, 2) == " colorize(str)).join("\n"); + highlighted += value.split(NEWLINE).map(str => colorize(str)).join("\n"); } else { - return args[0]; + highlighted += value; } - }); + } + + return highlighted; } function shouldHighlight(options) { diff --git a/tools/node_modules/eslint/node_modules/@babel/highlight/package.json b/tools/node_modules/eslint/node_modules/@babel/highlight/package.json index f126bb84aadcc8..5f693c7180050b 100644 --- a/tools/node_modules/eslint/node_modules/@babel/highlight/package.json +++ b/tools/node_modules/eslint/node_modules/@babel/highlight/package.json @@ -8,7 +8,7 @@ }, "bundleDependencies": false, "dependencies": { - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/helper-validator-identifier": "^7.12.11", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -17,8 +17,7 @@ "devDependencies": { "strip-ansi": "^4.0.0" }, - "gitHead": "7fd40d86a0d03ff0e9c3ea16b29689945433d4df", - "homepage": "https://babeljs.io/", + "homepage": "https://babel.dev/docs/en/next/babel-highlight", "license": "MIT", "main": "lib/index.js", "name": "@babel/highlight", @@ -30,5 +29,5 @@ "url": "git+https://github.com/babel/babel.git", "directory": "packages/babel-highlight" }, - "version": "7.10.4" + "version": "7.12.13" } \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/esprima/package.json b/tools/node_modules/eslint/node_modules/esprima/package.json index 4dfb4a142e7aa5..03d154ee722a3c 100644 --- a/tools/node_modules/eslint/node_modules/esprima/package.json +++ b/tools/node_modules/eslint/node_modules/esprima/package.json @@ -4,8 +4,8 @@ "email": "ariya.hidayat@gmail.com" }, "bin": { - "esparse": "./bin/esparse.js", - "esvalidate": "./bin/esvalidate.js" + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "bugs": { "url": "https://github.com/jquery/esprima/issues" diff --git a/tools/node_modules/eslint/node_modules/esquery/dist/esquery.esm.js b/tools/node_modules/eslint/node_modules/esquery/dist/esquery.esm.js index 88abe0ffb91100..7a62b8b39ada4e 100644 --- a/tools/node_modules/eslint/node_modules/esquery/dist/esquery.esm.js +++ b/tools/node_modules/eslint/node_modules/esquery/dist/esquery.esm.js @@ -66,7 +66,7 @@ function _unsupportedIterableToArray(o, minLen) { if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; - if (n === "Map" || n === "Set") return Array.from(n); + if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } @@ -86,6 +86,63 @@ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } +function _createForOfIteratorHelper(o, allowArrayLike) { + var it; + + if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + var i = 0; + + var F = function () {}; + + return { + s: F, + n: function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }, + e: function (e) { + throw e; + }, + f: F + }; + } + + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var normalCompletion = true, + didErr = false, + err; + return { + s: function () { + it = o[Symbol.iterator](); + }, + n: function () { + var step = it.next(); + normalCompletion = step.done; + return step; + }, + e: function (e) { + didErr = true; + err = e; + }, + f: function () { + try { + if (!normalCompletion && it.return != null) it.return(); + } finally { + if (didErr) throw err; + } + } + }; +} + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function createCommonjsModule(fn, module) { @@ -182,6 +239,7 @@ var estraverse = createCommonjsModule(function (module, exports) { BreakStatement: 'BreakStatement', CallExpression: 'CallExpression', CatchClause: 'CatchClause', + ChainExpression: 'ChainExpression', ClassBody: 'ClassBody', ClassDeclaration: 'ClassDeclaration', ClassExpression: 'ClassExpression', @@ -260,6 +318,7 @@ var estraverse = createCommonjsModule(function (module, exports) { BreakStatement: ['label'], CallExpression: ['callee', 'arguments'], CatchClause: ['param', 'body'], + ChainExpression: ['expression'], ClassBody: ['body'], ClassDeclaration: ['id', 'superClass', 'body'], ClassExpression: ['id', 'superClass', 'body'], @@ -1126,7 +1185,10 @@ var parser = createCommonjsModule(function (module) { peg$c41 = peg$classExpectation([">", "<"], false, false), peg$c42 = ".", peg$c43 = peg$literalExpectation(".", false), - peg$c44 = function peg$c44(name, op, value) { + peg$c44 = function peg$c44(a, as) { + return [].concat.apply([a], as).join(''); + }, + peg$c45 = function peg$c45(name, op, value) { return { type: 'attribute', name: name, @@ -1134,35 +1196,35 @@ var parser = createCommonjsModule(function (module) { value: value }; }, - peg$c45 = function peg$c45(name) { + peg$c46 = function peg$c46(name) { return { type: 'attribute', name: name }; }, - peg$c46 = "\"", - peg$c47 = peg$literalExpectation("\"", false), - peg$c48 = /^[^\\"]/, - peg$c49 = peg$classExpectation(["\\", "\""], true, false), - peg$c50 = "\\", - peg$c51 = peg$literalExpectation("\\", false), - peg$c52 = peg$anyExpectation(), - peg$c53 = function peg$c53(a, b) { + peg$c47 = "\"", + peg$c48 = peg$literalExpectation("\"", false), + peg$c49 = /^[^\\"]/, + peg$c50 = peg$classExpectation(["\\", "\""], true, false), + peg$c51 = "\\", + peg$c52 = peg$literalExpectation("\\", false), + peg$c53 = peg$anyExpectation(), + peg$c54 = function peg$c54(a, b) { return a + b; }, - peg$c54 = function peg$c54(d) { + peg$c55 = function peg$c55(d) { return { type: 'literal', value: strUnescape(d.join('')) }; }, - peg$c55 = "'", - peg$c56 = peg$literalExpectation("'", false), - peg$c57 = /^[^\\']/, - peg$c58 = peg$classExpectation(["\\", "'"], true, false), - peg$c59 = /^[0-9]/, - peg$c60 = peg$classExpectation([["0", "9"]], false, false), - peg$c61 = function peg$c61(a, b) { + peg$c56 = "'", + peg$c57 = peg$literalExpectation("'", false), + peg$c58 = /^[^\\']/, + peg$c59 = peg$classExpectation(["\\", "'"], true, false), + peg$c60 = /^[0-9]/, + peg$c61 = peg$classExpectation([["0", "9"]], false, false), + peg$c62 = function peg$c62(a, b) { // Can use `a.flat().join('')` once supported var leadingDecimals = a ? [].concat.apply([], a).join('') : ''; return { @@ -1170,37 +1232,37 @@ var parser = createCommonjsModule(function (module) { value: parseFloat(leadingDecimals + b.join('')) }; }, - peg$c62 = function peg$c62(i) { + peg$c63 = function peg$c63(i) { return { type: 'literal', value: i }; }, - peg$c63 = "type(", - peg$c64 = peg$literalExpectation("type(", false), - peg$c65 = /^[^ )]/, - peg$c66 = peg$classExpectation([" ", ")"], true, false), - peg$c67 = ")", - peg$c68 = peg$literalExpectation(")", false), - peg$c69 = function peg$c69(t) { + peg$c64 = "type(", + peg$c65 = peg$literalExpectation("type(", false), + peg$c66 = /^[^ )]/, + peg$c67 = peg$classExpectation([" ", ")"], true, false), + peg$c68 = ")", + peg$c69 = peg$literalExpectation(")", false), + peg$c70 = function peg$c70(t) { return { type: 'type', value: t.join('') }; }, - peg$c70 = /^[imsu]/, - peg$c71 = peg$classExpectation(["i", "m", "s", "u"], false, false), - peg$c72 = "/", - peg$c73 = peg$literalExpectation("/", false), - peg$c74 = /^[^\/]/, - peg$c75 = peg$classExpectation(["/"], true, false), - peg$c76 = function peg$c76(d, flgs) { + peg$c71 = /^[imsu]/, + peg$c72 = peg$classExpectation(["i", "m", "s", "u"], false, false), + peg$c73 = "/", + peg$c74 = peg$literalExpectation("/", false), + peg$c75 = /^[^\/]/, + peg$c76 = peg$classExpectation(["/"], true, false), + peg$c77 = function peg$c77(d, flgs) { return { type: 'regexp', value: new RegExp(d.join(''), flgs ? flgs.join('') : '') }; }, - peg$c77 = function peg$c77(i, is) { + peg$c78 = function peg$c78(i, is) { return { type: 'field', name: is.reduce(function (memo, p) { @@ -1208,63 +1270,63 @@ var parser = createCommonjsModule(function (module) { }, i) }; }, - peg$c78 = ":not(", - peg$c79 = peg$literalExpectation(":not(", false), - peg$c80 = function peg$c80(ss) { + peg$c79 = ":not(", + peg$c80 = peg$literalExpectation(":not(", false), + peg$c81 = function peg$c81(ss) { return { type: 'not', selectors: ss }; }, - peg$c81 = ":matches(", - peg$c82 = peg$literalExpectation(":matches(", false), - peg$c83 = function peg$c83(ss) { + peg$c82 = ":matches(", + peg$c83 = peg$literalExpectation(":matches(", false), + peg$c84 = function peg$c84(ss) { return { type: 'matches', selectors: ss }; }, - peg$c84 = ":has(", - peg$c85 = peg$literalExpectation(":has(", false), - peg$c86 = function peg$c86(ss) { + peg$c85 = ":has(", + peg$c86 = peg$literalExpectation(":has(", false), + peg$c87 = function peg$c87(ss) { return { type: 'has', selectors: ss }; }, - peg$c87 = ":first-child", - peg$c88 = peg$literalExpectation(":first-child", false), - peg$c89 = function peg$c89() { + peg$c88 = ":first-child", + peg$c89 = peg$literalExpectation(":first-child", false), + peg$c90 = function peg$c90() { return nth(1); }, - peg$c90 = ":last-child", - peg$c91 = peg$literalExpectation(":last-child", false), - peg$c92 = function peg$c92() { + peg$c91 = ":last-child", + peg$c92 = peg$literalExpectation(":last-child", false), + peg$c93 = function peg$c93() { return nthLast(1); }, - peg$c93 = ":nth-child(", - peg$c94 = peg$literalExpectation(":nth-child(", false), - peg$c95 = function peg$c95(n) { + peg$c94 = ":nth-child(", + peg$c95 = peg$literalExpectation(":nth-child(", false), + peg$c96 = function peg$c96(n) { return nth(parseInt(n.join(''), 10)); }, - peg$c96 = ":nth-last-child(", - peg$c97 = peg$literalExpectation(":nth-last-child(", false), - peg$c98 = function peg$c98(n) { + peg$c97 = ":nth-last-child(", + peg$c98 = peg$literalExpectation(":nth-last-child(", false), + peg$c99 = function peg$c99(n) { return nthLast(parseInt(n.join(''), 10)); }, - peg$c99 = ":", - peg$c100 = peg$literalExpectation(":", false), - peg$c101 = "statement", - peg$c102 = peg$literalExpectation("statement", true), - peg$c103 = "expression", - peg$c104 = peg$literalExpectation("expression", true), - peg$c105 = "declaration", - peg$c106 = peg$literalExpectation("declaration", true), - peg$c107 = "function", - peg$c108 = peg$literalExpectation("function", true), - peg$c109 = "pattern", - peg$c110 = peg$literalExpectation("pattern", true), - peg$c111 = function peg$c111(c) { + peg$c100 = ":", + peg$c101 = peg$literalExpectation(":", false), + peg$c102 = "statement", + peg$c103 = peg$literalExpectation("statement", true), + peg$c104 = "expression", + peg$c105 = peg$literalExpectation("expression", true), + peg$c106 = "declaration", + peg$c107 = peg$literalExpectation("declaration", true), + peg$c108 = "function", + peg$c109 = peg$literalExpectation("function", true), + peg$c110 = "pattern", + peg$c111 = peg$literalExpectation("pattern", true), + peg$c112 = function peg$c112(c) { return { type: 'class', name: c @@ -2295,7 +2357,7 @@ var parser = createCommonjsModule(function (module) { } function peg$parseattrName() { - var s0, s1, s2; + var s0, s1, s2, s3, s4, s5; var key = peg$currPos * 30 + 13, cached = peg$resultsCache[key]; @@ -2305,49 +2367,81 @@ var parser = createCommonjsModule(function (module) { } s0 = peg$currPos; - s1 = []; - s2 = peg$parseidentifierName(); + s1 = peg$parseidentifierName(); + + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; - if (s2 === peg$FAILED) { if (input.charCodeAt(peg$currPos) === 46) { - s2 = peg$c42; + s4 = peg$c42; peg$currPos++; } else { - s2 = peg$FAILED; + s4 = peg$FAILED; { peg$fail(peg$c43); } } - } - if (s2 !== peg$FAILED) { - while (s2 !== peg$FAILED) { - s1.push(s2); - s2 = peg$parseidentifierName(); + if (s4 !== peg$FAILED) { + s5 = peg$parseidentifierName(); - if (s2 === peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 46) { - s2 = peg$c42; - peg$currPos++; - } else { - s2 = peg$FAILED; + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } - { - peg$fail(peg$c43); - } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 46) { + s4 = peg$c42; + peg$currPos++; + } else { + s4 = peg$FAILED; + + { + peg$fail(peg$c43); } } + + if (s4 !== peg$FAILED) { + s5 = peg$parseidentifierName(); + + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } } - } else { - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - s1 = peg$c6(s1); + if (s2 !== peg$FAILED) { + s1 = peg$c44(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; } - s0 = s1; peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 @@ -2385,7 +2479,7 @@ var parser = createCommonjsModule(function (module) { } if (s5 !== peg$FAILED) { - s1 = peg$c44(s1, s3, s5); + s1 = peg$c45(s1, s3, s5); s0 = s1; } else { peg$currPos = s0; @@ -2433,7 +2527,7 @@ var parser = createCommonjsModule(function (module) { } if (s5 !== peg$FAILED) { - s1 = peg$c44(s1, s3, s5); + s1 = peg$c45(s1, s3, s5); s0 = s1; } else { peg$currPos = s0; @@ -2461,7 +2555,7 @@ var parser = createCommonjsModule(function (module) { s1 = peg$parseattrName(); if (s1 !== peg$FAILED) { - s1 = peg$c45(s1); + s1 = peg$c46(s1); } s0 = s1; @@ -2488,27 +2582,27 @@ var parser = createCommonjsModule(function (module) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 34) { - s1 = peg$c46; + s1 = peg$c47; peg$currPos++; } else { s1 = peg$FAILED; { - peg$fail(peg$c47); + peg$fail(peg$c48); } } if (s1 !== peg$FAILED) { s2 = []; - if (peg$c48.test(input.charAt(peg$currPos))) { + if (peg$c49.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c49); + peg$fail(peg$c50); } } @@ -2516,13 +2610,13 @@ var parser = createCommonjsModule(function (module) { s3 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s4 = peg$c50; + s4 = peg$c51; peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c51); + peg$fail(peg$c52); } } @@ -2534,12 +2628,12 @@ var parser = createCommonjsModule(function (module) { s5 = peg$FAILED; { - peg$fail(peg$c52); + peg$fail(peg$c53); } } if (s5 !== peg$FAILED) { - s4 = peg$c53(s4, s5); + s4 = peg$c54(s4, s5); s3 = s4; } else { peg$currPos = s3; @@ -2554,14 +2648,14 @@ var parser = createCommonjsModule(function (module) { while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c48.test(input.charAt(peg$currPos))) { + if (peg$c49.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c49); + peg$fail(peg$c50); } } @@ -2569,13 +2663,13 @@ var parser = createCommonjsModule(function (module) { s3 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s4 = peg$c50; + s4 = peg$c51; peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c51); + peg$fail(peg$c52); } } @@ -2587,12 +2681,12 @@ var parser = createCommonjsModule(function (module) { s5 = peg$FAILED; { - peg$fail(peg$c52); + peg$fail(peg$c53); } } if (s5 !== peg$FAILED) { - s4 = peg$c53(s4, s5); + s4 = peg$c54(s4, s5); s3 = s4; } else { peg$currPos = s3; @@ -2607,18 +2701,18 @@ var parser = createCommonjsModule(function (module) { if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s3 = peg$c46; + s3 = peg$c47; peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c47); + peg$fail(peg$c48); } } if (s3 !== peg$FAILED) { - s1 = peg$c54(s2); + s1 = peg$c55(s2); s0 = s1; } else { peg$currPos = s0; @@ -2637,27 +2731,27 @@ var parser = createCommonjsModule(function (module) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 39) { - s1 = peg$c55; + s1 = peg$c56; peg$currPos++; } else { s1 = peg$FAILED; { - peg$fail(peg$c56); + peg$fail(peg$c57); } } if (s1 !== peg$FAILED) { s2 = []; - if (peg$c57.test(input.charAt(peg$currPos))) { + if (peg$c58.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c58); + peg$fail(peg$c59); } } @@ -2665,13 +2759,13 @@ var parser = createCommonjsModule(function (module) { s3 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s4 = peg$c50; + s4 = peg$c51; peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c51); + peg$fail(peg$c52); } } @@ -2683,12 +2777,12 @@ var parser = createCommonjsModule(function (module) { s5 = peg$FAILED; { - peg$fail(peg$c52); + peg$fail(peg$c53); } } if (s5 !== peg$FAILED) { - s4 = peg$c53(s4, s5); + s4 = peg$c54(s4, s5); s3 = s4; } else { peg$currPos = s3; @@ -2703,14 +2797,14 @@ var parser = createCommonjsModule(function (module) { while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c57.test(input.charAt(peg$currPos))) { + if (peg$c58.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c58); + peg$fail(peg$c59); } } @@ -2718,13 +2812,13 @@ var parser = createCommonjsModule(function (module) { s3 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s4 = peg$c50; + s4 = peg$c51; peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c51); + peg$fail(peg$c52); } } @@ -2736,12 +2830,12 @@ var parser = createCommonjsModule(function (module) { s5 = peg$FAILED; { - peg$fail(peg$c52); + peg$fail(peg$c53); } } if (s5 !== peg$FAILED) { - s4 = peg$c53(s4, s5); + s4 = peg$c54(s4, s5); s3 = s4; } else { peg$currPos = s3; @@ -2756,18 +2850,18 @@ var parser = createCommonjsModule(function (module) { if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 39) { - s3 = peg$c55; + s3 = peg$c56; peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c56); + peg$fail(peg$c57); } } if (s3 !== peg$FAILED) { - s1 = peg$c54(s2); + s1 = peg$c55(s2); s0 = s1; } else { peg$currPos = s0; @@ -2804,28 +2898,28 @@ var parser = createCommonjsModule(function (module) { s1 = peg$currPos; s2 = []; - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } } @@ -2861,14 +2955,14 @@ var parser = createCommonjsModule(function (module) { if (s1 !== peg$FAILED) { s2 = []; - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } @@ -2876,14 +2970,14 @@ var parser = createCommonjsModule(function (module) { while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } } @@ -2892,7 +2986,7 @@ var parser = createCommonjsModule(function (module) { } if (s2 !== peg$FAILED) { - s1 = peg$c61(s1, s2); + s1 = peg$c62(s1, s2); s0 = s1; } else { peg$currPos = s0; @@ -2924,7 +3018,7 @@ var parser = createCommonjsModule(function (module) { s1 = peg$parseidentifierName(); if (s1 !== peg$FAILED) { - s1 = peg$c62(s1); + s1 = peg$c63(s1); } s0 = s1; @@ -2947,14 +3041,14 @@ var parser = createCommonjsModule(function (module) { s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c63) { - s1 = peg$c63; + if (input.substr(peg$currPos, 5) === peg$c64) { + s1 = peg$c64; peg$currPos += 5; } else { s1 = peg$FAILED; { - peg$fail(peg$c64); + peg$fail(peg$c65); } } @@ -2964,14 +3058,14 @@ var parser = createCommonjsModule(function (module) { if (s2 !== peg$FAILED) { s3 = []; - if (peg$c65.test(input.charAt(peg$currPos))) { + if (peg$c66.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c66); + peg$fail(peg$c67); } } @@ -2979,14 +3073,14 @@ var parser = createCommonjsModule(function (module) { while (s4 !== peg$FAILED) { s3.push(s4); - if (peg$c65.test(input.charAt(peg$currPos))) { + if (peg$c66.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c66); + peg$fail(peg$c67); } } } @@ -2999,18 +3093,18 @@ var parser = createCommonjsModule(function (module) { if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; { - peg$fail(peg$c68); + peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { - s1 = peg$c69(s3); + s1 = peg$c70(s3); s0 = s1; } else { peg$currPos = s0; @@ -3052,14 +3146,14 @@ var parser = createCommonjsModule(function (module) { s0 = []; - if (peg$c70.test(input.charAt(peg$currPos))) { + if (peg$c71.test(input.charAt(peg$currPos))) { s1 = input.charAt(peg$currPos); peg$currPos++; } else { s1 = peg$FAILED; { - peg$fail(peg$c71); + peg$fail(peg$c72); } } @@ -3067,14 +3161,14 @@ var parser = createCommonjsModule(function (module) { while (s1 !== peg$FAILED) { s0.push(s1); - if (peg$c70.test(input.charAt(peg$currPos))) { + if (peg$c71.test(input.charAt(peg$currPos))) { s1 = input.charAt(peg$currPos); peg$currPos++; } else { s1 = peg$FAILED; { - peg$fail(peg$c71); + peg$fail(peg$c72); } } } @@ -3102,27 +3196,27 @@ var parser = createCommonjsModule(function (module) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 47) { - s1 = peg$c72; + s1 = peg$c73; peg$currPos++; } else { s1 = peg$FAILED; { - peg$fail(peg$c73); + peg$fail(peg$c74); } } if (s1 !== peg$FAILED) { s2 = []; - if (peg$c74.test(input.charAt(peg$currPos))) { + if (peg$c75.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c75); + peg$fail(peg$c76); } } @@ -3130,14 +3224,14 @@ var parser = createCommonjsModule(function (module) { while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c74.test(input.charAt(peg$currPos))) { + if (peg$c75.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c75); + peg$fail(peg$c76); } } } @@ -3147,13 +3241,13 @@ var parser = createCommonjsModule(function (module) { if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 47) { - s3 = peg$c72; + s3 = peg$c73; peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c73); + peg$fail(peg$c74); } } @@ -3165,7 +3259,7 @@ var parser = createCommonjsModule(function (module) { } if (s4 !== peg$FAILED) { - s1 = peg$c76(s2, s4); + s1 = peg$c77(s2, s4); s0 = s1; } else { peg$currPos = s0; @@ -3279,7 +3373,7 @@ var parser = createCommonjsModule(function (module) { } if (s3 !== peg$FAILED) { - s1 = peg$c77(s2, s3); + s1 = peg$c78(s2, s3); s0 = s1; } else { peg$currPos = s0; @@ -3313,14 +3407,14 @@ var parser = createCommonjsModule(function (module) { s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c78) { - s1 = peg$c78; + if (input.substr(peg$currPos, 5) === peg$c79) { + s1 = peg$c79; peg$currPos += 5; } else { s1 = peg$FAILED; { - peg$fail(peg$c79); + peg$fail(peg$c80); } } @@ -3335,18 +3429,18 @@ var parser = createCommonjsModule(function (module) { if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; { - peg$fail(peg$c68); + peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { - s1 = peg$c80(s3); + s1 = peg$c81(s3); s0 = s1; } else { peg$currPos = s0; @@ -3388,14 +3482,14 @@ var parser = createCommonjsModule(function (module) { s0 = peg$currPos; - if (input.substr(peg$currPos, 9) === peg$c81) { - s1 = peg$c81; + if (input.substr(peg$currPos, 9) === peg$c82) { + s1 = peg$c82; peg$currPos += 9; } else { s1 = peg$FAILED; { - peg$fail(peg$c82); + peg$fail(peg$c83); } } @@ -3410,18 +3504,18 @@ var parser = createCommonjsModule(function (module) { if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; { - peg$fail(peg$c68); + peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { - s1 = peg$c83(s3); + s1 = peg$c84(s3); s0 = s1; } else { peg$currPos = s0; @@ -3463,14 +3557,14 @@ var parser = createCommonjsModule(function (module) { s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c84) { - s1 = peg$c84; + if (input.substr(peg$currPos, 5) === peg$c85) { + s1 = peg$c85; peg$currPos += 5; } else { s1 = peg$FAILED; { - peg$fail(peg$c85); + peg$fail(peg$c86); } } @@ -3485,18 +3579,18 @@ var parser = createCommonjsModule(function (module) { if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; { - peg$fail(peg$c68); + peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { - s1 = peg$c86(s3); + s1 = peg$c87(s3); s0 = s1; } else { peg$currPos = s0; @@ -3538,19 +3632,19 @@ var parser = createCommonjsModule(function (module) { s0 = peg$currPos; - if (input.substr(peg$currPos, 12) === peg$c87) { - s1 = peg$c87; + if (input.substr(peg$currPos, 12) === peg$c88) { + s1 = peg$c88; peg$currPos += 12; } else { s1 = peg$FAILED; { - peg$fail(peg$c88); + peg$fail(peg$c89); } } if (s1 !== peg$FAILED) { - s1 = peg$c89(); + s1 = peg$c90(); } s0 = s1; @@ -3573,19 +3667,19 @@ var parser = createCommonjsModule(function (module) { s0 = peg$currPos; - if (input.substr(peg$currPos, 11) === peg$c90) { - s1 = peg$c90; + if (input.substr(peg$currPos, 11) === peg$c91) { + s1 = peg$c91; peg$currPos += 11; } else { s1 = peg$FAILED; { - peg$fail(peg$c91); + peg$fail(peg$c92); } } if (s1 !== peg$FAILED) { - s1 = peg$c92(); + s1 = peg$c93(); } s0 = s1; @@ -3608,14 +3702,14 @@ var parser = createCommonjsModule(function (module) { s0 = peg$currPos; - if (input.substr(peg$currPos, 11) === peg$c93) { - s1 = peg$c93; + if (input.substr(peg$currPos, 11) === peg$c94) { + s1 = peg$c94; peg$currPos += 11; } else { s1 = peg$FAILED; { - peg$fail(peg$c94); + peg$fail(peg$c95); } } @@ -3625,14 +3719,14 @@ var parser = createCommonjsModule(function (module) { if (s2 !== peg$FAILED) { s3 = []; - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } @@ -3640,14 +3734,14 @@ var parser = createCommonjsModule(function (module) { while (s4 !== peg$FAILED) { s3.push(s4); - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } } @@ -3660,18 +3754,18 @@ var parser = createCommonjsModule(function (module) { if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; { - peg$fail(peg$c68); + peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { - s1 = peg$c95(s3); + s1 = peg$c96(s3); s0 = s1; } else { peg$currPos = s0; @@ -3713,14 +3807,14 @@ var parser = createCommonjsModule(function (module) { s0 = peg$currPos; - if (input.substr(peg$currPos, 16) === peg$c96) { - s1 = peg$c96; + if (input.substr(peg$currPos, 16) === peg$c97) { + s1 = peg$c97; peg$currPos += 16; } else { s1 = peg$FAILED; { - peg$fail(peg$c97); + peg$fail(peg$c98); } } @@ -3730,14 +3824,14 @@ var parser = createCommonjsModule(function (module) { if (s2 !== peg$FAILED) { s3 = []; - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } @@ -3745,14 +3839,14 @@ var parser = createCommonjsModule(function (module) { while (s4 !== peg$FAILED) { s3.push(s4); - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } } @@ -3765,18 +3859,18 @@ var parser = createCommonjsModule(function (module) { if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; { - peg$fail(peg$c68); + peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { - s1 = peg$c98(s3); + s1 = peg$c99(s3); s0 = s1; } else { peg$currPos = s0; @@ -3819,73 +3913,73 @@ var parser = createCommonjsModule(function (module) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 58) { - s1 = peg$c99; + s1 = peg$c100; peg$currPos++; } else { s1 = peg$FAILED; { - peg$fail(peg$c100); + peg$fail(peg$c101); } } if (s1 !== peg$FAILED) { - if (input.substr(peg$currPos, 9).toLowerCase() === peg$c101) { + if (input.substr(peg$currPos, 9).toLowerCase() === peg$c102) { s2 = input.substr(peg$currPos, 9); peg$currPos += 9; } else { s2 = peg$FAILED; { - peg$fail(peg$c102); + peg$fail(peg$c103); } } if (s2 === peg$FAILED) { - if (input.substr(peg$currPos, 10).toLowerCase() === peg$c103) { + if (input.substr(peg$currPos, 10).toLowerCase() === peg$c104) { s2 = input.substr(peg$currPos, 10); peg$currPos += 10; } else { s2 = peg$FAILED; { - peg$fail(peg$c104); + peg$fail(peg$c105); } } if (s2 === peg$FAILED) { - if (input.substr(peg$currPos, 11).toLowerCase() === peg$c105) { + if (input.substr(peg$currPos, 11).toLowerCase() === peg$c106) { s2 = input.substr(peg$currPos, 11); peg$currPos += 11; } else { s2 = peg$FAILED; { - peg$fail(peg$c106); + peg$fail(peg$c107); } } if (s2 === peg$FAILED) { - if (input.substr(peg$currPos, 8).toLowerCase() === peg$c107) { + if (input.substr(peg$currPos, 8).toLowerCase() === peg$c108) { s2 = input.substr(peg$currPos, 8); peg$currPos += 8; } else { s2 = peg$FAILED; { - peg$fail(peg$c108); + peg$fail(peg$c109); } } if (s2 === peg$FAILED) { - if (input.substr(peg$currPos, 7).toLowerCase() === peg$c109) { + if (input.substr(peg$currPos, 7).toLowerCase() === peg$c110) { s2 = input.substr(peg$currPos, 7); peg$currPos += 7; } else { s2 = peg$FAILED; { - peg$fail(peg$c110); + peg$fail(peg$c111); } } } @@ -3894,7 +3988,7 @@ var parser = createCommonjsModule(function (module) { } if (s2 !== peg$FAILED) { - s1 = peg$c111(s2); + s1 = peg$c112(s2); s0 = s1; } else { peg$currPos = s0; @@ -4020,12 +4114,23 @@ var RIGHT_SIDE = 'RIGHT_SIDE'; function getPath(obj, key) { var keys = key.split('.'); - for (var i = 0; i < keys.length; i++) { - if (obj == null) { - return obj; - } + var _iterator = _createForOfIteratorHelper(keys), + _step; + + try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var _key = _step.value; + + if (obj == null) { + return obj; + } - obj = obj[keys[i]]; + obj = obj[_key]; + } + } catch (err) { + _iterator.e(err); + } finally { + _iterator.f(); } return obj; @@ -4053,10 +4158,21 @@ function inPath(node, ancestor, path) { var remainingPath = path.slice(1); if (Array.isArray(field)) { - for (var i = 0, l = field.length; i < l; ++i) { - if (inPath(node, field[i], remainingPath)) { - return true; + var _iterator2 = _createForOfIteratorHelper(field), + _step2; + + try { + for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { + var component = _step2.value; + + if (inPath(node, component, remainingPath)) { + return true; + } } + } catch (err) { + _iterator2.e(err); + } finally { + _iterator2.f(); } return false; @@ -4064,19 +4180,32 @@ function inPath(node, ancestor, path) { return inPath(node, field, remainingPath); } } +/** + * @callback TraverseOptionFallback + * @param {external:AST} node The given node. + * @returns {string[]} An array of visitor keys for the given node. + */ + +/** + * @typedef {object} ESQueryOptions + * @property { { [nodeType: string]: string[] } } [visitorKeys] By passing `visitorKeys` mapping, we can extend the properties of the nodes that traverse the node. + * @property {TraverseOptionFallback} [fallback] By passing `fallback` option, we can control the properties of traversing nodes when encountering unknown nodes. + */ + /** * Given a `node` and its ancestors, determine if `node` is matched * by `selector`. * @param {?external:AST} node * @param {?SelectorAST} selector * @param {external:AST[]} [ancestry=[]] + * @param {ESQueryOptions} [options] * @throws {Error} Unknowns (operator, class name, selector type, or * selector value type) * @returns {boolean} */ -function matches(node, selector, ancestry) { +function matches(node, selector, ancestry, options) { if (!selector) { return true; } @@ -4104,28 +4233,61 @@ function matches(node, selector, ancestry) { } case 'matches': - for (var i = 0, l = selector.selectors.length; i < l; ++i) { - if (matches(node, selector.selectors[i], ancestry)) { - return true; + var _iterator3 = _createForOfIteratorHelper(selector.selectors), + _step3; + + try { + for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { + var sel = _step3.value; + + if (matches(node, sel, ancestry, options)) { + return true; + } } + } catch (err) { + _iterator3.e(err); + } finally { + _iterator3.f(); } return false; case 'compound': - for (var _i = 0, _l = selector.selectors.length; _i < _l; ++_i) { - if (!matches(node, selector.selectors[_i], ancestry)) { - return false; + var _iterator4 = _createForOfIteratorHelper(selector.selectors), + _step4; + + try { + for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { + var _sel = _step4.value; + + if (!matches(node, _sel, ancestry, options)) { + return false; + } } + } catch (err) { + _iterator4.e(err); + } finally { + _iterator4.f(); } return true; case 'not': - for (var _i2 = 0, _l2 = selector.selectors.length; _i2 < _l2; ++_i2) { - if (matches(node, selector.selectors[_i2], ancestry)) { - return false; + var _iterator5 = _createForOfIteratorHelper(selector.selectors), + _step5; + + try { + for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) { + var _sel2 = _step5.value; + + if (matches(node, _sel2, ancestry, options)) { + return false; + } } + } catch (err) { + _iterator5.e(err); + } finally { + _iterator5.f(); } return true; @@ -4135,27 +4297,38 @@ function matches(node, selector, ancestry) { var _ret = function () { var collector = []; - var _loop = function _loop(_i3, _l3) { - var a = []; - estraverse.traverse(node, { - enter: function enter(node, parent) { - if (parent != null) { - a.unshift(parent); - } - - if (matches(node, selector.selectors[_i3], a)) { - collector.push(node); - } - }, - leave: function leave() { - a.shift(); - }, - fallback: 'iteration' - }); - }; + var _iterator6 = _createForOfIteratorHelper(selector.selectors), + _step6; + + try { + var _loop = function _loop() { + var sel = _step6.value; + var a = []; + estraverse.traverse(node, { + enter: function enter(node, parent) { + if (parent != null) { + a.unshift(parent); + } - for (var _i3 = 0, _l3 = selector.selectors.length; _i3 < _l3; ++_i3) { - _loop(_i3); + if (matches(node, sel, a, options)) { + collector.push(node); + } + }, + leave: function leave() { + a.shift(); + }, + keys: options && options.visitorKeys, + fallback: options && options.fallback || 'iteration' + }); + }; + + for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) { + _loop(); + } + } catch (err) { + _iterator6.e(err); + } finally { + _iterator6.f(); } return { @@ -4167,16 +4340,16 @@ function matches(node, selector, ancestry) { } case 'child': - if (matches(node, selector.right, ancestry)) { - return matches(ancestry[0], selector.left, ancestry.slice(1)); + if (matches(node, selector.right, ancestry, options)) { + return matches(ancestry[0], selector.left, ancestry.slice(1), options); } return false; case 'descendant': - if (matches(node, selector.right, ancestry)) { - for (var _i4 = 0, _l4 = ancestry.length; _i4 < _l4; ++_i4) { - if (matches(ancestry[_i4], selector.left, ancestry.slice(_i4 + 1))) { + if (matches(node, selector.right, ancestry, options)) { + for (var i = 0, l = ancestry.length; i < l; ++i) { + if (matches(ancestry[i], selector.left, ancestry.slice(i + 1), options)) { return true; } } @@ -4237,20 +4410,20 @@ function matches(node, selector, ancestry) { } case 'sibling': - return matches(node, selector.right, ancestry) && sibling(node, selector.left, ancestry, LEFT_SIDE) || selector.left.subject && matches(node, selector.left, ancestry) && sibling(node, selector.right, ancestry, RIGHT_SIDE); + return matches(node, selector.right, ancestry, options) && sibling(node, selector.left, ancestry, LEFT_SIDE, options) || selector.left.subject && matches(node, selector.left, ancestry, options) && sibling(node, selector.right, ancestry, RIGHT_SIDE, options); case 'adjacent': - return matches(node, selector.right, ancestry) && adjacent(node, selector.left, ancestry, LEFT_SIDE) || selector.right.subject && matches(node, selector.left, ancestry) && adjacent(node, selector.right, ancestry, RIGHT_SIDE); + return matches(node, selector.right, ancestry, options) && adjacent(node, selector.left, ancestry, LEFT_SIDE, options) || selector.right.subject && matches(node, selector.left, ancestry, options) && adjacent(node, selector.right, ancestry, RIGHT_SIDE, options); case 'nth-child': - return matches(node, selector.right, ancestry) && nthChild(node, ancestry, function () { + return matches(node, selector.right, ancestry, options) && nthChild(node, ancestry, function () { return selector.index.value - 1; - }); + }, options); case 'nth-last-child': - return matches(node, selector.right, ancestry) && nthChild(node, ancestry, function (length) { + return matches(node, selector.right, ancestry, options) && nthChild(node, ancestry, function (length) { return length - selector.index.value; - }); + }, options); case 'class': switch (selector.name.toLowerCase()) { @@ -4277,6 +4450,44 @@ function matches(node, selector, ancestry) { throw new Error("Unknown selector type: ".concat(selector.type)); } +/** + * Get visitor keys of a given node. + * @param {external:AST} node The AST node to get keys. + * @param {ESQueryOptions|undefined} options + * @returns {string[]} Visitor keys of the node. + */ + + +function getVisitorKeys(node, options) { + var nodeType = node.type; + + if (options && options.visitorKeys && options.visitorKeys[nodeType]) { + return options.visitorKeys[nodeType]; + } + + if (estraverse.VisitorKeys[nodeType]) { + return estraverse.VisitorKeys[nodeType]; + } + + if (options && typeof options.fallback === 'function') { + return options.fallback(node); + } // 'iteration' fallback + + + return Object.keys(node).filter(function (key) { + return key !== 'type'; + }); +} +/** + * Check whether the given value is an ASTNode or not. + * @param {any} node The value to check. + * @returns {boolean} `true` if the value is an ASTNode. + */ + + +function isNode(node) { + return node !== null && _typeof(node) === 'object' && typeof node.type === 'string'; +} /** * Determines if the given node has a sibling that matches the * given selector. @@ -4284,11 +4495,12 @@ function matches(node, selector, ancestry) { * @param {SelectorSequenceAST} selector * @param {external:AST[]} ancestry * @param {Side} side + * @param {ESQueryOptions|undefined} options * @returns {boolean} */ -function sibling(node, selector, ancestry, side) { +function sibling(node, selector, ancestry, side, options) { var _ancestry = _slicedToArray(ancestry, 1), parent = _ancestry[0]; @@ -4296,35 +4508,45 @@ function sibling(node, selector, ancestry, side) { return false; } - var keys = estraverse.VisitorKeys[parent.type]; + var keys = getVisitorKeys(parent, options); - for (var i = 0, l = keys.length; i < l; ++i) { - var listProp = parent[keys[i]]; + var _iterator7 = _createForOfIteratorHelper(keys), + _step7; - if (Array.isArray(listProp)) { - var startIndex = listProp.indexOf(node); + try { + for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) { + var key = _step7.value; + var listProp = parent[key]; - if (startIndex < 0) { - continue; - } + if (Array.isArray(listProp)) { + var startIndex = listProp.indexOf(node); - var lowerBound = void 0, - upperBound = void 0; + if (startIndex < 0) { + continue; + } - if (side === LEFT_SIDE) { - lowerBound = 0; - upperBound = startIndex; - } else { - lowerBound = startIndex + 1; - upperBound = listProp.length; - } + var lowerBound = void 0, + upperBound = void 0; - for (var k = lowerBound; k < upperBound; ++k) { - if (matches(listProp[k], selector, ancestry)) { - return true; + if (side === LEFT_SIDE) { + lowerBound = 0; + upperBound = startIndex; + } else { + lowerBound = startIndex + 1; + upperBound = listProp.length; + } + + for (var k = lowerBound; k < upperBound; ++k) { + if (isNode(listProp[k]) && matches(listProp[k], selector, ancestry, options)) { + return true; + } } } } + } catch (err) { + _iterator7.e(err); + } finally { + _iterator7.f(); } return false; @@ -4336,11 +4558,12 @@ function sibling(node, selector, ancestry, side) { * @param {SelectorSequenceAST} selector * @param {external:AST[]} ancestry * @param {Side} side + * @param {ESQueryOptions|undefined} options * @returns {boolean} */ -function adjacent(node, selector, ancestry, side) { +function adjacent(node, selector, ancestry, side, options) { var _ancestry2 = _slicedToArray(ancestry, 1), parent = _ancestry2[0]; @@ -4348,26 +4571,36 @@ function adjacent(node, selector, ancestry, side) { return false; } - var keys = estraverse.VisitorKeys[parent.type]; + var keys = getVisitorKeys(parent, options); - for (var i = 0, l = keys.length; i < l; ++i) { - var listProp = parent[keys[i]]; + var _iterator8 = _createForOfIteratorHelper(keys), + _step8; - if (Array.isArray(listProp)) { - var idx = listProp.indexOf(node); + try { + for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) { + var key = _step8.value; + var listProp = parent[key]; - if (idx < 0) { - continue; - } + if (Array.isArray(listProp)) { + var idx = listProp.indexOf(node); - if (side === LEFT_SIDE && idx > 0 && matches(listProp[idx - 1], selector, ancestry)) { - return true; - } + if (idx < 0) { + continue; + } - if (side === RIGHT_SIDE && idx < listProp.length - 1 && matches(listProp[idx + 1], selector, ancestry)) { - return true; + if (side === LEFT_SIDE && idx > 0 && isNode(listProp[idx - 1]) && matches(listProp[idx - 1], selector, ancestry, options)) { + return true; + } + + if (side === RIGHT_SIDE && idx < listProp.length - 1 && isNode(listProp[idx + 1]) && matches(listProp[idx + 1], selector, ancestry, options)) { + return true; + } } } + } catch (err) { + _iterator8.e(err); + } finally { + _iterator8.f(); } return false; @@ -4384,11 +4617,12 @@ function adjacent(node, selector, ancestry, side) { * @param {external:AST} node * @param {external:AST[]} ancestry * @param {IndexFunction} idxFn + * @param {ESQueryOptions|undefined} options * @returns {boolean} */ -function nthChild(node, ancestry, idxFn) { +function nthChild(node, ancestry, idxFn, options) { var _ancestry3 = _slicedToArray(ancestry, 1), parent = _ancestry3[0]; @@ -4396,18 +4630,28 @@ function nthChild(node, ancestry, idxFn) { return false; } - var keys = estraverse.VisitorKeys[parent.type]; + var keys = getVisitorKeys(parent, options); - for (var i = 0, l = keys.length; i < l; ++i) { - var listProp = parent[keys[i]]; + var _iterator9 = _createForOfIteratorHelper(keys), + _step9; - if (Array.isArray(listProp)) { - var idx = listProp.indexOf(node); + try { + for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) { + var key = _step9.value; + var listProp = parent[key]; - if (idx >= 0 && idx === idxFn(listProp.length)) { - return true; + if (Array.isArray(listProp)) { + var idx = listProp.indexOf(node); + + if (idx >= 0 && idx === idxFn(listProp.length)) { + return true; + } } } + } catch (err) { + _iterator9.e(err); + } finally { + _iterator9.f(); } return false; @@ -4432,8 +4676,8 @@ function subjects(selector, ancestor) { var results = selector.subject ? [ancestor] : []; - for (var _i5 = 0, _Object$entries = _objectEntries(selector); _i5 < _Object$entries.length; _i5++) { - var _Object$entries$_i = _slicedToArray(_Object$entries[_i5], 2), + for (var _i = 0, _Object$entries = _objectEntries(selector); _i < _Object$entries.length; _i++) { + var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), p = _Object$entries$_i[0], sel = _Object$entries$_i[1]; @@ -4455,11 +4699,12 @@ function subjects(selector, ancestor) { * @param {external:AST} ast * @param {?SelectorAST} selector * @param {TraverseVisitor} visitor + * @param {ESQueryOptions} [options] * @returns {external:AST[]} */ -function traverse(ast, selector, visitor) { +function traverse(ast, selector, visitor, options) { if (!selector) { return; } @@ -4472,17 +4717,17 @@ function traverse(ast, selector, visitor) { ancestry.unshift(parent); } - if (matches(node, selector, ancestry)) { + if (matches(node, selector, ancestry, options)) { if (altSubjects.length) { for (var i = 0, l = altSubjects.length; i < l; ++i) { - if (matches(node, altSubjects[i], ancestry)) { + if (matches(node, altSubjects[i], ancestry, options)) { visitor(node, parent, ancestry); } for (var k = 0, m = ancestry.length; k < m; ++k) { var succeedingAncestry = ancestry.slice(k + 1); - if (matches(ancestry[k], altSubjects[i], succeedingAncestry)) { + if (matches(ancestry[k], altSubjects[i], succeedingAncestry, options)) { visitor(ancestry[k], parent, succeedingAncestry); } } @@ -4495,7 +4740,8 @@ function traverse(ast, selector, visitor) { leave: function leave() { ancestry.shift(); }, - fallback: 'iteration' + keys: options && options.visitorKeys, + fallback: options && options.fallback || 'iteration' }); } /** @@ -4503,15 +4749,16 @@ function traverse(ast, selector, visitor) { * match the selector. * @param {external:AST} ast * @param {?SelectorAST} selector + * @param {ESQueryOptions} [options] * @returns {external:AST[]} */ -function match(ast, selector) { +function match(ast, selector, options) { var results = []; traverse(ast, selector, function (node) { results.push(node); - }); + }, options); return results; } /** @@ -4528,12 +4775,13 @@ function parse(selector) { * Query the code AST using the selector string. * @param {external:AST} ast * @param {string} selector + * @param {ESQueryOptions} [options] * @returns {external:AST[]} */ -function query(ast, selector) { - return match(ast, parse(selector)); +function query(ast, selector, options) { + return match(ast, parse(selector), options); } query.parse = parse; diff --git a/tools/node_modules/eslint/node_modules/esquery/dist/esquery.esm.min.js b/tools/node_modules/eslint/node_modules/esquery/dist/esquery.esm.min.js index 474e093dcc8c93..cd5ac34bd428d3 100644 --- a/tools/node_modules/eslint/node_modules/esquery/dist/esquery.esm.min.js +++ b/tools/node_modules/eslint/node_modules/esquery/dist/esquery.esm.min.js @@ -1,2 +1,2 @@ -function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}function t(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if("undefined"==typeof Symbol||!(Symbol.iterator in Object(e)))return;var r=[],n=!0,o=!1,a=void 0;try{for(var s,i=e[Symbol.iterator]();!(n=(s=i.next()).done)&&(r.push(s.value),!t||r.length!==t);n=!0);}catch(e){o=!0,a=e}finally{try{n||null==i.return||i.return()}finally{if(o)throw a}}return r}(e,t)||n(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function r(e){return function(e){if(Array.isArray(e))return o(e)}(e)||function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}(e)||n(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function n(e,t){if(e){if("string"==typeof e)return o(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(r):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?o(e,t):void 0}}function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0;--r)if(e[r].node===t)return!0;return!1}function y(e,t){return(new p).traverse(e,t)}function m(e,t){var r;return r=function(e,t){var r,n,o,a;for(n=e.length,o=0;n;)t(e[a=o+(r=n>>>1)])?n=r:(o=a+1,n-=r+1);return o}(t,(function(t){return t.range[0]>e.range[0]})),e.extendedRange=[e.range[0],e.range[1]],r!==t.length&&(e.extendedRange[1]=t[r].range[0]),(r-=1)>=0&&(e.extendedRange[0]=t[r].range[1]),e}return r={AssignmentExpression:"AssignmentExpression",AssignmentPattern:"AssignmentPattern",ArrayExpression:"ArrayExpression",ArrayPattern:"ArrayPattern",ArrowFunctionExpression:"ArrowFunctionExpression",AwaitExpression:"AwaitExpression",BlockStatement:"BlockStatement",BinaryExpression:"BinaryExpression",BreakStatement:"BreakStatement",CallExpression:"CallExpression",CatchClause:"CatchClause",ClassBody:"ClassBody",ClassDeclaration:"ClassDeclaration",ClassExpression:"ClassExpression",ComprehensionBlock:"ComprehensionBlock",ComprehensionExpression:"ComprehensionExpression",ConditionalExpression:"ConditionalExpression",ContinueStatement:"ContinueStatement",DebuggerStatement:"DebuggerStatement",DirectiveStatement:"DirectiveStatement",DoWhileStatement:"DoWhileStatement",EmptyStatement:"EmptyStatement",ExportAllDeclaration:"ExportAllDeclaration",ExportDefaultDeclaration:"ExportDefaultDeclaration",ExportNamedDeclaration:"ExportNamedDeclaration",ExportSpecifier:"ExportSpecifier",ExpressionStatement:"ExpressionStatement",ForStatement:"ForStatement",ForInStatement:"ForInStatement",ForOfStatement:"ForOfStatement",FunctionDeclaration:"FunctionDeclaration",FunctionExpression:"FunctionExpression",GeneratorExpression:"GeneratorExpression",Identifier:"Identifier",IfStatement:"IfStatement",ImportExpression:"ImportExpression",ImportDeclaration:"ImportDeclaration",ImportDefaultSpecifier:"ImportDefaultSpecifier",ImportNamespaceSpecifier:"ImportNamespaceSpecifier",ImportSpecifier:"ImportSpecifier",Literal:"Literal",LabeledStatement:"LabeledStatement",LogicalExpression:"LogicalExpression",MemberExpression:"MemberExpression",MetaProperty:"MetaProperty",MethodDefinition:"MethodDefinition",ModuleSpecifier:"ModuleSpecifier",NewExpression:"NewExpression",ObjectExpression:"ObjectExpression",ObjectPattern:"ObjectPattern",Program:"Program",Property:"Property",RestElement:"RestElement",ReturnStatement:"ReturnStatement",SequenceExpression:"SequenceExpression",SpreadElement:"SpreadElement",Super:"Super",SwitchStatement:"SwitchStatement",SwitchCase:"SwitchCase",TaggedTemplateExpression:"TaggedTemplateExpression",TemplateElement:"TemplateElement",TemplateLiteral:"TemplateLiteral",ThisExpression:"ThisExpression",ThrowStatement:"ThrowStatement",TryStatement:"TryStatement",UnaryExpression:"UnaryExpression",UpdateExpression:"UpdateExpression",VariableDeclaration:"VariableDeclaration",VariableDeclarator:"VariableDeclarator",WhileStatement:"WhileStatement",WithStatement:"WithStatement",YieldExpression:"YieldExpression"},o={AssignmentExpression:["left","right"],AssignmentPattern:["left","right"],ArrayExpression:["elements"],ArrayPattern:["elements"],ArrowFunctionExpression:["params","body"],AwaitExpression:["argument"],BlockStatement:["body"],BinaryExpression:["left","right"],BreakStatement:["label"],CallExpression:["callee","arguments"],CatchClause:["param","body"],ClassBody:["body"],ClassDeclaration:["id","superClass","body"],ClassExpression:["id","superClass","body"],ComprehensionBlock:["left","right"],ComprehensionExpression:["blocks","filter","body"],ConditionalExpression:["test","consequent","alternate"],ContinueStatement:["label"],DebuggerStatement:[],DirectiveStatement:[],DoWhileStatement:["body","test"],EmptyStatement:[],ExportAllDeclaration:["source"],ExportDefaultDeclaration:["declaration"],ExportNamedDeclaration:["declaration","specifiers","source"],ExportSpecifier:["exported","local"],ExpressionStatement:["expression"],ForStatement:["init","test","update","body"],ForInStatement:["left","right","body"],ForOfStatement:["left","right","body"],FunctionDeclaration:["id","params","body"],FunctionExpression:["id","params","body"],GeneratorExpression:["blocks","filter","body"],Identifier:[],IfStatement:["test","consequent","alternate"],ImportExpression:["source"],ImportDeclaration:["specifiers","source"],ImportDefaultSpecifier:["local"],ImportNamespaceSpecifier:["local"],ImportSpecifier:["imported","local"],Literal:[],LabeledStatement:["label","body"],LogicalExpression:["left","right"],MemberExpression:["object","property"],MetaProperty:["meta","property"],MethodDefinition:["key","value"],ModuleSpecifier:[],NewExpression:["callee","arguments"],ObjectExpression:["properties"],ObjectPattern:["properties"],Program:["body"],Property:["key","value"],RestElement:["argument"],ReturnStatement:["argument"],SequenceExpression:["expressions"],SpreadElement:["argument"],Super:[],SwitchStatement:["discriminant","cases"],SwitchCase:["test","consequent"],TaggedTemplateExpression:["tag","quasi"],TemplateElement:[],TemplateLiteral:["quasis","expressions"],ThisExpression:[],ThrowStatement:["argument"],TryStatement:["block","handler","finalizer"],UnaryExpression:["argument"],UpdateExpression:["argument"],VariableDeclaration:["declarations"],VariableDeclarator:["id","init"],WhileStatement:["test","body"],WithStatement:["object","body"],YieldExpression:["argument"]},n={Break:a={},Skip:s={},Remove:i={}},u.prototype.replace=function(e){this.parent[this.key]=e},u.prototype.remove=function(){return Array.isArray(this.parent)?(this.parent.splice(this.key,1),!0):(this.replace(null),!1)},p.prototype.path=function(){var e,t,r,n,o;function a(e,t){if(Array.isArray(t))for(r=0,n=t.length;r=0;)if(g=i[p=x[y]])if(Array.isArray(g)){for(m=g.length;(m-=1)>=0;)if(g[m]&&!d(n,g[m])){if(h(l,x[y]))o=new c(g[m],[p,m],"Property",null);else{if(!f(g[m]))continue;o=new c(g[m],[p,m],null,null)}r.push(o)}}else if(f(g)){if(d(n,g))continue;r.push(new c(g,p,null,null))}}}else if(o=n.pop(),u=this.__execute(t.leave,o),this.__state===a||u===a)return},p.prototype.replace=function(e,t){var r,n,o,l,p,d,y,m,x,g,v,A,b;function E(e){var t,n,o,a;if(e.ref.remove())for(n=e.ref.key,a=e.ref.parent,t=r.length;t--;)if((o=r[t]).ref&&o.ref.parent===a){if(o.ref.key=0;)if(g=o[b=x[y]])if(Array.isArray(g)){for(m=g.length;(m-=1)>=0;)if(g[m]){if(h(l,x[y]))d=new c(g[m],[b,m],"Property",new u(g,m));else{if(!f(g[m]))continue;d=new c(g[m],[b,m],null,new u(g,m))}r.push(d)}}else f(g)&&r.push(new c(g,b,null,new u(o,b)))}}else if(d=n.pop(),void 0!==(p=this.__execute(t.leave,d))&&p!==a&&p!==s&&p!==i&&d.ref.replace(p),this.__state!==i&&p!==i||E(d),this.__state===a||p===a)return A.root;return A.root},t.Syntax=r,t.traverse=y,t.replace=function(e,t){return(new p).replace(e,t)},t.attachComments=function(e,t,r){var o,a,s,i,u=[];if(!e.range)throw new Error("attachComments needs range information");if(!r.length){if(t.length){for(s=0,a=t.length;se.range[0]);)t.extendedRange[1]===e.range[0]?(e.leadingComments||(e.leadingComments=[]),e.leadingComments.push(t),u.splice(i,1)):i+=1;return i===u.length?n.Break:u[i].extendedRange[0]>e.range[1]?n.Skip:void 0}}),i=0,y(e,{leave:function(e){for(var t;ie.range[1]?n.Skip:void 0}}),e},t.VisitorKeys=o,t.VisitorOption=n,t.Controller=p,t.cloneEnvironment=function(){return e({})},t}(t)})),i=a((function(e){e.exports&&(e.exports=function(){function e(t,r,n,o){this.message=t,this.expected=r,this.found=n,this.location=o,this.name="SyntaxError","function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,e)}return function(e,t){function r(){this.constructor=e}r.prototype=t.prototype,e.prototype=new r}(e,Error),e.buildMessage=function(e,t){var r={literal:function(e){return'"'+o(e.text)+'"'},class:function(e){var t,r="";for(t=0;t0){for(t=1,n=1;t<~+.]/,f=xe([" ","[","]",",","(",")",":","#","!","=",">","<","~","+","."],!0,!1),h=function(e){return e.join("")},d=me(">",!1),y=me("~",!1),m=me("+",!1),x=me(",",!1),g=me("!",!1),v=me("*",!1),A=me("#",!1),b=me("[",!1),E=me("]",!1),S=/^[>","<","!"],!1,!1),w=me("=",!1),C=function(e){return(e||"")+"="},P=/^[><]/,k=xe([">","<"],!1,!1),D=me(".",!1),I=function(e,t,r){return{type:"attribute",name:e,operator:t,value:r}},j=me('"',!1),F=/^[^\\"]/,T=xe(["\\",'"'],!0,!1),L=me("\\",!1),R={type:"any"},O=function(e,t){return e+t},B=function(e){return{type:"literal",value:(t=e.join(""),t.replace(/\\(.)/g,(function(e,t){switch(t){case"b":return"\b";case"f":return"\f";case"n":return"\n";case"r":return"\r";case"t":return"\t";case"v":return"\v";default:return t}})))};var t},M=me("'",!1),U=/^[^\\']/,V=xe(["\\","'"],!0,!1),q=/^[0-9]/,N=xe([["0","9"]],!1,!1),W=me("type(",!1),G=/^[^ )]/,z=xe([" ",")"],!0,!1),K=me(")",!1),H=/^[imsu]/,Y=xe(["i","m","s","u"],!1,!1),$=me("/",!1),J=/^[^\/]/,Q=xe(["/"],!0,!1),X=me(":not(",!1),Z=me(":matches(",!1),ee=me(":has(",!1),te=me(":first-child",!1),re=me(":last-child",!1),ne=me(":nth-child(",!1),oe=me(":nth-last-child(",!1),ae=me(":",!1),se=me("statement",!0),ie=me("expression",!0),le=me("declaration",!0),ue=me("function",!0),ce=me("pattern",!0),pe=0,fe=[{line:1,column:1}],he=0,de=[],ye={};if("startRule"in r){if(!(r.startRule in l))throw new Error("Can't start parsing from rule \""+r.startRule+'".');u=l[r.startRule]}function me(e,t){return{type:"literal",text:e,ignoreCase:t}}function xe(e,t,r){return{type:"class",parts:e,inverted:t,ignoreCase:r}}function ge(e){var r,n=fe[e];if(n)return n;for(r=e-1;!fe[r];)r--;for(n={line:(n=fe[r]).line,column:n.column};rhe&&(he=pe,de=[]),de.push(e))}function be(){var e,t,r,n,o=30*pe+0,a=ye[o];return a?(pe=a.nextPos,a.result):(e=pe,(t=Ee())!==i&&(r=we())!==i&&Ee()!==i?e=t=1===(n=r).length?n[0]:{type:"matches",selectors:n}:(pe=e,e=i),e===i&&(e=pe,(t=Ee())!==i&&(t=void 0),e=t),ye[o]={nextPos:pe,result:e},e)}function Ee(){var e,r,n=30*pe+1,o=ye[n];if(o)return pe=o.nextPos,o.result;for(e=[],32===t.charCodeAt(pe)?(r=" ",pe++):(r=i,Ae(c));r!==i;)e.push(r),32===t.charCodeAt(pe)?(r=" ",pe++):(r=i,Ae(c));return ye[n]={nextPos:pe,result:e},e}function Se(){var e,r,n,o=30*pe+2,a=ye[o];if(a)return pe=a.nextPos,a.result;if(r=[],p.test(t.charAt(pe))?(n=t.charAt(pe),pe++):(n=i,Ae(f)),n!==i)for(;n!==i;)r.push(n),p.test(t.charAt(pe))?(n=t.charAt(pe),pe++):(n=i,Ae(f));else r=i;return r!==i&&(r=h(r)),e=r,ye[o]={nextPos:pe,result:e},e}function _e(){var e,r,n,o=30*pe+3,a=ye[o];return a?(pe=a.nextPos,a.result):(e=pe,(r=Ee())!==i?(62===t.charCodeAt(pe)?(n=">",pe++):(n=i,Ae(d)),n!==i&&Ee()!==i?e=r="child":(pe=e,e=i)):(pe=e,e=i),e===i&&(e=pe,(r=Ee())!==i?(126===t.charCodeAt(pe)?(n="~",pe++):(n=i,Ae(y)),n!==i&&Ee()!==i?e=r="sibling":(pe=e,e=i)):(pe=e,e=i),e===i&&(e=pe,(r=Ee())!==i?(43===t.charCodeAt(pe)?(n="+",pe++):(n=i,Ae(m)),n!==i&&Ee()!==i?e=r="adjacent":(pe=e,e=i)):(pe=e,e=i),e===i&&(e=pe,32===t.charCodeAt(pe)?(r=" ",pe++):(r=i,Ae(c)),r!==i&&(n=Ee())!==i?e=r="descendant":(pe=e,e=i)))),ye[o]={nextPos:pe,result:e},e)}function we(){var e,r,n,o,a,s,l,u,c=30*pe+4,p=ye[c];if(p)return pe=p.nextPos,p.result;if(e=pe,(r=Ce())!==i){for(n=[],o=pe,(a=Ee())!==i?(44===t.charCodeAt(pe)?(s=",",pe++):(s=i,Ae(x)),s!==i&&(l=Ee())!==i&&(u=Ce())!==i?o=a=[a,s,l,u]:(pe=o,o=i)):(pe=o,o=i);o!==i;)n.push(o),o=pe,(a=Ee())!==i?(44===t.charCodeAt(pe)?(s=",",pe++):(s=i,Ae(x)),s!==i&&(l=Ee())!==i&&(u=Ce())!==i?o=a=[a,s,l,u]:(pe=o,o=i)):(pe=o,o=i);n!==i?e=r=[r].concat(n.map((function(e){return e[3]}))):(pe=e,e=i)}else pe=e,e=i;return ye[c]={nextPos:pe,result:e},e}function Ce(){var e,t,r,n,o,a,s,l=30*pe+5,u=ye[l];if(u)return pe=u.nextPos,u.result;if(e=pe,(t=Pe())!==i){for(r=[],n=pe,(o=_e())!==i&&(a=Pe())!==i?n=o=[o,a]:(pe=n,n=i);n!==i;)r.push(n),n=pe,(o=_e())!==i&&(a=Pe())!==i?n=o=[o,a]:(pe=n,n=i);r!==i?(s=t,e=t=r.reduce((function(e,t){return{type:t[0],left:e,right:t[1]}}),s)):(pe=e,e=i)}else pe=e,e=i;return ye[l]={nextPos:pe,result:e},e}function Pe(){var e,r,n,o,a,s,l,u=30*pe+6,c=ye[u];if(c)return pe=c.nextPos,c.result;if(e=pe,33===t.charCodeAt(pe)?(r="!",pe++):(r=i,Ae(g)),r===i&&(r=null),r!==i){if(n=[],(o=ke())!==i)for(;o!==i;)n.push(o),o=ke();else n=i;n!==i?(a=r,l=1===(s=n).length?s[0]:{type:"compound",selectors:s},a&&(l.subject=!0),e=r=l):(pe=e,e=i)}else pe=e,e=i;return ye[u]={nextPos:pe,result:e},e}function ke(){var e,r=30*pe+7,n=ye[r];return n?(pe=n.nextPos,n.result):((e=function(){var e,r,n=30*pe+8,o=ye[n];return o?(pe=o.nextPos,o.result):(42===t.charCodeAt(pe)?(r="*",pe++):(r=i,Ae(v)),r!==i&&(r={type:"wildcard",value:r}),e=r,ye[n]={nextPos:pe,result:e},e)}())===i&&(e=function(){var e,r,n,o=30*pe+9,a=ye[o];return a?(pe=a.nextPos,a.result):(e=pe,35===t.charCodeAt(pe)?(r="#",pe++):(r=i,Ae(A)),r===i&&(r=null),r!==i&&(n=Se())!==i?e=r={type:"identifier",value:n}:(pe=e,e=i),ye[o]={nextPos:pe,result:e},e)}())===i&&(e=function(){var e,r,n,o,a=30*pe+10,s=ye[a];return s?(pe=s.nextPos,s.result):(e=pe,91===t.charCodeAt(pe)?(r="[",pe++):(r=i,Ae(b)),r!==i&&Ee()!==i&&(n=function(){var e,r,n,o,a=30*pe+14,s=ye[a];return s?(pe=s.nextPos,s.result):(e=pe,(r=De())!==i&&Ee()!==i&&(n=function(){var e,r,n,o=30*pe+12,a=ye[o];return a?(pe=a.nextPos,a.result):(e=pe,33===t.charCodeAt(pe)?(r="!",pe++):(r=i,Ae(g)),r===i&&(r=null),r!==i?(61===t.charCodeAt(pe)?(n="=",pe++):(n=i,Ae(w)),n!==i?(r=C(r),e=r):(pe=e,e=i)):(pe=e,e=i),ye[o]={nextPos:pe,result:e},e)}())!==i&&Ee()!==i?((o=function(){var e,r,n,o,a,s=30*pe+18,l=ye[s];if(l)return pe=l.nextPos,l.result;if(e=pe,"type("===t.substr(pe,5)?(r="type(",pe+=5):(r=i,Ae(W)),r!==i)if(Ee()!==i){if(n=[],G.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(z)),o!==i)for(;o!==i;)n.push(o),G.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(z));else n=i;n!==i&&(o=Ee())!==i?(41===t.charCodeAt(pe)?(a=")",pe++):(a=i,Ae(K)),a!==i?(r={type:"type",value:n.join("")},e=r):(pe=e,e=i)):(pe=e,e=i)}else pe=e,e=i;else pe=e,e=i;return ye[s]={nextPos:pe,result:e},e}())===i&&(o=function(){var e,r,n,o,a,s,l=30*pe+20,u=ye[l];if(u)return pe=u.nextPos,u.result;if(e=pe,47===t.charCodeAt(pe)?(r="/",pe++):(r=i,Ae($)),r!==i){if(n=[],J.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(Q)),o!==i)for(;o!==i;)n.push(o),J.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(Q));else n=i;n!==i?(47===t.charCodeAt(pe)?(o="/",pe++):(o=i,Ae($)),o!==i?((a=function(){var e,r,n=30*pe+19,o=ye[n];if(o)return pe=o.nextPos,o.result;if(e=[],H.test(t.charAt(pe))?(r=t.charAt(pe),pe++):(r=i,Ae(Y)),r!==i)for(;r!==i;)e.push(r),H.test(t.charAt(pe))?(r=t.charAt(pe),pe++):(r=i,Ae(Y));else e=i;return ye[n]={nextPos:pe,result:e},e}())===i&&(a=null),a!==i?(s=a,r={type:"regexp",value:new RegExp(n.join(""),s?s.join(""):"")},e=r):(pe=e,e=i)):(pe=e,e=i)):(pe=e,e=i)}else pe=e,e=i;return ye[l]={nextPos:pe,result:e},e}()),o!==i?(r=I(r,n,o),e=r):(pe=e,e=i)):(pe=e,e=i),e===i&&(e=pe,(r=De())!==i&&Ee()!==i&&(n=function(){var e,r,n,o=30*pe+11,a=ye[o];return a?(pe=a.nextPos,a.result):(e=pe,S.test(t.charAt(pe))?(r=t.charAt(pe),pe++):(r=i,Ae(_)),r===i&&(r=null),r!==i?(61===t.charCodeAt(pe)?(n="=",pe++):(n=i,Ae(w)),n!==i?(r=C(r),e=r):(pe=e,e=i)):(pe=e,e=i),e===i&&(P.test(t.charAt(pe))?(e=t.charAt(pe),pe++):(e=i,Ae(k))),ye[o]={nextPos:pe,result:e},e)}())!==i&&Ee()!==i?((o=function(){var e,r,n,o,a,s,l=30*pe+15,u=ye[l];if(u)return pe=u.nextPos,u.result;if(e=pe,34===t.charCodeAt(pe)?(r='"',pe++):(r=i,Ae(j)),r!==i){for(n=[],F.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(T)),o===i&&(o=pe,92===t.charCodeAt(pe)?(a="\\",pe++):(a=i,Ae(L)),a!==i?(t.length>pe?(s=t.charAt(pe),pe++):(s=i,Ae(R)),s!==i?(a=O(a,s),o=a):(pe=o,o=i)):(pe=o,o=i));o!==i;)n.push(o),F.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(T)),o===i&&(o=pe,92===t.charCodeAt(pe)?(a="\\",pe++):(a=i,Ae(L)),a!==i?(t.length>pe?(s=t.charAt(pe),pe++):(s=i,Ae(R)),s!==i?(a=O(a,s),o=a):(pe=o,o=i)):(pe=o,o=i));n!==i?(34===t.charCodeAt(pe)?(o='"',pe++):(o=i,Ae(j)),o!==i?(r=B(n),e=r):(pe=e,e=i)):(pe=e,e=i)}else pe=e,e=i;if(e===i)if(e=pe,39===t.charCodeAt(pe)?(r="'",pe++):(r=i,Ae(M)),r!==i){for(n=[],U.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(V)),o===i&&(o=pe,92===t.charCodeAt(pe)?(a="\\",pe++):(a=i,Ae(L)),a!==i?(t.length>pe?(s=t.charAt(pe),pe++):(s=i,Ae(R)),s!==i?(a=O(a,s),o=a):(pe=o,o=i)):(pe=o,o=i));o!==i;)n.push(o),U.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(V)),o===i&&(o=pe,92===t.charCodeAt(pe)?(a="\\",pe++):(a=i,Ae(L)),a!==i?(t.length>pe?(s=t.charAt(pe),pe++):(s=i,Ae(R)),s!==i?(a=O(a,s),o=a):(pe=o,o=i)):(pe=o,o=i));n!==i?(39===t.charCodeAt(pe)?(o="'",pe++):(o=i,Ae(M)),o!==i?(r=B(n),e=r):(pe=e,e=i)):(pe=e,e=i)}else pe=e,e=i;return ye[l]={nextPos:pe,result:e},e}())===i&&(o=function(){var e,r,n,o,a,s,l,u=30*pe+16,c=ye[u];if(c)return pe=c.nextPos,c.result;for(e=pe,r=pe,n=[],q.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(N));o!==i;)n.push(o),q.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(N));if(n!==i?(46===t.charCodeAt(pe)?(o=".",pe++):(o=i,Ae(D)),o!==i?r=n=[n,o]:(pe=r,r=i)):(pe=r,r=i),r===i&&(r=null),r!==i){if(n=[],q.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(N)),o!==i)for(;o!==i;)n.push(o),q.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(N));else n=i;n!==i?(s=n,l=(a=r)?[].concat.apply([],a).join(""):"",r={type:"literal",value:parseFloat(l+s.join(""))},e=r):(pe=e,e=i)}else pe=e,e=i;return ye[u]={nextPos:pe,result:e},e}())===i&&(o=function(){var e,t,r=30*pe+17,n=ye[r];return n?(pe=n.nextPos,n.result):((t=Se())!==i&&(t={type:"literal",value:t}),e=t,ye[r]={nextPos:pe,result:e},e)}()),o!==i?(r=I(r,n,o),e=r):(pe=e,e=i)):(pe=e,e=i),e===i&&(e=pe,(r=De())!==i&&(r={type:"attribute",name:r}),e=r)),ye[a]={nextPos:pe,result:e},e)}())!==i&&Ee()!==i?(93===t.charCodeAt(pe)?(o="]",pe++):(o=i,Ae(E)),o!==i?e=r=n:(pe=e,e=i)):(pe=e,e=i),ye[a]={nextPos:pe,result:e},e)}())===i&&(e=function(){var e,r,n,o,a,s,l,u,c=30*pe+21,p=ye[c];if(p)return pe=p.nextPos,p.result;if(e=pe,46===t.charCodeAt(pe)?(r=".",pe++):(r=i,Ae(D)),r!==i)if((n=Se())!==i){for(o=[],a=pe,46===t.charCodeAt(pe)?(s=".",pe++):(s=i,Ae(D)),s!==i&&(l=Se())!==i?a=s=[s,l]:(pe=a,a=i);a!==i;)o.push(a),a=pe,46===t.charCodeAt(pe)?(s=".",pe++):(s=i,Ae(D)),s!==i&&(l=Se())!==i?a=s=[s,l]:(pe=a,a=i);o!==i?(u=n,r={type:"field",name:o.reduce((function(e,t){return e+t[0]+t[1]}),u)},e=r):(pe=e,e=i)}else pe=e,e=i;else pe=e,e=i;return ye[c]={nextPos:pe,result:e},e}())===i&&(e=function(){var e,r,n,o,a=30*pe+22,s=ye[a];return s?(pe=s.nextPos,s.result):(e=pe,":not("===t.substr(pe,5)?(r=":not(",pe+=5):(r=i,Ae(X)),r!==i&&Ee()!==i&&(n=we())!==i&&Ee()!==i?(41===t.charCodeAt(pe)?(o=")",pe++):(o=i,Ae(K)),o!==i?e=r={type:"not",selectors:n}:(pe=e,e=i)):(pe=e,e=i),ye[a]={nextPos:pe,result:e},e)}())===i&&(e=function(){var e,r,n,o,a=30*pe+23,s=ye[a];return s?(pe=s.nextPos,s.result):(e=pe,":matches("===t.substr(pe,9)?(r=":matches(",pe+=9):(r=i,Ae(Z)),r!==i&&Ee()!==i&&(n=we())!==i&&Ee()!==i?(41===t.charCodeAt(pe)?(o=")",pe++):(o=i,Ae(K)),o!==i?e=r={type:"matches",selectors:n}:(pe=e,e=i)):(pe=e,e=i),ye[a]={nextPos:pe,result:e},e)}())===i&&(e=function(){var e,r,n,o,a=30*pe+24,s=ye[a];return s?(pe=s.nextPos,s.result):(e=pe,":has("===t.substr(pe,5)?(r=":has(",pe+=5):(r=i,Ae(ee)),r!==i&&Ee()!==i&&(n=we())!==i&&Ee()!==i?(41===t.charCodeAt(pe)?(o=")",pe++):(o=i,Ae(K)),o!==i?e=r={type:"has",selectors:n}:(pe=e,e=i)):(pe=e,e=i),ye[a]={nextPos:pe,result:e},e)}())===i&&(e=function(){var e,r,n=30*pe+25,o=ye[n];return o?(pe=o.nextPos,o.result):(":first-child"===t.substr(pe,12)?(r=":first-child",pe+=12):(r=i,Ae(te)),r!==i&&(r=Ie(1)),e=r,ye[n]={nextPos:pe,result:e},e)}())===i&&(e=function(){var e,r,n=30*pe+26,o=ye[n];return o?(pe=o.nextPos,o.result):(":last-child"===t.substr(pe,11)?(r=":last-child",pe+=11):(r=i,Ae(re)),r!==i&&(r=je(1)),e=r,ye[n]={nextPos:pe,result:e},e)}())===i&&(e=function(){var e,r,n,o,a,s=30*pe+27,l=ye[s];if(l)return pe=l.nextPos,l.result;if(e=pe,":nth-child("===t.substr(pe,11)?(r=":nth-child(",pe+=11):(r=i,Ae(ne)),r!==i)if(Ee()!==i){if(n=[],q.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(N)),o!==i)for(;o!==i;)n.push(o),q.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(N));else n=i;n!==i&&(o=Ee())!==i?(41===t.charCodeAt(pe)?(a=")",pe++):(a=i,Ae(K)),a!==i?(r=Ie(parseInt(n.join(""),10)),e=r):(pe=e,e=i)):(pe=e,e=i)}else pe=e,e=i;else pe=e,e=i;return ye[s]={nextPos:pe,result:e},e}())===i&&(e=function(){var e,r,n,o,a,s=30*pe+28,l=ye[s];if(l)return pe=l.nextPos,l.result;if(e=pe,":nth-last-child("===t.substr(pe,16)?(r=":nth-last-child(",pe+=16):(r=i,Ae(oe)),r!==i)if(Ee()!==i){if(n=[],q.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(N)),o!==i)for(;o!==i;)n.push(o),q.test(t.charAt(pe))?(o=t.charAt(pe),pe++):(o=i,Ae(N));else n=i;n!==i&&(o=Ee())!==i?(41===t.charCodeAt(pe)?(a=")",pe++):(a=i,Ae(K)),a!==i?(r=je(parseInt(n.join(""),10)),e=r):(pe=e,e=i)):(pe=e,e=i)}else pe=e,e=i;else pe=e,e=i;return ye[s]={nextPos:pe,result:e},e}())===i&&(e=function(){var e,r,n,o=30*pe+29,a=ye[o];return a?(pe=a.nextPos,a.result):(e=pe,58===t.charCodeAt(pe)?(r=":",pe++):(r=i,Ae(ae)),r!==i?("statement"===t.substr(pe,9).toLowerCase()?(n=t.substr(pe,9),pe+=9):(n=i,Ae(se)),n===i&&("expression"===t.substr(pe,10).toLowerCase()?(n=t.substr(pe,10),pe+=10):(n=i,Ae(ie)),n===i&&("declaration"===t.substr(pe,11).toLowerCase()?(n=t.substr(pe,11),pe+=11):(n=i,Ae(le)),n===i&&("function"===t.substr(pe,8).toLowerCase()?(n=t.substr(pe,8),pe+=8):(n=i,Ae(ue)),n===i&&("pattern"===t.substr(pe,7).toLowerCase()?(n=t.substr(pe,7),pe+=7):(n=i,Ae(ce)))))),n!==i?e=r={type:"class",name:n}:(pe=e,e=i)):(pe=e,e=i),ye[o]={nextPos:pe,result:e},e)}()),ye[r]={nextPos:pe,result:e},e)}function De(){var e,r,n,o=30*pe+13,a=ye[o];if(a)return pe=a.nextPos,a.result;if(r=[],(n=Se())===i&&(46===t.charCodeAt(pe)?(n=".",pe++):(n=i,Ae(D))),n!==i)for(;n!==i;)r.push(n),(n=Se())===i&&(46===t.charCodeAt(pe)?(n=".",pe++):(n=i,Ae(D)));else r=i;return r!==i&&(r=h(r)),e=r,ye[o]={nextPos:pe,result:e},e}function Ie(e){return{type:"nth-child",index:{type:"literal",value:e}}}function je(e){return{type:"nth-last-child",index:{type:"literal",value:e}}}if((n=u())!==i&&pe===t.length)return n;throw n!==i&&pe":return A>r.value.value;case">=":return A>=r.value.value}throw new Error("Unknown operator: ".concat(r.operator));case"sibling":return l(t,r.right,n)&&u(t,r.left,n,"LEFT_SIDE")||r.left.subject&&l(t,r.left,n)&&u(t,r.right,n,"RIGHT_SIDE");case"adjacent":return l(t,r.right,n)&&c(t,r.left,n,"LEFT_SIDE")||r.right.subject&&l(t,r.left,n)&&c(t,r.right,n,"RIGHT_SIDE");case"nth-child":return l(t,r.right,n)&&p(t,n,(function(){return r.index.value-1}));case"nth-last-child":return l(t,r.right,n)&&p(t,n,(function(e){return e-r.index.value}));case"class":switch(r.name.toLowerCase()){case"statement":if("Statement"===t.type.slice(-9))return!0;case"declaration":return"Declaration"===t.type.slice(-11);case"pattern":if("Pattern"===t.type.slice(-7))return!0;case"expression":return"Expression"===t.type.slice(-10)||"Literal"===t.type.slice(-7)||"Identifier"===t.type&&(0===n.length||"MetaProperty"!==n[0].type)||"MetaProperty"===t.type;case"function":return"FunctionDeclaration"===t.type||"FunctionExpression"===t.type||"ArrowFunctionExpression"===t.type}throw new Error("Unknown class name: ".concat(r.name))}throw new Error("Unknown selector type: ".concat(r.type))}function u(e,r,n,o){var a=t(n,1)[0];if(!a)return!1;for(var i=s.VisitorKeys[a.type],u=0,c=i.length;u0&&l(p[f-1],r,n))return!0;if("RIGHT_SIDE"===o&&f=0&&c===n(u.length))return!0}}return!1}function f(n,o){if(null==n||"object"!=e(n))return[];null==o&&(o=n);for(var a=n.subject?[o]:[],s=0,i=function(e){for(var t=[],r=Object.keys(e),n=0;ne.length)&&(t=e.length);for(var r=0,n=new Array(t);r=e.length?{done:!0}:{done:!1,value:e[a++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,s=!0,l=!1;return{s:function(){r=e[Symbol.iterator]()},n:function(){var e=r.next();return s=e.done,e},e:function(e){l=!0,i=e},f:function(){try{s||null==r.return||r.return()}finally{if(l)throw i}}}}"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;function i(e,t){return e(t={exports:{}},t.exports),t.exports}var s=i((function(e,t){!function e(t){var r,n,a,o,i,s;function l(e){var t,r,n={};for(t in e)e.hasOwnProperty(t)&&(r=e[t],n[t]="object"==typeof r&&null!==r?l(r):r);return n}function u(e,t){this.parent=e,this.key=t}function c(e,t,r,n){this.node=e,this.path=t,this.wrap=r,this.ref=n}function f(){}function p(e){return null!=e&&("object"==typeof e&&"string"==typeof e.type)}function h(e,t){return(e===r.ObjectExpression||e===r.ObjectPattern)&&"properties"===t}function y(e,t){for(var r=e.length-1;r>=0;--r)if(e[r].node===t)return!0;return!1}function d(e,t){return(new f).traverse(e,t)}function m(e,t){var r;return r=function(e,t){var r,n,a,o;for(n=e.length,a=0;n;)t(e[o=a+(r=n>>>1)])?n=r:(a=o+1,n-=r+1);return a}(t,(function(t){return t.range[0]>e.range[0]})),e.extendedRange=[e.range[0],e.range[1]],r!==t.length&&(e.extendedRange[1]=t[r].range[0]),(r-=1)>=0&&(e.extendedRange[0]=t[r].range[1]),e}return r={AssignmentExpression:"AssignmentExpression",AssignmentPattern:"AssignmentPattern",ArrayExpression:"ArrayExpression",ArrayPattern:"ArrayPattern",ArrowFunctionExpression:"ArrowFunctionExpression",AwaitExpression:"AwaitExpression",BlockStatement:"BlockStatement",BinaryExpression:"BinaryExpression",BreakStatement:"BreakStatement",CallExpression:"CallExpression",CatchClause:"CatchClause",ChainExpression:"ChainExpression",ClassBody:"ClassBody",ClassDeclaration:"ClassDeclaration",ClassExpression:"ClassExpression",ComprehensionBlock:"ComprehensionBlock",ComprehensionExpression:"ComprehensionExpression",ConditionalExpression:"ConditionalExpression",ContinueStatement:"ContinueStatement",DebuggerStatement:"DebuggerStatement",DirectiveStatement:"DirectiveStatement",DoWhileStatement:"DoWhileStatement",EmptyStatement:"EmptyStatement",ExportAllDeclaration:"ExportAllDeclaration",ExportDefaultDeclaration:"ExportDefaultDeclaration",ExportNamedDeclaration:"ExportNamedDeclaration",ExportSpecifier:"ExportSpecifier",ExpressionStatement:"ExpressionStatement",ForStatement:"ForStatement",ForInStatement:"ForInStatement",ForOfStatement:"ForOfStatement",FunctionDeclaration:"FunctionDeclaration",FunctionExpression:"FunctionExpression",GeneratorExpression:"GeneratorExpression",Identifier:"Identifier",IfStatement:"IfStatement",ImportExpression:"ImportExpression",ImportDeclaration:"ImportDeclaration",ImportDefaultSpecifier:"ImportDefaultSpecifier",ImportNamespaceSpecifier:"ImportNamespaceSpecifier",ImportSpecifier:"ImportSpecifier",Literal:"Literal",LabeledStatement:"LabeledStatement",LogicalExpression:"LogicalExpression",MemberExpression:"MemberExpression",MetaProperty:"MetaProperty",MethodDefinition:"MethodDefinition",ModuleSpecifier:"ModuleSpecifier",NewExpression:"NewExpression",ObjectExpression:"ObjectExpression",ObjectPattern:"ObjectPattern",Program:"Program",Property:"Property",RestElement:"RestElement",ReturnStatement:"ReturnStatement",SequenceExpression:"SequenceExpression",SpreadElement:"SpreadElement",Super:"Super",SwitchStatement:"SwitchStatement",SwitchCase:"SwitchCase",TaggedTemplateExpression:"TaggedTemplateExpression",TemplateElement:"TemplateElement",TemplateLiteral:"TemplateLiteral",ThisExpression:"ThisExpression",ThrowStatement:"ThrowStatement",TryStatement:"TryStatement",UnaryExpression:"UnaryExpression",UpdateExpression:"UpdateExpression",VariableDeclaration:"VariableDeclaration",VariableDeclarator:"VariableDeclarator",WhileStatement:"WhileStatement",WithStatement:"WithStatement",YieldExpression:"YieldExpression"},a={AssignmentExpression:["left","right"],AssignmentPattern:["left","right"],ArrayExpression:["elements"],ArrayPattern:["elements"],ArrowFunctionExpression:["params","body"],AwaitExpression:["argument"],BlockStatement:["body"],BinaryExpression:["left","right"],BreakStatement:["label"],CallExpression:["callee","arguments"],CatchClause:["param","body"],ChainExpression:["expression"],ClassBody:["body"],ClassDeclaration:["id","superClass","body"],ClassExpression:["id","superClass","body"],ComprehensionBlock:["left","right"],ComprehensionExpression:["blocks","filter","body"],ConditionalExpression:["test","consequent","alternate"],ContinueStatement:["label"],DebuggerStatement:[],DirectiveStatement:[],DoWhileStatement:["body","test"],EmptyStatement:[],ExportAllDeclaration:["source"],ExportDefaultDeclaration:["declaration"],ExportNamedDeclaration:["declaration","specifiers","source"],ExportSpecifier:["exported","local"],ExpressionStatement:["expression"],ForStatement:["init","test","update","body"],ForInStatement:["left","right","body"],ForOfStatement:["left","right","body"],FunctionDeclaration:["id","params","body"],FunctionExpression:["id","params","body"],GeneratorExpression:["blocks","filter","body"],Identifier:[],IfStatement:["test","consequent","alternate"],ImportExpression:["source"],ImportDeclaration:["specifiers","source"],ImportDefaultSpecifier:["local"],ImportNamespaceSpecifier:["local"],ImportSpecifier:["imported","local"],Literal:[],LabeledStatement:["label","body"],LogicalExpression:["left","right"],MemberExpression:["object","property"],MetaProperty:["meta","property"],MethodDefinition:["key","value"],ModuleSpecifier:[],NewExpression:["callee","arguments"],ObjectExpression:["properties"],ObjectPattern:["properties"],Program:["body"],Property:["key","value"],RestElement:["argument"],ReturnStatement:["argument"],SequenceExpression:["expressions"],SpreadElement:["argument"],Super:[],SwitchStatement:["discriminant","cases"],SwitchCase:["test","consequent"],TaggedTemplateExpression:["tag","quasi"],TemplateElement:[],TemplateLiteral:["quasis","expressions"],ThisExpression:[],ThrowStatement:["argument"],TryStatement:["block","handler","finalizer"],UnaryExpression:["argument"],UpdateExpression:["argument"],VariableDeclaration:["declarations"],VariableDeclarator:["id","init"],WhileStatement:["test","body"],WithStatement:["object","body"],YieldExpression:["argument"]},n={Break:o={},Skip:i={},Remove:s={}},u.prototype.replace=function(e){this.parent[this.key]=e},u.prototype.remove=function(){return Array.isArray(this.parent)?(this.parent.splice(this.key,1),!0):(this.replace(null),!1)},f.prototype.path=function(){var e,t,r,n,a;function o(e,t){if(Array.isArray(t))for(r=0,n=t.length;r=0;)if(v=s[f=x[d]])if(Array.isArray(v)){for(m=v.length;(m-=1)>=0;)if(v[m]&&!y(n,v[m])){if(h(l,x[d]))a=new c(v[m],[f,m],"Property",null);else{if(!p(v[m]))continue;a=new c(v[m],[f,m],null,null)}r.push(a)}}else if(p(v)){if(y(n,v))continue;r.push(new c(v,f,null,null))}}}else if(a=n.pop(),u=this.__execute(t.leave,a),this.__state===o||u===o)return},f.prototype.replace=function(e,t){var r,n,a,l,f,y,d,m,x,v,g,b,A;function E(e){var t,n,a,o;if(e.ref.remove())for(n=e.ref.key,o=e.ref.parent,t=r.length;t--;)if((a=r[t]).ref&&a.ref.parent===o){if(a.ref.key=0;)if(v=a[A=x[d]])if(Array.isArray(v)){for(m=v.length;(m-=1)>=0;)if(v[m]){if(h(l,x[d]))y=new c(v[m],[A,m],"Property",new u(v,m));else{if(!p(v[m]))continue;y=new c(v[m],[A,m],null,new u(v,m))}r.push(y)}}else p(v)&&r.push(new c(v,A,null,new u(a,A)))}}else if(y=n.pop(),void 0!==(f=this.__execute(t.leave,y))&&f!==o&&f!==i&&f!==s&&y.ref.replace(f),this.__state!==s&&f!==s||E(y),this.__state===o||f===o)return b.root;return b.root},t.Syntax=r,t.traverse=d,t.replace=function(e,t){return(new f).replace(e,t)},t.attachComments=function(e,t,r){var a,o,i,s,u=[];if(!e.range)throw new Error("attachComments needs range information");if(!r.length){if(t.length){for(i=0,o=t.length;ie.range[0]);)t.extendedRange[1]===e.range[0]?(e.leadingComments||(e.leadingComments=[]),e.leadingComments.push(t),u.splice(s,1)):s+=1;return s===u.length?n.Break:u[s].extendedRange[0]>e.range[1]?n.Skip:void 0}}),s=0,d(e,{leave:function(e){for(var t;se.range[1]?n.Skip:void 0}}),e},t.VisitorKeys=a,t.VisitorOption=n,t.Controller=f,t.cloneEnvironment=function(){return e({})},t}(t)})),l=i((function(e){e.exports&&(e.exports=function(){function e(t,r,n,a){this.message=t,this.expected=r,this.found=n,this.location=a,this.name="SyntaxError","function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,e)}return function(e,t){function r(){this.constructor=e}r.prototype=t.prototype,e.prototype=new r}(e,Error),e.buildMessage=function(e,t){var r={literal:function(e){return'"'+a(e.text)+'"'},class:function(e){var t,r="";for(t=0;t0){for(t=1,n=1;t<~+.]/,p=me([" ","[","]",",","(",")",":","#","!","=",">","<","~","+","."],!0,!1),h=de(">",!1),y=de("~",!1),d=de("+",!1),m=de(",",!1),x=de("!",!1),v=de("*",!1),g=de("#",!1),b=de("[",!1),A=de("]",!1),E=/^[>","<","!"],!1,!1),_=de("=",!1),w=function(e){return(e||"")+"="},C=/^[><]/,P=me([">","<"],!1,!1),k=de(".",!1),D=function(e,t,r){return{type:"attribute",name:e,operator:t,value:r}},j=de('"',!1),I=/^[^\\"]/,T=me(["\\",'"'],!0,!1),F=de("\\",!1),L={type:"any"},O=function(e,t){return e+t},R=function(e){return{type:"literal",value:(t=e.join(""),t.replace(/\\(.)/g,(function(e,t){switch(t){case"b":return"\b";case"f":return"\f";case"n":return"\n";case"r":return"\r";case"t":return"\t";case"v":return"\v";default:return t}})))};var t},B=de("'",!1),M=/^[^\\']/,U=me(["\\","'"],!0,!1),V=/^[0-9]/,q=me([["0","9"]],!1,!1),N=de("type(",!1),W=/^[^ )]/,K=me([" ",")"],!0,!1),G=de(")",!1),z=/^[imsu]/,H=me(["i","m","s","u"],!1,!1),Y=de("/",!1),$=/^[^\/]/,J=me(["/"],!0,!1),Q=de(":not(",!1),X=de(":matches(",!1),Z=de(":has(",!1),ee=de(":first-child",!1),te=de(":last-child",!1),re=de(":nth-child(",!1),ne=de(":nth-last-child(",!1),ae=de(":",!1),oe=de("statement",!0),ie=de("expression",!0),se=de("declaration",!0),le=de("function",!0),ue=de("pattern",!0),ce=0,fe=[{line:1,column:1}],pe=0,he=[],ye={};if("startRule"in r){if(!(r.startRule in l))throw new Error("Can't start parsing from rule \""+r.startRule+'".');u=l[r.startRule]}function de(e,t){return{type:"literal",text:e,ignoreCase:t}}function me(e,t,r){return{type:"class",parts:e,inverted:t,ignoreCase:r}}function xe(e){var r,n=fe[e];if(n)return n;for(r=e-1;!fe[r];)r--;for(n={line:(n=fe[r]).line,column:n.column};rpe&&(pe=ce,he=[]),he.push(e))}function be(){var e,t,r,n,a=30*ce+0,o=ye[a];return o?(ce=o.nextPos,o.result):(e=ce,(t=Ae())!==s&&(r=_e())!==s&&Ae()!==s?e=t=1===(n=r).length?n[0]:{type:"matches",selectors:n}:(ce=e,e=s),e===s&&(e=ce,(t=Ae())!==s&&(t=void 0),e=t),ye[a]={nextPos:ce,result:e},e)}function Ae(){var e,r,n=30*ce+1,a=ye[n];if(a)return ce=a.nextPos,a.result;for(e=[],32===t.charCodeAt(ce)?(r=" ",ce++):(r=s,ge(c));r!==s;)e.push(r),32===t.charCodeAt(ce)?(r=" ",ce++):(r=s,ge(c));return ye[n]={nextPos:ce,result:e},e}function Ee(){var e,r,n,a=30*ce+2,o=ye[a];if(o)return ce=o.nextPos,o.result;if(r=[],f.test(t.charAt(ce))?(n=t.charAt(ce),ce++):(n=s,ge(p)),n!==s)for(;n!==s;)r.push(n),f.test(t.charAt(ce))?(n=t.charAt(ce),ce++):(n=s,ge(p));else r=s;return r!==s&&(r=r.join("")),e=r,ye[a]={nextPos:ce,result:e},e}function Se(){var e,r,n,a=30*ce+3,o=ye[a];return o?(ce=o.nextPos,o.result):(e=ce,(r=Ae())!==s?(62===t.charCodeAt(ce)?(n=">",ce++):(n=s,ge(h)),n!==s&&Ae()!==s?e=r="child":(ce=e,e=s)):(ce=e,e=s),e===s&&(e=ce,(r=Ae())!==s?(126===t.charCodeAt(ce)?(n="~",ce++):(n=s,ge(y)),n!==s&&Ae()!==s?e=r="sibling":(ce=e,e=s)):(ce=e,e=s),e===s&&(e=ce,(r=Ae())!==s?(43===t.charCodeAt(ce)?(n="+",ce++):(n=s,ge(d)),n!==s&&Ae()!==s?e=r="adjacent":(ce=e,e=s)):(ce=e,e=s),e===s&&(e=ce,32===t.charCodeAt(ce)?(r=" ",ce++):(r=s,ge(c)),r!==s&&(n=Ae())!==s?e=r="descendant":(ce=e,e=s)))),ye[a]={nextPos:ce,result:e},e)}function _e(){var e,r,n,a,o,i,l,u,c=30*ce+4,f=ye[c];if(f)return ce=f.nextPos,f.result;if(e=ce,(r=we())!==s){for(n=[],a=ce,(o=Ae())!==s?(44===t.charCodeAt(ce)?(i=",",ce++):(i=s,ge(m)),i!==s&&(l=Ae())!==s&&(u=we())!==s?a=o=[o,i,l,u]:(ce=a,a=s)):(ce=a,a=s);a!==s;)n.push(a),a=ce,(o=Ae())!==s?(44===t.charCodeAt(ce)?(i=",",ce++):(i=s,ge(m)),i!==s&&(l=Ae())!==s&&(u=we())!==s?a=o=[o,i,l,u]:(ce=a,a=s)):(ce=a,a=s);n!==s?e=r=[r].concat(n.map((function(e){return e[3]}))):(ce=e,e=s)}else ce=e,e=s;return ye[c]={nextPos:ce,result:e},e}function we(){var e,t,r,n,a,o,i,l=30*ce+5,u=ye[l];if(u)return ce=u.nextPos,u.result;if(e=ce,(t=Ce())!==s){for(r=[],n=ce,(a=Se())!==s&&(o=Ce())!==s?n=a=[a,o]:(ce=n,n=s);n!==s;)r.push(n),n=ce,(a=Se())!==s&&(o=Ce())!==s?n=a=[a,o]:(ce=n,n=s);r!==s?(i=t,e=t=r.reduce((function(e,t){return{type:t[0],left:e,right:t[1]}}),i)):(ce=e,e=s)}else ce=e,e=s;return ye[l]={nextPos:ce,result:e},e}function Ce(){var e,r,n,a,o,i,l,u=30*ce+6,c=ye[u];if(c)return ce=c.nextPos,c.result;if(e=ce,33===t.charCodeAt(ce)?(r="!",ce++):(r=s,ge(x)),r===s&&(r=null),r!==s){if(n=[],(a=Pe())!==s)for(;a!==s;)n.push(a),a=Pe();else n=s;n!==s?(o=r,l=1===(i=n).length?i[0]:{type:"compound",selectors:i},o&&(l.subject=!0),e=r=l):(ce=e,e=s)}else ce=e,e=s;return ye[u]={nextPos:ce,result:e},e}function Pe(){var e,r=30*ce+7,n=ye[r];return n?(ce=n.nextPos,n.result):((e=function(){var e,r,n=30*ce+8,a=ye[n];return a?(ce=a.nextPos,a.result):(42===t.charCodeAt(ce)?(r="*",ce++):(r=s,ge(v)),r!==s&&(r={type:"wildcard",value:r}),e=r,ye[n]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n,a=30*ce+9,o=ye[a];return o?(ce=o.nextPos,o.result):(e=ce,35===t.charCodeAt(ce)?(r="#",ce++):(r=s,ge(g)),r===s&&(r=null),r!==s&&(n=Ee())!==s?e=r={type:"identifier",value:n}:(ce=e,e=s),ye[a]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n,a,o=30*ce+10,i=ye[o];return i?(ce=i.nextPos,i.result):(e=ce,91===t.charCodeAt(ce)?(r="[",ce++):(r=s,ge(b)),r!==s&&Ae()!==s&&(n=function(){var e,r,n,a,o=30*ce+14,i=ye[o];return i?(ce=i.nextPos,i.result):(e=ce,(r=ke())!==s&&Ae()!==s&&(n=function(){var e,r,n,a=30*ce+12,o=ye[a];return o?(ce=o.nextPos,o.result):(e=ce,33===t.charCodeAt(ce)?(r="!",ce++):(r=s,ge(x)),r===s&&(r=null),r!==s?(61===t.charCodeAt(ce)?(n="=",ce++):(n=s,ge(_)),n!==s?(r=w(r),e=r):(ce=e,e=s)):(ce=e,e=s),ye[a]={nextPos:ce,result:e},e)}())!==s&&Ae()!==s?((a=function(){var e,r,n,a,o,i=30*ce+18,l=ye[i];if(l)return ce=l.nextPos,l.result;if(e=ce,"type("===t.substr(ce,5)?(r="type(",ce+=5):(r=s,ge(N)),r!==s)if(Ae()!==s){if(n=[],W.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(K)),a!==s)for(;a!==s;)n.push(a),W.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(K));else n=s;n!==s&&(a=Ae())!==s?(41===t.charCodeAt(ce)?(o=")",ce++):(o=s,ge(G)),o!==s?(r={type:"type",value:n.join("")},e=r):(ce=e,e=s)):(ce=e,e=s)}else ce=e,e=s;else ce=e,e=s;return ye[i]={nextPos:ce,result:e},e}())===s&&(a=function(){var e,r,n,a,o,i,l=30*ce+20,u=ye[l];if(u)return ce=u.nextPos,u.result;if(e=ce,47===t.charCodeAt(ce)?(r="/",ce++):(r=s,ge(Y)),r!==s){if(n=[],$.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(J)),a!==s)for(;a!==s;)n.push(a),$.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(J));else n=s;n!==s?(47===t.charCodeAt(ce)?(a="/",ce++):(a=s,ge(Y)),a!==s?((o=function(){var e,r,n=30*ce+19,a=ye[n];if(a)return ce=a.nextPos,a.result;if(e=[],z.test(t.charAt(ce))?(r=t.charAt(ce),ce++):(r=s,ge(H)),r!==s)for(;r!==s;)e.push(r),z.test(t.charAt(ce))?(r=t.charAt(ce),ce++):(r=s,ge(H));else e=s;return ye[n]={nextPos:ce,result:e},e}())===s&&(o=null),o!==s?(i=o,r={type:"regexp",value:new RegExp(n.join(""),i?i.join(""):"")},e=r):(ce=e,e=s)):(ce=e,e=s)):(ce=e,e=s)}else ce=e,e=s;return ye[l]={nextPos:ce,result:e},e}()),a!==s?(r=D(r,n,a),e=r):(ce=e,e=s)):(ce=e,e=s),e===s&&(e=ce,(r=ke())!==s&&Ae()!==s&&(n=function(){var e,r,n,a=30*ce+11,o=ye[a];return o?(ce=o.nextPos,o.result):(e=ce,E.test(t.charAt(ce))?(r=t.charAt(ce),ce++):(r=s,ge(S)),r===s&&(r=null),r!==s?(61===t.charCodeAt(ce)?(n="=",ce++):(n=s,ge(_)),n!==s?(r=w(r),e=r):(ce=e,e=s)):(ce=e,e=s),e===s&&(C.test(t.charAt(ce))?(e=t.charAt(ce),ce++):(e=s,ge(P))),ye[a]={nextPos:ce,result:e},e)}())!==s&&Ae()!==s?((a=function(){var e,r,n,a,o,i,l=30*ce+15,u=ye[l];if(u)return ce=u.nextPos,u.result;if(e=ce,34===t.charCodeAt(ce)?(r='"',ce++):(r=s,ge(j)),r!==s){for(n=[],I.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(T)),a===s&&(a=ce,92===t.charCodeAt(ce)?(o="\\",ce++):(o=s,ge(F)),o!==s?(t.length>ce?(i=t.charAt(ce),ce++):(i=s,ge(L)),i!==s?(o=O(o,i),a=o):(ce=a,a=s)):(ce=a,a=s));a!==s;)n.push(a),I.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(T)),a===s&&(a=ce,92===t.charCodeAt(ce)?(o="\\",ce++):(o=s,ge(F)),o!==s?(t.length>ce?(i=t.charAt(ce),ce++):(i=s,ge(L)),i!==s?(o=O(o,i),a=o):(ce=a,a=s)):(ce=a,a=s));n!==s?(34===t.charCodeAt(ce)?(a='"',ce++):(a=s,ge(j)),a!==s?(r=R(n),e=r):(ce=e,e=s)):(ce=e,e=s)}else ce=e,e=s;if(e===s)if(e=ce,39===t.charCodeAt(ce)?(r="'",ce++):(r=s,ge(B)),r!==s){for(n=[],M.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(U)),a===s&&(a=ce,92===t.charCodeAt(ce)?(o="\\",ce++):(o=s,ge(F)),o!==s?(t.length>ce?(i=t.charAt(ce),ce++):(i=s,ge(L)),i!==s?(o=O(o,i),a=o):(ce=a,a=s)):(ce=a,a=s));a!==s;)n.push(a),M.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(U)),a===s&&(a=ce,92===t.charCodeAt(ce)?(o="\\",ce++):(o=s,ge(F)),o!==s?(t.length>ce?(i=t.charAt(ce),ce++):(i=s,ge(L)),i!==s?(o=O(o,i),a=o):(ce=a,a=s)):(ce=a,a=s));n!==s?(39===t.charCodeAt(ce)?(a="'",ce++):(a=s,ge(B)),a!==s?(r=R(n),e=r):(ce=e,e=s)):(ce=e,e=s)}else ce=e,e=s;return ye[l]={nextPos:ce,result:e},e}())===s&&(a=function(){var e,r,n,a,o,i,l,u=30*ce+16,c=ye[u];if(c)return ce=c.nextPos,c.result;for(e=ce,r=ce,n=[],V.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(q));a!==s;)n.push(a),V.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(q));if(n!==s?(46===t.charCodeAt(ce)?(a=".",ce++):(a=s,ge(k)),a!==s?r=n=[n,a]:(ce=r,r=s)):(ce=r,r=s),r===s&&(r=null),r!==s){if(n=[],V.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(q)),a!==s)for(;a!==s;)n.push(a),V.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(q));else n=s;n!==s?(i=n,l=(o=r)?[].concat.apply([],o).join(""):"",r={type:"literal",value:parseFloat(l+i.join(""))},e=r):(ce=e,e=s)}else ce=e,e=s;return ye[u]={nextPos:ce,result:e},e}())===s&&(a=function(){var e,t,r=30*ce+17,n=ye[r];return n?(ce=n.nextPos,n.result):((t=Ee())!==s&&(t={type:"literal",value:t}),e=t,ye[r]={nextPos:ce,result:e},e)}()),a!==s?(r=D(r,n,a),e=r):(ce=e,e=s)):(ce=e,e=s),e===s&&(e=ce,(r=ke())!==s&&(r={type:"attribute",name:r}),e=r)),ye[o]={nextPos:ce,result:e},e)}())!==s&&Ae()!==s?(93===t.charCodeAt(ce)?(a="]",ce++):(a=s,ge(A)),a!==s?e=r=n:(ce=e,e=s)):(ce=e,e=s),ye[o]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n,a,o,i,l,u,c=30*ce+21,f=ye[c];if(f)return ce=f.nextPos,f.result;if(e=ce,46===t.charCodeAt(ce)?(r=".",ce++):(r=s,ge(k)),r!==s)if((n=Ee())!==s){for(a=[],o=ce,46===t.charCodeAt(ce)?(i=".",ce++):(i=s,ge(k)),i!==s&&(l=Ee())!==s?o=i=[i,l]:(ce=o,o=s);o!==s;)a.push(o),o=ce,46===t.charCodeAt(ce)?(i=".",ce++):(i=s,ge(k)),i!==s&&(l=Ee())!==s?o=i=[i,l]:(ce=o,o=s);a!==s?(u=n,r={type:"field",name:a.reduce((function(e,t){return e+t[0]+t[1]}),u)},e=r):(ce=e,e=s)}else ce=e,e=s;else ce=e,e=s;return ye[c]={nextPos:ce,result:e},e}())===s&&(e=function(){var e,r,n,a,o=30*ce+22,i=ye[o];return i?(ce=i.nextPos,i.result):(e=ce,":not("===t.substr(ce,5)?(r=":not(",ce+=5):(r=s,ge(Q)),r!==s&&Ae()!==s&&(n=_e())!==s&&Ae()!==s?(41===t.charCodeAt(ce)?(a=")",ce++):(a=s,ge(G)),a!==s?e=r={type:"not",selectors:n}:(ce=e,e=s)):(ce=e,e=s),ye[o]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n,a,o=30*ce+23,i=ye[o];return i?(ce=i.nextPos,i.result):(e=ce,":matches("===t.substr(ce,9)?(r=":matches(",ce+=9):(r=s,ge(X)),r!==s&&Ae()!==s&&(n=_e())!==s&&Ae()!==s?(41===t.charCodeAt(ce)?(a=")",ce++):(a=s,ge(G)),a!==s?e=r={type:"matches",selectors:n}:(ce=e,e=s)):(ce=e,e=s),ye[o]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n,a,o=30*ce+24,i=ye[o];return i?(ce=i.nextPos,i.result):(e=ce,":has("===t.substr(ce,5)?(r=":has(",ce+=5):(r=s,ge(Z)),r!==s&&Ae()!==s&&(n=_e())!==s&&Ae()!==s?(41===t.charCodeAt(ce)?(a=")",ce++):(a=s,ge(G)),a!==s?e=r={type:"has",selectors:n}:(ce=e,e=s)):(ce=e,e=s),ye[o]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n=30*ce+25,a=ye[n];return a?(ce=a.nextPos,a.result):(":first-child"===t.substr(ce,12)?(r=":first-child",ce+=12):(r=s,ge(ee)),r!==s&&(r=De(1)),e=r,ye[n]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n=30*ce+26,a=ye[n];return a?(ce=a.nextPos,a.result):(":last-child"===t.substr(ce,11)?(r=":last-child",ce+=11):(r=s,ge(te)),r!==s&&(r=je(1)),e=r,ye[n]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n,a,o,i=30*ce+27,l=ye[i];if(l)return ce=l.nextPos,l.result;if(e=ce,":nth-child("===t.substr(ce,11)?(r=":nth-child(",ce+=11):(r=s,ge(re)),r!==s)if(Ae()!==s){if(n=[],V.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(q)),a!==s)for(;a!==s;)n.push(a),V.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(q));else n=s;n!==s&&(a=Ae())!==s?(41===t.charCodeAt(ce)?(o=")",ce++):(o=s,ge(G)),o!==s?(r=De(parseInt(n.join(""),10)),e=r):(ce=e,e=s)):(ce=e,e=s)}else ce=e,e=s;else ce=e,e=s;return ye[i]={nextPos:ce,result:e},e}())===s&&(e=function(){var e,r,n,a,o,i=30*ce+28,l=ye[i];if(l)return ce=l.nextPos,l.result;if(e=ce,":nth-last-child("===t.substr(ce,16)?(r=":nth-last-child(",ce+=16):(r=s,ge(ne)),r!==s)if(Ae()!==s){if(n=[],V.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(q)),a!==s)for(;a!==s;)n.push(a),V.test(t.charAt(ce))?(a=t.charAt(ce),ce++):(a=s,ge(q));else n=s;n!==s&&(a=Ae())!==s?(41===t.charCodeAt(ce)?(o=")",ce++):(o=s,ge(G)),o!==s?(r=je(parseInt(n.join(""),10)),e=r):(ce=e,e=s)):(ce=e,e=s)}else ce=e,e=s;else ce=e,e=s;return ye[i]={nextPos:ce,result:e},e}())===s&&(e=function(){var e,r,n,a=30*ce+29,o=ye[a];return o?(ce=o.nextPos,o.result):(e=ce,58===t.charCodeAt(ce)?(r=":",ce++):(r=s,ge(ae)),r!==s?("statement"===t.substr(ce,9).toLowerCase()?(n=t.substr(ce,9),ce+=9):(n=s,ge(oe)),n===s&&("expression"===t.substr(ce,10).toLowerCase()?(n=t.substr(ce,10),ce+=10):(n=s,ge(ie)),n===s&&("declaration"===t.substr(ce,11).toLowerCase()?(n=t.substr(ce,11),ce+=11):(n=s,ge(se)),n===s&&("function"===t.substr(ce,8).toLowerCase()?(n=t.substr(ce,8),ce+=8):(n=s,ge(le)),n===s&&("pattern"===t.substr(ce,7).toLowerCase()?(n=t.substr(ce,7),ce+=7):(n=s,ge(ue)))))),n!==s?e=r={type:"class",name:n}:(ce=e,e=s)):(ce=e,e=s),ye[a]={nextPos:ce,result:e},e)}()),ye[r]={nextPos:ce,result:e},e)}function ke(){var e,r,n,a,o,i,l,u,c=30*ce+13,f=ye[c];if(f)return ce=f.nextPos,f.result;if(e=ce,(r=Ee())!==s){for(n=[],a=ce,46===t.charCodeAt(ce)?(o=".",ce++):(o=s,ge(k)),o!==s&&(i=Ee())!==s?a=o=[o,i]:(ce=a,a=s);a!==s;)n.push(a),a=ce,46===t.charCodeAt(ce)?(o=".",ce++):(o=s,ge(k)),o!==s&&(i=Ee())!==s?a=o=[o,i]:(ce=a,a=s);n!==s?(l=r,u=n,e=r=[].concat.apply([l],u).join("")):(ce=e,e=s)}else ce=e,e=s;return ye[c]={nextPos:ce,result:e},e}function De(e){return{type:"nth-child",index:{type:"literal",value:e}}}function je(e){return{type:"nth-last-child",index:{type:"literal",value:e}}}if((n=u())!==s&&ce===t.length)return n;throw n!==s&&ce":return w>r.value.value;case">=":return w>=r.value.value}throw new Error("Unknown operator: ".concat(r.operator));case"sibling":return u(t,r.right,n,a)&&p(t,r.left,n,"LEFT_SIDE",a)||r.left.subject&&u(t,r.left,n,a)&&p(t,r.right,n,"RIGHT_SIDE",a);case"adjacent":return u(t,r.right,n,a)&&h(t,r.left,n,"LEFT_SIDE",a)||r.right.subject&&u(t,r.left,n,a)&&h(t,r.right,n,"RIGHT_SIDE",a);case"nth-child":return u(t,r.right,n,a)&&y(t,n,(function(){return r.index.value-1}),a);case"nth-last-child":return u(t,r.right,n,a)&&y(t,n,(function(e){return e-r.index.value}),a);case"class":switch(r.name.toLowerCase()){case"statement":if("Statement"===t.type.slice(-9))return!0;case"declaration":return"Declaration"===t.type.slice(-11);case"pattern":if("Pattern"===t.type.slice(-7))return!0;case"expression":return"Expression"===t.type.slice(-10)||"Literal"===t.type.slice(-7)||"Identifier"===t.type&&(0===n.length||"MetaProperty"!==n[0].type)||"MetaProperty"===t.type;case"function":return"FunctionDeclaration"===t.type||"FunctionExpression"===t.type||"ArrowFunctionExpression"===t.type}throw new Error("Unknown class name: ".concat(r.name))}throw new Error("Unknown selector type: ".concat(r.type))}function c(e,t){var r=e.type;return t&&t.visitorKeys&&t.visitorKeys[r]?t.visitorKeys[r]:s.VisitorKeys[r]?s.VisitorKeys[r]:t&&"function"==typeof t.fallback?t.fallback(e):Object.keys(e).filter((function(e){return"type"!==e}))}function f(t){return null!==t&&"object"===e(t)&&"string"==typeof t.type}function p(e,r,n,a,i){var s=t(n,1)[0];if(!s)return!1;var l,p=o(c(s,i));try{for(p.s();!(l=p.n()).done;){var h=s[l.value];if(Array.isArray(h)){var y=h.indexOf(e);if(y<0)continue;var d=void 0,m=void 0;"LEFT_SIDE"===a?(d=0,m=y):(d=y+1,m=h.length);for(var x=d;x0&&f(h[y-1])&&u(h[y-1],r,n,i))return!0;if("RIGHT_SIDE"===a&&y=0&&f===n(u.length))return!0}}}catch(e){l.e(e)}finally{l.f()}return!1}function d(n,a){if(null==n||"object"!=e(n))return[];null==a&&(a=n);for(var o=n.subject?[a]:[],i=0,s=function(e){for(var t=[],r=Object.keys(e),n=0;n= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }, + e: function (e) { + throw e; + }, + f: F + }; + } + + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var normalCompletion = true, + didErr = false, + err; + return { + s: function () { + it = o[Symbol.iterator](); + }, + n: function () { + var step = it.next(); + normalCompletion = step.done; + return step; + }, + e: function (e) { + didErr = true; + err = e; + }, + f: function () { + try { + if (!normalCompletion && it.return != null) it.return(); + } finally { + if (didErr) throw err; + } + } + }; + } + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function createCommonjsModule(fn, module) { @@ -188,6 +245,7 @@ BreakStatement: 'BreakStatement', CallExpression: 'CallExpression', CatchClause: 'CatchClause', + ChainExpression: 'ChainExpression', ClassBody: 'ClassBody', ClassDeclaration: 'ClassDeclaration', ClassExpression: 'ClassExpression', @@ -266,6 +324,7 @@ BreakStatement: ['label'], CallExpression: ['callee', 'arguments'], CatchClause: ['param', 'body'], + ChainExpression: ['expression'], ClassBody: ['body'], ClassDeclaration: ['id', 'superClass', 'body'], ClassExpression: ['id', 'superClass', 'body'], @@ -1132,7 +1191,10 @@ peg$c41 = peg$classExpectation([">", "<"], false, false), peg$c42 = ".", peg$c43 = peg$literalExpectation(".", false), - peg$c44 = function peg$c44(name, op, value) { + peg$c44 = function peg$c44(a, as) { + return [].concat.apply([a], as).join(''); + }, + peg$c45 = function peg$c45(name, op, value) { return { type: 'attribute', name: name, @@ -1140,35 +1202,35 @@ value: value }; }, - peg$c45 = function peg$c45(name) { + peg$c46 = function peg$c46(name) { return { type: 'attribute', name: name }; }, - peg$c46 = "\"", - peg$c47 = peg$literalExpectation("\"", false), - peg$c48 = /^[^\\"]/, - peg$c49 = peg$classExpectation(["\\", "\""], true, false), - peg$c50 = "\\", - peg$c51 = peg$literalExpectation("\\", false), - peg$c52 = peg$anyExpectation(), - peg$c53 = function peg$c53(a, b) { + peg$c47 = "\"", + peg$c48 = peg$literalExpectation("\"", false), + peg$c49 = /^[^\\"]/, + peg$c50 = peg$classExpectation(["\\", "\""], true, false), + peg$c51 = "\\", + peg$c52 = peg$literalExpectation("\\", false), + peg$c53 = peg$anyExpectation(), + peg$c54 = function peg$c54(a, b) { return a + b; }, - peg$c54 = function peg$c54(d) { + peg$c55 = function peg$c55(d) { return { type: 'literal', value: strUnescape(d.join('')) }; }, - peg$c55 = "'", - peg$c56 = peg$literalExpectation("'", false), - peg$c57 = /^[^\\']/, - peg$c58 = peg$classExpectation(["\\", "'"], true, false), - peg$c59 = /^[0-9]/, - peg$c60 = peg$classExpectation([["0", "9"]], false, false), - peg$c61 = function peg$c61(a, b) { + peg$c56 = "'", + peg$c57 = peg$literalExpectation("'", false), + peg$c58 = /^[^\\']/, + peg$c59 = peg$classExpectation(["\\", "'"], true, false), + peg$c60 = /^[0-9]/, + peg$c61 = peg$classExpectation([["0", "9"]], false, false), + peg$c62 = function peg$c62(a, b) { // Can use `a.flat().join('')` once supported var leadingDecimals = a ? [].concat.apply([], a).join('') : ''; return { @@ -1176,37 +1238,37 @@ value: parseFloat(leadingDecimals + b.join('')) }; }, - peg$c62 = function peg$c62(i) { + peg$c63 = function peg$c63(i) { return { type: 'literal', value: i }; }, - peg$c63 = "type(", - peg$c64 = peg$literalExpectation("type(", false), - peg$c65 = /^[^ )]/, - peg$c66 = peg$classExpectation([" ", ")"], true, false), - peg$c67 = ")", - peg$c68 = peg$literalExpectation(")", false), - peg$c69 = function peg$c69(t) { + peg$c64 = "type(", + peg$c65 = peg$literalExpectation("type(", false), + peg$c66 = /^[^ )]/, + peg$c67 = peg$classExpectation([" ", ")"], true, false), + peg$c68 = ")", + peg$c69 = peg$literalExpectation(")", false), + peg$c70 = function peg$c70(t) { return { type: 'type', value: t.join('') }; }, - peg$c70 = /^[imsu]/, - peg$c71 = peg$classExpectation(["i", "m", "s", "u"], false, false), - peg$c72 = "/", - peg$c73 = peg$literalExpectation("/", false), - peg$c74 = /^[^\/]/, - peg$c75 = peg$classExpectation(["/"], true, false), - peg$c76 = function peg$c76(d, flgs) { + peg$c71 = /^[imsu]/, + peg$c72 = peg$classExpectation(["i", "m", "s", "u"], false, false), + peg$c73 = "/", + peg$c74 = peg$literalExpectation("/", false), + peg$c75 = /^[^\/]/, + peg$c76 = peg$classExpectation(["/"], true, false), + peg$c77 = function peg$c77(d, flgs) { return { type: 'regexp', value: new RegExp(d.join(''), flgs ? flgs.join('') : '') }; }, - peg$c77 = function peg$c77(i, is) { + peg$c78 = function peg$c78(i, is) { return { type: 'field', name: is.reduce(function (memo, p) { @@ -1214,63 +1276,63 @@ }, i) }; }, - peg$c78 = ":not(", - peg$c79 = peg$literalExpectation(":not(", false), - peg$c80 = function peg$c80(ss) { + peg$c79 = ":not(", + peg$c80 = peg$literalExpectation(":not(", false), + peg$c81 = function peg$c81(ss) { return { type: 'not', selectors: ss }; }, - peg$c81 = ":matches(", - peg$c82 = peg$literalExpectation(":matches(", false), - peg$c83 = function peg$c83(ss) { + peg$c82 = ":matches(", + peg$c83 = peg$literalExpectation(":matches(", false), + peg$c84 = function peg$c84(ss) { return { type: 'matches', selectors: ss }; }, - peg$c84 = ":has(", - peg$c85 = peg$literalExpectation(":has(", false), - peg$c86 = function peg$c86(ss) { + peg$c85 = ":has(", + peg$c86 = peg$literalExpectation(":has(", false), + peg$c87 = function peg$c87(ss) { return { type: 'has', selectors: ss }; }, - peg$c87 = ":first-child", - peg$c88 = peg$literalExpectation(":first-child", false), - peg$c89 = function peg$c89() { + peg$c88 = ":first-child", + peg$c89 = peg$literalExpectation(":first-child", false), + peg$c90 = function peg$c90() { return nth(1); }, - peg$c90 = ":last-child", - peg$c91 = peg$literalExpectation(":last-child", false), - peg$c92 = function peg$c92() { + peg$c91 = ":last-child", + peg$c92 = peg$literalExpectation(":last-child", false), + peg$c93 = function peg$c93() { return nthLast(1); }, - peg$c93 = ":nth-child(", - peg$c94 = peg$literalExpectation(":nth-child(", false), - peg$c95 = function peg$c95(n) { + peg$c94 = ":nth-child(", + peg$c95 = peg$literalExpectation(":nth-child(", false), + peg$c96 = function peg$c96(n) { return nth(parseInt(n.join(''), 10)); }, - peg$c96 = ":nth-last-child(", - peg$c97 = peg$literalExpectation(":nth-last-child(", false), - peg$c98 = function peg$c98(n) { + peg$c97 = ":nth-last-child(", + peg$c98 = peg$literalExpectation(":nth-last-child(", false), + peg$c99 = function peg$c99(n) { return nthLast(parseInt(n.join(''), 10)); }, - peg$c99 = ":", - peg$c100 = peg$literalExpectation(":", false), - peg$c101 = "statement", - peg$c102 = peg$literalExpectation("statement", true), - peg$c103 = "expression", - peg$c104 = peg$literalExpectation("expression", true), - peg$c105 = "declaration", - peg$c106 = peg$literalExpectation("declaration", true), - peg$c107 = "function", - peg$c108 = peg$literalExpectation("function", true), - peg$c109 = "pattern", - peg$c110 = peg$literalExpectation("pattern", true), - peg$c111 = function peg$c111(c) { + peg$c100 = ":", + peg$c101 = peg$literalExpectation(":", false), + peg$c102 = "statement", + peg$c103 = peg$literalExpectation("statement", true), + peg$c104 = "expression", + peg$c105 = peg$literalExpectation("expression", true), + peg$c106 = "declaration", + peg$c107 = peg$literalExpectation("declaration", true), + peg$c108 = "function", + peg$c109 = peg$literalExpectation("function", true), + peg$c110 = "pattern", + peg$c111 = peg$literalExpectation("pattern", true), + peg$c112 = function peg$c112(c) { return { type: 'class', name: c @@ -2301,7 +2363,7 @@ } function peg$parseattrName() { - var s0, s1, s2; + var s0, s1, s2, s3, s4, s5; var key = peg$currPos * 30 + 13, cached = peg$resultsCache[key]; @@ -2311,49 +2373,81 @@ } s0 = peg$currPos; - s1 = []; - s2 = peg$parseidentifierName(); + s1 = peg$parseidentifierName(); + + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; - if (s2 === peg$FAILED) { if (input.charCodeAt(peg$currPos) === 46) { - s2 = peg$c42; + s4 = peg$c42; peg$currPos++; } else { - s2 = peg$FAILED; + s4 = peg$FAILED; { peg$fail(peg$c43); } } - } - if (s2 !== peg$FAILED) { - while (s2 !== peg$FAILED) { - s1.push(s2); - s2 = peg$parseidentifierName(); + if (s4 !== peg$FAILED) { + s5 = peg$parseidentifierName(); - if (s2 === peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 46) { - s2 = peg$c42; - peg$currPos++; - } else { - s2 = peg$FAILED; + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } - { - peg$fail(peg$c43); - } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 46) { + s4 = peg$c42; + peg$currPos++; + } else { + s4 = peg$FAILED; + + { + peg$fail(peg$c43); } } + + if (s4 !== peg$FAILED) { + s5 = peg$parseidentifierName(); + + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } } - } else { - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - s1 = peg$c6(s1); + if (s2 !== peg$FAILED) { + s1 = peg$c44(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; } - s0 = s1; peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 @@ -2391,7 +2485,7 @@ } if (s5 !== peg$FAILED) { - s1 = peg$c44(s1, s3, s5); + s1 = peg$c45(s1, s3, s5); s0 = s1; } else { peg$currPos = s0; @@ -2439,7 +2533,7 @@ } if (s5 !== peg$FAILED) { - s1 = peg$c44(s1, s3, s5); + s1 = peg$c45(s1, s3, s5); s0 = s1; } else { peg$currPos = s0; @@ -2467,7 +2561,7 @@ s1 = peg$parseattrName(); if (s1 !== peg$FAILED) { - s1 = peg$c45(s1); + s1 = peg$c46(s1); } s0 = s1; @@ -2494,27 +2588,27 @@ s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 34) { - s1 = peg$c46; + s1 = peg$c47; peg$currPos++; } else { s1 = peg$FAILED; { - peg$fail(peg$c47); + peg$fail(peg$c48); } } if (s1 !== peg$FAILED) { s2 = []; - if (peg$c48.test(input.charAt(peg$currPos))) { + if (peg$c49.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c49); + peg$fail(peg$c50); } } @@ -2522,13 +2616,13 @@ s3 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s4 = peg$c50; + s4 = peg$c51; peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c51); + peg$fail(peg$c52); } } @@ -2540,12 +2634,12 @@ s5 = peg$FAILED; { - peg$fail(peg$c52); + peg$fail(peg$c53); } } if (s5 !== peg$FAILED) { - s4 = peg$c53(s4, s5); + s4 = peg$c54(s4, s5); s3 = s4; } else { peg$currPos = s3; @@ -2560,14 +2654,14 @@ while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c48.test(input.charAt(peg$currPos))) { + if (peg$c49.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c49); + peg$fail(peg$c50); } } @@ -2575,13 +2669,13 @@ s3 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s4 = peg$c50; + s4 = peg$c51; peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c51); + peg$fail(peg$c52); } } @@ -2593,12 +2687,12 @@ s5 = peg$FAILED; { - peg$fail(peg$c52); + peg$fail(peg$c53); } } if (s5 !== peg$FAILED) { - s4 = peg$c53(s4, s5); + s4 = peg$c54(s4, s5); s3 = s4; } else { peg$currPos = s3; @@ -2613,18 +2707,18 @@ if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s3 = peg$c46; + s3 = peg$c47; peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c47); + peg$fail(peg$c48); } } if (s3 !== peg$FAILED) { - s1 = peg$c54(s2); + s1 = peg$c55(s2); s0 = s1; } else { peg$currPos = s0; @@ -2643,27 +2737,27 @@ s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 39) { - s1 = peg$c55; + s1 = peg$c56; peg$currPos++; } else { s1 = peg$FAILED; { - peg$fail(peg$c56); + peg$fail(peg$c57); } } if (s1 !== peg$FAILED) { s2 = []; - if (peg$c57.test(input.charAt(peg$currPos))) { + if (peg$c58.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c58); + peg$fail(peg$c59); } } @@ -2671,13 +2765,13 @@ s3 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s4 = peg$c50; + s4 = peg$c51; peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c51); + peg$fail(peg$c52); } } @@ -2689,12 +2783,12 @@ s5 = peg$FAILED; { - peg$fail(peg$c52); + peg$fail(peg$c53); } } if (s5 !== peg$FAILED) { - s4 = peg$c53(s4, s5); + s4 = peg$c54(s4, s5); s3 = s4; } else { peg$currPos = s3; @@ -2709,14 +2803,14 @@ while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c57.test(input.charAt(peg$currPos))) { + if (peg$c58.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c58); + peg$fail(peg$c59); } } @@ -2724,13 +2818,13 @@ s3 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s4 = peg$c50; + s4 = peg$c51; peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c51); + peg$fail(peg$c52); } } @@ -2742,12 +2836,12 @@ s5 = peg$FAILED; { - peg$fail(peg$c52); + peg$fail(peg$c53); } } if (s5 !== peg$FAILED) { - s4 = peg$c53(s4, s5); + s4 = peg$c54(s4, s5); s3 = s4; } else { peg$currPos = s3; @@ -2762,18 +2856,18 @@ if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 39) { - s3 = peg$c55; + s3 = peg$c56; peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c56); + peg$fail(peg$c57); } } if (s3 !== peg$FAILED) { - s1 = peg$c54(s2); + s1 = peg$c55(s2); s0 = s1; } else { peg$currPos = s0; @@ -2810,28 +2904,28 @@ s1 = peg$currPos; s2 = []; - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } } @@ -2867,14 +2961,14 @@ if (s1 !== peg$FAILED) { s2 = []; - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } @@ -2882,14 +2976,14 @@ while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } } @@ -2898,7 +2992,7 @@ } if (s2 !== peg$FAILED) { - s1 = peg$c61(s1, s2); + s1 = peg$c62(s1, s2); s0 = s1; } else { peg$currPos = s0; @@ -2930,7 +3024,7 @@ s1 = peg$parseidentifierName(); if (s1 !== peg$FAILED) { - s1 = peg$c62(s1); + s1 = peg$c63(s1); } s0 = s1; @@ -2953,14 +3047,14 @@ s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c63) { - s1 = peg$c63; + if (input.substr(peg$currPos, 5) === peg$c64) { + s1 = peg$c64; peg$currPos += 5; } else { s1 = peg$FAILED; { - peg$fail(peg$c64); + peg$fail(peg$c65); } } @@ -2970,14 +3064,14 @@ if (s2 !== peg$FAILED) { s3 = []; - if (peg$c65.test(input.charAt(peg$currPos))) { + if (peg$c66.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c66); + peg$fail(peg$c67); } } @@ -2985,14 +3079,14 @@ while (s4 !== peg$FAILED) { s3.push(s4); - if (peg$c65.test(input.charAt(peg$currPos))) { + if (peg$c66.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c66); + peg$fail(peg$c67); } } } @@ -3005,18 +3099,18 @@ if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; { - peg$fail(peg$c68); + peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { - s1 = peg$c69(s3); + s1 = peg$c70(s3); s0 = s1; } else { peg$currPos = s0; @@ -3058,14 +3152,14 @@ s0 = []; - if (peg$c70.test(input.charAt(peg$currPos))) { + if (peg$c71.test(input.charAt(peg$currPos))) { s1 = input.charAt(peg$currPos); peg$currPos++; } else { s1 = peg$FAILED; { - peg$fail(peg$c71); + peg$fail(peg$c72); } } @@ -3073,14 +3167,14 @@ while (s1 !== peg$FAILED) { s0.push(s1); - if (peg$c70.test(input.charAt(peg$currPos))) { + if (peg$c71.test(input.charAt(peg$currPos))) { s1 = input.charAt(peg$currPos); peg$currPos++; } else { s1 = peg$FAILED; { - peg$fail(peg$c71); + peg$fail(peg$c72); } } } @@ -3108,27 +3202,27 @@ s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 47) { - s1 = peg$c72; + s1 = peg$c73; peg$currPos++; } else { s1 = peg$FAILED; { - peg$fail(peg$c73); + peg$fail(peg$c74); } } if (s1 !== peg$FAILED) { s2 = []; - if (peg$c74.test(input.charAt(peg$currPos))) { + if (peg$c75.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c75); + peg$fail(peg$c76); } } @@ -3136,14 +3230,14 @@ while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c74.test(input.charAt(peg$currPos))) { + if (peg$c75.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c75); + peg$fail(peg$c76); } } } @@ -3153,13 +3247,13 @@ if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 47) { - s3 = peg$c72; + s3 = peg$c73; peg$currPos++; } else { s3 = peg$FAILED; { - peg$fail(peg$c73); + peg$fail(peg$c74); } } @@ -3171,7 +3265,7 @@ } if (s4 !== peg$FAILED) { - s1 = peg$c76(s2, s4); + s1 = peg$c77(s2, s4); s0 = s1; } else { peg$currPos = s0; @@ -3285,7 +3379,7 @@ } if (s3 !== peg$FAILED) { - s1 = peg$c77(s2, s3); + s1 = peg$c78(s2, s3); s0 = s1; } else { peg$currPos = s0; @@ -3319,14 +3413,14 @@ s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c78) { - s1 = peg$c78; + if (input.substr(peg$currPos, 5) === peg$c79) { + s1 = peg$c79; peg$currPos += 5; } else { s1 = peg$FAILED; { - peg$fail(peg$c79); + peg$fail(peg$c80); } } @@ -3341,18 +3435,18 @@ if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; { - peg$fail(peg$c68); + peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { - s1 = peg$c80(s3); + s1 = peg$c81(s3); s0 = s1; } else { peg$currPos = s0; @@ -3394,14 +3488,14 @@ s0 = peg$currPos; - if (input.substr(peg$currPos, 9) === peg$c81) { - s1 = peg$c81; + if (input.substr(peg$currPos, 9) === peg$c82) { + s1 = peg$c82; peg$currPos += 9; } else { s1 = peg$FAILED; { - peg$fail(peg$c82); + peg$fail(peg$c83); } } @@ -3416,18 +3510,18 @@ if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; { - peg$fail(peg$c68); + peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { - s1 = peg$c83(s3); + s1 = peg$c84(s3); s0 = s1; } else { peg$currPos = s0; @@ -3469,14 +3563,14 @@ s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c84) { - s1 = peg$c84; + if (input.substr(peg$currPos, 5) === peg$c85) { + s1 = peg$c85; peg$currPos += 5; } else { s1 = peg$FAILED; { - peg$fail(peg$c85); + peg$fail(peg$c86); } } @@ -3491,18 +3585,18 @@ if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; { - peg$fail(peg$c68); + peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { - s1 = peg$c86(s3); + s1 = peg$c87(s3); s0 = s1; } else { peg$currPos = s0; @@ -3544,19 +3638,19 @@ s0 = peg$currPos; - if (input.substr(peg$currPos, 12) === peg$c87) { - s1 = peg$c87; + if (input.substr(peg$currPos, 12) === peg$c88) { + s1 = peg$c88; peg$currPos += 12; } else { s1 = peg$FAILED; { - peg$fail(peg$c88); + peg$fail(peg$c89); } } if (s1 !== peg$FAILED) { - s1 = peg$c89(); + s1 = peg$c90(); } s0 = s1; @@ -3579,19 +3673,19 @@ s0 = peg$currPos; - if (input.substr(peg$currPos, 11) === peg$c90) { - s1 = peg$c90; + if (input.substr(peg$currPos, 11) === peg$c91) { + s1 = peg$c91; peg$currPos += 11; } else { s1 = peg$FAILED; { - peg$fail(peg$c91); + peg$fail(peg$c92); } } if (s1 !== peg$FAILED) { - s1 = peg$c92(); + s1 = peg$c93(); } s0 = s1; @@ -3614,14 +3708,14 @@ s0 = peg$currPos; - if (input.substr(peg$currPos, 11) === peg$c93) { - s1 = peg$c93; + if (input.substr(peg$currPos, 11) === peg$c94) { + s1 = peg$c94; peg$currPos += 11; } else { s1 = peg$FAILED; { - peg$fail(peg$c94); + peg$fail(peg$c95); } } @@ -3631,14 +3725,14 @@ if (s2 !== peg$FAILED) { s3 = []; - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } @@ -3646,14 +3740,14 @@ while (s4 !== peg$FAILED) { s3.push(s4); - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } } @@ -3666,18 +3760,18 @@ if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; { - peg$fail(peg$c68); + peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { - s1 = peg$c95(s3); + s1 = peg$c96(s3); s0 = s1; } else { peg$currPos = s0; @@ -3719,14 +3813,14 @@ s0 = peg$currPos; - if (input.substr(peg$currPos, 16) === peg$c96) { - s1 = peg$c96; + if (input.substr(peg$currPos, 16) === peg$c97) { + s1 = peg$c97; peg$currPos += 16; } else { s1 = peg$FAILED; { - peg$fail(peg$c97); + peg$fail(peg$c98); } } @@ -3736,14 +3830,14 @@ if (s2 !== peg$FAILED) { s3 = []; - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } @@ -3751,14 +3845,14 @@ while (s4 !== peg$FAILED) { s3.push(s4); - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; { - peg$fail(peg$c60); + peg$fail(peg$c61); } } } @@ -3771,18 +3865,18 @@ if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; { - peg$fail(peg$c68); + peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { - s1 = peg$c98(s3); + s1 = peg$c99(s3); s0 = s1; } else { peg$currPos = s0; @@ -3825,73 +3919,73 @@ s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 58) { - s1 = peg$c99; + s1 = peg$c100; peg$currPos++; } else { s1 = peg$FAILED; { - peg$fail(peg$c100); + peg$fail(peg$c101); } } if (s1 !== peg$FAILED) { - if (input.substr(peg$currPos, 9).toLowerCase() === peg$c101) { + if (input.substr(peg$currPos, 9).toLowerCase() === peg$c102) { s2 = input.substr(peg$currPos, 9); peg$currPos += 9; } else { s2 = peg$FAILED; { - peg$fail(peg$c102); + peg$fail(peg$c103); } } if (s2 === peg$FAILED) { - if (input.substr(peg$currPos, 10).toLowerCase() === peg$c103) { + if (input.substr(peg$currPos, 10).toLowerCase() === peg$c104) { s2 = input.substr(peg$currPos, 10); peg$currPos += 10; } else { s2 = peg$FAILED; { - peg$fail(peg$c104); + peg$fail(peg$c105); } } if (s2 === peg$FAILED) { - if (input.substr(peg$currPos, 11).toLowerCase() === peg$c105) { + if (input.substr(peg$currPos, 11).toLowerCase() === peg$c106) { s2 = input.substr(peg$currPos, 11); peg$currPos += 11; } else { s2 = peg$FAILED; { - peg$fail(peg$c106); + peg$fail(peg$c107); } } if (s2 === peg$FAILED) { - if (input.substr(peg$currPos, 8).toLowerCase() === peg$c107) { + if (input.substr(peg$currPos, 8).toLowerCase() === peg$c108) { s2 = input.substr(peg$currPos, 8); peg$currPos += 8; } else { s2 = peg$FAILED; { - peg$fail(peg$c108); + peg$fail(peg$c109); } } if (s2 === peg$FAILED) { - if (input.substr(peg$currPos, 7).toLowerCase() === peg$c109) { + if (input.substr(peg$currPos, 7).toLowerCase() === peg$c110) { s2 = input.substr(peg$currPos, 7); peg$currPos += 7; } else { s2 = peg$FAILED; { - peg$fail(peg$c110); + peg$fail(peg$c111); } } } @@ -3900,7 +3994,7 @@ } if (s2 !== peg$FAILED) { - s1 = peg$c111(s2); + s1 = peg$c112(s2); s0 = s1; } else { peg$currPos = s0; @@ -4026,12 +4120,23 @@ function getPath(obj, key) { var keys = key.split('.'); - for (var i = 0; i < keys.length; i++) { - if (obj == null) { - return obj; - } + var _iterator = _createForOfIteratorHelper(keys), + _step; + + try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var _key = _step.value; + + if (obj == null) { + return obj; + } - obj = obj[keys[i]]; + obj = obj[_key]; + } + } catch (err) { + _iterator.e(err); + } finally { + _iterator.f(); } return obj; @@ -4059,10 +4164,21 @@ var remainingPath = path.slice(1); if (Array.isArray(field)) { - for (var i = 0, l = field.length; i < l; ++i) { - if (inPath(node, field[i], remainingPath)) { - return true; + var _iterator2 = _createForOfIteratorHelper(field), + _step2; + + try { + for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { + var component = _step2.value; + + if (inPath(node, component, remainingPath)) { + return true; + } } + } catch (err) { + _iterator2.e(err); + } finally { + _iterator2.f(); } return false; @@ -4070,19 +4186,32 @@ return inPath(node, field, remainingPath); } } + /** + * @callback TraverseOptionFallback + * @param {external:AST} node The given node. + * @returns {string[]} An array of visitor keys for the given node. + */ + + /** + * @typedef {object} ESQueryOptions + * @property { { [nodeType: string]: string[] } } [visitorKeys] By passing `visitorKeys` mapping, we can extend the properties of the nodes that traverse the node. + * @property {TraverseOptionFallback} [fallback] By passing `fallback` option, we can control the properties of traversing nodes when encountering unknown nodes. + */ + /** * Given a `node` and its ancestors, determine if `node` is matched * by `selector`. * @param {?external:AST} node * @param {?SelectorAST} selector * @param {external:AST[]} [ancestry=[]] + * @param {ESQueryOptions} [options] * @throws {Error} Unknowns (operator, class name, selector type, or * selector value type) * @returns {boolean} */ - function matches(node, selector, ancestry) { + function matches(node, selector, ancestry, options) { if (!selector) { return true; } @@ -4110,28 +4239,61 @@ } case 'matches': - for (var i = 0, l = selector.selectors.length; i < l; ++i) { - if (matches(node, selector.selectors[i], ancestry)) { - return true; + var _iterator3 = _createForOfIteratorHelper(selector.selectors), + _step3; + + try { + for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { + var sel = _step3.value; + + if (matches(node, sel, ancestry, options)) { + return true; + } } + } catch (err) { + _iterator3.e(err); + } finally { + _iterator3.f(); } return false; case 'compound': - for (var _i = 0, _l = selector.selectors.length; _i < _l; ++_i) { - if (!matches(node, selector.selectors[_i], ancestry)) { - return false; + var _iterator4 = _createForOfIteratorHelper(selector.selectors), + _step4; + + try { + for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { + var _sel = _step4.value; + + if (!matches(node, _sel, ancestry, options)) { + return false; + } } + } catch (err) { + _iterator4.e(err); + } finally { + _iterator4.f(); } return true; case 'not': - for (var _i2 = 0, _l2 = selector.selectors.length; _i2 < _l2; ++_i2) { - if (matches(node, selector.selectors[_i2], ancestry)) { - return false; + var _iterator5 = _createForOfIteratorHelper(selector.selectors), + _step5; + + try { + for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) { + var _sel2 = _step5.value; + + if (matches(node, _sel2, ancestry, options)) { + return false; + } } + } catch (err) { + _iterator5.e(err); + } finally { + _iterator5.f(); } return true; @@ -4141,27 +4303,38 @@ var _ret = function () { var collector = []; - var _loop = function _loop(_i3, _l3) { - var a = []; - estraverse.traverse(node, { - enter: function enter(node, parent) { - if (parent != null) { - a.unshift(parent); - } - - if (matches(node, selector.selectors[_i3], a)) { - collector.push(node); - } - }, - leave: function leave() { - a.shift(); - }, - fallback: 'iteration' - }); - }; + var _iterator6 = _createForOfIteratorHelper(selector.selectors), + _step6; + + try { + var _loop = function _loop() { + var sel = _step6.value; + var a = []; + estraverse.traverse(node, { + enter: function enter(node, parent) { + if (parent != null) { + a.unshift(parent); + } - for (var _i3 = 0, _l3 = selector.selectors.length; _i3 < _l3; ++_i3) { - _loop(_i3); + if (matches(node, sel, a, options)) { + collector.push(node); + } + }, + leave: function leave() { + a.shift(); + }, + keys: options && options.visitorKeys, + fallback: options && options.fallback || 'iteration' + }); + }; + + for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) { + _loop(); + } + } catch (err) { + _iterator6.e(err); + } finally { + _iterator6.f(); } return { @@ -4173,16 +4346,16 @@ } case 'child': - if (matches(node, selector.right, ancestry)) { - return matches(ancestry[0], selector.left, ancestry.slice(1)); + if (matches(node, selector.right, ancestry, options)) { + return matches(ancestry[0], selector.left, ancestry.slice(1), options); } return false; case 'descendant': - if (matches(node, selector.right, ancestry)) { - for (var _i4 = 0, _l4 = ancestry.length; _i4 < _l4; ++_i4) { - if (matches(ancestry[_i4], selector.left, ancestry.slice(_i4 + 1))) { + if (matches(node, selector.right, ancestry, options)) { + for (var i = 0, l = ancestry.length; i < l; ++i) { + if (matches(ancestry[i], selector.left, ancestry.slice(i + 1), options)) { return true; } } @@ -4243,20 +4416,20 @@ } case 'sibling': - return matches(node, selector.right, ancestry) && sibling(node, selector.left, ancestry, LEFT_SIDE) || selector.left.subject && matches(node, selector.left, ancestry) && sibling(node, selector.right, ancestry, RIGHT_SIDE); + return matches(node, selector.right, ancestry, options) && sibling(node, selector.left, ancestry, LEFT_SIDE, options) || selector.left.subject && matches(node, selector.left, ancestry, options) && sibling(node, selector.right, ancestry, RIGHT_SIDE, options); case 'adjacent': - return matches(node, selector.right, ancestry) && adjacent(node, selector.left, ancestry, LEFT_SIDE) || selector.right.subject && matches(node, selector.left, ancestry) && adjacent(node, selector.right, ancestry, RIGHT_SIDE); + return matches(node, selector.right, ancestry, options) && adjacent(node, selector.left, ancestry, LEFT_SIDE, options) || selector.right.subject && matches(node, selector.left, ancestry, options) && adjacent(node, selector.right, ancestry, RIGHT_SIDE, options); case 'nth-child': - return matches(node, selector.right, ancestry) && nthChild(node, ancestry, function () { + return matches(node, selector.right, ancestry, options) && nthChild(node, ancestry, function () { return selector.index.value - 1; - }); + }, options); case 'nth-last-child': - return matches(node, selector.right, ancestry) && nthChild(node, ancestry, function (length) { + return matches(node, selector.right, ancestry, options) && nthChild(node, ancestry, function (length) { return length - selector.index.value; - }); + }, options); case 'class': switch (selector.name.toLowerCase()) { @@ -4283,6 +4456,44 @@ throw new Error("Unknown selector type: ".concat(selector.type)); } + /** + * Get visitor keys of a given node. + * @param {external:AST} node The AST node to get keys. + * @param {ESQueryOptions|undefined} options + * @returns {string[]} Visitor keys of the node. + */ + + + function getVisitorKeys(node, options) { + var nodeType = node.type; + + if (options && options.visitorKeys && options.visitorKeys[nodeType]) { + return options.visitorKeys[nodeType]; + } + + if (estraverse.VisitorKeys[nodeType]) { + return estraverse.VisitorKeys[nodeType]; + } + + if (options && typeof options.fallback === 'function') { + return options.fallback(node); + } // 'iteration' fallback + + + return Object.keys(node).filter(function (key) { + return key !== 'type'; + }); + } + /** + * Check whether the given value is an ASTNode or not. + * @param {any} node The value to check. + * @returns {boolean} `true` if the value is an ASTNode. + */ + + + function isNode(node) { + return node !== null && _typeof(node) === 'object' && typeof node.type === 'string'; + } /** * Determines if the given node has a sibling that matches the * given selector. @@ -4290,11 +4501,12 @@ * @param {SelectorSequenceAST} selector * @param {external:AST[]} ancestry * @param {Side} side + * @param {ESQueryOptions|undefined} options * @returns {boolean} */ - function sibling(node, selector, ancestry, side) { + function sibling(node, selector, ancestry, side, options) { var _ancestry = _slicedToArray(ancestry, 1), parent = _ancestry[0]; @@ -4302,35 +4514,45 @@ return false; } - var keys = estraverse.VisitorKeys[parent.type]; + var keys = getVisitorKeys(parent, options); - for (var i = 0, l = keys.length; i < l; ++i) { - var listProp = parent[keys[i]]; + var _iterator7 = _createForOfIteratorHelper(keys), + _step7; - if (Array.isArray(listProp)) { - var startIndex = listProp.indexOf(node); + try { + for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) { + var key = _step7.value; + var listProp = parent[key]; - if (startIndex < 0) { - continue; - } + if (Array.isArray(listProp)) { + var startIndex = listProp.indexOf(node); - var lowerBound = void 0, - upperBound = void 0; + if (startIndex < 0) { + continue; + } - if (side === LEFT_SIDE) { - lowerBound = 0; - upperBound = startIndex; - } else { - lowerBound = startIndex + 1; - upperBound = listProp.length; - } + var lowerBound = void 0, + upperBound = void 0; - for (var k = lowerBound; k < upperBound; ++k) { - if (matches(listProp[k], selector, ancestry)) { - return true; + if (side === LEFT_SIDE) { + lowerBound = 0; + upperBound = startIndex; + } else { + lowerBound = startIndex + 1; + upperBound = listProp.length; + } + + for (var k = lowerBound; k < upperBound; ++k) { + if (isNode(listProp[k]) && matches(listProp[k], selector, ancestry, options)) { + return true; + } } } } + } catch (err) { + _iterator7.e(err); + } finally { + _iterator7.f(); } return false; @@ -4342,11 +4564,12 @@ * @param {SelectorSequenceAST} selector * @param {external:AST[]} ancestry * @param {Side} side + * @param {ESQueryOptions|undefined} options * @returns {boolean} */ - function adjacent(node, selector, ancestry, side) { + function adjacent(node, selector, ancestry, side, options) { var _ancestry2 = _slicedToArray(ancestry, 1), parent = _ancestry2[0]; @@ -4354,26 +4577,36 @@ return false; } - var keys = estraverse.VisitorKeys[parent.type]; + var keys = getVisitorKeys(parent, options); - for (var i = 0, l = keys.length; i < l; ++i) { - var listProp = parent[keys[i]]; + var _iterator8 = _createForOfIteratorHelper(keys), + _step8; - if (Array.isArray(listProp)) { - var idx = listProp.indexOf(node); + try { + for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) { + var key = _step8.value; + var listProp = parent[key]; - if (idx < 0) { - continue; - } + if (Array.isArray(listProp)) { + var idx = listProp.indexOf(node); - if (side === LEFT_SIDE && idx > 0 && matches(listProp[idx - 1], selector, ancestry)) { - return true; - } + if (idx < 0) { + continue; + } - if (side === RIGHT_SIDE && idx < listProp.length - 1 && matches(listProp[idx + 1], selector, ancestry)) { - return true; + if (side === LEFT_SIDE && idx > 0 && isNode(listProp[idx - 1]) && matches(listProp[idx - 1], selector, ancestry, options)) { + return true; + } + + if (side === RIGHT_SIDE && idx < listProp.length - 1 && isNode(listProp[idx + 1]) && matches(listProp[idx + 1], selector, ancestry, options)) { + return true; + } } } + } catch (err) { + _iterator8.e(err); + } finally { + _iterator8.f(); } return false; @@ -4390,11 +4623,12 @@ * @param {external:AST} node * @param {external:AST[]} ancestry * @param {IndexFunction} idxFn + * @param {ESQueryOptions|undefined} options * @returns {boolean} */ - function nthChild(node, ancestry, idxFn) { + function nthChild(node, ancestry, idxFn, options) { var _ancestry3 = _slicedToArray(ancestry, 1), parent = _ancestry3[0]; @@ -4402,18 +4636,28 @@ return false; } - var keys = estraverse.VisitorKeys[parent.type]; + var keys = getVisitorKeys(parent, options); - for (var i = 0, l = keys.length; i < l; ++i) { - var listProp = parent[keys[i]]; + var _iterator9 = _createForOfIteratorHelper(keys), + _step9; - if (Array.isArray(listProp)) { - var idx = listProp.indexOf(node); + try { + for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) { + var key = _step9.value; + var listProp = parent[key]; - if (idx >= 0 && idx === idxFn(listProp.length)) { - return true; + if (Array.isArray(listProp)) { + var idx = listProp.indexOf(node); + + if (idx >= 0 && idx === idxFn(listProp.length)) { + return true; + } } } + } catch (err) { + _iterator9.e(err); + } finally { + _iterator9.f(); } return false; @@ -4438,8 +4682,8 @@ var results = selector.subject ? [ancestor] : []; - for (var _i5 = 0, _Object$entries = _objectEntries(selector); _i5 < _Object$entries.length; _i5++) { - var _Object$entries$_i = _slicedToArray(_Object$entries[_i5], 2), + for (var _i = 0, _Object$entries = _objectEntries(selector); _i < _Object$entries.length; _i++) { + var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), p = _Object$entries$_i[0], sel = _Object$entries$_i[1]; @@ -4461,11 +4705,12 @@ * @param {external:AST} ast * @param {?SelectorAST} selector * @param {TraverseVisitor} visitor + * @param {ESQueryOptions} [options] * @returns {external:AST[]} */ - function traverse(ast, selector, visitor) { + function traverse(ast, selector, visitor, options) { if (!selector) { return; } @@ -4478,17 +4723,17 @@ ancestry.unshift(parent); } - if (matches(node, selector, ancestry)) { + if (matches(node, selector, ancestry, options)) { if (altSubjects.length) { for (var i = 0, l = altSubjects.length; i < l; ++i) { - if (matches(node, altSubjects[i], ancestry)) { + if (matches(node, altSubjects[i], ancestry, options)) { visitor(node, parent, ancestry); } for (var k = 0, m = ancestry.length; k < m; ++k) { var succeedingAncestry = ancestry.slice(k + 1); - if (matches(ancestry[k], altSubjects[i], succeedingAncestry)) { + if (matches(ancestry[k], altSubjects[i], succeedingAncestry, options)) { visitor(ancestry[k], parent, succeedingAncestry); } } @@ -4501,7 +4746,8 @@ leave: function leave() { ancestry.shift(); }, - fallback: 'iteration' + keys: options && options.visitorKeys, + fallback: options && options.fallback || 'iteration' }); } /** @@ -4509,15 +4755,16 @@ * match the selector. * @param {external:AST} ast * @param {?SelectorAST} selector + * @param {ESQueryOptions} [options] * @returns {external:AST[]} */ - function match(ast, selector) { + function match(ast, selector, options) { var results = []; traverse(ast, selector, function (node) { results.push(node); - }); + }, options); return results; } /** @@ -4534,12 +4781,13 @@ * Query the code AST using the selector string. * @param {external:AST} ast * @param {string} selector + * @param {ESQueryOptions} [options] * @returns {external:AST[]} */ - function query(ast, selector) { - return match(ast, parse(selector)); + function query(ast, selector, options) { + return match(ast, parse(selector), options); } query.parse = parse; diff --git a/tools/node_modules/eslint/node_modules/esquery/dist/esquery.lite.js b/tools/node_modules/eslint/node_modules/esquery/dist/esquery.lite.js new file mode 100644 index 00000000000000..8a181abec8df8c --- /dev/null +++ b/tools/node_modules/eslint/node_modules/esquery/dist/esquery.lite.js @@ -0,0 +1,3995 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('estraverse')) : + typeof define === 'function' && define.amd ? define(['estraverse'], factory) : + (global = global || self, global.esquery = factory(global.estraverse)); +}(this, (function (estraverse) { 'use strict'; + + estraverse = estraverse && Object.prototype.hasOwnProperty.call(estraverse, 'default') ? estraverse['default'] : estraverse; + + function _typeof(obj) { + "@babel/helpers - typeof"; + + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); + } + + function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); + } + + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); + } + + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); + } + + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } + + function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); + } + + function _iterableToArrayLimit(arr, i) { + if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; + } + + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + function _createForOfIteratorHelper(o, allowArrayLike) { + var it; + + if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + var i = 0; + + var F = function () {}; + + return { + s: F, + n: function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }, + e: function (e) { + throw e; + }, + f: F + }; + } + + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var normalCompletion = true, + didErr = false, + err; + return { + s: function () { + it = o[Symbol.iterator](); + }, + n: function () { + var step = it.next(); + normalCompletion = step.done; + return step; + }, + e: function (e) { + didErr = true; + err = e; + }, + f: function () { + try { + if (!normalCompletion && it.return != null) it.return(); + } finally { + if (didErr) throw err; + } + } + }; + } + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var parser = createCommonjsModule(function (module) { + /* + * Generated by PEG.js 0.10.0. + * + * http://pegjs.org/ + */ + (function (root, factory) { + if ( module.exports) { + module.exports = factory(); + } + })(commonjsGlobal, function () { + + function peg$subclass(child, parent) { + function ctor() { + this.constructor = child; + } + + ctor.prototype = parent.prototype; + child.prototype = new ctor(); + } + + function peg$SyntaxError(message, expected, found, location) { + this.message = message; + this.expected = expected; + this.found = found; + this.location = location; + this.name = "SyntaxError"; + + if (typeof Error.captureStackTrace === "function") { + Error.captureStackTrace(this, peg$SyntaxError); + } + } + + peg$subclass(peg$SyntaxError, Error); + + peg$SyntaxError.buildMessage = function (expected, found) { + var DESCRIBE_EXPECTATION_FNS = { + literal: function literal(expectation) { + return "\"" + literalEscape(expectation.text) + "\""; + }, + "class": function _class(expectation) { + var escapedParts = "", + i; + + for (i = 0; i < expectation.parts.length; i++) { + escapedParts += expectation.parts[i] instanceof Array ? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1]) : classEscape(expectation.parts[i]); + } + + return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]"; + }, + any: function any(expectation) { + return "any character"; + }, + end: function end(expectation) { + return "end of input"; + }, + other: function other(expectation) { + return expectation.description; + } + }; + + function hex(ch) { + return ch.charCodeAt(0).toString(16).toUpperCase(); + } + + function literalEscape(s) { + return s.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\0/g, '\\0').replace(/\t/g, '\\t').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/[\x00-\x0F]/g, function (ch) { + return '\\x0' + hex(ch); + }).replace(/[\x10-\x1F\x7F-\x9F]/g, function (ch) { + return '\\x' + hex(ch); + }); + } + + function classEscape(s) { + return s.replace(/\\/g, '\\\\').replace(/\]/g, '\\]').replace(/\^/g, '\\^').replace(/-/g, '\\-').replace(/\0/g, '\\0').replace(/\t/g, '\\t').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/[\x00-\x0F]/g, function (ch) { + return '\\x0' + hex(ch); + }).replace(/[\x10-\x1F\x7F-\x9F]/g, function (ch) { + return '\\x' + hex(ch); + }); + } + + function describeExpectation(expectation) { + return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation); + } + + function describeExpected(expected) { + var descriptions = new Array(expected.length), + i, + j; + + for (i = 0; i < expected.length; i++) { + descriptions[i] = describeExpectation(expected[i]); + } + + descriptions.sort(); + + if (descriptions.length > 0) { + for (i = 1, j = 1; i < descriptions.length; i++) { + if (descriptions[i - 1] !== descriptions[i]) { + descriptions[j] = descriptions[i]; + j++; + } + } + + descriptions.length = j; + } + + switch (descriptions.length) { + case 1: + return descriptions[0]; + + case 2: + return descriptions[0] + " or " + descriptions[1]; + + default: + return descriptions.slice(0, -1).join(", ") + ", or " + descriptions[descriptions.length - 1]; + } + } + + function describeFound(found) { + return found ? "\"" + literalEscape(found) + "\"" : "end of input"; + } + + return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found."; + }; + + function peg$parse(input, options) { + options = options !== void 0 ? options : {}; + + var peg$FAILED = {}, + peg$startRuleFunctions = { + start: peg$parsestart + }, + peg$startRuleFunction = peg$parsestart, + peg$c0 = function peg$c0(ss) { + return ss.length === 1 ? ss[0] : { + type: 'matches', + selectors: ss + }; + }, + peg$c1 = function peg$c1() { + return void 0; + }, + peg$c2 = " ", + peg$c3 = peg$literalExpectation(" ", false), + peg$c4 = /^[^ [\],():#!=><~+.]/, + peg$c5 = peg$classExpectation([" ", "[", "]", ",", "(", ")", ":", "#", "!", "=", ">", "<", "~", "+", "."], true, false), + peg$c6 = function peg$c6(i) { + return i.join(''); + }, + peg$c7 = ">", + peg$c8 = peg$literalExpectation(">", false), + peg$c9 = function peg$c9() { + return 'child'; + }, + peg$c10 = "~", + peg$c11 = peg$literalExpectation("~", false), + peg$c12 = function peg$c12() { + return 'sibling'; + }, + peg$c13 = "+", + peg$c14 = peg$literalExpectation("+", false), + peg$c15 = function peg$c15() { + return 'adjacent'; + }, + peg$c16 = function peg$c16() { + return 'descendant'; + }, + peg$c17 = ",", + peg$c18 = peg$literalExpectation(",", false), + peg$c19 = function peg$c19(s, ss) { + return [s].concat(ss.map(function (s) { + return s[3]; + })); + }, + peg$c20 = function peg$c20(a, ops) { + return ops.reduce(function (memo, rhs) { + return { + type: rhs[0], + left: memo, + right: rhs[1] + }; + }, a); + }, + peg$c21 = "!", + peg$c22 = peg$literalExpectation("!", false), + peg$c23 = function peg$c23(subject, as) { + var b = as.length === 1 ? as[0] : { + type: 'compound', + selectors: as + }; + if (subject) b.subject = true; + return b; + }, + peg$c24 = "*", + peg$c25 = peg$literalExpectation("*", false), + peg$c26 = function peg$c26(a) { + return { + type: 'wildcard', + value: a + }; + }, + peg$c27 = "#", + peg$c28 = peg$literalExpectation("#", false), + peg$c29 = function peg$c29(i) { + return { + type: 'identifier', + value: i + }; + }, + peg$c30 = "[", + peg$c31 = peg$literalExpectation("[", false), + peg$c32 = "]", + peg$c33 = peg$literalExpectation("]", false), + peg$c34 = function peg$c34(v) { + return v; + }, + peg$c35 = /^[>", "<", "!"], false, false), + peg$c37 = "=", + peg$c38 = peg$literalExpectation("=", false), + peg$c39 = function peg$c39(a) { + return (a || '') + '='; + }, + peg$c40 = /^[><]/, + peg$c41 = peg$classExpectation([">", "<"], false, false), + peg$c42 = ".", + peg$c43 = peg$literalExpectation(".", false), + peg$c44 = function peg$c44(a, as) { + return [].concat.apply([a], as).join(''); + }, + peg$c45 = function peg$c45(name, op, value) { + return { + type: 'attribute', + name: name, + operator: op, + value: value + }; + }, + peg$c46 = function peg$c46(name) { + return { + type: 'attribute', + name: name + }; + }, + peg$c47 = "\"", + peg$c48 = peg$literalExpectation("\"", false), + peg$c49 = /^[^\\"]/, + peg$c50 = peg$classExpectation(["\\", "\""], true, false), + peg$c51 = "\\", + peg$c52 = peg$literalExpectation("\\", false), + peg$c53 = peg$anyExpectation(), + peg$c54 = function peg$c54(a, b) { + return a + b; + }, + peg$c55 = function peg$c55(d) { + return { + type: 'literal', + value: strUnescape(d.join('')) + }; + }, + peg$c56 = "'", + peg$c57 = peg$literalExpectation("'", false), + peg$c58 = /^[^\\']/, + peg$c59 = peg$classExpectation(["\\", "'"], true, false), + peg$c60 = /^[0-9]/, + peg$c61 = peg$classExpectation([["0", "9"]], false, false), + peg$c62 = function peg$c62(a, b) { + // Can use `a.flat().join('')` once supported + var leadingDecimals = a ? [].concat.apply([], a).join('') : ''; + return { + type: 'literal', + value: parseFloat(leadingDecimals + b.join('')) + }; + }, + peg$c63 = function peg$c63(i) { + return { + type: 'literal', + value: i + }; + }, + peg$c64 = "type(", + peg$c65 = peg$literalExpectation("type(", false), + peg$c66 = /^[^ )]/, + peg$c67 = peg$classExpectation([" ", ")"], true, false), + peg$c68 = ")", + peg$c69 = peg$literalExpectation(")", false), + peg$c70 = function peg$c70(t) { + return { + type: 'type', + value: t.join('') + }; + }, + peg$c71 = /^[imsu]/, + peg$c72 = peg$classExpectation(["i", "m", "s", "u"], false, false), + peg$c73 = "/", + peg$c74 = peg$literalExpectation("/", false), + peg$c75 = /^[^\/]/, + peg$c76 = peg$classExpectation(["/"], true, false), + peg$c77 = function peg$c77(d, flgs) { + return { + type: 'regexp', + value: new RegExp(d.join(''), flgs ? flgs.join('') : '') + }; + }, + peg$c78 = function peg$c78(i, is) { + return { + type: 'field', + name: is.reduce(function (memo, p) { + return memo + p[0] + p[1]; + }, i) + }; + }, + peg$c79 = ":not(", + peg$c80 = peg$literalExpectation(":not(", false), + peg$c81 = function peg$c81(ss) { + return { + type: 'not', + selectors: ss + }; + }, + peg$c82 = ":matches(", + peg$c83 = peg$literalExpectation(":matches(", false), + peg$c84 = function peg$c84(ss) { + return { + type: 'matches', + selectors: ss + }; + }, + peg$c85 = ":has(", + peg$c86 = peg$literalExpectation(":has(", false), + peg$c87 = function peg$c87(ss) { + return { + type: 'has', + selectors: ss + }; + }, + peg$c88 = ":first-child", + peg$c89 = peg$literalExpectation(":first-child", false), + peg$c90 = function peg$c90() { + return nth(1); + }, + peg$c91 = ":last-child", + peg$c92 = peg$literalExpectation(":last-child", false), + peg$c93 = function peg$c93() { + return nthLast(1); + }, + peg$c94 = ":nth-child(", + peg$c95 = peg$literalExpectation(":nth-child(", false), + peg$c96 = function peg$c96(n) { + return nth(parseInt(n.join(''), 10)); + }, + peg$c97 = ":nth-last-child(", + peg$c98 = peg$literalExpectation(":nth-last-child(", false), + peg$c99 = function peg$c99(n) { + return nthLast(parseInt(n.join(''), 10)); + }, + peg$c100 = ":", + peg$c101 = peg$literalExpectation(":", false), + peg$c102 = "statement", + peg$c103 = peg$literalExpectation("statement", true), + peg$c104 = "expression", + peg$c105 = peg$literalExpectation("expression", true), + peg$c106 = "declaration", + peg$c107 = peg$literalExpectation("declaration", true), + peg$c108 = "function", + peg$c109 = peg$literalExpectation("function", true), + peg$c110 = "pattern", + peg$c111 = peg$literalExpectation("pattern", true), + peg$c112 = function peg$c112(c) { + return { + type: 'class', + name: c + }; + }, + peg$currPos = 0, + peg$posDetailsCache = [{ + line: 1, + column: 1 + }], + peg$maxFailPos = 0, + peg$maxFailExpected = [], + peg$resultsCache = {}, + peg$result; + + if ("startRule" in options) { + if (!(options.startRule in peg$startRuleFunctions)) { + throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); + } + + peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; + } + + function peg$literalExpectation(text, ignoreCase) { + return { + type: "literal", + text: text, + ignoreCase: ignoreCase + }; + } + + function peg$classExpectation(parts, inverted, ignoreCase) { + return { + type: "class", + parts: parts, + inverted: inverted, + ignoreCase: ignoreCase + }; + } + + function peg$anyExpectation() { + return { + type: "any" + }; + } + + function peg$endExpectation() { + return { + type: "end" + }; + } + + function peg$computePosDetails(pos) { + var details = peg$posDetailsCache[pos], + p; + + if (details) { + return details; + } else { + p = pos - 1; + + while (!peg$posDetailsCache[p]) { + p--; + } + + details = peg$posDetailsCache[p]; + details = { + line: details.line, + column: details.column + }; + + while (p < pos) { + if (input.charCodeAt(p) === 10) { + details.line++; + details.column = 1; + } else { + details.column++; + } + + p++; + } + + peg$posDetailsCache[pos] = details; + return details; + } + } + + function peg$computeLocation(startPos, endPos) { + var startPosDetails = peg$computePosDetails(startPos), + endPosDetails = peg$computePosDetails(endPos); + return { + start: { + offset: startPos, + line: startPosDetails.line, + column: startPosDetails.column + }, + end: { + offset: endPos, + line: endPosDetails.line, + column: endPosDetails.column + } + }; + } + + function peg$fail(expected) { + if (peg$currPos < peg$maxFailPos) { + return; + } + + if (peg$currPos > peg$maxFailPos) { + peg$maxFailPos = peg$currPos; + peg$maxFailExpected = []; + } + + peg$maxFailExpected.push(expected); + } + + function peg$buildStructuredError(expected, found, location) { + return new peg$SyntaxError(peg$SyntaxError.buildMessage(expected, found), expected, found, location); + } + + function peg$parsestart() { + var s0, s1, s2, s3; + var key = peg$currPos * 30 + 0, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parse_(); + + if (s1 !== peg$FAILED) { + s2 = peg$parseselectors(); + + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + + if (s3 !== peg$FAILED) { + s1 = peg$c0(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parse_(); + + if (s1 !== peg$FAILED) { + s1 = peg$c1(); + } + + s0 = s1; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parse_() { + var s0, s1; + var key = peg$currPos * 30 + 1, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = []; + + if (input.charCodeAt(peg$currPos) === 32) { + s1 = peg$c2; + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c3); + } + } + + while (s1 !== peg$FAILED) { + s0.push(s1); + + if (input.charCodeAt(peg$currPos) === 32) { + s1 = peg$c2; + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c3); + } + } + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parseidentifierName() { + var s0, s1, s2; + var key = peg$currPos * 30 + 2, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + s1 = []; + + if (peg$c4.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + + { + peg$fail(peg$c5); + } + } + + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + + if (peg$c4.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + + { + peg$fail(peg$c5); + } + } + } + } else { + s1 = peg$FAILED; + } + + if (s1 !== peg$FAILED) { + s1 = peg$c6(s1); + } + + s0 = s1; + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parsebinaryOp() { + var s0, s1, s2, s3; + var key = peg$currPos * 30 + 3, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parse_(); + + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 62) { + s2 = peg$c7; + peg$currPos++; + } else { + s2 = peg$FAILED; + + { + peg$fail(peg$c8); + } + } + + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + + if (s3 !== peg$FAILED) { + s1 = peg$c9(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parse_(); + + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 126) { + s2 = peg$c10; + peg$currPos++; + } else { + s2 = peg$FAILED; + + { + peg$fail(peg$c11); + } + } + + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + + if (s3 !== peg$FAILED) { + s1 = peg$c12(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parse_(); + + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 43) { + s2 = peg$c13; + peg$currPos++; + } else { + s2 = peg$FAILED; + + { + peg$fail(peg$c14); + } + } + + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + + if (s3 !== peg$FAILED) { + s1 = peg$c15(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + if (s0 === peg$FAILED) { + s0 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 32) { + s1 = peg$c2; + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c3); + } + } + + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + + if (s2 !== peg$FAILED) { + s1 = peg$c16(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parseselectors() { + var s0, s1, s2, s3, s4, s5, s6, s7; + var key = peg$currPos * 30 + 4, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parseselector(); + + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse_(); + + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 44) { + s5 = peg$c17; + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c18); + } + } + + if (s5 !== peg$FAILED) { + s6 = peg$parse_(); + + if (s6 !== peg$FAILED) { + s7 = peg$parseselector(); + + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse_(); + + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 44) { + s5 = peg$c17; + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c18); + } + } + + if (s5 !== peg$FAILED) { + s6 = peg$parse_(); + + if (s6 !== peg$FAILED) { + s7 = peg$parseselector(); + + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + + if (s2 !== peg$FAILED) { + s1 = peg$c19(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parseselector() { + var s0, s1, s2, s3, s4, s5; + var key = peg$currPos * 30 + 5, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsesequence(); + + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parsebinaryOp(); + + if (s4 !== peg$FAILED) { + s5 = peg$parsesequence(); + + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parsebinaryOp(); + + if (s4 !== peg$FAILED) { + s5 = peg$parsesequence(); + + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + + if (s2 !== peg$FAILED) { + s1 = peg$c20(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parsesequence() { + var s0, s1, s2, s3; + var key = peg$currPos * 30 + 6, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 33) { + s1 = peg$c21; + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c22); + } + } + + if (s1 === peg$FAILED) { + s1 = null; + } + + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseatom(); + + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseatom(); + } + } else { + s2 = peg$FAILED; + } + + if (s2 !== peg$FAILED) { + s1 = peg$c23(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parseatom() { + var s0; + var key = peg$currPos * 30 + 7, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$parsewildcard(); + + if (s0 === peg$FAILED) { + s0 = peg$parseidentifier(); + + if (s0 === peg$FAILED) { + s0 = peg$parseattr(); + + if (s0 === peg$FAILED) { + s0 = peg$parsefield(); + + if (s0 === peg$FAILED) { + s0 = peg$parsenegation(); + + if (s0 === peg$FAILED) { + s0 = peg$parsematches(); + + if (s0 === peg$FAILED) { + s0 = peg$parsehas(); + + if (s0 === peg$FAILED) { + s0 = peg$parsefirstChild(); + + if (s0 === peg$FAILED) { + s0 = peg$parselastChild(); + + if (s0 === peg$FAILED) { + s0 = peg$parsenthChild(); + + if (s0 === peg$FAILED) { + s0 = peg$parsenthLastChild(); + + if (s0 === peg$FAILED) { + s0 = peg$parseclass(); + } + } + } + } + } + } + } + } + } + } + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parsewildcard() { + var s0, s1; + var key = peg$currPos * 30 + 8, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 42) { + s1 = peg$c24; + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c25); + } + } + + if (s1 !== peg$FAILED) { + s1 = peg$c26(s1); + } + + s0 = s1; + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parseidentifier() { + var s0, s1, s2; + var key = peg$currPos * 30 + 9, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 35) { + s1 = peg$c27; + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c28); + } + } + + if (s1 === peg$FAILED) { + s1 = null; + } + + if (s1 !== peg$FAILED) { + s2 = peg$parseidentifierName(); + + if (s2 !== peg$FAILED) { + s1 = peg$c29(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parseattr() { + var s0, s1, s2, s3, s4, s5; + var key = peg$currPos * 30 + 10, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 91) { + s1 = peg$c30; + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c31); + } + } + + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + + if (s2 !== peg$FAILED) { + s3 = peg$parseattrValue(); + + if (s3 !== peg$FAILED) { + s4 = peg$parse_(); + + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 93) { + s5 = peg$c32; + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c33); + } + } + + if (s5 !== peg$FAILED) { + s1 = peg$c34(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parseattrOps() { + var s0, s1, s2; + var key = peg$currPos * 30 + 11, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (peg$c35.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c36); + } + } + + if (s1 === peg$FAILED) { + s1 = null; + } + + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 61) { + s2 = peg$c37; + peg$currPos++; + } else { + s2 = peg$FAILED; + + { + peg$fail(peg$c38); + } + } + + if (s2 !== peg$FAILED) { + s1 = peg$c39(s1); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + if (s0 === peg$FAILED) { + if (peg$c40.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + + { + peg$fail(peg$c41); + } + } + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parseattrEqOps() { + var s0, s1, s2; + var key = peg$currPos * 30 + 12, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 33) { + s1 = peg$c21; + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c22); + } + } + + if (s1 === peg$FAILED) { + s1 = null; + } + + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 61) { + s2 = peg$c37; + peg$currPos++; + } else { + s2 = peg$FAILED; + + { + peg$fail(peg$c38); + } + } + + if (s2 !== peg$FAILED) { + s1 = peg$c39(s1); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parseattrName() { + var s0, s1, s2, s3, s4, s5; + var key = peg$currPos * 30 + 13, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parseidentifierName(); + + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 46) { + s4 = peg$c42; + peg$currPos++; + } else { + s4 = peg$FAILED; + + { + peg$fail(peg$c43); + } + } + + if (s4 !== peg$FAILED) { + s5 = peg$parseidentifierName(); + + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 46) { + s4 = peg$c42; + peg$currPos++; + } else { + s4 = peg$FAILED; + + { + peg$fail(peg$c43); + } + } + + if (s4 !== peg$FAILED) { + s5 = peg$parseidentifierName(); + + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + + if (s2 !== peg$FAILED) { + s1 = peg$c44(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parseattrValue() { + var s0, s1, s2, s3, s4, s5; + var key = peg$currPos * 30 + 14, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parseattrName(); + + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + + if (s2 !== peg$FAILED) { + s3 = peg$parseattrEqOps(); + + if (s3 !== peg$FAILED) { + s4 = peg$parse_(); + + if (s4 !== peg$FAILED) { + s5 = peg$parsetype(); + + if (s5 === peg$FAILED) { + s5 = peg$parseregex(); + } + + if (s5 !== peg$FAILED) { + s1 = peg$c45(s1, s3, s5); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseattrName(); + + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + + if (s2 !== peg$FAILED) { + s3 = peg$parseattrOps(); + + if (s3 !== peg$FAILED) { + s4 = peg$parse_(); + + if (s4 !== peg$FAILED) { + s5 = peg$parsestring(); + + if (s5 === peg$FAILED) { + s5 = peg$parsenumber(); + + if (s5 === peg$FAILED) { + s5 = peg$parsepath(); + } + } + + if (s5 !== peg$FAILED) { + s1 = peg$c45(s1, s3, s5); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseattrName(); + + if (s1 !== peg$FAILED) { + s1 = peg$c46(s1); + } + + s0 = s1; + } + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parsestring() { + var s0, s1, s2, s3, s4, s5; + var key = peg$currPos * 30 + 15, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 34) { + s1 = peg$c47; + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c48); + } + } + + if (s1 !== peg$FAILED) { + s2 = []; + + if (peg$c49.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + + { + peg$fail(peg$c50); + } + } + + if (s3 === peg$FAILED) { + s3 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 92) { + s4 = peg$c51; + peg$currPos++; + } else { + s4 = peg$FAILED; + + { + peg$fail(peg$c52); + } + } + + if (s4 !== peg$FAILED) { + if (input.length > peg$currPos) { + s5 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c53); + } + } + + if (s5 !== peg$FAILED) { + s4 = peg$c54(s4, s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + + while (s3 !== peg$FAILED) { + s2.push(s3); + + if (peg$c49.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + + { + peg$fail(peg$c50); + } + } + + if (s3 === peg$FAILED) { + s3 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 92) { + s4 = peg$c51; + peg$currPos++; + } else { + s4 = peg$FAILED; + + { + peg$fail(peg$c52); + } + } + + if (s4 !== peg$FAILED) { + if (input.length > peg$currPos) { + s5 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c53); + } + } + + if (s5 !== peg$FAILED) { + s4 = peg$c54(s4, s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + } + + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 34) { + s3 = peg$c47; + peg$currPos++; + } else { + s3 = peg$FAILED; + + { + peg$fail(peg$c48); + } + } + + if (s3 !== peg$FAILED) { + s1 = peg$c55(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + if (s0 === peg$FAILED) { + s0 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 39) { + s1 = peg$c56; + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c57); + } + } + + if (s1 !== peg$FAILED) { + s2 = []; + + if (peg$c58.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + + { + peg$fail(peg$c59); + } + } + + if (s3 === peg$FAILED) { + s3 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 92) { + s4 = peg$c51; + peg$currPos++; + } else { + s4 = peg$FAILED; + + { + peg$fail(peg$c52); + } + } + + if (s4 !== peg$FAILED) { + if (input.length > peg$currPos) { + s5 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c53); + } + } + + if (s5 !== peg$FAILED) { + s4 = peg$c54(s4, s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + + while (s3 !== peg$FAILED) { + s2.push(s3); + + if (peg$c58.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + + { + peg$fail(peg$c59); + } + } + + if (s3 === peg$FAILED) { + s3 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 92) { + s4 = peg$c51; + peg$currPos++; + } else { + s4 = peg$FAILED; + + { + peg$fail(peg$c52); + } + } + + if (s4 !== peg$FAILED) { + if (input.length > peg$currPos) { + s5 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c53); + } + } + + if (s5 !== peg$FAILED) { + s4 = peg$c54(s4, s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + } + + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 39) { + s3 = peg$c56; + peg$currPos++; + } else { + s3 = peg$FAILED; + + { + peg$fail(peg$c57); + } + } + + if (s3 !== peg$FAILED) { + s1 = peg$c55(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parsenumber() { + var s0, s1, s2, s3; + var key = peg$currPos * 30 + 16, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = []; + + if (peg$c60.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + + { + peg$fail(peg$c61); + } + } + + while (s3 !== peg$FAILED) { + s2.push(s3); + + if (peg$c60.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + + { + peg$fail(peg$c61); + } + } + } + + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 46) { + s3 = peg$c42; + peg$currPos++; + } else { + s3 = peg$FAILED; + + { + peg$fail(peg$c43); + } + } + + if (s3 !== peg$FAILED) { + s2 = [s2, s3]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + + if (s1 === peg$FAILED) { + s1 = null; + } + + if (s1 !== peg$FAILED) { + s2 = []; + + if (peg$c60.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + + { + peg$fail(peg$c61); + } + } + + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + + if (peg$c60.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + + { + peg$fail(peg$c61); + } + } + } + } else { + s2 = peg$FAILED; + } + + if (s2 !== peg$FAILED) { + s1 = peg$c62(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parsepath() { + var s0, s1; + var key = peg$currPos * 30 + 17, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parseidentifierName(); + + if (s1 !== peg$FAILED) { + s1 = peg$c63(s1); + } + + s0 = s1; + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parsetype() { + var s0, s1, s2, s3, s4, s5; + var key = peg$currPos * 30 + 18, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.substr(peg$currPos, 5) === peg$c64) { + s1 = peg$c64; + peg$currPos += 5; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c65); + } + } + + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + + if (s2 !== peg$FAILED) { + s3 = []; + + if (peg$c66.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + + { + peg$fail(peg$c67); + } + } + + if (s4 !== peg$FAILED) { + while (s4 !== peg$FAILED) { + s3.push(s4); + + if (peg$c66.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + + { + peg$fail(peg$c67); + } + } + } + } else { + s3 = peg$FAILED; + } + + if (s3 !== peg$FAILED) { + s4 = peg$parse_(); + + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 41) { + s5 = peg$c68; + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c69); + } + } + + if (s5 !== peg$FAILED) { + s1 = peg$c70(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parseflags() { + var s0, s1; + var key = peg$currPos * 30 + 19, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = []; + + if (peg$c71.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c72); + } + } + + if (s1 !== peg$FAILED) { + while (s1 !== peg$FAILED) { + s0.push(s1); + + if (peg$c71.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c72); + } + } + } + } else { + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parseregex() { + var s0, s1, s2, s3, s4; + var key = peg$currPos * 30 + 20, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 47) { + s1 = peg$c73; + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c74); + } + } + + if (s1 !== peg$FAILED) { + s2 = []; + + if (peg$c75.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + + { + peg$fail(peg$c76); + } + } + + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + + if (peg$c75.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + + { + peg$fail(peg$c76); + } + } + } + } else { + s2 = peg$FAILED; + } + + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 47) { + s3 = peg$c73; + peg$currPos++; + } else { + s3 = peg$FAILED; + + { + peg$fail(peg$c74); + } + } + + if (s3 !== peg$FAILED) { + s4 = peg$parseflags(); + + if (s4 === peg$FAILED) { + s4 = null; + } + + if (s4 !== peg$FAILED) { + s1 = peg$c77(s2, s4); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parsefield() { + var s0, s1, s2, s3, s4, s5, s6; + var key = peg$currPos * 30 + 21, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 46) { + s1 = peg$c42; + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c43); + } + } + + if (s1 !== peg$FAILED) { + s2 = peg$parseidentifierName(); + + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 46) { + s5 = peg$c42; + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c43); + } + } + + if (s5 !== peg$FAILED) { + s6 = peg$parseidentifierName(); + + if (s6 !== peg$FAILED) { + s5 = [s5, s6]; + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 46) { + s5 = peg$c42; + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c43); + } + } + + if (s5 !== peg$FAILED) { + s6 = peg$parseidentifierName(); + + if (s6 !== peg$FAILED) { + s5 = [s5, s6]; + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } + + if (s3 !== peg$FAILED) { + s1 = peg$c78(s2, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parsenegation() { + var s0, s1, s2, s3, s4, s5; + var key = peg$currPos * 30 + 22, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.substr(peg$currPos, 5) === peg$c79) { + s1 = peg$c79; + peg$currPos += 5; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c80); + } + } + + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + + if (s2 !== peg$FAILED) { + s3 = peg$parseselectors(); + + if (s3 !== peg$FAILED) { + s4 = peg$parse_(); + + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 41) { + s5 = peg$c68; + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c69); + } + } + + if (s5 !== peg$FAILED) { + s1 = peg$c81(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parsematches() { + var s0, s1, s2, s3, s4, s5; + var key = peg$currPos * 30 + 23, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.substr(peg$currPos, 9) === peg$c82) { + s1 = peg$c82; + peg$currPos += 9; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c83); + } + } + + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + + if (s2 !== peg$FAILED) { + s3 = peg$parseselectors(); + + if (s3 !== peg$FAILED) { + s4 = peg$parse_(); + + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 41) { + s5 = peg$c68; + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c69); + } + } + + if (s5 !== peg$FAILED) { + s1 = peg$c84(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parsehas() { + var s0, s1, s2, s3, s4, s5; + var key = peg$currPos * 30 + 24, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.substr(peg$currPos, 5) === peg$c85) { + s1 = peg$c85; + peg$currPos += 5; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c86); + } + } + + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + + if (s2 !== peg$FAILED) { + s3 = peg$parseselectors(); + + if (s3 !== peg$FAILED) { + s4 = peg$parse_(); + + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 41) { + s5 = peg$c68; + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c69); + } + } + + if (s5 !== peg$FAILED) { + s1 = peg$c87(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parsefirstChild() { + var s0, s1; + var key = peg$currPos * 30 + 25, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.substr(peg$currPos, 12) === peg$c88) { + s1 = peg$c88; + peg$currPos += 12; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c89); + } + } + + if (s1 !== peg$FAILED) { + s1 = peg$c90(); + } + + s0 = s1; + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parselastChild() { + var s0, s1; + var key = peg$currPos * 30 + 26, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.substr(peg$currPos, 11) === peg$c91) { + s1 = peg$c91; + peg$currPos += 11; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c92); + } + } + + if (s1 !== peg$FAILED) { + s1 = peg$c93(); + } + + s0 = s1; + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parsenthChild() { + var s0, s1, s2, s3, s4, s5; + var key = peg$currPos * 30 + 27, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.substr(peg$currPos, 11) === peg$c94) { + s1 = peg$c94; + peg$currPos += 11; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c95); + } + } + + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + + if (s2 !== peg$FAILED) { + s3 = []; + + if (peg$c60.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + + { + peg$fail(peg$c61); + } + } + + if (s4 !== peg$FAILED) { + while (s4 !== peg$FAILED) { + s3.push(s4); + + if (peg$c60.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + + { + peg$fail(peg$c61); + } + } + } + } else { + s3 = peg$FAILED; + } + + if (s3 !== peg$FAILED) { + s4 = peg$parse_(); + + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 41) { + s5 = peg$c68; + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c69); + } + } + + if (s5 !== peg$FAILED) { + s1 = peg$c96(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parsenthLastChild() { + var s0, s1, s2, s3, s4, s5; + var key = peg$currPos * 30 + 28, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.substr(peg$currPos, 16) === peg$c97) { + s1 = peg$c97; + peg$currPos += 16; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c98); + } + } + + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + + if (s2 !== peg$FAILED) { + s3 = []; + + if (peg$c60.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + + { + peg$fail(peg$c61); + } + } + + if (s4 !== peg$FAILED) { + while (s4 !== peg$FAILED) { + s3.push(s4); + + if (peg$c60.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + + { + peg$fail(peg$c61); + } + } + } + } else { + s3 = peg$FAILED; + } + + if (s3 !== peg$FAILED) { + s4 = peg$parse_(); + + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 41) { + s5 = peg$c68; + peg$currPos++; + } else { + s5 = peg$FAILED; + + { + peg$fail(peg$c69); + } + } + + if (s5 !== peg$FAILED) { + s1 = peg$c99(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function peg$parseclass() { + var s0, s1, s2; + var key = peg$currPos * 30 + 29, + cached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + return cached.result; + } + + s0 = peg$currPos; + + if (input.charCodeAt(peg$currPos) === 58) { + s1 = peg$c100; + peg$currPos++; + } else { + s1 = peg$FAILED; + + { + peg$fail(peg$c101); + } + } + + if (s1 !== peg$FAILED) { + if (input.substr(peg$currPos, 9).toLowerCase() === peg$c102) { + s2 = input.substr(peg$currPos, 9); + peg$currPos += 9; + } else { + s2 = peg$FAILED; + + { + peg$fail(peg$c103); + } + } + + if (s2 === peg$FAILED) { + if (input.substr(peg$currPos, 10).toLowerCase() === peg$c104) { + s2 = input.substr(peg$currPos, 10); + peg$currPos += 10; + } else { + s2 = peg$FAILED; + + { + peg$fail(peg$c105); + } + } + + if (s2 === peg$FAILED) { + if (input.substr(peg$currPos, 11).toLowerCase() === peg$c106) { + s2 = input.substr(peg$currPos, 11); + peg$currPos += 11; + } else { + s2 = peg$FAILED; + + { + peg$fail(peg$c107); + } + } + + if (s2 === peg$FAILED) { + if (input.substr(peg$currPos, 8).toLowerCase() === peg$c108) { + s2 = input.substr(peg$currPos, 8); + peg$currPos += 8; + } else { + s2 = peg$FAILED; + + { + peg$fail(peg$c109); + } + } + + if (s2 === peg$FAILED) { + if (input.substr(peg$currPos, 7).toLowerCase() === peg$c110) { + s2 = input.substr(peg$currPos, 7); + peg$currPos += 7; + } else { + s2 = peg$FAILED; + + { + peg$fail(peg$c111); + } + } + } + } + } + } + + if (s2 !== peg$FAILED) { + s1 = peg$c112(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { + nextPos: peg$currPos, + result: s0 + }; + return s0; + } + + function nth(n) { + return { + type: 'nth-child', + index: { + type: 'literal', + value: n + } + }; + } + + function nthLast(n) { + return { + type: 'nth-last-child', + index: { + type: 'literal', + value: n + } + }; + } + + function strUnescape(s) { + return s.replace(/\\(.)/g, function (match, ch) { + switch (ch) { + case 'b': + return '\b'; + + case 'f': + return '\f'; + + case 'n': + return '\n'; + + case 'r': + return '\r'; + + case 't': + return '\t'; + + case 'v': + return '\v'; + + default: + return ch; + } + }); + } + + peg$result = peg$startRuleFunction(); + + if (peg$result !== peg$FAILED && peg$currPos === input.length) { + return peg$result; + } else { + if (peg$result !== peg$FAILED && peg$currPos < input.length) { + peg$fail(peg$endExpectation()); + } + + throw peg$buildStructuredError(peg$maxFailExpected, peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, peg$maxFailPos < input.length ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) : peg$computeLocation(peg$maxFailPos, peg$maxFailPos)); + } + } + + return { + SyntaxError: peg$SyntaxError, + parse: peg$parse + }; + }); + }); + + function _objectEntries(obj) { + var entries = []; + var keys = Object.keys(obj); + + for (var k = 0; k < keys.length; k++) entries.push([keys[k], obj[keys[k]]]); + + return entries; + } + /** + * @typedef {"LEFT_SIDE"|"RIGHT_SIDE"} Side + */ + + var LEFT_SIDE = 'LEFT_SIDE'; + var RIGHT_SIDE = 'RIGHT_SIDE'; + /** + * @external AST + * @see https://esprima.readthedocs.io/en/latest/syntax-tree-format.html + */ + + /** + * One of the rules of `grammar.pegjs` + * @typedef {PlainObject} SelectorAST + * @see grammar.pegjs + */ + + /** + * The `sequence` production of `grammar.pegjs` + * @typedef {PlainObject} SelectorSequenceAST + */ + + /** + * Get the value of a property which may be multiple levels down + * in the object. + * @param {?PlainObject} obj + * @param {string} key + * @returns {undefined|boolean|string|number|external:AST} + */ + + function getPath(obj, key) { + var keys = key.split('.'); + + var _iterator = _createForOfIteratorHelper(keys), + _step; + + try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var _key = _step.value; + + if (obj == null) { + return obj; + } + + obj = obj[_key]; + } + } catch (err) { + _iterator.e(err); + } finally { + _iterator.f(); + } + + return obj; + } + /** + * Determine whether `node` can be reached by following `path`, + * starting at `ancestor`. + * @param {?external:AST} node + * @param {?external:AST} ancestor + * @param {string[]} path + * @returns {boolean} + */ + + + function inPath(node, ancestor, path) { + if (path.length === 0) { + return node === ancestor; + } + + if (ancestor == null) { + return false; + } + + var field = ancestor[path[0]]; + var remainingPath = path.slice(1); + + if (Array.isArray(field)) { + var _iterator2 = _createForOfIteratorHelper(field), + _step2; + + try { + for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { + var component = _step2.value; + + if (inPath(node, component, remainingPath)) { + return true; + } + } + } catch (err) { + _iterator2.e(err); + } finally { + _iterator2.f(); + } + + return false; + } else { + return inPath(node, field, remainingPath); + } + } + /** + * @callback TraverseOptionFallback + * @param {external:AST} node The given node. + * @returns {string[]} An array of visitor keys for the given node. + */ + + /** + * @typedef {object} ESQueryOptions + * @property { { [nodeType: string]: string[] } } [visitorKeys] By passing `visitorKeys` mapping, we can extend the properties of the nodes that traverse the node. + * @property {TraverseOptionFallback} [fallback] By passing `fallback` option, we can control the properties of traversing nodes when encountering unknown nodes. + */ + + /** + * Given a `node` and its ancestors, determine if `node` is matched + * by `selector`. + * @param {?external:AST} node + * @param {?SelectorAST} selector + * @param {external:AST[]} [ancestry=[]] + * @param {ESQueryOptions} [options] + * @throws {Error} Unknowns (operator, class name, selector type, or + * selector value type) + * @returns {boolean} + */ + + + function matches(node, selector, ancestry, options) { + if (!selector) { + return true; + } + + if (!node) { + return false; + } + + if (!ancestry) { + ancestry = []; + } + + switch (selector.type) { + case 'wildcard': + return true; + + case 'identifier': + return selector.value.toLowerCase() === node.type.toLowerCase(); + + case 'field': + { + var path = selector.name.split('.'); + var ancestor = ancestry[path.length - 1]; + return inPath(node, ancestor, path); + } + + case 'matches': + var _iterator3 = _createForOfIteratorHelper(selector.selectors), + _step3; + + try { + for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { + var sel = _step3.value; + + if (matches(node, sel, ancestry, options)) { + return true; + } + } + } catch (err) { + _iterator3.e(err); + } finally { + _iterator3.f(); + } + + return false; + + case 'compound': + var _iterator4 = _createForOfIteratorHelper(selector.selectors), + _step4; + + try { + for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { + var _sel = _step4.value; + + if (!matches(node, _sel, ancestry, options)) { + return false; + } + } + } catch (err) { + _iterator4.e(err); + } finally { + _iterator4.f(); + } + + return true; + + case 'not': + var _iterator5 = _createForOfIteratorHelper(selector.selectors), + _step5; + + try { + for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) { + var _sel2 = _step5.value; + + if (matches(node, _sel2, ancestry, options)) { + return false; + } + } + } catch (err) { + _iterator5.e(err); + } finally { + _iterator5.f(); + } + + return true; + + case 'has': + { + var _ret = function () { + var collector = []; + + var _iterator6 = _createForOfIteratorHelper(selector.selectors), + _step6; + + try { + var _loop = function _loop() { + var sel = _step6.value; + var a = []; + estraverse.traverse(node, { + enter: function enter(node, parent) { + if (parent != null) { + a.unshift(parent); + } + + if (matches(node, sel, a, options)) { + collector.push(node); + } + }, + leave: function leave() { + a.shift(); + }, + keys: options && options.visitorKeys, + fallback: options && options.fallback || 'iteration' + }); + }; + + for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) { + _loop(); + } + } catch (err) { + _iterator6.e(err); + } finally { + _iterator6.f(); + } + + return { + v: collector.length !== 0 + }; + }(); + + if (_typeof(_ret) === "object") return _ret.v; + } + + case 'child': + if (matches(node, selector.right, ancestry, options)) { + return matches(ancestry[0], selector.left, ancestry.slice(1), options); + } + + return false; + + case 'descendant': + if (matches(node, selector.right, ancestry, options)) { + for (var i = 0, l = ancestry.length; i < l; ++i) { + if (matches(ancestry[i], selector.left, ancestry.slice(i + 1), options)) { + return true; + } + } + } + + return false; + + case 'attribute': + { + var p = getPath(node, selector.name); + + switch (selector.operator) { + case void 0: + return p != null; + + case '=': + switch (selector.value.type) { + case 'regexp': + return typeof p === 'string' && selector.value.value.test(p); + + case 'literal': + return "".concat(selector.value.value) === "".concat(p); + + case 'type': + return selector.value.value === _typeof(p); + } + + throw new Error("Unknown selector value type: ".concat(selector.value.type)); + + case '!=': + switch (selector.value.type) { + case 'regexp': + return !selector.value.value.test(p); + + case 'literal': + return "".concat(selector.value.value) !== "".concat(p); + + case 'type': + return selector.value.value !== _typeof(p); + } + + throw new Error("Unknown selector value type: ".concat(selector.value.type)); + + case '<=': + return p <= selector.value.value; + + case '<': + return p < selector.value.value; + + case '>': + return p > selector.value.value; + + case '>=': + return p >= selector.value.value; + } + + throw new Error("Unknown operator: ".concat(selector.operator)); + } + + case 'sibling': + return matches(node, selector.right, ancestry, options) && sibling(node, selector.left, ancestry, LEFT_SIDE, options) || selector.left.subject && matches(node, selector.left, ancestry, options) && sibling(node, selector.right, ancestry, RIGHT_SIDE, options); + + case 'adjacent': + return matches(node, selector.right, ancestry, options) && adjacent(node, selector.left, ancestry, LEFT_SIDE, options) || selector.right.subject && matches(node, selector.left, ancestry, options) && adjacent(node, selector.right, ancestry, RIGHT_SIDE, options); + + case 'nth-child': + return matches(node, selector.right, ancestry, options) && nthChild(node, ancestry, function () { + return selector.index.value - 1; + }, options); + + case 'nth-last-child': + return matches(node, selector.right, ancestry, options) && nthChild(node, ancestry, function (length) { + return length - selector.index.value; + }, options); + + case 'class': + switch (selector.name.toLowerCase()) { + case 'statement': + if (node.type.slice(-9) === 'Statement') return true; + // fallthrough: interface Declaration <: Statement { } + + case 'declaration': + return node.type.slice(-11) === 'Declaration'; + + case 'pattern': + if (node.type.slice(-7) === 'Pattern') return true; + // fallthrough: interface Expression <: Node, Pattern { } + + case 'expression': + return node.type.slice(-10) === 'Expression' || node.type.slice(-7) === 'Literal' || node.type === 'Identifier' && (ancestry.length === 0 || ancestry[0].type !== 'MetaProperty') || node.type === 'MetaProperty'; + + case 'function': + return node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression'; + } + + throw new Error("Unknown class name: ".concat(selector.name)); + } + + throw new Error("Unknown selector type: ".concat(selector.type)); + } + /** + * Get visitor keys of a given node. + * @param {external:AST} node The AST node to get keys. + * @param {ESQueryOptions|undefined} options + * @returns {string[]} Visitor keys of the node. + */ + + + function getVisitorKeys(node, options) { + var nodeType = node.type; + + if (options && options.visitorKeys && options.visitorKeys[nodeType]) { + return options.visitorKeys[nodeType]; + } + + if (estraverse.VisitorKeys[nodeType]) { + return estraverse.VisitorKeys[nodeType]; + } + + if (options && typeof options.fallback === 'function') { + return options.fallback(node); + } // 'iteration' fallback + + + return Object.keys(node).filter(function (key) { + return key !== 'type'; + }); + } + /** + * Check whether the given value is an ASTNode or not. + * @param {any} node The value to check. + * @returns {boolean} `true` if the value is an ASTNode. + */ + + + function isNode(node) { + return node !== null && _typeof(node) === 'object' && typeof node.type === 'string'; + } + /** + * Determines if the given node has a sibling that matches the + * given selector. + * @param {external:AST} node + * @param {SelectorSequenceAST} selector + * @param {external:AST[]} ancestry + * @param {Side} side + * @param {ESQueryOptions|undefined} options + * @returns {boolean} + */ + + + function sibling(node, selector, ancestry, side, options) { + var _ancestry = _slicedToArray(ancestry, 1), + parent = _ancestry[0]; + + if (!parent) { + return false; + } + + var keys = getVisitorKeys(parent, options); + + var _iterator7 = _createForOfIteratorHelper(keys), + _step7; + + try { + for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) { + var key = _step7.value; + var listProp = parent[key]; + + if (Array.isArray(listProp)) { + var startIndex = listProp.indexOf(node); + + if (startIndex < 0) { + continue; + } + + var lowerBound = void 0, + upperBound = void 0; + + if (side === LEFT_SIDE) { + lowerBound = 0; + upperBound = startIndex; + } else { + lowerBound = startIndex + 1; + upperBound = listProp.length; + } + + for (var k = lowerBound; k < upperBound; ++k) { + if (isNode(listProp[k]) && matches(listProp[k], selector, ancestry, options)) { + return true; + } + } + } + } + } catch (err) { + _iterator7.e(err); + } finally { + _iterator7.f(); + } + + return false; + } + /** + * Determines if the given node has an adjacent sibling that matches + * the given selector. + * @param {external:AST} node + * @param {SelectorSequenceAST} selector + * @param {external:AST[]} ancestry + * @param {Side} side + * @param {ESQueryOptions|undefined} options + * @returns {boolean} + */ + + + function adjacent(node, selector, ancestry, side, options) { + var _ancestry2 = _slicedToArray(ancestry, 1), + parent = _ancestry2[0]; + + if (!parent) { + return false; + } + + var keys = getVisitorKeys(parent, options); + + var _iterator8 = _createForOfIteratorHelper(keys), + _step8; + + try { + for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) { + var key = _step8.value; + var listProp = parent[key]; + + if (Array.isArray(listProp)) { + var idx = listProp.indexOf(node); + + if (idx < 0) { + continue; + } + + if (side === LEFT_SIDE && idx > 0 && isNode(listProp[idx - 1]) && matches(listProp[idx - 1], selector, ancestry, options)) { + return true; + } + + if (side === RIGHT_SIDE && idx < listProp.length - 1 && isNode(listProp[idx + 1]) && matches(listProp[idx + 1], selector, ancestry, options)) { + return true; + } + } + } + } catch (err) { + _iterator8.e(err); + } finally { + _iterator8.f(); + } + + return false; + } + /** + * @callback IndexFunction + * @param {Integer} len Containing list's length + * @returns {Integer} + */ + + /** + * Determines if the given node is the nth child, determined by + * `idxFn`, which is given the containing list's length. + * @param {external:AST} node + * @param {external:AST[]} ancestry + * @param {IndexFunction} idxFn + * @param {ESQueryOptions|undefined} options + * @returns {boolean} + */ + + + function nthChild(node, ancestry, idxFn, options) { + var _ancestry3 = _slicedToArray(ancestry, 1), + parent = _ancestry3[0]; + + if (!parent) { + return false; + } + + var keys = getVisitorKeys(parent, options); + + var _iterator9 = _createForOfIteratorHelper(keys), + _step9; + + try { + for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) { + var key = _step9.value; + var listProp = parent[key]; + + if (Array.isArray(listProp)) { + var idx = listProp.indexOf(node); + + if (idx >= 0 && idx === idxFn(listProp.length)) { + return true; + } + } + } + } catch (err) { + _iterator9.e(err); + } finally { + _iterator9.f(); + } + + return false; + } + /** + * For each selector node marked as a subject, find the portion of the + * selector that the subject must match. + * @param {SelectorAST} selector + * @param {SelectorAST} [ancestor] Defaults to `selector` + * @returns {SelectorAST[]} + */ + + + function subjects(selector, ancestor) { + if (selector == null || _typeof(selector) != 'object') { + return []; + } + + if (ancestor == null) { + ancestor = selector; + } + + var results = selector.subject ? [ancestor] : []; + + for (var _i = 0, _Object$entries = _objectEntries(selector); _i < _Object$entries.length; _i++) { + var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), + p = _Object$entries$_i[0], + sel = _Object$entries$_i[1]; + + results.push.apply(results, _toConsumableArray(subjects(sel, p === 'left' ? sel : ancestor))); + } + + return results; + } + /** + * @callback TraverseVisitor + * @param {?external:AST} node + * @param {?external:AST} parent + * @param {external:AST[]} ancestry + */ + + /** + * From a JS AST and a selector AST, collect all JS AST nodes that + * match the selector. + * @param {external:AST} ast + * @param {?SelectorAST} selector + * @param {TraverseVisitor} visitor + * @param {ESQueryOptions} [options] + * @returns {external:AST[]} + */ + + + function traverse(ast, selector, visitor, options) { + if (!selector) { + return; + } + + var ancestry = []; + var altSubjects = subjects(selector); + estraverse.traverse(ast, { + enter: function enter(node, parent) { + if (parent != null) { + ancestry.unshift(parent); + } + + if (matches(node, selector, ancestry, options)) { + if (altSubjects.length) { + for (var i = 0, l = altSubjects.length; i < l; ++i) { + if (matches(node, altSubjects[i], ancestry, options)) { + visitor(node, parent, ancestry); + } + + for (var k = 0, m = ancestry.length; k < m; ++k) { + var succeedingAncestry = ancestry.slice(k + 1); + + if (matches(ancestry[k], altSubjects[i], succeedingAncestry, options)) { + visitor(ancestry[k], parent, succeedingAncestry); + } + } + } + } else { + visitor(node, parent, ancestry); + } + } + }, + leave: function leave() { + ancestry.shift(); + }, + keys: options && options.visitorKeys, + fallback: options && options.fallback || 'iteration' + }); + } + /** + * From a JS AST and a selector AST, collect all JS AST nodes that + * match the selector. + * @param {external:AST} ast + * @param {?SelectorAST} selector + * @param {ESQueryOptions} [options] + * @returns {external:AST[]} + */ + + + function match(ast, selector, options) { + var results = []; + traverse(ast, selector, function (node) { + results.push(node); + }, options); + return results; + } + /** + * Parse a selector string and return its AST. + * @param {string} selector + * @returns {SelectorAST} + */ + + + function parse(selector) { + return parser.parse(selector); + } + /** + * Query the code AST using the selector string. + * @param {external:AST} ast + * @param {string} selector + * @param {ESQueryOptions} [options] + * @returns {external:AST[]} + */ + + + function query(ast, selector, options) { + return match(ast, parse(selector), options); + } + + query.parse = parse; + query.match = match; + query.traverse = traverse; + query.matches = matches; + query.query = query; + + return query; + +}))); diff --git a/tools/node_modules/eslint/node_modules/esquery/dist/esquery.lite.min.js b/tools/node_modules/eslint/node_modules/esquery/dist/esquery.lite.min.js new file mode 100644 index 00000000000000..70d7b762a975c0 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/esquery/dist/esquery.lite.min.js @@ -0,0 +1,2 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("estraverse")):"function"==typeof define&&define.amd?define(["estraverse"],e):(t=t||self).esquery=e(t.estraverse)}(this,(function(t){"use strict";function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function r(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){if("undefined"==typeof Symbol||!(Symbol.iterator in Object(t)))return;var r=[],n=!0,a=!1,o=void 0;try{for(var u,s=t[Symbol.iterator]();!(n=(u=s.next()).done)&&(r.push(u.value),!e||r.length!==e);n=!0);}catch(t){a=!0,o=t}finally{try{n||null==s.return||s.return()}finally{if(a)throw o}}return r}(t,e)||a(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function n(t){return function(t){if(Array.isArray(t))return o(t)}(t)||function(t){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(t))return Array.from(t)}(t)||a(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(t,e){if(t){if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?o(t,e):void 0}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var u,s=!0,c=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return s=t.done,t},e:function(t){c=!0,u=t},f:function(){try{s||null==r.return||r.return()}finally{if(c)throw u}}}}t=t&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var s=function(t,e){return t(e={exports:{}},e.exports),e.exports}((function(t){t.exports&&(t.exports=function(){function t(e,r,n,a){this.message=e,this.expected=r,this.found=n,this.location=a,this.name="SyntaxError","function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,t)}return function(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}(t,Error),t.buildMessage=function(t,e){var r={literal:function(t){return'"'+a(t.text)+'"'},class:function(t){var e,r="";for(e=0;e0){for(e=1,n=1;e<~+.]/,h=dt([" ","[","]",",","(",")",":","#","!","=",">","<","~","+","."],!0,!1),p=vt(">",!1),y=vt("~",!1),v=vt("+",!1),d=vt(",",!1),A=vt("!",!1),x=vt("*",!1),g=vt("#",!1),b=vt("[",!1),m=vt("]",!1),P=/^[>","<","!"],!1,!1),C=vt("=",!1),j=function(t){return(t||"")+"="},S=/^[><]/,E=dt([">","<"],!1,!1),I=vt(".",!1),k=function(t,e,r){return{type:"attribute",name:t,operator:e,value:r}},F=vt('"',!1),T=/^[^\\"]/,L=dt(["\\",'"'],!0,!1),O=vt("\\",!1),D={type:"any"},R=function(t,e){return t+e},K=function(t){return{type:"literal",value:(e=t.join(""),e.replace(/\\(.)/g,(function(t,e){switch(e){case"b":return"\b";case"f":return"\f";case"n":return"\n";case"r":return"\r";case"t":return"\t";case"v":return"\v";default:return e}})))};var e},U=vt("'",!1),_=/^[^\\']/,M=dt(["\\","'"],!0,!1),q=/^[0-9]/,G=dt([["0","9"]],!1,!1),H=vt("type(",!1),V=/^[^ )]/,$=dt([" ",")"],!0,!1),z=vt(")",!1),B=/^[imsu]/,J=dt(["i","m","s","u"],!1,!1),N=vt("/",!1),Q=/^[^\/]/,W=dt(["/"],!0,!1),X=vt(":not(",!1),Y=vt(":matches(",!1),Z=vt(":has(",!1),tt=vt(":first-child",!1),et=vt(":last-child",!1),rt=vt(":nth-child(",!1),nt=vt(":nth-last-child(",!1),at=vt(":",!1),ot=vt("statement",!0),ut=vt("expression",!0),st=vt("declaration",!0),ct=vt("function",!0),it=vt("pattern",!0),lt=0,ft=[{line:1,column:1}],ht=0,pt=[],yt={};if("startRule"in r){if(!(r.startRule in c))throw new Error("Can't start parsing from rule \""+r.startRule+'".');i=c[r.startRule]}function vt(t,e){return{type:"literal",text:t,ignoreCase:e}}function dt(t,e,r){return{type:"class",parts:t,inverted:e,ignoreCase:r}}function At(t){var r,n=ft[t];if(n)return n;for(r=t-1;!ft[r];)r--;for(n={line:(n=ft[r]).line,column:n.column};rht&&(ht=lt,pt=[]),pt.push(t))}function bt(){var t,e,r,n,a=30*lt+0,o=yt[a];return o?(lt=o.nextPos,o.result):(t=lt,(e=mt())!==s&&(r=Ct())!==s&&mt()!==s?t=e=1===(n=r).length?n[0]:{type:"matches",selectors:n}:(lt=t,t=s),t===s&&(t=lt,(e=mt())!==s&&(e=void 0),t=e),yt[a]={nextPos:lt,result:t},t)}function mt(){var t,r,n=30*lt+1,a=yt[n];if(a)return lt=a.nextPos,a.result;for(t=[],32===e.charCodeAt(lt)?(r=" ",lt++):(r=s,gt(l));r!==s;)t.push(r),32===e.charCodeAt(lt)?(r=" ",lt++):(r=s,gt(l));return yt[n]={nextPos:lt,result:t},t}function Pt(){var t,r,n,a=30*lt+2,o=yt[a];if(o)return lt=o.nextPos,o.result;if(r=[],f.test(e.charAt(lt))?(n=e.charAt(lt),lt++):(n=s,gt(h)),n!==s)for(;n!==s;)r.push(n),f.test(e.charAt(lt))?(n=e.charAt(lt),lt++):(n=s,gt(h));else r=s;return r!==s&&(r=r.join("")),t=r,yt[a]={nextPos:lt,result:t},t}function wt(){var t,r,n,a=30*lt+3,o=yt[a];return o?(lt=o.nextPos,o.result):(t=lt,(r=mt())!==s?(62===e.charCodeAt(lt)?(n=">",lt++):(n=s,gt(p)),n!==s&&mt()!==s?t=r="child":(lt=t,t=s)):(lt=t,t=s),t===s&&(t=lt,(r=mt())!==s?(126===e.charCodeAt(lt)?(n="~",lt++):(n=s,gt(y)),n!==s&&mt()!==s?t=r="sibling":(lt=t,t=s)):(lt=t,t=s),t===s&&(t=lt,(r=mt())!==s?(43===e.charCodeAt(lt)?(n="+",lt++):(n=s,gt(v)),n!==s&&mt()!==s?t=r="adjacent":(lt=t,t=s)):(lt=t,t=s),t===s&&(t=lt,32===e.charCodeAt(lt)?(r=" ",lt++):(r=s,gt(l)),r!==s&&(n=mt())!==s?t=r="descendant":(lt=t,t=s)))),yt[a]={nextPos:lt,result:t},t)}function Ct(){var t,r,n,a,o,u,c,i,l=30*lt+4,f=yt[l];if(f)return lt=f.nextPos,f.result;if(t=lt,(r=jt())!==s){for(n=[],a=lt,(o=mt())!==s?(44===e.charCodeAt(lt)?(u=",",lt++):(u=s,gt(d)),u!==s&&(c=mt())!==s&&(i=jt())!==s?a=o=[o,u,c,i]:(lt=a,a=s)):(lt=a,a=s);a!==s;)n.push(a),a=lt,(o=mt())!==s?(44===e.charCodeAt(lt)?(u=",",lt++):(u=s,gt(d)),u!==s&&(c=mt())!==s&&(i=jt())!==s?a=o=[o,u,c,i]:(lt=a,a=s)):(lt=a,a=s);n!==s?t=r=[r].concat(n.map((function(t){return t[3]}))):(lt=t,t=s)}else lt=t,t=s;return yt[l]={nextPos:lt,result:t},t}function jt(){var t,e,r,n,a,o,u,c=30*lt+5,i=yt[c];if(i)return lt=i.nextPos,i.result;if(t=lt,(e=St())!==s){for(r=[],n=lt,(a=wt())!==s&&(o=St())!==s?n=a=[a,o]:(lt=n,n=s);n!==s;)r.push(n),n=lt,(a=wt())!==s&&(o=St())!==s?n=a=[a,o]:(lt=n,n=s);r!==s?(u=e,t=e=r.reduce((function(t,e){return{type:e[0],left:t,right:e[1]}}),u)):(lt=t,t=s)}else lt=t,t=s;return yt[c]={nextPos:lt,result:t},t}function St(){var t,r,n,a,o,u,c,i=30*lt+6,l=yt[i];if(l)return lt=l.nextPos,l.result;if(t=lt,33===e.charCodeAt(lt)?(r="!",lt++):(r=s,gt(A)),r===s&&(r=null),r!==s){if(n=[],(a=Et())!==s)for(;a!==s;)n.push(a),a=Et();else n=s;n!==s?(o=r,c=1===(u=n).length?u[0]:{type:"compound",selectors:u},o&&(c.subject=!0),t=r=c):(lt=t,t=s)}else lt=t,t=s;return yt[i]={nextPos:lt,result:t},t}function Et(){var t,r=30*lt+7,n=yt[r];return n?(lt=n.nextPos,n.result):((t=function(){var t,r,n=30*lt+8,a=yt[n];return a?(lt=a.nextPos,a.result):(42===e.charCodeAt(lt)?(r="*",lt++):(r=s,gt(x)),r!==s&&(r={type:"wildcard",value:r}),t=r,yt[n]={nextPos:lt,result:t},t)}())===s&&(t=function(){var t,r,n,a=30*lt+9,o=yt[a];return o?(lt=o.nextPos,o.result):(t=lt,35===e.charCodeAt(lt)?(r="#",lt++):(r=s,gt(g)),r===s&&(r=null),r!==s&&(n=Pt())!==s?t=r={type:"identifier",value:n}:(lt=t,t=s),yt[a]={nextPos:lt,result:t},t)}())===s&&(t=function(){var t,r,n,a,o=30*lt+10,u=yt[o];return u?(lt=u.nextPos,u.result):(t=lt,91===e.charCodeAt(lt)?(r="[",lt++):(r=s,gt(b)),r!==s&&mt()!==s&&(n=function(){var t,r,n,a,o=30*lt+14,u=yt[o];return u?(lt=u.nextPos,u.result):(t=lt,(r=It())!==s&&mt()!==s&&(n=function(){var t,r,n,a=30*lt+12,o=yt[a];return o?(lt=o.nextPos,o.result):(t=lt,33===e.charCodeAt(lt)?(r="!",lt++):(r=s,gt(A)),r===s&&(r=null),r!==s?(61===e.charCodeAt(lt)?(n="=",lt++):(n=s,gt(C)),n!==s?(r=j(r),t=r):(lt=t,t=s)):(lt=t,t=s),yt[a]={nextPos:lt,result:t},t)}())!==s&&mt()!==s?((a=function(){var t,r,n,a,o,u=30*lt+18,c=yt[u];if(c)return lt=c.nextPos,c.result;if(t=lt,"type("===e.substr(lt,5)?(r="type(",lt+=5):(r=s,gt(H)),r!==s)if(mt()!==s){if(n=[],V.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt($)),a!==s)for(;a!==s;)n.push(a),V.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt($));else n=s;n!==s&&(a=mt())!==s?(41===e.charCodeAt(lt)?(o=")",lt++):(o=s,gt(z)),o!==s?(r={type:"type",value:n.join("")},t=r):(lt=t,t=s)):(lt=t,t=s)}else lt=t,t=s;else lt=t,t=s;return yt[u]={nextPos:lt,result:t},t}())===s&&(a=function(){var t,r,n,a,o,u,c=30*lt+20,i=yt[c];if(i)return lt=i.nextPos,i.result;if(t=lt,47===e.charCodeAt(lt)?(r="/",lt++):(r=s,gt(N)),r!==s){if(n=[],Q.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt(W)),a!==s)for(;a!==s;)n.push(a),Q.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt(W));else n=s;n!==s?(47===e.charCodeAt(lt)?(a="/",lt++):(a=s,gt(N)),a!==s?((o=function(){var t,r,n=30*lt+19,a=yt[n];if(a)return lt=a.nextPos,a.result;if(t=[],B.test(e.charAt(lt))?(r=e.charAt(lt),lt++):(r=s,gt(J)),r!==s)for(;r!==s;)t.push(r),B.test(e.charAt(lt))?(r=e.charAt(lt),lt++):(r=s,gt(J));else t=s;return yt[n]={nextPos:lt,result:t},t}())===s&&(o=null),o!==s?(u=o,r={type:"regexp",value:new RegExp(n.join(""),u?u.join(""):"")},t=r):(lt=t,t=s)):(lt=t,t=s)):(lt=t,t=s)}else lt=t,t=s;return yt[c]={nextPos:lt,result:t},t}()),a!==s?(r=k(r,n,a),t=r):(lt=t,t=s)):(lt=t,t=s),t===s&&(t=lt,(r=It())!==s&&mt()!==s&&(n=function(){var t,r,n,a=30*lt+11,o=yt[a];return o?(lt=o.nextPos,o.result):(t=lt,P.test(e.charAt(lt))?(r=e.charAt(lt),lt++):(r=s,gt(w)),r===s&&(r=null),r!==s?(61===e.charCodeAt(lt)?(n="=",lt++):(n=s,gt(C)),n!==s?(r=j(r),t=r):(lt=t,t=s)):(lt=t,t=s),t===s&&(S.test(e.charAt(lt))?(t=e.charAt(lt),lt++):(t=s,gt(E))),yt[a]={nextPos:lt,result:t},t)}())!==s&&mt()!==s?((a=function(){var t,r,n,a,o,u,c=30*lt+15,i=yt[c];if(i)return lt=i.nextPos,i.result;if(t=lt,34===e.charCodeAt(lt)?(r='"',lt++):(r=s,gt(F)),r!==s){for(n=[],T.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt(L)),a===s&&(a=lt,92===e.charCodeAt(lt)?(o="\\",lt++):(o=s,gt(O)),o!==s?(e.length>lt?(u=e.charAt(lt),lt++):(u=s,gt(D)),u!==s?(o=R(o,u),a=o):(lt=a,a=s)):(lt=a,a=s));a!==s;)n.push(a),T.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt(L)),a===s&&(a=lt,92===e.charCodeAt(lt)?(o="\\",lt++):(o=s,gt(O)),o!==s?(e.length>lt?(u=e.charAt(lt),lt++):(u=s,gt(D)),u!==s?(o=R(o,u),a=o):(lt=a,a=s)):(lt=a,a=s));n!==s?(34===e.charCodeAt(lt)?(a='"',lt++):(a=s,gt(F)),a!==s?(r=K(n),t=r):(lt=t,t=s)):(lt=t,t=s)}else lt=t,t=s;if(t===s)if(t=lt,39===e.charCodeAt(lt)?(r="'",lt++):(r=s,gt(U)),r!==s){for(n=[],_.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt(M)),a===s&&(a=lt,92===e.charCodeAt(lt)?(o="\\",lt++):(o=s,gt(O)),o!==s?(e.length>lt?(u=e.charAt(lt),lt++):(u=s,gt(D)),u!==s?(o=R(o,u),a=o):(lt=a,a=s)):(lt=a,a=s));a!==s;)n.push(a),_.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt(M)),a===s&&(a=lt,92===e.charCodeAt(lt)?(o="\\",lt++):(o=s,gt(O)),o!==s?(e.length>lt?(u=e.charAt(lt),lt++):(u=s,gt(D)),u!==s?(o=R(o,u),a=o):(lt=a,a=s)):(lt=a,a=s));n!==s?(39===e.charCodeAt(lt)?(a="'",lt++):(a=s,gt(U)),a!==s?(r=K(n),t=r):(lt=t,t=s)):(lt=t,t=s)}else lt=t,t=s;return yt[c]={nextPos:lt,result:t},t}())===s&&(a=function(){var t,r,n,a,o,u,c,i=30*lt+16,l=yt[i];if(l)return lt=l.nextPos,l.result;for(t=lt,r=lt,n=[],q.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt(G));a!==s;)n.push(a),q.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt(G));if(n!==s?(46===e.charCodeAt(lt)?(a=".",lt++):(a=s,gt(I)),a!==s?r=n=[n,a]:(lt=r,r=s)):(lt=r,r=s),r===s&&(r=null),r!==s){if(n=[],q.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt(G)),a!==s)for(;a!==s;)n.push(a),q.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt(G));else n=s;n!==s?(u=n,c=(o=r)?[].concat.apply([],o).join(""):"",r={type:"literal",value:parseFloat(c+u.join(""))},t=r):(lt=t,t=s)}else lt=t,t=s;return yt[i]={nextPos:lt,result:t},t}())===s&&(a=function(){var t,e,r=30*lt+17,n=yt[r];return n?(lt=n.nextPos,n.result):((e=Pt())!==s&&(e={type:"literal",value:e}),t=e,yt[r]={nextPos:lt,result:t},t)}()),a!==s?(r=k(r,n,a),t=r):(lt=t,t=s)):(lt=t,t=s),t===s&&(t=lt,(r=It())!==s&&(r={type:"attribute",name:r}),t=r)),yt[o]={nextPos:lt,result:t},t)}())!==s&&mt()!==s?(93===e.charCodeAt(lt)?(a="]",lt++):(a=s,gt(m)),a!==s?t=r=n:(lt=t,t=s)):(lt=t,t=s),yt[o]={nextPos:lt,result:t},t)}())===s&&(t=function(){var t,r,n,a,o,u,c,i,l=30*lt+21,f=yt[l];if(f)return lt=f.nextPos,f.result;if(t=lt,46===e.charCodeAt(lt)?(r=".",lt++):(r=s,gt(I)),r!==s)if((n=Pt())!==s){for(a=[],o=lt,46===e.charCodeAt(lt)?(u=".",lt++):(u=s,gt(I)),u!==s&&(c=Pt())!==s?o=u=[u,c]:(lt=o,o=s);o!==s;)a.push(o),o=lt,46===e.charCodeAt(lt)?(u=".",lt++):(u=s,gt(I)),u!==s&&(c=Pt())!==s?o=u=[u,c]:(lt=o,o=s);a!==s?(i=n,r={type:"field",name:a.reduce((function(t,e){return t+e[0]+e[1]}),i)},t=r):(lt=t,t=s)}else lt=t,t=s;else lt=t,t=s;return yt[l]={nextPos:lt,result:t},t}())===s&&(t=function(){var t,r,n,a,o=30*lt+22,u=yt[o];return u?(lt=u.nextPos,u.result):(t=lt,":not("===e.substr(lt,5)?(r=":not(",lt+=5):(r=s,gt(X)),r!==s&&mt()!==s&&(n=Ct())!==s&&mt()!==s?(41===e.charCodeAt(lt)?(a=")",lt++):(a=s,gt(z)),a!==s?t=r={type:"not",selectors:n}:(lt=t,t=s)):(lt=t,t=s),yt[o]={nextPos:lt,result:t},t)}())===s&&(t=function(){var t,r,n,a,o=30*lt+23,u=yt[o];return u?(lt=u.nextPos,u.result):(t=lt,":matches("===e.substr(lt,9)?(r=":matches(",lt+=9):(r=s,gt(Y)),r!==s&&mt()!==s&&(n=Ct())!==s&&mt()!==s?(41===e.charCodeAt(lt)?(a=")",lt++):(a=s,gt(z)),a!==s?t=r={type:"matches",selectors:n}:(lt=t,t=s)):(lt=t,t=s),yt[o]={nextPos:lt,result:t},t)}())===s&&(t=function(){var t,r,n,a,o=30*lt+24,u=yt[o];return u?(lt=u.nextPos,u.result):(t=lt,":has("===e.substr(lt,5)?(r=":has(",lt+=5):(r=s,gt(Z)),r!==s&&mt()!==s&&(n=Ct())!==s&&mt()!==s?(41===e.charCodeAt(lt)?(a=")",lt++):(a=s,gt(z)),a!==s?t=r={type:"has",selectors:n}:(lt=t,t=s)):(lt=t,t=s),yt[o]={nextPos:lt,result:t},t)}())===s&&(t=function(){var t,r,n=30*lt+25,a=yt[n];return a?(lt=a.nextPos,a.result):(":first-child"===e.substr(lt,12)?(r=":first-child",lt+=12):(r=s,gt(tt)),r!==s&&(r=kt(1)),t=r,yt[n]={nextPos:lt,result:t},t)}())===s&&(t=function(){var t,r,n=30*lt+26,a=yt[n];return a?(lt=a.nextPos,a.result):(":last-child"===e.substr(lt,11)?(r=":last-child",lt+=11):(r=s,gt(et)),r!==s&&(r=Ft(1)),t=r,yt[n]={nextPos:lt,result:t},t)}())===s&&(t=function(){var t,r,n,a,o,u=30*lt+27,c=yt[u];if(c)return lt=c.nextPos,c.result;if(t=lt,":nth-child("===e.substr(lt,11)?(r=":nth-child(",lt+=11):(r=s,gt(rt)),r!==s)if(mt()!==s){if(n=[],q.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt(G)),a!==s)for(;a!==s;)n.push(a),q.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt(G));else n=s;n!==s&&(a=mt())!==s?(41===e.charCodeAt(lt)?(o=")",lt++):(o=s,gt(z)),o!==s?(r=kt(parseInt(n.join(""),10)),t=r):(lt=t,t=s)):(lt=t,t=s)}else lt=t,t=s;else lt=t,t=s;return yt[u]={nextPos:lt,result:t},t}())===s&&(t=function(){var t,r,n,a,o,u=30*lt+28,c=yt[u];if(c)return lt=c.nextPos,c.result;if(t=lt,":nth-last-child("===e.substr(lt,16)?(r=":nth-last-child(",lt+=16):(r=s,gt(nt)),r!==s)if(mt()!==s){if(n=[],q.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt(G)),a!==s)for(;a!==s;)n.push(a),q.test(e.charAt(lt))?(a=e.charAt(lt),lt++):(a=s,gt(G));else n=s;n!==s&&(a=mt())!==s?(41===e.charCodeAt(lt)?(o=")",lt++):(o=s,gt(z)),o!==s?(r=Ft(parseInt(n.join(""),10)),t=r):(lt=t,t=s)):(lt=t,t=s)}else lt=t,t=s;else lt=t,t=s;return yt[u]={nextPos:lt,result:t},t}())===s&&(t=function(){var t,r,n,a=30*lt+29,o=yt[a];return o?(lt=o.nextPos,o.result):(t=lt,58===e.charCodeAt(lt)?(r=":",lt++):(r=s,gt(at)),r!==s?("statement"===e.substr(lt,9).toLowerCase()?(n=e.substr(lt,9),lt+=9):(n=s,gt(ot)),n===s&&("expression"===e.substr(lt,10).toLowerCase()?(n=e.substr(lt,10),lt+=10):(n=s,gt(ut)),n===s&&("declaration"===e.substr(lt,11).toLowerCase()?(n=e.substr(lt,11),lt+=11):(n=s,gt(st)),n===s&&("function"===e.substr(lt,8).toLowerCase()?(n=e.substr(lt,8),lt+=8):(n=s,gt(ct)),n===s&&("pattern"===e.substr(lt,7).toLowerCase()?(n=e.substr(lt,7),lt+=7):(n=s,gt(it)))))),n!==s?t=r={type:"class",name:n}:(lt=t,t=s)):(lt=t,t=s),yt[a]={nextPos:lt,result:t},t)}()),yt[r]={nextPos:lt,result:t},t)}function It(){var t,r,n,a,o,u,c,i,l=30*lt+13,f=yt[l];if(f)return lt=f.nextPos,f.result;if(t=lt,(r=Pt())!==s){for(n=[],a=lt,46===e.charCodeAt(lt)?(o=".",lt++):(o=s,gt(I)),o!==s&&(u=Pt())!==s?a=o=[o,u]:(lt=a,a=s);a!==s;)n.push(a),a=lt,46===e.charCodeAt(lt)?(o=".",lt++):(o=s,gt(I)),o!==s&&(u=Pt())!==s?a=o=[o,u]:(lt=a,a=s);n!==s?(c=r,i=n,t=r=[].concat.apply([c],i).join("")):(lt=t,t=s)}else lt=t,t=s;return yt[l]={nextPos:lt,result:t},t}function kt(t){return{type:"nth-child",index:{type:"literal",value:t}}}function Ft(t){return{type:"nth-last-child",index:{type:"literal",value:t}}}if((n=i())!==s&<===e.length)return n;throw n!==s&<":return j>n.value.value;case">=":return j>=n.value.value}throw new Error("Unknown operator: ".concat(n.operator));case"sibling":return c(r,n.right,a,o)&&f(r,n.left,a,"LEFT_SIDE",o)||n.left.subject&&c(r,n.left,a,o)&&f(r,n.right,a,"RIGHT_SIDE",o);case"adjacent":return c(r,n.right,a,o)&&h(r,n.left,a,"LEFT_SIDE",o)||n.right.subject&&c(r,n.left,a,o)&&h(r,n.right,a,"RIGHT_SIDE",o);case"nth-child":return c(r,n.right,a,o)&&p(r,a,(function(){return n.index.value-1}),o);case"nth-last-child":return c(r,n.right,a,o)&&p(r,a,(function(t){return t-n.index.value}),o);case"class":switch(n.name.toLowerCase()){case"statement":if("Statement"===r.type.slice(-9))return!0;case"declaration":return"Declaration"===r.type.slice(-11);case"pattern":if("Pattern"===r.type.slice(-7))return!0;case"expression":return"Expression"===r.type.slice(-10)||"Literal"===r.type.slice(-7)||"Identifier"===r.type&&(0===a.length||"MetaProperty"!==a[0].type)||"MetaProperty"===r.type;case"function":return"FunctionDeclaration"===r.type||"FunctionExpression"===r.type||"ArrowFunctionExpression"===r.type}throw new Error("Unknown class name: ".concat(n.name))}throw new Error("Unknown selector type: ".concat(n.type))}function i(e,r){var n=e.type;return r&&r.visitorKeys&&r.visitorKeys[n]?r.visitorKeys[n]:t.VisitorKeys[n]?t.VisitorKeys[n]:r&&"function"==typeof r.fallback?r.fallback(e):Object.keys(e).filter((function(t){return"type"!==t}))}function l(t){return null!==t&&"object"===e(t)&&"string"==typeof t.type}function f(t,e,n,a,o){var s=r(n,1)[0];if(!s)return!1;var f,h=u(i(s,o));try{for(h.s();!(f=h.n()).done;){var p=s[f.value];if(Array.isArray(p)){var y=p.indexOf(t);if(y<0)continue;var v=void 0,d=void 0;"LEFT_SIDE"===a?(v=0,d=y):(v=y+1,d=p.length);for(var A=v;A0&&l(p[y-1])&&c(p[y-1],e,n,o))return!0;if("RIGHT_SIDE"===a&&y=0&&f===n(l.length))return!0}}}catch(t){c.e(t)}finally{c.f()}return!1}function y(t,a){if(null==t||"object"!=e(t))return[];null==a&&(a=t);for(var o=t.subject?[a]:[],u=0,s=function(t){for(var e=[],r=Object.keys(t),n=0;ne.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0;--r)if(e[r].node===t)return!0;return!1}function y(e,t){return(new f).traverse(e,t)}function m(e,t){var r;return r=function(e,t){var r,n,o,a;for(n=e.length,o=0;n;)t(e[a=o+(r=n>>>1)])?n=r:(o=a+1,n-=r+1);return o}(t,(function(t){return t.range[0]>e.range[0]})),e.extendedRange=[e.range[0],e.range[1]],r!==t.length&&(e.extendedRange[1]=t[r].range[0]),(r-=1)>=0&&(e.extendedRange[0]=t[r].range[1]),e}return r={AssignmentExpression:"AssignmentExpression",AssignmentPattern:"AssignmentPattern",ArrayExpression:"ArrayExpression",ArrayPattern:"ArrayPattern",ArrowFunctionExpression:"ArrowFunctionExpression",AwaitExpression:"AwaitExpression",BlockStatement:"BlockStatement",BinaryExpression:"BinaryExpression",BreakStatement:"BreakStatement",CallExpression:"CallExpression",CatchClause:"CatchClause",ClassBody:"ClassBody",ClassDeclaration:"ClassDeclaration",ClassExpression:"ClassExpression",ComprehensionBlock:"ComprehensionBlock",ComprehensionExpression:"ComprehensionExpression",ConditionalExpression:"ConditionalExpression",ContinueStatement:"ContinueStatement",DebuggerStatement:"DebuggerStatement",DirectiveStatement:"DirectiveStatement",DoWhileStatement:"DoWhileStatement",EmptyStatement:"EmptyStatement",ExportAllDeclaration:"ExportAllDeclaration",ExportDefaultDeclaration:"ExportDefaultDeclaration",ExportNamedDeclaration:"ExportNamedDeclaration",ExportSpecifier:"ExportSpecifier",ExpressionStatement:"ExpressionStatement",ForStatement:"ForStatement",ForInStatement:"ForInStatement",ForOfStatement:"ForOfStatement",FunctionDeclaration:"FunctionDeclaration",FunctionExpression:"FunctionExpression",GeneratorExpression:"GeneratorExpression",Identifier:"Identifier",IfStatement:"IfStatement",ImportExpression:"ImportExpression",ImportDeclaration:"ImportDeclaration",ImportDefaultSpecifier:"ImportDefaultSpecifier",ImportNamespaceSpecifier:"ImportNamespaceSpecifier",ImportSpecifier:"ImportSpecifier",Literal:"Literal",LabeledStatement:"LabeledStatement",LogicalExpression:"LogicalExpression",MemberExpression:"MemberExpression",MetaProperty:"MetaProperty",MethodDefinition:"MethodDefinition",ModuleSpecifier:"ModuleSpecifier",NewExpression:"NewExpression",ObjectExpression:"ObjectExpression",ObjectPattern:"ObjectPattern",Program:"Program",Property:"Property",RestElement:"RestElement",ReturnStatement:"ReturnStatement",SequenceExpression:"SequenceExpression",SpreadElement:"SpreadElement",Super:"Super",SwitchStatement:"SwitchStatement",SwitchCase:"SwitchCase",TaggedTemplateExpression:"TaggedTemplateExpression",TemplateElement:"TemplateElement",TemplateLiteral:"TemplateLiteral",ThisExpression:"ThisExpression",ThrowStatement:"ThrowStatement",TryStatement:"TryStatement",UnaryExpression:"UnaryExpression",UpdateExpression:"UpdateExpression",VariableDeclaration:"VariableDeclaration",VariableDeclarator:"VariableDeclarator",WhileStatement:"WhileStatement",WithStatement:"WithStatement",YieldExpression:"YieldExpression"},o={AssignmentExpression:["left","right"],AssignmentPattern:["left","right"],ArrayExpression:["elements"],ArrayPattern:["elements"],ArrowFunctionExpression:["params","body"],AwaitExpression:["argument"],BlockStatement:["body"],BinaryExpression:["left","right"],BreakStatement:["label"],CallExpression:["callee","arguments"],CatchClause:["param","body"],ClassBody:["body"],ClassDeclaration:["id","superClass","body"],ClassExpression:["id","superClass","body"],ComprehensionBlock:["left","right"],ComprehensionExpression:["blocks","filter","body"],ConditionalExpression:["test","consequent","alternate"],ContinueStatement:["label"],DebuggerStatement:[],DirectiveStatement:[],DoWhileStatement:["body","test"],EmptyStatement:[],ExportAllDeclaration:["source"],ExportDefaultDeclaration:["declaration"],ExportNamedDeclaration:["declaration","specifiers","source"],ExportSpecifier:["exported","local"],ExpressionStatement:["expression"],ForStatement:["init","test","update","body"],ForInStatement:["left","right","body"],ForOfStatement:["left","right","body"],FunctionDeclaration:["id","params","body"],FunctionExpression:["id","params","body"],GeneratorExpression:["blocks","filter","body"],Identifier:[],IfStatement:["test","consequent","alternate"],ImportExpression:["source"],ImportDeclaration:["specifiers","source"],ImportDefaultSpecifier:["local"],ImportNamespaceSpecifier:["local"],ImportSpecifier:["imported","local"],Literal:[],LabeledStatement:["label","body"],LogicalExpression:["left","right"],MemberExpression:["object","property"],MetaProperty:["meta","property"],MethodDefinition:["key","value"],ModuleSpecifier:[],NewExpression:["callee","arguments"],ObjectExpression:["properties"],ObjectPattern:["properties"],Program:["body"],Property:["key","value"],RestElement:["argument"],ReturnStatement:["argument"],SequenceExpression:["expressions"],SpreadElement:["argument"],Super:[],SwitchStatement:["discriminant","cases"],SwitchCase:["test","consequent"],TaggedTemplateExpression:["tag","quasi"],TemplateElement:[],TemplateLiteral:["quasis","expressions"],ThisExpression:[],ThrowStatement:["argument"],TryStatement:["block","handler","finalizer"],UnaryExpression:["argument"],UpdateExpression:["argument"],VariableDeclaration:["declarations"],VariableDeclarator:["id","init"],WhileStatement:["test","body"],WithStatement:["object","body"],YieldExpression:["argument"]},n={Break:a={},Skip:s={},Remove:i={}},u.prototype.replace=function(e){this.parent[this.key]=e},u.prototype.remove=function(){return Array.isArray(this.parent)?(this.parent.splice(this.key,1),!0):(this.replace(null),!1)},f.prototype.path=function(){var e,t,r,n,o;function a(e,t){if(Array.isArray(t))for(r=0,n=t.length;r=0;)if(g=i[f=x[y]])if(Array.isArray(g)){for(m=g.length;(m-=1)>=0;)if(g[m]&&!d(n,g[m])){if(h(l,x[y]))o=new c(g[m],[f,m],"Property",null);else{if(!p(g[m]))continue;o=new c(g[m],[f,m],null,null)}r.push(o)}}else if(p(g)){if(d(n,g))continue;r.push(new c(g,f,null,null))}}}else if(o=n.pop(),u=this.__execute(t.leave,o),this.__state===a||u===a)return},f.prototype.replace=function(e,t){var r,n,o,l,f,d,y,m,x,g,v,A,b;function E(e){var t,n,o,a;if(e.ref.remove())for(n=e.ref.key,a=e.ref.parent,t=r.length;t--;)if((o=r[t]).ref&&o.ref.parent===a){if(o.ref.key=0;)if(g=o[b=x[y]])if(Array.isArray(g)){for(m=g.length;(m-=1)>=0;)if(g[m]){if(h(l,x[y]))d=new c(g[m],[b,m],"Property",new u(g,m));else{if(!p(g[m]))continue;d=new c(g[m],[b,m],null,new u(g,m))}r.push(d)}}else p(g)&&r.push(new c(g,b,null,new u(o,b)))}}else if(d=n.pop(),void 0!==(f=this.__execute(t.leave,d))&&f!==a&&f!==s&&f!==i&&d.ref.replace(f),this.__state!==i&&f!==i||E(d),this.__state===a||f===a)return A.root;return A.root},t.Syntax=r,t.traverse=y,t.replace=function(e,t){return(new f).replace(e,t)},t.attachComments=function(e,t,r){var o,a,s,i,u=[];if(!e.range)throw new Error("attachComments needs range information");if(!r.length){if(t.length){for(s=0,a=t.length;se.range[0]);)t.extendedRange[1]===e.range[0]?(e.leadingComments||(e.leadingComments=[]),e.leadingComments.push(t),u.splice(i,1)):i+=1;return i===u.length?n.Break:u[i].extendedRange[0]>e.range[1]?n.Skip:void 0}}),i=0,y(e,{leave:function(e){for(var t;ie.range[1]?n.Skip:void 0}}),e},t.VisitorKeys=o,t.VisitorOption=n,t.Controller=f,t.cloneEnvironment=function(){return e({})},t}(t)})),i=a((function(e){e.exports&&(e.exports=function(){function e(t,r,n,o){this.message=t,this.expected=r,this.found=n,this.location=o,this.name="SyntaxError","function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,e)}return function(e,t){function r(){this.constructor=e}r.prototype=t.prototype,e.prototype=new r}(e,Error),e.buildMessage=function(e,t){var r={literal:function(e){return'"'+o(e.text)+'"'},class:function(e){var t,r="";for(t=0;t0){for(t=1,n=1;t<~+.]/,p=xe([" ","[","]",",","(",")",":","#","!","=",">","<","~","+","."],!0,!1),h=function(e){return e.join("")},d=me(">",!1),y=me("~",!1),m=me("+",!1),x=me(",",!1),g=me("!",!1),v=me("*",!1),A=me("#",!1),b=me("[",!1),E=me("]",!1),S=/^[>","<","!"],!1,!1),w=me("=",!1),C=function(e){return(e||"")+"="},P=/^[><]/,k=xe([">","<"],!1,!1),D=me(".",!1),I=function(e,t,r){return{type:"attribute",name:e,operator:t,value:r}},j=me('"',!1),F=/^[^\\"]/,T=xe(["\\",'"'],!0,!1),L=me("\\",!1),R={type:"any"},O=function(e,t){return e+t},B=function(e){return{type:"literal",value:(t=e.join(""),t.replace(/\\(.)/g,(function(e,t){switch(t){case"b":return"\b";case"f":return"\f";case"n":return"\n";case"r":return"\r";case"t":return"\t";case"v":return"\v";default:return t}})))};var t},M=me("'",!1),U=/^[^\\']/,V=xe(["\\","'"],!0,!1),q=/^[0-9]/,N=xe([["0","9"]],!1,!1),W=me("type(",!1),G=/^[^ )]/,z=xe([" ",")"],!0,!1),K=me(")",!1),H=/^[imsu]/,Y=xe(["i","m","s","u"],!1,!1),$=me("/",!1),J=/^[^\/]/,Q=xe(["/"],!0,!1),X=me(":not(",!1),Z=me(":matches(",!1),ee=me(":has(",!1),te=me(":first-child",!1),re=me(":last-child",!1),ne=me(":nth-child(",!1),oe=me(":nth-last-child(",!1),ae=me(":",!1),se=me("statement",!0),ie=me("expression",!0),le=me("declaration",!0),ue=me("function",!0),ce=me("pattern",!0),fe=0,pe=[{line:1,column:1}],he=0,de=[],ye={};if("startRule"in r){if(!(r.startRule in l))throw new Error("Can't start parsing from rule \""+r.startRule+'".');u=l[r.startRule]}function me(e,t){return{type:"literal",text:e,ignoreCase:t}}function xe(e,t,r){return{type:"class",parts:e,inverted:t,ignoreCase:r}}function ge(e){var r,n=pe[e];if(n)return n;for(r=e-1;!pe[r];)r--;for(n={line:(n=pe[r]).line,column:n.column};rhe&&(he=fe,de=[]),de.push(e))}function be(){var e,t,r,n,o=30*fe+0,a=ye[o];return a?(fe=a.nextPos,a.result):(e=fe,(t=Ee())!==i&&(r=we())!==i&&Ee()!==i?e=t=1===(n=r).length?n[0]:{type:"matches",selectors:n}:(fe=e,e=i),e===i&&(e=fe,(t=Ee())!==i&&(t=void 0),e=t),ye[o]={nextPos:fe,result:e},e)}function Ee(){var e,r,n=30*fe+1,o=ye[n];if(o)return fe=o.nextPos,o.result;for(e=[],32===t.charCodeAt(fe)?(r=" ",fe++):(r=i,Ae(c));r!==i;)e.push(r),32===t.charCodeAt(fe)?(r=" ",fe++):(r=i,Ae(c));return ye[n]={nextPos:fe,result:e},e}function Se(){var e,r,n,o=30*fe+2,a=ye[o];if(a)return fe=a.nextPos,a.result;if(r=[],f.test(t.charAt(fe))?(n=t.charAt(fe),fe++):(n=i,Ae(p)),n!==i)for(;n!==i;)r.push(n),f.test(t.charAt(fe))?(n=t.charAt(fe),fe++):(n=i,Ae(p));else r=i;return r!==i&&(r=h(r)),e=r,ye[o]={nextPos:fe,result:e},e}function _e(){var e,r,n,o=30*fe+3,a=ye[o];return a?(fe=a.nextPos,a.result):(e=fe,(r=Ee())!==i?(62===t.charCodeAt(fe)?(n=">",fe++):(n=i,Ae(d)),n!==i&&Ee()!==i?e=r="child":(fe=e,e=i)):(fe=e,e=i),e===i&&(e=fe,(r=Ee())!==i?(126===t.charCodeAt(fe)?(n="~",fe++):(n=i,Ae(y)),n!==i&&Ee()!==i?e=r="sibling":(fe=e,e=i)):(fe=e,e=i),e===i&&(e=fe,(r=Ee())!==i?(43===t.charCodeAt(fe)?(n="+",fe++):(n=i,Ae(m)),n!==i&&Ee()!==i?e=r="adjacent":(fe=e,e=i)):(fe=e,e=i),e===i&&(e=fe,32===t.charCodeAt(fe)?(r=" ",fe++):(r=i,Ae(c)),r!==i&&(n=Ee())!==i?e=r="descendant":(fe=e,e=i)))),ye[o]={nextPos:fe,result:e},e)}function we(){var e,r,n,o,a,s,l,u,c=30*fe+4,f=ye[c];if(f)return fe=f.nextPos,f.result;if(e=fe,(r=Ce())!==i){for(n=[],o=fe,(a=Ee())!==i?(44===t.charCodeAt(fe)?(s=",",fe++):(s=i,Ae(x)),s!==i&&(l=Ee())!==i&&(u=Ce())!==i?o=a=[a,s,l,u]:(fe=o,o=i)):(fe=o,o=i);o!==i;)n.push(o),o=fe,(a=Ee())!==i?(44===t.charCodeAt(fe)?(s=",",fe++):(s=i,Ae(x)),s!==i&&(l=Ee())!==i&&(u=Ce())!==i?o=a=[a,s,l,u]:(fe=o,o=i)):(fe=o,o=i);n!==i?e=r=[r].concat(n.map((function(e){return e[3]}))):(fe=e,e=i)}else fe=e,e=i;return ye[c]={nextPos:fe,result:e},e}function Ce(){var e,t,r,n,o,a,s,l=30*fe+5,u=ye[l];if(u)return fe=u.nextPos,u.result;if(e=fe,(t=Pe())!==i){for(r=[],n=fe,(o=_e())!==i&&(a=Pe())!==i?n=o=[o,a]:(fe=n,n=i);n!==i;)r.push(n),n=fe,(o=_e())!==i&&(a=Pe())!==i?n=o=[o,a]:(fe=n,n=i);r!==i?(s=t,e=t=r.reduce((function(e,t){return{type:t[0],left:e,right:t[1]}}),s)):(fe=e,e=i)}else fe=e,e=i;return ye[l]={nextPos:fe,result:e},e}function Pe(){var e,r,n,o,a,s,l,u=30*fe+6,c=ye[u];if(c)return fe=c.nextPos,c.result;if(e=fe,33===t.charCodeAt(fe)?(r="!",fe++):(r=i,Ae(g)),r===i&&(r=null),r!==i){if(n=[],(o=ke())!==i)for(;o!==i;)n.push(o),o=ke();else n=i;n!==i?(a=r,l=1===(s=n).length?s[0]:{type:"compound",selectors:s},a&&(l.subject=!0),e=r=l):(fe=e,e=i)}else fe=e,e=i;return ye[u]={nextPos:fe,result:e},e}function ke(){var e,r=30*fe+7,n=ye[r];return n?(fe=n.nextPos,n.result):((e=function(){var e,r,n=30*fe+8,o=ye[n];return o?(fe=o.nextPos,o.result):(42===t.charCodeAt(fe)?(r="*",fe++):(r=i,Ae(v)),r!==i&&(r={type:"wildcard",value:r}),e=r,ye[n]={nextPos:fe,result:e},e)}())===i&&(e=function(){var e,r,n,o=30*fe+9,a=ye[o];return a?(fe=a.nextPos,a.result):(e=fe,35===t.charCodeAt(fe)?(r="#",fe++):(r=i,Ae(A)),r===i&&(r=null),r!==i&&(n=Se())!==i?e=r={type:"identifier",value:n}:(fe=e,e=i),ye[o]={nextPos:fe,result:e},e)}())===i&&(e=function(){var e,r,n,o,a=30*fe+10,s=ye[a];return s?(fe=s.nextPos,s.result):(e=fe,91===t.charCodeAt(fe)?(r="[",fe++):(r=i,Ae(b)),r!==i&&Ee()!==i&&(n=function(){var e,r,n,o,a=30*fe+14,s=ye[a];return s?(fe=s.nextPos,s.result):(e=fe,(r=De())!==i&&Ee()!==i&&(n=function(){var e,r,n,o=30*fe+12,a=ye[o];return a?(fe=a.nextPos,a.result):(e=fe,33===t.charCodeAt(fe)?(r="!",fe++):(r=i,Ae(g)),r===i&&(r=null),r!==i?(61===t.charCodeAt(fe)?(n="=",fe++):(n=i,Ae(w)),n!==i?(r=C(r),e=r):(fe=e,e=i)):(fe=e,e=i),ye[o]={nextPos:fe,result:e},e)}())!==i&&Ee()!==i?((o=function(){var e,r,n,o,a,s=30*fe+18,l=ye[s];if(l)return fe=l.nextPos,l.result;if(e=fe,"type("===t.substr(fe,5)?(r="type(",fe+=5):(r=i,Ae(W)),r!==i)if(Ee()!==i){if(n=[],G.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(z)),o!==i)for(;o!==i;)n.push(o),G.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(z));else n=i;n!==i&&(o=Ee())!==i?(41===t.charCodeAt(fe)?(a=")",fe++):(a=i,Ae(K)),a!==i?(r={type:"type",value:n.join("")},e=r):(fe=e,e=i)):(fe=e,e=i)}else fe=e,e=i;else fe=e,e=i;return ye[s]={nextPos:fe,result:e},e}())===i&&(o=function(){var e,r,n,o,a,s,l=30*fe+20,u=ye[l];if(u)return fe=u.nextPos,u.result;if(e=fe,47===t.charCodeAt(fe)?(r="/",fe++):(r=i,Ae($)),r!==i){if(n=[],J.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(Q)),o!==i)for(;o!==i;)n.push(o),J.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(Q));else n=i;n!==i?(47===t.charCodeAt(fe)?(o="/",fe++):(o=i,Ae($)),o!==i?((a=function(){var e,r,n=30*fe+19,o=ye[n];if(o)return fe=o.nextPos,o.result;if(e=[],H.test(t.charAt(fe))?(r=t.charAt(fe),fe++):(r=i,Ae(Y)),r!==i)for(;r!==i;)e.push(r),H.test(t.charAt(fe))?(r=t.charAt(fe),fe++):(r=i,Ae(Y));else e=i;return ye[n]={nextPos:fe,result:e},e}())===i&&(a=null),a!==i?(s=a,r={type:"regexp",value:new RegExp(n.join(""),s?s.join(""):"")},e=r):(fe=e,e=i)):(fe=e,e=i)):(fe=e,e=i)}else fe=e,e=i;return ye[l]={nextPos:fe,result:e},e}()),o!==i?(r=I(r,n,o),e=r):(fe=e,e=i)):(fe=e,e=i),e===i&&(e=fe,(r=De())!==i&&Ee()!==i&&(n=function(){var e,r,n,o=30*fe+11,a=ye[o];return a?(fe=a.nextPos,a.result):(e=fe,S.test(t.charAt(fe))?(r=t.charAt(fe),fe++):(r=i,Ae(_)),r===i&&(r=null),r!==i?(61===t.charCodeAt(fe)?(n="=",fe++):(n=i,Ae(w)),n!==i?(r=C(r),e=r):(fe=e,e=i)):(fe=e,e=i),e===i&&(P.test(t.charAt(fe))?(e=t.charAt(fe),fe++):(e=i,Ae(k))),ye[o]={nextPos:fe,result:e},e)}())!==i&&Ee()!==i?((o=function(){var e,r,n,o,a,s,l=30*fe+15,u=ye[l];if(u)return fe=u.nextPos,u.result;if(e=fe,34===t.charCodeAt(fe)?(r='"',fe++):(r=i,Ae(j)),r!==i){for(n=[],F.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(T)),o===i&&(o=fe,92===t.charCodeAt(fe)?(a="\\",fe++):(a=i,Ae(L)),a!==i?(t.length>fe?(s=t.charAt(fe),fe++):(s=i,Ae(R)),s!==i?(a=O(a,s),o=a):(fe=o,o=i)):(fe=o,o=i));o!==i;)n.push(o),F.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(T)),o===i&&(o=fe,92===t.charCodeAt(fe)?(a="\\",fe++):(a=i,Ae(L)),a!==i?(t.length>fe?(s=t.charAt(fe),fe++):(s=i,Ae(R)),s!==i?(a=O(a,s),o=a):(fe=o,o=i)):(fe=o,o=i));n!==i?(34===t.charCodeAt(fe)?(o='"',fe++):(o=i,Ae(j)),o!==i?(r=B(n),e=r):(fe=e,e=i)):(fe=e,e=i)}else fe=e,e=i;if(e===i)if(e=fe,39===t.charCodeAt(fe)?(r="'",fe++):(r=i,Ae(M)),r!==i){for(n=[],U.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(V)),o===i&&(o=fe,92===t.charCodeAt(fe)?(a="\\",fe++):(a=i,Ae(L)),a!==i?(t.length>fe?(s=t.charAt(fe),fe++):(s=i,Ae(R)),s!==i?(a=O(a,s),o=a):(fe=o,o=i)):(fe=o,o=i));o!==i;)n.push(o),U.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(V)),o===i&&(o=fe,92===t.charCodeAt(fe)?(a="\\",fe++):(a=i,Ae(L)),a!==i?(t.length>fe?(s=t.charAt(fe),fe++):(s=i,Ae(R)),s!==i?(a=O(a,s),o=a):(fe=o,o=i)):(fe=o,o=i));n!==i?(39===t.charCodeAt(fe)?(o="'",fe++):(o=i,Ae(M)),o!==i?(r=B(n),e=r):(fe=e,e=i)):(fe=e,e=i)}else fe=e,e=i;return ye[l]={nextPos:fe,result:e},e}())===i&&(o=function(){var e,r,n,o,a,s,l,u=30*fe+16,c=ye[u];if(c)return fe=c.nextPos,c.result;for(e=fe,r=fe,n=[],q.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(N));o!==i;)n.push(o),q.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(N));if(n!==i?(46===t.charCodeAt(fe)?(o=".",fe++):(o=i,Ae(D)),o!==i?r=n=[n,o]:(fe=r,r=i)):(fe=r,r=i),r===i&&(r=null),r!==i){if(n=[],q.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(N)),o!==i)for(;o!==i;)n.push(o),q.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(N));else n=i;n!==i?(s=n,l=(a=r)?[].concat.apply([],a).join(""):"",r={type:"literal",value:parseFloat(l+s.join(""))},e=r):(fe=e,e=i)}else fe=e,e=i;return ye[u]={nextPos:fe,result:e},e}())===i&&(o=function(){var e,t,r=30*fe+17,n=ye[r];return n?(fe=n.nextPos,n.result):((t=Se())!==i&&(t={type:"literal",value:t}),e=t,ye[r]={nextPos:fe,result:e},e)}()),o!==i?(r=I(r,n,o),e=r):(fe=e,e=i)):(fe=e,e=i),e===i&&(e=fe,(r=De())!==i&&(r={type:"attribute",name:r}),e=r)),ye[a]={nextPos:fe,result:e},e)}())!==i&&Ee()!==i?(93===t.charCodeAt(fe)?(o="]",fe++):(o=i,Ae(E)),o!==i?e=r=n:(fe=e,e=i)):(fe=e,e=i),ye[a]={nextPos:fe,result:e},e)}())===i&&(e=function(){var e,r,n,o,a,s,l,u,c=30*fe+21,f=ye[c];if(f)return fe=f.nextPos,f.result;if(e=fe,46===t.charCodeAt(fe)?(r=".",fe++):(r=i,Ae(D)),r!==i)if((n=Se())!==i){for(o=[],a=fe,46===t.charCodeAt(fe)?(s=".",fe++):(s=i,Ae(D)),s!==i&&(l=Se())!==i?a=s=[s,l]:(fe=a,a=i);a!==i;)o.push(a),a=fe,46===t.charCodeAt(fe)?(s=".",fe++):(s=i,Ae(D)),s!==i&&(l=Se())!==i?a=s=[s,l]:(fe=a,a=i);o!==i?(u=n,r={type:"field",name:o.reduce((function(e,t){return e+t[0]+t[1]}),u)},e=r):(fe=e,e=i)}else fe=e,e=i;else fe=e,e=i;return ye[c]={nextPos:fe,result:e},e}())===i&&(e=function(){var e,r,n,o,a=30*fe+22,s=ye[a];return s?(fe=s.nextPos,s.result):(e=fe,":not("===t.substr(fe,5)?(r=":not(",fe+=5):(r=i,Ae(X)),r!==i&&Ee()!==i&&(n=we())!==i&&Ee()!==i?(41===t.charCodeAt(fe)?(o=")",fe++):(o=i,Ae(K)),o!==i?e=r={type:"not",selectors:n}:(fe=e,e=i)):(fe=e,e=i),ye[a]={nextPos:fe,result:e},e)}())===i&&(e=function(){var e,r,n,o,a=30*fe+23,s=ye[a];return s?(fe=s.nextPos,s.result):(e=fe,":matches("===t.substr(fe,9)?(r=":matches(",fe+=9):(r=i,Ae(Z)),r!==i&&Ee()!==i&&(n=we())!==i&&Ee()!==i?(41===t.charCodeAt(fe)?(o=")",fe++):(o=i,Ae(K)),o!==i?e=r={type:"matches",selectors:n}:(fe=e,e=i)):(fe=e,e=i),ye[a]={nextPos:fe,result:e},e)}())===i&&(e=function(){var e,r,n,o,a=30*fe+24,s=ye[a];return s?(fe=s.nextPos,s.result):(e=fe,":has("===t.substr(fe,5)?(r=":has(",fe+=5):(r=i,Ae(ee)),r!==i&&Ee()!==i&&(n=we())!==i&&Ee()!==i?(41===t.charCodeAt(fe)?(o=")",fe++):(o=i,Ae(K)),o!==i?e=r={type:"has",selectors:n}:(fe=e,e=i)):(fe=e,e=i),ye[a]={nextPos:fe,result:e},e)}())===i&&(e=function(){var e,r,n=30*fe+25,o=ye[n];return o?(fe=o.nextPos,o.result):(":first-child"===t.substr(fe,12)?(r=":first-child",fe+=12):(r=i,Ae(te)),r!==i&&(r=Ie(1)),e=r,ye[n]={nextPos:fe,result:e},e)}())===i&&(e=function(){var e,r,n=30*fe+26,o=ye[n];return o?(fe=o.nextPos,o.result):(":last-child"===t.substr(fe,11)?(r=":last-child",fe+=11):(r=i,Ae(re)),r!==i&&(r=je(1)),e=r,ye[n]={nextPos:fe,result:e},e)}())===i&&(e=function(){var e,r,n,o,a,s=30*fe+27,l=ye[s];if(l)return fe=l.nextPos,l.result;if(e=fe,":nth-child("===t.substr(fe,11)?(r=":nth-child(",fe+=11):(r=i,Ae(ne)),r!==i)if(Ee()!==i){if(n=[],q.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(N)),o!==i)for(;o!==i;)n.push(o),q.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(N));else n=i;n!==i&&(o=Ee())!==i?(41===t.charCodeAt(fe)?(a=")",fe++):(a=i,Ae(K)),a!==i?(r=Ie(parseInt(n.join(""),10)),e=r):(fe=e,e=i)):(fe=e,e=i)}else fe=e,e=i;else fe=e,e=i;return ye[s]={nextPos:fe,result:e},e}())===i&&(e=function(){var e,r,n,o,a,s=30*fe+28,l=ye[s];if(l)return fe=l.nextPos,l.result;if(e=fe,":nth-last-child("===t.substr(fe,16)?(r=":nth-last-child(",fe+=16):(r=i,Ae(oe)),r!==i)if(Ee()!==i){if(n=[],q.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(N)),o!==i)for(;o!==i;)n.push(o),q.test(t.charAt(fe))?(o=t.charAt(fe),fe++):(o=i,Ae(N));else n=i;n!==i&&(o=Ee())!==i?(41===t.charCodeAt(fe)?(a=")",fe++):(a=i,Ae(K)),a!==i?(r=je(parseInt(n.join(""),10)),e=r):(fe=e,e=i)):(fe=e,e=i)}else fe=e,e=i;else fe=e,e=i;return ye[s]={nextPos:fe,result:e},e}())===i&&(e=function(){var e,r,n,o=30*fe+29,a=ye[o];return a?(fe=a.nextPos,a.result):(e=fe,58===t.charCodeAt(fe)?(r=":",fe++):(r=i,Ae(ae)),r!==i?("statement"===t.substr(fe,9).toLowerCase()?(n=t.substr(fe,9),fe+=9):(n=i,Ae(se)),n===i&&("expression"===t.substr(fe,10).toLowerCase()?(n=t.substr(fe,10),fe+=10):(n=i,Ae(ie)),n===i&&("declaration"===t.substr(fe,11).toLowerCase()?(n=t.substr(fe,11),fe+=11):(n=i,Ae(le)),n===i&&("function"===t.substr(fe,8).toLowerCase()?(n=t.substr(fe,8),fe+=8):(n=i,Ae(ue)),n===i&&("pattern"===t.substr(fe,7).toLowerCase()?(n=t.substr(fe,7),fe+=7):(n=i,Ae(ce)))))),n!==i?e=r={type:"class",name:n}:(fe=e,e=i)):(fe=e,e=i),ye[o]={nextPos:fe,result:e},e)}()),ye[r]={nextPos:fe,result:e},e)}function De(){var e,r,n,o=30*fe+13,a=ye[o];if(a)return fe=a.nextPos,a.result;if(r=[],(n=Se())===i&&(46===t.charCodeAt(fe)?(n=".",fe++):(n=i,Ae(D))),n!==i)for(;n!==i;)r.push(n),(n=Se())===i&&(46===t.charCodeAt(fe)?(n=".",fe++):(n=i,Ae(D)));else r=i;return r!==i&&(r=h(r)),e=r,ye[o]={nextPos:fe,result:e},e}function Ie(e){return{type:"nth-child",index:{type:"literal",value:e}}}function je(e){return{type:"nth-last-child",index:{type:"literal",value:e}}}if((n=u())!==i&&fe===t.length)return n;throw n!==i&&fe":return A>r.value.value;case">=":return A>=r.value.value}throw new Error("Unknown operator: ".concat(r.operator));case"sibling":return l(t,r.right,n)&&u(t,r.left,n,"LEFT_SIDE")||r.left.subject&&l(t,r.left,n)&&u(t,r.right,n,"RIGHT_SIDE");case"adjacent":return l(t,r.right,n)&&c(t,r.left,n,"LEFT_SIDE")||r.right.subject&&l(t,r.left,n)&&c(t,r.right,n,"RIGHT_SIDE");case"nth-child":return l(t,r.right,n)&&f(t,n,(function(){return r.index.value-1}));case"nth-last-child":return l(t,r.right,n)&&f(t,n,(function(e){return e-r.index.value}));case"class":switch(r.name.toLowerCase()){case"statement":if("Statement"===t.type.slice(-9))return!0;case"declaration":return"Declaration"===t.type.slice(-11);case"pattern":if("Pattern"===t.type.slice(-7))return!0;case"expression":return"Expression"===t.type.slice(-10)||"Literal"===t.type.slice(-7)||"Identifier"===t.type&&(0===n.length||"MetaProperty"!==n[0].type)||"MetaProperty"===t.type;case"function":return"FunctionDeclaration"===t.type||"FunctionExpression"===t.type||"ArrowFunctionExpression"===t.type}throw new Error("Unknown class name: ".concat(r.name))}throw new Error("Unknown selector type: ".concat(r.type))}function u(e,r,n,o){var a=t(n,1)[0];if(!a)return!1;for(var i=s.VisitorKeys[a.type],u=0,c=i.length;u0&&l(f[p-1],r,n))return!0;if("RIGHT_SIDE"===o&&p=0&&c===n(u.length))return!0}}return!1}function p(n,o){if(null==n||"object"!=e(n))return[];null==o&&(o=n);for(var a=n.subject?[o]:[],s=0,i=function(e){for(var t=[],r=Object.keys(e),n=0;ne.length)&&(t=e.length);for(var r=0,n=new Array(t);r=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,s=!0,l=!1;return{s:function(){r=e[Symbol.iterator]()},n:function(){var e=r.next();return s=e.done,e},e:function(e){l=!0,i=e},f:function(){try{s||null==r.return||r.return()}finally{if(l)throw i}}}}"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;function i(e,t){return e(t={exports:{}},t.exports),t.exports}var s=i((function(e,t){!function e(t){var r,n,o,a,i,s;function l(e){var t,r,n={};for(t in e)e.hasOwnProperty(t)&&(r=e[t],n[t]="object"==typeof r&&null!==r?l(r):r);return n}function u(e,t){this.parent=e,this.key=t}function c(e,t,r,n){this.node=e,this.path=t,this.wrap=r,this.ref=n}function f(){}function p(e){return null!=e&&("object"==typeof e&&"string"==typeof e.type)}function h(e,t){return(e===r.ObjectExpression||e===r.ObjectPattern)&&"properties"===t}function y(e,t){for(var r=e.length-1;r>=0;--r)if(e[r].node===t)return!0;return!1}function d(e,t){return(new f).traverse(e,t)}function m(e,t){var r;return r=function(e,t){var r,n,o,a;for(n=e.length,o=0;n;)t(e[a=o+(r=n>>>1)])?n=r:(o=a+1,n-=r+1);return o}(t,(function(t){return t.range[0]>e.range[0]})),e.extendedRange=[e.range[0],e.range[1]],r!==t.length&&(e.extendedRange[1]=t[r].range[0]),(r-=1)>=0&&(e.extendedRange[0]=t[r].range[1]),e}return r={AssignmentExpression:"AssignmentExpression",AssignmentPattern:"AssignmentPattern",ArrayExpression:"ArrayExpression",ArrayPattern:"ArrayPattern",ArrowFunctionExpression:"ArrowFunctionExpression",AwaitExpression:"AwaitExpression",BlockStatement:"BlockStatement",BinaryExpression:"BinaryExpression",BreakStatement:"BreakStatement",CallExpression:"CallExpression",CatchClause:"CatchClause",ChainExpression:"ChainExpression",ClassBody:"ClassBody",ClassDeclaration:"ClassDeclaration",ClassExpression:"ClassExpression",ComprehensionBlock:"ComprehensionBlock",ComprehensionExpression:"ComprehensionExpression",ConditionalExpression:"ConditionalExpression",ContinueStatement:"ContinueStatement",DebuggerStatement:"DebuggerStatement",DirectiveStatement:"DirectiveStatement",DoWhileStatement:"DoWhileStatement",EmptyStatement:"EmptyStatement",ExportAllDeclaration:"ExportAllDeclaration",ExportDefaultDeclaration:"ExportDefaultDeclaration",ExportNamedDeclaration:"ExportNamedDeclaration",ExportSpecifier:"ExportSpecifier",ExpressionStatement:"ExpressionStatement",ForStatement:"ForStatement",ForInStatement:"ForInStatement",ForOfStatement:"ForOfStatement",FunctionDeclaration:"FunctionDeclaration",FunctionExpression:"FunctionExpression",GeneratorExpression:"GeneratorExpression",Identifier:"Identifier",IfStatement:"IfStatement",ImportExpression:"ImportExpression",ImportDeclaration:"ImportDeclaration",ImportDefaultSpecifier:"ImportDefaultSpecifier",ImportNamespaceSpecifier:"ImportNamespaceSpecifier",ImportSpecifier:"ImportSpecifier",Literal:"Literal",LabeledStatement:"LabeledStatement",LogicalExpression:"LogicalExpression",MemberExpression:"MemberExpression",MetaProperty:"MetaProperty",MethodDefinition:"MethodDefinition",ModuleSpecifier:"ModuleSpecifier",NewExpression:"NewExpression",ObjectExpression:"ObjectExpression",ObjectPattern:"ObjectPattern",Program:"Program",Property:"Property",RestElement:"RestElement",ReturnStatement:"ReturnStatement",SequenceExpression:"SequenceExpression",SpreadElement:"SpreadElement",Super:"Super",SwitchStatement:"SwitchStatement",SwitchCase:"SwitchCase",TaggedTemplateExpression:"TaggedTemplateExpression",TemplateElement:"TemplateElement",TemplateLiteral:"TemplateLiteral",ThisExpression:"ThisExpression",ThrowStatement:"ThrowStatement",TryStatement:"TryStatement",UnaryExpression:"UnaryExpression",UpdateExpression:"UpdateExpression",VariableDeclaration:"VariableDeclaration",VariableDeclarator:"VariableDeclarator",WhileStatement:"WhileStatement",WithStatement:"WithStatement",YieldExpression:"YieldExpression"},o={AssignmentExpression:["left","right"],AssignmentPattern:["left","right"],ArrayExpression:["elements"],ArrayPattern:["elements"],ArrowFunctionExpression:["params","body"],AwaitExpression:["argument"],BlockStatement:["body"],BinaryExpression:["left","right"],BreakStatement:["label"],CallExpression:["callee","arguments"],CatchClause:["param","body"],ChainExpression:["expression"],ClassBody:["body"],ClassDeclaration:["id","superClass","body"],ClassExpression:["id","superClass","body"],ComprehensionBlock:["left","right"],ComprehensionExpression:["blocks","filter","body"],ConditionalExpression:["test","consequent","alternate"],ContinueStatement:["label"],DebuggerStatement:[],DirectiveStatement:[],DoWhileStatement:["body","test"],EmptyStatement:[],ExportAllDeclaration:["source"],ExportDefaultDeclaration:["declaration"],ExportNamedDeclaration:["declaration","specifiers","source"],ExportSpecifier:["exported","local"],ExpressionStatement:["expression"],ForStatement:["init","test","update","body"],ForInStatement:["left","right","body"],ForOfStatement:["left","right","body"],FunctionDeclaration:["id","params","body"],FunctionExpression:["id","params","body"],GeneratorExpression:["blocks","filter","body"],Identifier:[],IfStatement:["test","consequent","alternate"],ImportExpression:["source"],ImportDeclaration:["specifiers","source"],ImportDefaultSpecifier:["local"],ImportNamespaceSpecifier:["local"],ImportSpecifier:["imported","local"],Literal:[],LabeledStatement:["label","body"],LogicalExpression:["left","right"],MemberExpression:["object","property"],MetaProperty:["meta","property"],MethodDefinition:["key","value"],ModuleSpecifier:[],NewExpression:["callee","arguments"],ObjectExpression:["properties"],ObjectPattern:["properties"],Program:["body"],Property:["key","value"],RestElement:["argument"],ReturnStatement:["argument"],SequenceExpression:["expressions"],SpreadElement:["argument"],Super:[],SwitchStatement:["discriminant","cases"],SwitchCase:["test","consequent"],TaggedTemplateExpression:["tag","quasi"],TemplateElement:[],TemplateLiteral:["quasis","expressions"],ThisExpression:[],ThrowStatement:["argument"],TryStatement:["block","handler","finalizer"],UnaryExpression:["argument"],UpdateExpression:["argument"],VariableDeclaration:["declarations"],VariableDeclarator:["id","init"],WhileStatement:["test","body"],WithStatement:["object","body"],YieldExpression:["argument"]},n={Break:a={},Skip:i={},Remove:s={}},u.prototype.replace=function(e){this.parent[this.key]=e},u.prototype.remove=function(){return Array.isArray(this.parent)?(this.parent.splice(this.key,1),!0):(this.replace(null),!1)},f.prototype.path=function(){var e,t,r,n,o;function a(e,t){if(Array.isArray(t))for(r=0,n=t.length;r=0;)if(v=s[f=x[d]])if(Array.isArray(v)){for(m=v.length;(m-=1)>=0;)if(v[m]&&!y(n,v[m])){if(h(l,x[d]))o=new c(v[m],[f,m],"Property",null);else{if(!p(v[m]))continue;o=new c(v[m],[f,m],null,null)}r.push(o)}}else if(p(v)){if(y(n,v))continue;r.push(new c(v,f,null,null))}}}else if(o=n.pop(),u=this.__execute(t.leave,o),this.__state===a||u===a)return},f.prototype.replace=function(e,t){var r,n,o,l,f,y,d,m,x,v,g,b,A;function E(e){var t,n,o,a;if(e.ref.remove())for(n=e.ref.key,a=e.ref.parent,t=r.length;t--;)if((o=r[t]).ref&&o.ref.parent===a){if(o.ref.key=0;)if(v=o[A=x[d]])if(Array.isArray(v)){for(m=v.length;(m-=1)>=0;)if(v[m]){if(h(l,x[d]))y=new c(v[m],[A,m],"Property",new u(v,m));else{if(!p(v[m]))continue;y=new c(v[m],[A,m],null,new u(v,m))}r.push(y)}}else p(v)&&r.push(new c(v,A,null,new u(o,A)))}}else if(y=n.pop(),void 0!==(f=this.__execute(t.leave,y))&&f!==a&&f!==i&&f!==s&&y.ref.replace(f),this.__state!==s&&f!==s||E(y),this.__state===a||f===a)return b.root;return b.root},t.Syntax=r,t.traverse=d,t.replace=function(e,t){return(new f).replace(e,t)},t.attachComments=function(e,t,r){var o,a,i,s,u=[];if(!e.range)throw new Error("attachComments needs range information");if(!r.length){if(t.length){for(i=0,a=t.length;ie.range[0]);)t.extendedRange[1]===e.range[0]?(e.leadingComments||(e.leadingComments=[]),e.leadingComments.push(t),u.splice(s,1)):s+=1;return s===u.length?n.Break:u[s].extendedRange[0]>e.range[1]?n.Skip:void 0}}),s=0,d(e,{leave:function(e){for(var t;se.range[1]?n.Skip:void 0}}),e},t.VisitorKeys=o,t.VisitorOption=n,t.Controller=f,t.cloneEnvironment=function(){return e({})},t}(t)})),l=i((function(e){e.exports&&(e.exports=function(){function e(t,r,n,o){this.message=t,this.expected=r,this.found=n,this.location=o,this.name="SyntaxError","function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,e)}return function(e,t){function r(){this.constructor=e}r.prototype=t.prototype,e.prototype=new r}(e,Error),e.buildMessage=function(e,t){var r={literal:function(e){return'"'+o(e.text)+'"'},class:function(e){var t,r="";for(t=0;t0){for(t=1,n=1;t<~+.]/,p=me([" ","[","]",",","(",")",":","#","!","=",">","<","~","+","."],!0,!1),h=de(">",!1),y=de("~",!1),d=de("+",!1),m=de(",",!1),x=de("!",!1),v=de("*",!1),g=de("#",!1),b=de("[",!1),A=de("]",!1),E=/^[>","<","!"],!1,!1),_=de("=",!1),w=function(e){return(e||"")+"="},C=/^[><]/,P=me([">","<"],!1,!1),k=de(".",!1),D=function(e,t,r){return{type:"attribute",name:e,operator:t,value:r}},j=de('"',!1),I=/^[^\\"]/,T=me(["\\",'"'],!0,!1),F=de("\\",!1),L={type:"any"},O=function(e,t){return e+t},R=function(e){return{type:"literal",value:(t=e.join(""),t.replace(/\\(.)/g,(function(e,t){switch(t){case"b":return"\b";case"f":return"\f";case"n":return"\n";case"r":return"\r";case"t":return"\t";case"v":return"\v";default:return t}})))};var t},B=de("'",!1),M=/^[^\\']/,U=me(["\\","'"],!0,!1),q=/^[0-9]/,V=me([["0","9"]],!1,!1),N=de("type(",!1),W=/^[^ )]/,K=me([" ",")"],!0,!1),G=de(")",!1),z=/^[imsu]/,H=me(["i","m","s","u"],!1,!1),Y=de("/",!1),$=/^[^\/]/,J=me(["/"],!0,!1),Q=de(":not(",!1),X=de(":matches(",!1),Z=de(":has(",!1),ee=de(":first-child",!1),te=de(":last-child",!1),re=de(":nth-child(",!1),ne=de(":nth-last-child(",!1),oe=de(":",!1),ae=de("statement",!0),ie=de("expression",!0),se=de("declaration",!0),le=de("function",!0),ue=de("pattern",!0),ce=0,fe=[{line:1,column:1}],pe=0,he=[],ye={};if("startRule"in r){if(!(r.startRule in l))throw new Error("Can't start parsing from rule \""+r.startRule+'".');u=l[r.startRule]}function de(e,t){return{type:"literal",text:e,ignoreCase:t}}function me(e,t,r){return{type:"class",parts:e,inverted:t,ignoreCase:r}}function xe(e){var r,n=fe[e];if(n)return n;for(r=e-1;!fe[r];)r--;for(n={line:(n=fe[r]).line,column:n.column};rpe&&(pe=ce,he=[]),he.push(e))}function be(){var e,t,r,n,o=30*ce+0,a=ye[o];return a?(ce=a.nextPos,a.result):(e=ce,(t=Ae())!==s&&(r=_e())!==s&&Ae()!==s?e=t=1===(n=r).length?n[0]:{type:"matches",selectors:n}:(ce=e,e=s),e===s&&(e=ce,(t=Ae())!==s&&(t=void 0),e=t),ye[o]={nextPos:ce,result:e},e)}function Ae(){var e,r,n=30*ce+1,o=ye[n];if(o)return ce=o.nextPos,o.result;for(e=[],32===t.charCodeAt(ce)?(r=" ",ce++):(r=s,ge(c));r!==s;)e.push(r),32===t.charCodeAt(ce)?(r=" ",ce++):(r=s,ge(c));return ye[n]={nextPos:ce,result:e},e}function Ee(){var e,r,n,o=30*ce+2,a=ye[o];if(a)return ce=a.nextPos,a.result;if(r=[],f.test(t.charAt(ce))?(n=t.charAt(ce),ce++):(n=s,ge(p)),n!==s)for(;n!==s;)r.push(n),f.test(t.charAt(ce))?(n=t.charAt(ce),ce++):(n=s,ge(p));else r=s;return r!==s&&(r=r.join("")),e=r,ye[o]={nextPos:ce,result:e},e}function Se(){var e,r,n,o=30*ce+3,a=ye[o];return a?(ce=a.nextPos,a.result):(e=ce,(r=Ae())!==s?(62===t.charCodeAt(ce)?(n=">",ce++):(n=s,ge(h)),n!==s&&Ae()!==s?e=r="child":(ce=e,e=s)):(ce=e,e=s),e===s&&(e=ce,(r=Ae())!==s?(126===t.charCodeAt(ce)?(n="~",ce++):(n=s,ge(y)),n!==s&&Ae()!==s?e=r="sibling":(ce=e,e=s)):(ce=e,e=s),e===s&&(e=ce,(r=Ae())!==s?(43===t.charCodeAt(ce)?(n="+",ce++):(n=s,ge(d)),n!==s&&Ae()!==s?e=r="adjacent":(ce=e,e=s)):(ce=e,e=s),e===s&&(e=ce,32===t.charCodeAt(ce)?(r=" ",ce++):(r=s,ge(c)),r!==s&&(n=Ae())!==s?e=r="descendant":(ce=e,e=s)))),ye[o]={nextPos:ce,result:e},e)}function _e(){var e,r,n,o,a,i,l,u,c=30*ce+4,f=ye[c];if(f)return ce=f.nextPos,f.result;if(e=ce,(r=we())!==s){for(n=[],o=ce,(a=Ae())!==s?(44===t.charCodeAt(ce)?(i=",",ce++):(i=s,ge(m)),i!==s&&(l=Ae())!==s&&(u=we())!==s?o=a=[a,i,l,u]:(ce=o,o=s)):(ce=o,o=s);o!==s;)n.push(o),o=ce,(a=Ae())!==s?(44===t.charCodeAt(ce)?(i=",",ce++):(i=s,ge(m)),i!==s&&(l=Ae())!==s&&(u=we())!==s?o=a=[a,i,l,u]:(ce=o,o=s)):(ce=o,o=s);n!==s?e=r=[r].concat(n.map((function(e){return e[3]}))):(ce=e,e=s)}else ce=e,e=s;return ye[c]={nextPos:ce,result:e},e}function we(){var e,t,r,n,o,a,i,l=30*ce+5,u=ye[l];if(u)return ce=u.nextPos,u.result;if(e=ce,(t=Ce())!==s){for(r=[],n=ce,(o=Se())!==s&&(a=Ce())!==s?n=o=[o,a]:(ce=n,n=s);n!==s;)r.push(n),n=ce,(o=Se())!==s&&(a=Ce())!==s?n=o=[o,a]:(ce=n,n=s);r!==s?(i=t,e=t=r.reduce((function(e,t){return{type:t[0],left:e,right:t[1]}}),i)):(ce=e,e=s)}else ce=e,e=s;return ye[l]={nextPos:ce,result:e},e}function Ce(){var e,r,n,o,a,i,l,u=30*ce+6,c=ye[u];if(c)return ce=c.nextPos,c.result;if(e=ce,33===t.charCodeAt(ce)?(r="!",ce++):(r=s,ge(x)),r===s&&(r=null),r!==s){if(n=[],(o=Pe())!==s)for(;o!==s;)n.push(o),o=Pe();else n=s;n!==s?(a=r,l=1===(i=n).length?i[0]:{type:"compound",selectors:i},a&&(l.subject=!0),e=r=l):(ce=e,e=s)}else ce=e,e=s;return ye[u]={nextPos:ce,result:e},e}function Pe(){var e,r=30*ce+7,n=ye[r];return n?(ce=n.nextPos,n.result):((e=function(){var e,r,n=30*ce+8,o=ye[n];return o?(ce=o.nextPos,o.result):(42===t.charCodeAt(ce)?(r="*",ce++):(r=s,ge(v)),r!==s&&(r={type:"wildcard",value:r}),e=r,ye[n]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n,o=30*ce+9,a=ye[o];return a?(ce=a.nextPos,a.result):(e=ce,35===t.charCodeAt(ce)?(r="#",ce++):(r=s,ge(g)),r===s&&(r=null),r!==s&&(n=Ee())!==s?e=r={type:"identifier",value:n}:(ce=e,e=s),ye[o]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n,o,a=30*ce+10,i=ye[a];return i?(ce=i.nextPos,i.result):(e=ce,91===t.charCodeAt(ce)?(r="[",ce++):(r=s,ge(b)),r!==s&&Ae()!==s&&(n=function(){var e,r,n,o,a=30*ce+14,i=ye[a];return i?(ce=i.nextPos,i.result):(e=ce,(r=ke())!==s&&Ae()!==s&&(n=function(){var e,r,n,o=30*ce+12,a=ye[o];return a?(ce=a.nextPos,a.result):(e=ce,33===t.charCodeAt(ce)?(r="!",ce++):(r=s,ge(x)),r===s&&(r=null),r!==s?(61===t.charCodeAt(ce)?(n="=",ce++):(n=s,ge(_)),n!==s?(r=w(r),e=r):(ce=e,e=s)):(ce=e,e=s),ye[o]={nextPos:ce,result:e},e)}())!==s&&Ae()!==s?((o=function(){var e,r,n,o,a,i=30*ce+18,l=ye[i];if(l)return ce=l.nextPos,l.result;if(e=ce,"type("===t.substr(ce,5)?(r="type(",ce+=5):(r=s,ge(N)),r!==s)if(Ae()!==s){if(n=[],W.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(K)),o!==s)for(;o!==s;)n.push(o),W.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(K));else n=s;n!==s&&(o=Ae())!==s?(41===t.charCodeAt(ce)?(a=")",ce++):(a=s,ge(G)),a!==s?(r={type:"type",value:n.join("")},e=r):(ce=e,e=s)):(ce=e,e=s)}else ce=e,e=s;else ce=e,e=s;return ye[i]={nextPos:ce,result:e},e}())===s&&(o=function(){var e,r,n,o,a,i,l=30*ce+20,u=ye[l];if(u)return ce=u.nextPos,u.result;if(e=ce,47===t.charCodeAt(ce)?(r="/",ce++):(r=s,ge(Y)),r!==s){if(n=[],$.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(J)),o!==s)for(;o!==s;)n.push(o),$.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(J));else n=s;n!==s?(47===t.charCodeAt(ce)?(o="/",ce++):(o=s,ge(Y)),o!==s?((a=function(){var e,r,n=30*ce+19,o=ye[n];if(o)return ce=o.nextPos,o.result;if(e=[],z.test(t.charAt(ce))?(r=t.charAt(ce),ce++):(r=s,ge(H)),r!==s)for(;r!==s;)e.push(r),z.test(t.charAt(ce))?(r=t.charAt(ce),ce++):(r=s,ge(H));else e=s;return ye[n]={nextPos:ce,result:e},e}())===s&&(a=null),a!==s?(i=a,r={type:"regexp",value:new RegExp(n.join(""),i?i.join(""):"")},e=r):(ce=e,e=s)):(ce=e,e=s)):(ce=e,e=s)}else ce=e,e=s;return ye[l]={nextPos:ce,result:e},e}()),o!==s?(r=D(r,n,o),e=r):(ce=e,e=s)):(ce=e,e=s),e===s&&(e=ce,(r=ke())!==s&&Ae()!==s&&(n=function(){var e,r,n,o=30*ce+11,a=ye[o];return a?(ce=a.nextPos,a.result):(e=ce,E.test(t.charAt(ce))?(r=t.charAt(ce),ce++):(r=s,ge(S)),r===s&&(r=null),r!==s?(61===t.charCodeAt(ce)?(n="=",ce++):(n=s,ge(_)),n!==s?(r=w(r),e=r):(ce=e,e=s)):(ce=e,e=s),e===s&&(C.test(t.charAt(ce))?(e=t.charAt(ce),ce++):(e=s,ge(P))),ye[o]={nextPos:ce,result:e},e)}())!==s&&Ae()!==s?((o=function(){var e,r,n,o,a,i,l=30*ce+15,u=ye[l];if(u)return ce=u.nextPos,u.result;if(e=ce,34===t.charCodeAt(ce)?(r='"',ce++):(r=s,ge(j)),r!==s){for(n=[],I.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(T)),o===s&&(o=ce,92===t.charCodeAt(ce)?(a="\\",ce++):(a=s,ge(F)),a!==s?(t.length>ce?(i=t.charAt(ce),ce++):(i=s,ge(L)),i!==s?(a=O(a,i),o=a):(ce=o,o=s)):(ce=o,o=s));o!==s;)n.push(o),I.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(T)),o===s&&(o=ce,92===t.charCodeAt(ce)?(a="\\",ce++):(a=s,ge(F)),a!==s?(t.length>ce?(i=t.charAt(ce),ce++):(i=s,ge(L)),i!==s?(a=O(a,i),o=a):(ce=o,o=s)):(ce=o,o=s));n!==s?(34===t.charCodeAt(ce)?(o='"',ce++):(o=s,ge(j)),o!==s?(r=R(n),e=r):(ce=e,e=s)):(ce=e,e=s)}else ce=e,e=s;if(e===s)if(e=ce,39===t.charCodeAt(ce)?(r="'",ce++):(r=s,ge(B)),r!==s){for(n=[],M.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(U)),o===s&&(o=ce,92===t.charCodeAt(ce)?(a="\\",ce++):(a=s,ge(F)),a!==s?(t.length>ce?(i=t.charAt(ce),ce++):(i=s,ge(L)),i!==s?(a=O(a,i),o=a):(ce=o,o=s)):(ce=o,o=s));o!==s;)n.push(o),M.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(U)),o===s&&(o=ce,92===t.charCodeAt(ce)?(a="\\",ce++):(a=s,ge(F)),a!==s?(t.length>ce?(i=t.charAt(ce),ce++):(i=s,ge(L)),i!==s?(a=O(a,i),o=a):(ce=o,o=s)):(ce=o,o=s));n!==s?(39===t.charCodeAt(ce)?(o="'",ce++):(o=s,ge(B)),o!==s?(r=R(n),e=r):(ce=e,e=s)):(ce=e,e=s)}else ce=e,e=s;return ye[l]={nextPos:ce,result:e},e}())===s&&(o=function(){var e,r,n,o,a,i,l,u=30*ce+16,c=ye[u];if(c)return ce=c.nextPos,c.result;for(e=ce,r=ce,n=[],q.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(V));o!==s;)n.push(o),q.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(V));if(n!==s?(46===t.charCodeAt(ce)?(o=".",ce++):(o=s,ge(k)),o!==s?r=n=[n,o]:(ce=r,r=s)):(ce=r,r=s),r===s&&(r=null),r!==s){if(n=[],q.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(V)),o!==s)for(;o!==s;)n.push(o),q.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(V));else n=s;n!==s?(i=n,l=(a=r)?[].concat.apply([],a).join(""):"",r={type:"literal",value:parseFloat(l+i.join(""))},e=r):(ce=e,e=s)}else ce=e,e=s;return ye[u]={nextPos:ce,result:e},e}())===s&&(o=function(){var e,t,r=30*ce+17,n=ye[r];return n?(ce=n.nextPos,n.result):((t=Ee())!==s&&(t={type:"literal",value:t}),e=t,ye[r]={nextPos:ce,result:e},e)}()),o!==s?(r=D(r,n,o),e=r):(ce=e,e=s)):(ce=e,e=s),e===s&&(e=ce,(r=ke())!==s&&(r={type:"attribute",name:r}),e=r)),ye[a]={nextPos:ce,result:e},e)}())!==s&&Ae()!==s?(93===t.charCodeAt(ce)?(o="]",ce++):(o=s,ge(A)),o!==s?e=r=n:(ce=e,e=s)):(ce=e,e=s),ye[a]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n,o,a,i,l,u,c=30*ce+21,f=ye[c];if(f)return ce=f.nextPos,f.result;if(e=ce,46===t.charCodeAt(ce)?(r=".",ce++):(r=s,ge(k)),r!==s)if((n=Ee())!==s){for(o=[],a=ce,46===t.charCodeAt(ce)?(i=".",ce++):(i=s,ge(k)),i!==s&&(l=Ee())!==s?a=i=[i,l]:(ce=a,a=s);a!==s;)o.push(a),a=ce,46===t.charCodeAt(ce)?(i=".",ce++):(i=s,ge(k)),i!==s&&(l=Ee())!==s?a=i=[i,l]:(ce=a,a=s);o!==s?(u=n,r={type:"field",name:o.reduce((function(e,t){return e+t[0]+t[1]}),u)},e=r):(ce=e,e=s)}else ce=e,e=s;else ce=e,e=s;return ye[c]={nextPos:ce,result:e},e}())===s&&(e=function(){var e,r,n,o,a=30*ce+22,i=ye[a];return i?(ce=i.nextPos,i.result):(e=ce,":not("===t.substr(ce,5)?(r=":not(",ce+=5):(r=s,ge(Q)),r!==s&&Ae()!==s&&(n=_e())!==s&&Ae()!==s?(41===t.charCodeAt(ce)?(o=")",ce++):(o=s,ge(G)),o!==s?e=r={type:"not",selectors:n}:(ce=e,e=s)):(ce=e,e=s),ye[a]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n,o,a=30*ce+23,i=ye[a];return i?(ce=i.nextPos,i.result):(e=ce,":matches("===t.substr(ce,9)?(r=":matches(",ce+=9):(r=s,ge(X)),r!==s&&Ae()!==s&&(n=_e())!==s&&Ae()!==s?(41===t.charCodeAt(ce)?(o=")",ce++):(o=s,ge(G)),o!==s?e=r={type:"matches",selectors:n}:(ce=e,e=s)):(ce=e,e=s),ye[a]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n,o,a=30*ce+24,i=ye[a];return i?(ce=i.nextPos,i.result):(e=ce,":has("===t.substr(ce,5)?(r=":has(",ce+=5):(r=s,ge(Z)),r!==s&&Ae()!==s&&(n=_e())!==s&&Ae()!==s?(41===t.charCodeAt(ce)?(o=")",ce++):(o=s,ge(G)),o!==s?e=r={type:"has",selectors:n}:(ce=e,e=s)):(ce=e,e=s),ye[a]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n=30*ce+25,o=ye[n];return o?(ce=o.nextPos,o.result):(":first-child"===t.substr(ce,12)?(r=":first-child",ce+=12):(r=s,ge(ee)),r!==s&&(r=De(1)),e=r,ye[n]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n=30*ce+26,o=ye[n];return o?(ce=o.nextPos,o.result):(":last-child"===t.substr(ce,11)?(r=":last-child",ce+=11):(r=s,ge(te)),r!==s&&(r=je(1)),e=r,ye[n]={nextPos:ce,result:e},e)}())===s&&(e=function(){var e,r,n,o,a,i=30*ce+27,l=ye[i];if(l)return ce=l.nextPos,l.result;if(e=ce,":nth-child("===t.substr(ce,11)?(r=":nth-child(",ce+=11):(r=s,ge(re)),r!==s)if(Ae()!==s){if(n=[],q.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(V)),o!==s)for(;o!==s;)n.push(o),q.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(V));else n=s;n!==s&&(o=Ae())!==s?(41===t.charCodeAt(ce)?(a=")",ce++):(a=s,ge(G)),a!==s?(r=De(parseInt(n.join(""),10)),e=r):(ce=e,e=s)):(ce=e,e=s)}else ce=e,e=s;else ce=e,e=s;return ye[i]={nextPos:ce,result:e},e}())===s&&(e=function(){var e,r,n,o,a,i=30*ce+28,l=ye[i];if(l)return ce=l.nextPos,l.result;if(e=ce,":nth-last-child("===t.substr(ce,16)?(r=":nth-last-child(",ce+=16):(r=s,ge(ne)),r!==s)if(Ae()!==s){if(n=[],q.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(V)),o!==s)for(;o!==s;)n.push(o),q.test(t.charAt(ce))?(o=t.charAt(ce),ce++):(o=s,ge(V));else n=s;n!==s&&(o=Ae())!==s?(41===t.charCodeAt(ce)?(a=")",ce++):(a=s,ge(G)),a!==s?(r=je(parseInt(n.join(""),10)),e=r):(ce=e,e=s)):(ce=e,e=s)}else ce=e,e=s;else ce=e,e=s;return ye[i]={nextPos:ce,result:e},e}())===s&&(e=function(){var e,r,n,o=30*ce+29,a=ye[o];return a?(ce=a.nextPos,a.result):(e=ce,58===t.charCodeAt(ce)?(r=":",ce++):(r=s,ge(oe)),r!==s?("statement"===t.substr(ce,9).toLowerCase()?(n=t.substr(ce,9),ce+=9):(n=s,ge(ae)),n===s&&("expression"===t.substr(ce,10).toLowerCase()?(n=t.substr(ce,10),ce+=10):(n=s,ge(ie)),n===s&&("declaration"===t.substr(ce,11).toLowerCase()?(n=t.substr(ce,11),ce+=11):(n=s,ge(se)),n===s&&("function"===t.substr(ce,8).toLowerCase()?(n=t.substr(ce,8),ce+=8):(n=s,ge(le)),n===s&&("pattern"===t.substr(ce,7).toLowerCase()?(n=t.substr(ce,7),ce+=7):(n=s,ge(ue)))))),n!==s?e=r={type:"class",name:n}:(ce=e,e=s)):(ce=e,e=s),ye[o]={nextPos:ce,result:e},e)}()),ye[r]={nextPos:ce,result:e},e)}function ke(){var e,r,n,o,a,i,l,u,c=30*ce+13,f=ye[c];if(f)return ce=f.nextPos,f.result;if(e=ce,(r=Ee())!==s){for(n=[],o=ce,46===t.charCodeAt(ce)?(a=".",ce++):(a=s,ge(k)),a!==s&&(i=Ee())!==s?o=a=[a,i]:(ce=o,o=s);o!==s;)n.push(o),o=ce,46===t.charCodeAt(ce)?(a=".",ce++):(a=s,ge(k)),a!==s&&(i=Ee())!==s?o=a=[a,i]:(ce=o,o=s);n!==s?(l=r,u=n,e=r=[].concat.apply([l],u).join("")):(ce=e,e=s)}else ce=e,e=s;return ye[c]={nextPos:ce,result:e},e}function De(e){return{type:"nth-child",index:{type:"literal",value:e}}}function je(e){return{type:"nth-last-child",index:{type:"literal",value:e}}}if((n=u())!==s&&ce===t.length)return n;throw n!==s&&ce":return w>r.value.value;case">=":return w>=r.value.value}throw new Error("Unknown operator: ".concat(r.operator));case"sibling":return u(t,r.right,n,o)&&p(t,r.left,n,"LEFT_SIDE",o)||r.left.subject&&u(t,r.left,n,o)&&p(t,r.right,n,"RIGHT_SIDE",o);case"adjacent":return u(t,r.right,n,o)&&h(t,r.left,n,"LEFT_SIDE",o)||r.right.subject&&u(t,r.left,n,o)&&h(t,r.right,n,"RIGHT_SIDE",o);case"nth-child":return u(t,r.right,n,o)&&y(t,n,(function(){return r.index.value-1}),o);case"nth-last-child":return u(t,r.right,n,o)&&y(t,n,(function(e){return e-r.index.value}),o);case"class":switch(r.name.toLowerCase()){case"statement":if("Statement"===t.type.slice(-9))return!0;case"declaration":return"Declaration"===t.type.slice(-11);case"pattern":if("Pattern"===t.type.slice(-7))return!0;case"expression":return"Expression"===t.type.slice(-10)||"Literal"===t.type.slice(-7)||"Identifier"===t.type&&(0===n.length||"MetaProperty"!==n[0].type)||"MetaProperty"===t.type;case"function":return"FunctionDeclaration"===t.type||"FunctionExpression"===t.type||"ArrowFunctionExpression"===t.type}throw new Error("Unknown class name: ".concat(r.name))}throw new Error("Unknown selector type: ".concat(r.type))}function c(e,t){var r=e.type;return t&&t.visitorKeys&&t.visitorKeys[r]?t.visitorKeys[r]:s.VisitorKeys[r]?s.VisitorKeys[r]:t&&"function"==typeof t.fallback?t.fallback(e):Object.keys(e).filter((function(e){return"type"!==e}))}function f(t){return null!==t&&"object"===e(t)&&"string"==typeof t.type}function p(e,r,n,o,i){var s=t(n,1)[0];if(!s)return!1;var l,p=a(c(s,i));try{for(p.s();!(l=p.n()).done;){var h=s[l.value];if(Array.isArray(h)){var y=h.indexOf(e);if(y<0)continue;var d=void 0,m=void 0;"LEFT_SIDE"===o?(d=0,m=y):(d=y+1,m=h.length);for(var x=d;x0&&f(h[y-1])&&u(h[y-1],r,n,i))return!0;if("RIGHT_SIDE"===o&&y=0&&f===n(u.length))return!0}}}catch(e){l.e(e)}finally{l.f()}return!1}function d(n,o){if(null==n||"object"!=e(n))return[];null==o&&(o=n);for(var a=n.subject?[o]:[],i=0,s=function(e){for(var t=[],r=Object.keys(e),n=0;n", "<"], false, false), peg$c42 = ".", peg$c43 = peg$literalExpectation(".", false), - peg$c44 = function(name, op, value) { + peg$c44 = function(a, as) { + return [].concat.apply([a], as).join(''); + }, + peg$c45 = function(name, op, value) { return { type: 'attribute', name: name, operator: op, value: value }; }, - peg$c45 = function(name) { return { type: 'attribute', name: name }; }, - peg$c46 = "\"", - peg$c47 = peg$literalExpectation("\"", false), - peg$c48 = /^[^\\"]/, - peg$c49 = peg$classExpectation(["\\", "\""], true, false), - peg$c50 = "\\", - peg$c51 = peg$literalExpectation("\\", false), - peg$c52 = peg$anyExpectation(), - peg$c53 = function(a, b) { return a + b; }, - peg$c54 = function(d) { + peg$c46 = function(name) { return { type: 'attribute', name: name }; }, + peg$c47 = "\"", + peg$c48 = peg$literalExpectation("\"", false), + peg$c49 = /^[^\\"]/, + peg$c50 = peg$classExpectation(["\\", "\""], true, false), + peg$c51 = "\\", + peg$c52 = peg$literalExpectation("\\", false), + peg$c53 = peg$anyExpectation(), + peg$c54 = function(a, b) { return a + b; }, + peg$c55 = function(d) { return { type: 'literal', value: strUnescape(d.join('')) }; }, - peg$c55 = "'", - peg$c56 = peg$literalExpectation("'", false), - peg$c57 = /^[^\\']/, - peg$c58 = peg$classExpectation(["\\", "'"], true, false), - peg$c59 = /^[0-9]/, - peg$c60 = peg$classExpectation([["0", "9"]], false, false), - peg$c61 = function(a, b) { + peg$c56 = "'", + peg$c57 = peg$literalExpectation("'", false), + peg$c58 = /^[^\\']/, + peg$c59 = peg$classExpectation(["\\", "'"], true, false), + peg$c60 = /^[0-9]/, + peg$c61 = peg$classExpectation([["0", "9"]], false, false), + peg$c62 = function(a, b) { // Can use `a.flat().join('')` once supported const leadingDecimals = a ? [].concat.apply([], a).join('') : ''; return { type: 'literal', value: parseFloat(leadingDecimals + b.join('')) }; }, - peg$c62 = function(i) { return { type: 'literal', value: i }; }, - peg$c63 = "type(", - peg$c64 = peg$literalExpectation("type(", false), - peg$c65 = /^[^ )]/, - peg$c66 = peg$classExpectation([" ", ")"], true, false), - peg$c67 = ")", - peg$c68 = peg$literalExpectation(")", false), - peg$c69 = function(t) { return { type: 'type', value: t.join('') }; }, - peg$c70 = /^[imsu]/, - peg$c71 = peg$classExpectation(["i", "m", "s", "u"], false, false), - peg$c72 = "/", - peg$c73 = peg$literalExpectation("/", false), - peg$c74 = /^[^\/]/, - peg$c75 = peg$classExpectation(["/"], true, false), - peg$c76 = function(d, flgs) { return { + peg$c63 = function(i) { return { type: 'literal', value: i }; }, + peg$c64 = "type(", + peg$c65 = peg$literalExpectation("type(", false), + peg$c66 = /^[^ )]/, + peg$c67 = peg$classExpectation([" ", ")"], true, false), + peg$c68 = ")", + peg$c69 = peg$literalExpectation(")", false), + peg$c70 = function(t) { return { type: 'type', value: t.join('') }; }, + peg$c71 = /^[imsu]/, + peg$c72 = peg$classExpectation(["i", "m", "s", "u"], false, false), + peg$c73 = "/", + peg$c74 = peg$literalExpectation("/", false), + peg$c75 = /^[^\/]/, + peg$c76 = peg$classExpectation(["/"], true, false), + peg$c77 = function(d, flgs) { return { type: 'regexp', value: new RegExp(d.join(''), flgs ? flgs.join('') : '') }; }, - peg$c77 = function(i, is) { + peg$c78 = function(i, is) { return { type: 'field', name: is.reduce(function(memo, p){ return memo + p[0] + p[1]; }, i)}; }, - peg$c78 = ":not(", - peg$c79 = peg$literalExpectation(":not(", false), - peg$c80 = function(ss) { return { type: 'not', selectors: ss }; }, - peg$c81 = ":matches(", - peg$c82 = peg$literalExpectation(":matches(", false), - peg$c83 = function(ss) { return { type: 'matches', selectors: ss }; }, - peg$c84 = ":has(", - peg$c85 = peg$literalExpectation(":has(", false), - peg$c86 = function(ss) { return { type: 'has', selectors: ss }; }, - peg$c87 = ":first-child", - peg$c88 = peg$literalExpectation(":first-child", false), - peg$c89 = function() { return nth(1); }, - peg$c90 = ":last-child", - peg$c91 = peg$literalExpectation(":last-child", false), - peg$c92 = function() { return nthLast(1); }, - peg$c93 = ":nth-child(", - peg$c94 = peg$literalExpectation(":nth-child(", false), - peg$c95 = function(n) { return nth(parseInt(n.join(''), 10)); }, - peg$c96 = ":nth-last-child(", - peg$c97 = peg$literalExpectation(":nth-last-child(", false), - peg$c98 = function(n) { return nthLast(parseInt(n.join(''), 10)); }, - peg$c99 = ":", - peg$c100 = peg$literalExpectation(":", false), - peg$c101 = "statement", - peg$c102 = peg$literalExpectation("statement", true), - peg$c103 = "expression", - peg$c104 = peg$literalExpectation("expression", true), - peg$c105 = "declaration", - peg$c106 = peg$literalExpectation("declaration", true), - peg$c107 = "function", - peg$c108 = peg$literalExpectation("function", true), - peg$c109 = "pattern", - peg$c110 = peg$literalExpectation("pattern", true), - peg$c111 = function(c) { + peg$c79 = ":not(", + peg$c80 = peg$literalExpectation(":not(", false), + peg$c81 = function(ss) { return { type: 'not', selectors: ss }; }, + peg$c82 = ":matches(", + peg$c83 = peg$literalExpectation(":matches(", false), + peg$c84 = function(ss) { return { type: 'matches', selectors: ss }; }, + peg$c85 = ":has(", + peg$c86 = peg$literalExpectation(":has(", false), + peg$c87 = function(ss) { return { type: 'has', selectors: ss }; }, + peg$c88 = ":first-child", + peg$c89 = peg$literalExpectation(":first-child", false), + peg$c90 = function() { return nth(1); }, + peg$c91 = ":last-child", + peg$c92 = peg$literalExpectation(":last-child", false), + peg$c93 = function() { return nthLast(1); }, + peg$c94 = ":nth-child(", + peg$c95 = peg$literalExpectation(":nth-child(", false), + peg$c96 = function(n) { return nth(parseInt(n.join(''), 10)); }, + peg$c97 = ":nth-last-child(", + peg$c98 = peg$literalExpectation(":nth-last-child(", false), + peg$c99 = function(n) { return nthLast(parseInt(n.join(''), 10)); }, + peg$c100 = ":", + peg$c101 = peg$literalExpectation(":", false), + peg$c102 = "statement", + peg$c103 = peg$literalExpectation("statement", true), + peg$c104 = "expression", + peg$c105 = peg$literalExpectation("expression", true), + peg$c106 = "declaration", + peg$c107 = peg$literalExpectation("declaration", true), + peg$c108 = "function", + peg$c109 = peg$literalExpectation("function", true), + peg$c110 = "pattern", + peg$c111 = peg$literalExpectation("pattern", true), + peg$c112 = function(c) { return { type: 'class', name: c }; }, @@ -1205,7 +1208,7 @@ } function peg$parseattrName() { - var s0, s1, s2; + var s0, s1, s2, s3, s4, s5; var key = peg$currPos * 30 + 13, cached = peg$resultsCache[key]; @@ -1217,39 +1220,66 @@ } s0 = peg$currPos; - s1 = []; - s2 = peg$parseidentifierName(); - if (s2 === peg$FAILED) { + s1 = peg$parseidentifierName(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; if (input.charCodeAt(peg$currPos) === 46) { - s2 = peg$c42; + s4 = peg$c42; peg$currPos++; } else { - s2 = peg$FAILED; + s4 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$c43); } } - } - if (s2 !== peg$FAILED) { - while (s2 !== peg$FAILED) { - s1.push(s2); - s2 = peg$parseidentifierName(); - if (s2 === peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 46) { - s2 = peg$c42; - peg$currPos++; + if (s4 !== peg$FAILED) { + s5 = peg$parseidentifierName(); + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 46) { + s4 = peg$c42; + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } + } + if (s4 !== peg$FAILED) { + s5 = peg$parseidentifierName(); + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c43); } + peg$currPos = s3; + s3 = peg$FAILED; } + } else { + peg$currPos = s3; + s3 = peg$FAILED; } } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c44(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } } else { - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c6(s1); + peg$currPos = s0; + s0 = peg$FAILED; } - s0 = s1; peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; @@ -1283,7 +1313,7 @@ } if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c44(s1, s3, s5); + s1 = peg$c45(s1, s3, s5); s0 = s1; } else { peg$currPos = s0; @@ -1324,7 +1354,7 @@ } if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c44(s1, s3, s5); + s1 = peg$c45(s1, s3, s5); s0 = s1; } else { peg$currPos = s0; @@ -1351,7 +1381,7 @@ s1 = peg$parseattrName(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c45(s1); + s1 = peg$c46(s1); } s0 = s1; } @@ -1376,29 +1406,29 @@ s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 34) { - s1 = peg$c46; + s1 = peg$c47; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c47); } + if (peg$silentFails === 0) { peg$fail(peg$c48); } } if (s1 !== peg$FAILED) { s2 = []; - if (peg$c48.test(input.charAt(peg$currPos))) { + if (peg$c49.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c49); } + if (peg$silentFails === 0) { peg$fail(peg$c50); } } if (s3 === peg$FAILED) { s3 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s4 = peg$c50; + s4 = peg$c51; peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c51); } + if (peg$silentFails === 0) { peg$fail(peg$c52); } } if (s4 !== peg$FAILED) { if (input.length > peg$currPos) { @@ -1406,11 +1436,11 @@ peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c52); } + if (peg$silentFails === 0) { peg$fail(peg$c53); } } if (s5 !== peg$FAILED) { peg$savedPos = s3; - s4 = peg$c53(s4, s5); + s4 = peg$c54(s4, s5); s3 = s4; } else { peg$currPos = s3; @@ -1423,21 +1453,21 @@ } while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c48.test(input.charAt(peg$currPos))) { + if (peg$c49.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c49); } + if (peg$silentFails === 0) { peg$fail(peg$c50); } } if (s3 === peg$FAILED) { s3 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s4 = peg$c50; + s4 = peg$c51; peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c51); } + if (peg$silentFails === 0) { peg$fail(peg$c52); } } if (s4 !== peg$FAILED) { if (input.length > peg$currPos) { @@ -1445,11 +1475,11 @@ peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c52); } + if (peg$silentFails === 0) { peg$fail(peg$c53); } } if (s5 !== peg$FAILED) { peg$savedPos = s3; - s4 = peg$c53(s4, s5); + s4 = peg$c54(s4, s5); s3 = s4; } else { peg$currPos = s3; @@ -1463,15 +1493,15 @@ } if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s3 = peg$c46; + s3 = peg$c47; peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c47); } + if (peg$silentFails === 0) { peg$fail(peg$c48); } } if (s3 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c54(s2); + s1 = peg$c55(s2); s0 = s1; } else { peg$currPos = s0; @@ -1488,29 +1518,29 @@ if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 39) { - s1 = peg$c55; + s1 = peg$c56; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c56); } + if (peg$silentFails === 0) { peg$fail(peg$c57); } } if (s1 !== peg$FAILED) { s2 = []; - if (peg$c57.test(input.charAt(peg$currPos))) { + if (peg$c58.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c58); } + if (peg$silentFails === 0) { peg$fail(peg$c59); } } if (s3 === peg$FAILED) { s3 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s4 = peg$c50; + s4 = peg$c51; peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c51); } + if (peg$silentFails === 0) { peg$fail(peg$c52); } } if (s4 !== peg$FAILED) { if (input.length > peg$currPos) { @@ -1518,11 +1548,11 @@ peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c52); } + if (peg$silentFails === 0) { peg$fail(peg$c53); } } if (s5 !== peg$FAILED) { peg$savedPos = s3; - s4 = peg$c53(s4, s5); + s4 = peg$c54(s4, s5); s3 = s4; } else { peg$currPos = s3; @@ -1535,21 +1565,21 @@ } while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c57.test(input.charAt(peg$currPos))) { + if (peg$c58.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c58); } + if (peg$silentFails === 0) { peg$fail(peg$c59); } } if (s3 === peg$FAILED) { s3 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s4 = peg$c50; + s4 = peg$c51; peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c51); } + if (peg$silentFails === 0) { peg$fail(peg$c52); } } if (s4 !== peg$FAILED) { if (input.length > peg$currPos) { @@ -1557,11 +1587,11 @@ peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c52); } + if (peg$silentFails === 0) { peg$fail(peg$c53); } } if (s5 !== peg$FAILED) { peg$savedPos = s3; - s4 = peg$c53(s4, s5); + s4 = peg$c54(s4, s5); s3 = s4; } else { peg$currPos = s3; @@ -1575,15 +1605,15 @@ } if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 39) { - s3 = peg$c55; + s3 = peg$c56; peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c56); } + if (peg$silentFails === 0) { peg$fail(peg$c57); } } if (s3 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c54(s2); + s1 = peg$c55(s2); s0 = s1; } else { peg$currPos = s0; @@ -1619,21 +1649,21 @@ s0 = peg$currPos; s1 = peg$currPos; s2 = []; - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c60); } + if (peg$silentFails === 0) { peg$fail(peg$c61); } } while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c60); } + if (peg$silentFails === 0) { peg$fail(peg$c61); } } } if (s2 !== peg$FAILED) { @@ -1660,22 +1690,22 @@ } if (s1 !== peg$FAILED) { s2 = []; - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c60); } + if (peg$silentFails === 0) { peg$fail(peg$c61); } } if (s3 !== peg$FAILED) { while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c60); } + if (peg$silentFails === 0) { peg$fail(peg$c61); } } } } else { @@ -1683,7 +1713,7 @@ } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c61(s1, s2); + s1 = peg$c62(s1, s2); s0 = s1; } else { peg$currPos = s0; @@ -1715,7 +1745,7 @@ s1 = peg$parseidentifierName(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c62(s1); + s1 = peg$c63(s1); } s0 = s1; @@ -1737,33 +1767,33 @@ } s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c63) { - s1 = peg$c63; + if (input.substr(peg$currPos, 5) === peg$c64) { + s1 = peg$c64; peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c64); } + if (peg$silentFails === 0) { peg$fail(peg$c65); } } if (s1 !== peg$FAILED) { s2 = peg$parse_(); if (s2 !== peg$FAILED) { s3 = []; - if (peg$c65.test(input.charAt(peg$currPos))) { + if (peg$c66.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c66); } + if (peg$silentFails === 0) { peg$fail(peg$c67); } } if (s4 !== peg$FAILED) { while (s4 !== peg$FAILED) { s3.push(s4); - if (peg$c65.test(input.charAt(peg$currPos))) { + if (peg$c66.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c66); } + if (peg$silentFails === 0) { peg$fail(peg$c67); } } } } else { @@ -1773,15 +1803,15 @@ s4 = peg$parse_(); if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c68); } + if (peg$silentFails === 0) { peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c69(s3); + s1 = peg$c70(s3); s0 = s1; } else { peg$currPos = s0; @@ -1822,22 +1852,22 @@ } s0 = []; - if (peg$c70.test(input.charAt(peg$currPos))) { + if (peg$c71.test(input.charAt(peg$currPos))) { s1 = input.charAt(peg$currPos); peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c71); } + if (peg$silentFails === 0) { peg$fail(peg$c72); } } if (s1 !== peg$FAILED) { while (s1 !== peg$FAILED) { s0.push(s1); - if (peg$c70.test(input.charAt(peg$currPos))) { + if (peg$c71.test(input.charAt(peg$currPos))) { s1 = input.charAt(peg$currPos); peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c71); } + if (peg$silentFails === 0) { peg$fail(peg$c72); } } } } else { @@ -1863,30 +1893,30 @@ s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 47) { - s1 = peg$c72; + s1 = peg$c73; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c73); } + if (peg$silentFails === 0) { peg$fail(peg$c74); } } if (s1 !== peg$FAILED) { s2 = []; - if (peg$c74.test(input.charAt(peg$currPos))) { + if (peg$c75.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c75); } + if (peg$silentFails === 0) { peg$fail(peg$c76); } } if (s3 !== peg$FAILED) { while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c74.test(input.charAt(peg$currPos))) { + if (peg$c75.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c75); } + if (peg$silentFails === 0) { peg$fail(peg$c76); } } } } else { @@ -1894,11 +1924,11 @@ } if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 47) { - s3 = peg$c72; + s3 = peg$c73; peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c73); } + if (peg$silentFails === 0) { peg$fail(peg$c74); } } if (s3 !== peg$FAILED) { s4 = peg$parseflags(); @@ -1907,7 +1937,7 @@ } if (s4 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c76(s2, s4); + s1 = peg$c77(s2, s4); s0 = s1; } else { peg$currPos = s0; @@ -2002,7 +2032,7 @@ } if (s3 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c77(s2, s3); + s1 = peg$c78(s2, s3); s0 = s1; } else { peg$currPos = s0; @@ -2035,12 +2065,12 @@ } s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c78) { - s1 = peg$c78; + if (input.substr(peg$currPos, 5) === peg$c79) { + s1 = peg$c79; peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c79); } + if (peg$silentFails === 0) { peg$fail(peg$c80); } } if (s1 !== peg$FAILED) { s2 = peg$parse_(); @@ -2050,15 +2080,15 @@ s4 = peg$parse_(); if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c68); } + if (peg$silentFails === 0) { peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c80(s3); + s1 = peg$c81(s3); s0 = s1; } else { peg$currPos = s0; @@ -2099,12 +2129,12 @@ } s0 = peg$currPos; - if (input.substr(peg$currPos, 9) === peg$c81) { - s1 = peg$c81; + if (input.substr(peg$currPos, 9) === peg$c82) { + s1 = peg$c82; peg$currPos += 9; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c82); } + if (peg$silentFails === 0) { peg$fail(peg$c83); } } if (s1 !== peg$FAILED) { s2 = peg$parse_(); @@ -2114,15 +2144,15 @@ s4 = peg$parse_(); if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c68); } + if (peg$silentFails === 0) { peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c83(s3); + s1 = peg$c84(s3); s0 = s1; } else { peg$currPos = s0; @@ -2163,12 +2193,12 @@ } s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c84) { - s1 = peg$c84; + if (input.substr(peg$currPos, 5) === peg$c85) { + s1 = peg$c85; peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c85); } + if (peg$silentFails === 0) { peg$fail(peg$c86); } } if (s1 !== peg$FAILED) { s2 = peg$parse_(); @@ -2178,15 +2208,15 @@ s4 = peg$parse_(); if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c68); } + if (peg$silentFails === 0) { peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c86(s3); + s1 = peg$c87(s3); s0 = s1; } else { peg$currPos = s0; @@ -2227,16 +2257,16 @@ } s0 = peg$currPos; - if (input.substr(peg$currPos, 12) === peg$c87) { - s1 = peg$c87; + if (input.substr(peg$currPos, 12) === peg$c88) { + s1 = peg$c88; peg$currPos += 12; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c88); } + if (peg$silentFails === 0) { peg$fail(peg$c89); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c89(); + s1 = peg$c90(); } s0 = s1; @@ -2258,16 +2288,16 @@ } s0 = peg$currPos; - if (input.substr(peg$currPos, 11) === peg$c90) { - s1 = peg$c90; + if (input.substr(peg$currPos, 11) === peg$c91) { + s1 = peg$c91; peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c91); } + if (peg$silentFails === 0) { peg$fail(peg$c92); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c92(); + s1 = peg$c93(); } s0 = s1; @@ -2289,33 +2319,33 @@ } s0 = peg$currPos; - if (input.substr(peg$currPos, 11) === peg$c93) { - s1 = peg$c93; + if (input.substr(peg$currPos, 11) === peg$c94) { + s1 = peg$c94; peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c94); } + if (peg$silentFails === 0) { peg$fail(peg$c95); } } if (s1 !== peg$FAILED) { s2 = peg$parse_(); if (s2 !== peg$FAILED) { s3 = []; - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c60); } + if (peg$silentFails === 0) { peg$fail(peg$c61); } } if (s4 !== peg$FAILED) { while (s4 !== peg$FAILED) { s3.push(s4); - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c60); } + if (peg$silentFails === 0) { peg$fail(peg$c61); } } } } else { @@ -2325,15 +2355,15 @@ s4 = peg$parse_(); if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c68); } + if (peg$silentFails === 0) { peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c95(s3); + s1 = peg$c96(s3); s0 = s1; } else { peg$currPos = s0; @@ -2374,33 +2404,33 @@ } s0 = peg$currPos; - if (input.substr(peg$currPos, 16) === peg$c96) { - s1 = peg$c96; + if (input.substr(peg$currPos, 16) === peg$c97) { + s1 = peg$c97; peg$currPos += 16; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c97); } + if (peg$silentFails === 0) { peg$fail(peg$c98); } } if (s1 !== peg$FAILED) { s2 = peg$parse_(); if (s2 !== peg$FAILED) { s3 = []; - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c60); } + if (peg$silentFails === 0) { peg$fail(peg$c61); } } if (s4 !== peg$FAILED) { while (s4 !== peg$FAILED) { s3.push(s4); - if (peg$c59.test(input.charAt(peg$currPos))) { + if (peg$c60.test(input.charAt(peg$currPos))) { s4 = input.charAt(peg$currPos); peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c60); } + if (peg$silentFails === 0) { peg$fail(peg$c61); } } } } else { @@ -2410,15 +2440,15 @@ s4 = peg$parse_(); if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c67; + s5 = peg$c68; peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c68); } + if (peg$silentFails === 0) { peg$fail(peg$c69); } } if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c98(s3); + s1 = peg$c99(s3); s0 = s1; } else { peg$currPos = s0; @@ -2460,51 +2490,51 @@ s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 58) { - s1 = peg$c99; + s1 = peg$c100; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c100); } + if (peg$silentFails === 0) { peg$fail(peg$c101); } } if (s1 !== peg$FAILED) { - if (input.substr(peg$currPos, 9).toLowerCase() === peg$c101) { + if (input.substr(peg$currPos, 9).toLowerCase() === peg$c102) { s2 = input.substr(peg$currPos, 9); peg$currPos += 9; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c102); } + if (peg$silentFails === 0) { peg$fail(peg$c103); } } if (s2 === peg$FAILED) { - if (input.substr(peg$currPos, 10).toLowerCase() === peg$c103) { + if (input.substr(peg$currPos, 10).toLowerCase() === peg$c104) { s2 = input.substr(peg$currPos, 10); peg$currPos += 10; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c104); } + if (peg$silentFails === 0) { peg$fail(peg$c105); } } if (s2 === peg$FAILED) { - if (input.substr(peg$currPos, 11).toLowerCase() === peg$c105) { + if (input.substr(peg$currPos, 11).toLowerCase() === peg$c106) { s2 = input.substr(peg$currPos, 11); peg$currPos += 11; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c106); } + if (peg$silentFails === 0) { peg$fail(peg$c107); } } if (s2 === peg$FAILED) { - if (input.substr(peg$currPos, 8).toLowerCase() === peg$c107) { + if (input.substr(peg$currPos, 8).toLowerCase() === peg$c108) { s2 = input.substr(peg$currPos, 8); peg$currPos += 8; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c108); } + if (peg$silentFails === 0) { peg$fail(peg$c109); } } if (s2 === peg$FAILED) { - if (input.substr(peg$currPos, 7).toLowerCase() === peg$c109) { + if (input.substr(peg$currPos, 7).toLowerCase() === peg$c110) { s2 = input.substr(peg$currPos, 7); peg$currPos += 7; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c110); } + if (peg$silentFails === 0) { peg$fail(peg$c111); } } } } @@ -2512,7 +2542,7 @@ } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c111(s2); + s1 = peg$c112(s2); s0 = s1; } else { peg$currPos = s0; diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/README.md b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/README.md index 65368f5fe1f9c8..41a995cc7620e3 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/README.md +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/README.md @@ -1,8 +1,8 @@ Ajv logo -# Ajv: Another JSON Schema Validator +# Ajv: Another JSON schema validator -The fastest JSON Schema validator for Node.js and browser. Supports draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)). +The fastest JSON schema validator for Node.js and browser. Supports JSON Schema draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)) and JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/). [![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild) [![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv) @@ -17,9 +17,10 @@ The fastest JSON Schema validator for Node.js and browser. Supports draft-06/07/ ## Using version 7 -Ajv version 7 is released with these changes: +Ajv version 7 has these new features: - support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./docs/json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./docs/json-schema.md#unevaluateditems), [dynamic recursive references](./docs/validation.md#extending-recursive-schemas) and other [additional keywords](./docs/json-schema.md#json-schema-draft-2019-09). +- NEW: support of JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/) (from [v7.1.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v7.1.0)) - to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements. - to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%). - to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0)) @@ -71,6 +72,9 @@ Please review [Contributing guidelines](./CONTRIBUTING.md) and [Code components] - [Performance](#performance) - [Features](#features) - [Getting started](#usage) +- [Choosing schema language](#choosing-schema-language) + - [JSON Schema](#json-schema) + - [JSON Type Definition](#json-type-definition) - [Frequently Asked Questions](./docs/faq.md) - [Using in browser](#using-in-browser) - [Content Security Policy](./docs/security.md#content-security-policy) @@ -166,7 +170,7 @@ Performance of different validators by [json-schema-benchmark](https://github.co ## Features -- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6): +- Ajv implements JSON Schema [draft-06/07/2019-09](http://json-schema.org/) standards (draft-04 is supported in v6): - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md)) - keyword "nullable" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/). - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available) @@ -174,6 +178,10 @@ Performance of different validators by [json-schema-benchmark](https://github.co - correct string lengths for strings with unicode pairs - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off) - [validates schemas against meta-schema](./docs/api.md#api-validateschema) +- NEW: supports [JSON Type Definition](https://datatracker.ietf.org/doc/rfc8927/): + - all forms (see [JSON Type Definition schema forms](./docs/json-type-definition.md)) + - meta-schema for JTD schemas + - "union" keyword and user-defined keywords (can be used inside "metadata" member of the schema) - supports [browsers](#using-in-browser) and Node.js 0.10-14.x - [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation - "All errors" validation mode with [option allErrors](./docs/api.md#options) @@ -262,6 +270,26 @@ if (validate(data)) { } ``` +With JSON Type Definition schema: + +```javascript +const Ajv = require("ajv").default + +const ajv = new Ajv() // options can be passed, e.g. {allErrors: true} +const schema = { + properties: { + foo: {type: "float64"}, + }, +} +const validate = ajv.compile(schema) +const valid = validate({foo: 1}) // true +if (!valid) console.log(validate.errors) +// Unlike JSON Schema: +const valid1 = validate(1) // false, bot an object +const valid2 = validate({}) // false, foo is required +const valid3 = validate({foo: 1, bar: 2}) // false, bar is additional +``` + See [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details. Ajv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again. @@ -290,7 +318,7 @@ Then you need to load Ajv with support of JSON Schema draft-07 in the browser: ``` -or to load the bundle that supports JSONSchema draft-2019-09: +To load the bundle that supports JSON Schema draft-2019-09: ```html @@ -302,12 +330,75 @@ or to load the bundle that supports JSONSchema draft-2019-09: ``` +To load the bundle that supports JSON Type Definition: + +```html + + +``` + This bundle can be used with different module systems; it creates global `ajv` (or `ajv2019`) if no module system is found. The browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv). **Please note**: some frameworks, e.g. Dojo, may redefine global require in a way that is not compatible with CommonJS module format. In this case Ajv bundle has to be loaded before the framework and then you can use global `ajv` (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)). +## Choosing schema language + +Both JSON Schema and JSON Type Definition are cross-platform specifications with implementations in multiple programming languages that help you define the shape and requirements to your JSON data. + +This section compares their pros/cons to help decide which specification fits your application better. + +### JSON Schema + +- Pros + - Wide specification adoption. + - Used as part of OpenAPI specification. + - Support of complex validation scenarios: + - untagged unions and boolean logic + - conditional schemas and dependencies + - restrictions on the number ranges and the size of strings, arrays and objects + - semantic validation with formats, patterns and content keywords + - distribute strict record definitions across multiple schemas (with unevaluatedProperties) + - Can be effectively used for validation of any JavaScript objects and configuration files. +- Cons + - Defines the collection of restrictions on the data, rather than the shape of the data. + - No standard support for tagged unions. + - Complex and error prone for the new users (Ajv has [strict mode](./docs/strict-mode) to compensate for it, but it is not cross-platform). + - Some parts of specification are difficult to implement, creating the risk of implementations divergence: + - reference resolution model + - unevaluatedProperties/unevaluatedItems + - dynamic recursive references + - Internet draft status (rather than RFC) + +See [JSON Schema](./docs/json-schema.md) for the list of defined keywords. + +### JSON Type Definition + +- Pros: + - Aligned with type systems of many languages - can be used to generate type definitions and efficient parsers and serializers to/from these types. + - Very simple, enforcing the best practices for cross-platform JSON API modelling. + - Simple to implement, ensuring consistency across implementations. + - Defines the shape of JSON data via strictly defined schema forms (rather than the collection of restrictions). + - Effective support for tagged unions. + - Designed to protect against user mistakes. + - Approved as [RFC8927](https://datatracker.ietf.org/doc/rfc8927/) +- Cons: + - Limited, compared with JSON Schema - no support for untagged unions\*, conditionals, references between different schema files\*\*, etc. + - No meta-schema in the specification\*. + - Brand new - limited industry adoption (as of January 2021). + +\* Ajv defines meta-schema for JTD schemas and non-standard keyword "union" that can be used inside "metadata" object. + +\*\* You can still combine schemas from multiple files in the application code. + +See [JSON Type Definition](./docs/json-type-definition.md) for the list of defined schema forms. + ## Using in ES5 environment You need to: @@ -334,7 +425,7 @@ CLI is available as a separate npm package [ajv-cli](https://github.com/ajv-vali - user-defined meta-schemas, validation keywords and formats - files in JSON, JSON5, YAML, and JavaScript format - all Ajv options -- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format +- reporting changes in data after validation in [JSON-patch](https://datatracker.ietf.org/doc/rfc6902/) format ## Extending Ajv diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/ajv.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/ajv.js index be8275b51a8082..8aa63972897683 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/ajv.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/ajv.js @@ -22,10 +22,9 @@ class Ajv extends core_1.default { } _addDefaultMetaSchema() { super._addDefaultMetaSchema(); - const { $data, meta } = this.opts; - if (!meta) + if (!this.opts.meta) return; - const metaSchema = $data + const metaSchema = this.opts.$data ? this.$dataMetaSchema(draft7MetaSchema, META_SUPPORT_DATA) : draft7MetaSchema; this.addMetaSchema(metaSchema, META_SCHEMA_ID, false); diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/codegen/scope.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/codegen/scope.js index ef1b1670127d50..91919e8880b493 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/codegen/scope.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/codegen/scope.js @@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.ValueScope = exports.ValueScopeName = exports.Scope = exports.varKinds = void 0; +exports.ValueScope = exports.ValueScopeName = exports.Scope = exports.varKinds = exports.UsedValueState = void 0; const code_1 = require("./code"); class ValueError extends Error { constructor(name) { @@ -8,6 +8,11 @@ class ValueError extends Error { this.value = name.value; } } +var UsedValueState; +(function (UsedValueState) { + UsedValueState[UsedValueState["Started"] = 0] = "Started"; + UsedValueState[UsedValueState["Completed"] = 1] = "Completed"; +})(UsedValueState = exports.UsedValueState || (exports.UsedValueState = {})); exports.varKinds = { const: new code_1.Name("const"), let: new code_1.Name("let"), @@ -112,11 +117,11 @@ class ValueScope extends Scope { const vs = values[prefix]; if (!vs) continue; - const nameSet = (usedValues[prefix] = usedValues[prefix] || new Set()); + const nameSet = (usedValues[prefix] = usedValues[prefix] || new Map()); vs.forEach((name) => { if (nameSet.has(name)) return; - nameSet.add(name); + nameSet.set(name, UsedValueState.Started); let c = valueCode(name); if (c) { const def = this.opts.es5 ? exports.varKinds.var : exports.varKinds.const; @@ -128,6 +133,7 @@ class ValueScope extends Scope { else { throw new ValueError(name); } + nameSet.set(name, UsedValueState.Completed); }); } return code; diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/context.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/context.js index fc3e3f7e1d9005..17dd9ba110080a 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/context.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/context.js @@ -79,7 +79,7 @@ class KeywordCxt { } error(append) { ; - (append ? errors_1.reportExtraError : errors_1.reportError)(this, this.def.error || errors_1.keywordError); + (append ? errors_1.reportExtraError : errors_1.reportError)(this, this.def.error); } $dataError() { errors_1.reportError(this, this.def.$dataError || errors_1.keyword$DataError); diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/error_classes.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/error_classes.js index 753d657af035c2..ef391070002a52 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/error_classes.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/error_classes.js @@ -11,8 +11,8 @@ class ValidationError extends Error { } exports.ValidationError = ValidationError; class MissingRefError extends Error { - constructor(baseId, ref) { - super(`can't resolve reference ${ref} from id ${baseId}`); + constructor(baseId, ref, msg) { + super(msg || `can't resolve reference ${ref} from id ${baseId}`); this.missingRef = resolve_1.resolveUrl(baseId, ref); this.missingSchema = resolve_1.normalizeId(resolve_1.getFullPath(this.missingRef)); } diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/errors.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/errors.js index f248e67c2c7866..fa886d80d90c58 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/errors.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/errors.js @@ -11,7 +11,7 @@ exports.keyword$DataError = { ? codegen_1.str `"${keyword}" keyword must be ${schemaType} ($data)` : codegen_1.str `"${keyword}" keyword is invalid ($data)`, }; -function reportError(cxt, error, overrideAllErrors) { +function reportError(cxt, error = exports.keywordError, overrideAllErrors) { const { it } = cxt; const { gen, compositeRule, allErrors } = it; const errObj = errorObjectCode(cxt, error); @@ -23,7 +23,7 @@ function reportError(cxt, error, overrideAllErrors) { } } exports.reportError = reportError; -function reportExtraError(cxt, error) { +function reportExtraError(cxt, error = exports.keywordError) { const { it } = cxt; const { gen, compositeRule, allErrors } = it; const errObj = errorObjectCode(cxt, error); @@ -77,11 +77,30 @@ const E = { message: new codegen_1.Name("message"), schema: new codegen_1.Name("schema"), parentSchema: new codegen_1.Name("parentSchema"), + // JTD error properties + instancePath: new codegen_1.Name("instancePath"), }; function errorObjectCode(cxt, error) { - const { keyword, data, schemaValue, it: { gen, createErrors, topSchemaRef, schemaPath, errorPath, errSchemaPath, propertyName, opts }, } = cxt; + const { createErrors, opts } = cxt.it; if (createErrors === false) return codegen_1._ `{}`; + return (opts.jtd && !opts.ajvErrors ? jtdErrorObject : ajvErrorObject)(cxt, error); +} +function jtdErrorObject(cxt, { message }) { + const { gen, keyword, it } = cxt; + const { errorPath, errSchemaPath, opts } = it; + const keyValues = [ + [E.instancePath, codegen_1.strConcat(names_1.default.dataPath, errorPath)], + [E.schemaPath, codegen_1.str `${errSchemaPath}/${keyword}`], + ]; + if (opts.messages) { + keyValues.push([E.message, typeof message == "function" ? message(cxt) : message]); + } + return gen.object(...keyValues); +} +function ajvErrorObject(cxt, error) { + const { gen, keyword, data, schemaValue, it } = cxt; + const { topSchemaRef, schemaPath, errorPath, errSchemaPath, propertyName, opts } = it; const { params, message } = error; const keyValues = [ [E.keyword, keyword], @@ -91,9 +110,8 @@ function errorObjectCode(cxt, error) { ]; if (propertyName) keyValues.push([E.propertyName, propertyName]); - if (opts.messages !== false) { - const msg = typeof message == "function" ? message(cxt) : message; - keyValues.push([E.message, msg]); + if (opts.messages) { + keyValues.push([E.message, typeof message == "function" ? message(cxt) : message]); } if (opts.verbose) { keyValues.push([E.schema, schemaValue], [E.parentSchema, codegen_1._ `${topSchemaRef}${schemaPath}`], [names_1.default.data, data]); diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/index.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/index.js index b9d9bfb09974ce..05a7a27df28242 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/index.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/index.js @@ -64,11 +64,10 @@ function compileSchema(sch) { ValidationError: _ValidationError, schema: sch.schema, schemaEnv: sch, - strictSchema: true, rootId, baseId: sch.baseId || rootId, schemaPath: codegen_1.nil, - errSchemaPath: "#", + errSchemaPath: this.opts.jtd ? "" : "#", errorPath: codegen_1._ `""`, opts: this.opts, self: this, @@ -171,7 +170,7 @@ ref // reference to resolve ) { const p = URI.parse(ref); const refPath = resolve_1._getFullPath(p); - const baseId = resolve_1.getFullPath(root.baseId); + let baseId = resolve_1.getFullPath(root.baseId); // TODO `Object.keys(root.schema).length > 0` should not be needed - but removing breaks 2 tests if (Object.keys(root.schema).length > 0 && refPath === baseId) { return getJsonPointer.call(this, p, root); @@ -188,8 +187,12 @@ ref // reference to resolve return; if (!schOrRef.validate) compileSchema.call(this, schOrRef); - if (id === resolve_1.normalizeId(ref)) - return new SchemaEnv({ schema: schOrRef.schema, root, baseId }); + if (id === resolve_1.normalizeId(ref)) { + const { schema } = schOrRef; + if (schema.$id) + baseId = resolve_1.resolveUrl(baseId, schema.$id); + return new SchemaEnv({ schema, root, baseId }); + } return getJsonPointer.call(this, p, schOrRef); } exports.resolveSchema = resolveSchema; diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/rules.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/rules.js index 11c114a4c33477..82a591ff4dbdd8 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/rules.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/rules.js @@ -18,8 +18,8 @@ function getRules() { types: { ...groups, integer: true, boolean: true, null: true }, rules: [{ rules: [] }, groups.number, groups.string, groups.array, groups.object], post: { rules: [] }, - all: { type: true, $comment: true }, - keywords: { type: true, $comment: true }, + all: {}, + keywords: {}, }; } exports.getRules = getRules; diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/subschema.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/subschema.js index df69e4cc54bf7e..1d6de6358606b8 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/subschema.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/subschema.js @@ -18,7 +18,7 @@ function applySubschema(it, appl, valid) { return nextContext; } exports.applySubschema = applySubschema; -function getSubschema(it, { keyword, schemaProp, schema, strictSchema, schemaPath, errSchemaPath, topSchemaRef, }) { +function getSubschema(it, { keyword, schemaProp, schema, schemaPath, errSchemaPath, topSchemaRef }) { if (keyword !== undefined && schema !== undefined) { throw new Error('both "keyword" and "schema" passed, only one allowed'); } @@ -42,7 +42,6 @@ function getSubschema(it, { keyword, schemaProp, schema, strictSchema, schemaPat } return { schema, - strictSchema, schemaPath, topSchemaRef, errSchemaPath, @@ -80,14 +79,15 @@ function extendSubschemaData(subschema, it, { dataProp, dataPropType: dpType, da subschema.dataNames = [...it.dataNames, _nextData]; } } -function extendSubschemaMode(subschema, { compositeRule, createErrors, allErrors, strictSchema }) { +function extendSubschemaMode(subschema, { jtdDiscriminator, jtdMetadata, compositeRule, createErrors, allErrors }) { if (compositeRule !== undefined) subschema.compositeRule = compositeRule; if (createErrors !== undefined) subschema.createErrors = createErrors; if (allErrors !== undefined) subschema.allErrors = allErrors; - subschema.strictSchema = strictSchema; // not inherited + subschema.jtdDiscriminator = jtdDiscriminator; // not inherited + subschema.jtdMetadata = jtdMetadata; // not inherited } function getErrorPath(dataProp, dataPropType, jsPropertySyntax) { // let path diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/timestamp.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/timestamp.js new file mode 100644 index 00000000000000..fcb61fe51c793b --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/timestamp.js @@ -0,0 +1,29 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const DATE_TIME = /^(\d\d\d\d)-(\d\d)-(\d\d)(?:t|\s)(\d\d):(\d\d):(\d\d)(?:\.\d+)?(?:z|([+-]\d\d)(?::?(\d\d))?)$/i; +const DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; +function validTimestamp(str) { + // http://tools.ietf.org/html/rfc3339#section-5.6 + const matches = DATE_TIME.exec(str); + if (!matches) + return false; + const y = +matches[1]; + const m = +matches[2]; + const d = +matches[3]; + const hr = +matches[4]; + const min = +matches[5]; + const sec = +matches[6]; + const tzH = +(matches[7] || 0); + const tzM = +(matches[8] || 0); + return (m >= 1 && + m <= 12 && + d >= 1 && + (d <= DAYS[m] || + // leap year: https://tools.ietf.org/html/rfc3339#appendix-C + (m === 2 && d === 29 && (y % 100 === 0 ? y % 400 === 0 : y % 4 === 0))) && + ((hr <= 23 && min <= 59 && sec <= 59) || + // leap second + (hr - tzH === 23 && min - tzM === 59 && sec === 60))); +} +exports.default = validTimestamp; +//# sourceMappingURL=timestamp.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/validate/index.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/validate/index.js index 0db360a2cfc3e9..eb26357b1fcb29 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/validate/index.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/validate/index.js @@ -119,6 +119,8 @@ function checkKeywords(it) { checkRefsAndKeywords(it); } function typeAndKeywords(it, errsCount) { + if (it.opts.jtd) + return iterate_1.schemaKeywords(it, [], false, errsCount); const types = dataType_1.getSchemaTypes(it.schema); const checkedTypes = dataType_1.coerceAndCheckDataType(it, types); iterate_1.schemaKeywords(it, types, !checkedTypes, errsCount); diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/validate/iterate.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/validate/iterate.js index fb97c64def071e..cabe37a971bd04 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/validate/iterate.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/compile/validate/iterate.js @@ -16,7 +16,8 @@ function schemaKeywords(it, types, typeErrors, errsCount) { gen.block(() => keyword_1.keywordCode(it, "$ref", RULES.all.$ref.definition)); // TODO typecast return; } - checkStrictTypes(it, types); + if (!opts.jtd) + checkStrictTypes(it, types); gen.block(() => { for (const group of RULES.rules) groupKeywords(group); diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/core.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/core.js index 23aae7ea64e951..465201b21268f9 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/core.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/core.js @@ -409,8 +409,11 @@ class Ajv { } } _addSchema(schema, meta, validateSchema = this.opts.validateSchema, addSchema = this.opts.addUsedSchema) { - if (typeof schema != "object" && typeof schema != "boolean") { - throw new Error("schema must be object or boolean"); + if (typeof schema != "object") { + if (this.opts.jtd) + throw new Error("schema must be object"); + else if (typeof schema != "boolean") + throw new Error("schema must be object or boolean"); } let sch = this._cache.get(schema); if (sch !== undefined) @@ -515,7 +518,7 @@ function getLogger(logger) { return logger; throw new Error("logger must implement log, warn and error methods"); } -const KEYWORD_NAME = /^[a-z_$][a-z0-9_$-]*$/i; +const KEYWORD_NAME = /^[a-z_$][a-z0-9_$-:]*$/i; function checkKeyword(keyword, def) { const { RULES } = this; util_1.eachItem(keyword, (kwd) => { diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/jtd.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/jtd.js new file mode 100644 index 00000000000000..6d7924b97ae931 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/jtd.js @@ -0,0 +1,44 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CodeGen = exports.Name = exports.nil = exports.stringify = exports.str = exports._ = exports.KeywordCxt = void 0; +const context_1 = require("./compile/context"); +exports.KeywordCxt = context_1.default; +// export {DefinedError} from "./vocabularies/errors" +var codegen_1 = require("./compile/codegen"); +Object.defineProperty(exports, "_", { enumerable: true, get: function () { return codegen_1._; } }); +Object.defineProperty(exports, "str", { enumerable: true, get: function () { return codegen_1.str; } }); +Object.defineProperty(exports, "stringify", { enumerable: true, get: function () { return codegen_1.stringify; } }); +Object.defineProperty(exports, "nil", { enumerable: true, get: function () { return codegen_1.nil; } }); +Object.defineProperty(exports, "Name", { enumerable: true, get: function () { return codegen_1.Name; } }); +Object.defineProperty(exports, "CodeGen", { enumerable: true, get: function () { return codegen_1.CodeGen; } }); +const core_1 = require("./core"); +const jtd_1 = require("./vocabularies/jtd"); +const jtd_schema_1 = require("./refs/jtd-schema"); +// const META_SUPPORT_DATA = ["/properties"] +const META_SCHEMA_ID = "JTD-meta-schema"; +class Ajv extends core_1.default { + constructor(opts = {}) { + var _a; + super({ + ...opts, + jtd: true, + messages: (_a = opts.messages) !== null && _a !== void 0 ? _a : false, + }); + } + _addVocabularies() { + super._addVocabularies(); + this.addVocabulary(jtd_1.default); + } + _addDefaultMetaSchema() { + super._addDefaultMetaSchema(); + if (!this.opts.meta) + return; + this.addMetaSchema(jtd_schema_1.default, META_SCHEMA_ID, false); + } + defaultMeta() { + return (this.opts.defaultMeta = + super.defaultMeta() || (this.getSchema(META_SCHEMA_ID) ? META_SCHEMA_ID : undefined)); + } +} +exports.default = Ajv; +//# sourceMappingURL=jtd.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/refs/jtd-schema.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/refs/jtd-schema.js new file mode 100644 index 00000000000000..1ee940afb219a1 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/refs/jtd-schema.js @@ -0,0 +1,118 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const shared = (root) => { + const sch = { + nullable: { type: "boolean" }, + metadata: { + optionalProperties: { + union: { elements: { ref: "schema" } }, + }, + additionalProperties: true, + }, + }; + if (root) + sch.definitions = { values: { ref: "schema" } }; + return sch; +}; +const emptyForm = (root) => ({ + optionalProperties: shared(root), +}); +const refForm = (root) => ({ + properties: { + ref: { type: "string" }, + }, + optionalProperties: shared(root), +}); +const typeForm = (root) => ({ + properties: { + type: { + enum: [ + "boolean", + "timestamp", + "string", + "float32", + "float64", + "int8", + "uint8", + "int16", + "uint16", + "int32", + "uint32", + ], + }, + }, + optionalProperties: shared(root), +}); +const enumForm = (root) => ({ + properties: { + enum: { elements: { type: "string" } }, + }, + optionalProperties: shared(root), +}); +const elementsForm = (root) => ({ + properties: { + elements: { ref: "schema" }, + }, + optionalProperties: shared(root), +}); +const propertiesForm = (root) => ({ + properties: { + properties: { values: { ref: "schema" } }, + }, + optionalProperties: { + optionalProperties: { values: { ref: "schema" } }, + additionalProperties: { type: "boolean" }, + ...shared(root), + }, +}); +const optionalPropertiesForm = (root) => ({ + properties: { + optionalProperties: { values: { ref: "schema" } }, + }, + optionalProperties: { + additionalProperties: { type: "boolean" }, + ...shared(root), + }, +}); +const discriminatorForm = (root) => ({ + properties: { + discriminator: { type: "string" }, + mapping: { + values: { + metadata: { + union: [propertiesForm(false), optionalPropertiesForm(false)], + }, + }, + }, + }, + optionalProperties: shared(root), +}); +const valuesForm = (root) => ({ + properties: { + values: { ref: "schema" }, + }, + optionalProperties: shared(root), +}); +const schema = (root) => ({ + metadata: { + union: [ + emptyForm, + refForm, + typeForm, + enumForm, + elementsForm, + propertiesForm, + optionalPropertiesForm, + discriminatorForm, + valuesForm, + ].map((s) => s(root)), + }, +}); +const jtdMetaSchema = { + definitions: { + schema: schema(false), + }, + ...schema(true), +}; +exports.default = jtdMetaSchema; +//# sourceMappingURL=jtd-schema.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/standalone/index.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/standalone/index.js index c49bde936bcb33..f58ebb6977bfba 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/standalone/index.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/standalone/index.js @@ -40,9 +40,9 @@ function standaloneCode(ajv, refsOrFunc) { function validateCode(usedValues, s) { if (!s) throw new Error('moduleCode: function does not have "source" property'); - const { prefix } = s.validateName; - const nameSet = (usedValues[prefix] = usedValues[prefix] || new Set()); - nameSet.add(s.validateName); + if (usedState(s.validateName) === scope_1.UsedValueState.Completed) + return code_1.nil; + setUsedState(s.validateName, scope_1.UsedValueState.Started); const scopeCode = ajv.scope.scopeCode(s.scopeValues, usedValues, refValidateCode); const code = new code_1._Code(`${scopeCode}${_n}${s.validateCode}`); return s.evaluated ? code_1._ `${code}${s.validateName}.evaluated = ${s.evaluated};${_n}` : code; @@ -55,12 +55,26 @@ function standaloneCode(ajv, refsOrFunc) { } else if ((n.prefix === "root" || n.prefix === "wrapper") && typeof vRef == "object") { const { validate, validateName } = vRef; - const vCode = validateCode(usedValues, validate === null || validate === void 0 ? void 0 : validate.source); + if (!validateName) + throw new Error("ajv internal error"); const def = ajv.opts.code.es5 ? scope_1.varKinds.var : scope_1.varKinds.const; - return code_1._ `${def} ${n} = {validate: ${validateName}};${_n}${vCode}`; + const wrapper = code_1._ `${def} ${n} = {validate: ${validateName}};`; + if (usedState(validateName) === scope_1.UsedValueState.Started) + return wrapper; + const vCode = validateCode(usedValues, validate === null || validate === void 0 ? void 0 : validate.source); + return code_1._ `${wrapper}${_n}${vCode}`; } return undefined; } + function usedState(name) { + var _a; + return (_a = usedValues[name.prefix]) === null || _a === void 0 ? void 0 : _a.get(name); + } + function setUsedState(name, state) { + const { prefix } = name; + const names = (usedValues[prefix] = usedValues[prefix] || new Map()); + names.set(name, state); + } } } exports.default = standaloneCode; diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js index 226c2a7a13ba49..998b9666926b7b 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js @@ -41,8 +41,13 @@ const def = { let definedProp; if (props.length > 8) { // TODO maybe an option instead of hard-coded 8? + const hasProp = gen.scopeValue("func", { + // eslint-disable-next-line @typescript-eslint/unbound-method + ref: Object.prototype.hasOwnProperty, + code: codegen_1._ `Object.prototype.hasOwnProperty`, + }); const propsSchema = util_1.schemaRefOrVal(it, parentSchema.properties, "properties"); - definedProp = codegen_1._ `${propsSchema}.hasOwnProperty(${key})`; + definedProp = codegen_1._ `${hasProp}.call(${propsSchema}, ${key})`; } else if (props.length) { definedProp = codegen_1.or(...props.map((p) => codegen_1._ `${key} === ${p}`)); @@ -53,7 +58,7 @@ const def = { if (patProps.length) { definedProp = codegen_1.or(definedProp, ...patProps.map((p) => codegen_1._ `${code_1.usePattern(gen, p)}.test(${key})`)); } - return codegen_1._ `!(${definedProp})`; + return codegen_1.not(definedProp); } function deleteAdditional(key) { gen.code(codegen_1._ `delete ${data}[${key}]`); @@ -91,7 +96,6 @@ const def = { keyword: "additionalProperties", dataProp: key, dataPropType: subschema_1.Type.Str, - strictSchema: it.strictSchema, }; if (errors === false) { Object.assign(subschema, { diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/anyOf.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/anyOf.js index e209708a548e39..784c475d42d888 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/anyOf.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/anyOf.js @@ -1,36 +1,11 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const codegen_1 = require("../../compile/codegen"); -const util_1 = require("../../compile/util"); +const code_1 = require("../code"); const def = { keyword: "anyOf", schemaType: "array", trackErrors: true, - code(cxt) { - const { gen, schema, it } = cxt; - /* istanbul ignore if */ - if (!Array.isArray(schema)) - throw new Error("ajv implementation error"); - const alwaysValid = schema.some((sch) => util_1.alwaysValidSchema(it, sch)); - if (alwaysValid && !it.opts.unevaluated) - return; - const valid = gen.let("valid", false); - const schValid = gen.name("_valid"); - gen.block(() => schema.forEach((_sch, i) => { - const schCxt = cxt.subschema({ - keyword: "anyOf", - schemaProp: i, - compositeRule: true, - }, schValid); - gen.assign(valid, codegen_1._ `${valid} || ${schValid}`); - const merged = cxt.mergeValidEvaluated(schCxt, schValid); - // can short-circuit if `unevaluatedProperties/Items` not supported (opts.unevaluated !== true) - // or if all properties and items were evaluated (it.props === true && it.items === true) - if (!merged) - gen.if(codegen_1.not(valid)); - })); - cxt.result(valid, () => cxt.reset(), () => cxt.error(true)); - }, + code: code_1.validateUnion, error: { message: "should match some schema in anyOf", }, diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/items.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/items.js index e398dfbc7af2f1..ecc6f1a5c12a1d 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/items.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/items.js @@ -1,17 +1,16 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const codegen_1 = require("../../compile/codegen"); -const subschema_1 = require("../../compile/subschema"); const util_1 = require("../../compile/util"); const validate_1 = require("../../compile/validate"); +const code_1 = require("../code"); const def = { keyword: "items", type: "array", schemaType: ["object", "array", "boolean"], before: "uniqueItems", code(cxt) { - const { gen, schema, parentSchema, data, it } = cxt; - const len = gen.const("len", codegen_1._ `${data}.length`); + const { gen, schema, it } = cxt; if (Array.isArray(schema)) { if (it.opts.unevaluated && schema.length && it.items !== true) { it.items = util_1.mergeEvaluated.items(gen, schema.length, it.items); @@ -20,15 +19,18 @@ const def = { } else { it.items = true; - if (!util_1.alwaysValidSchema(it, schema)) - validateArray(); + if (util_1.alwaysValidSchema(it, schema)) + return; + cxt.ok(code_1.validateArray(cxt)); } function validateTuple(schArr) { - if (it.opts.strictTuples && !fullTupleSchema(schema.length, parentSchema)) { + const { parentSchema, data } = cxt; + if (it.opts.strictTuples && !fullTupleSchema(schArr.length, parentSchema)) { const msg = `"items" is ${schArr.length}-tuple, but minItems or maxItems/additionalItems are not specified or different`; validate_1.checkStrictMode(it, msg, it.opts.strictTuples); } const valid = gen.name("valid"); + const len = gen.const("len", codegen_1._ `${data}.length`); schArr.forEach((sch, i) => { if (util_1.alwaysValidSchema(it, sch)) return; @@ -36,25 +38,10 @@ const def = { keyword: "items", schemaProp: i, dataProp: i, - strictSchema: it.strictSchema, }, valid)); cxt.ok(valid); }); } - function validateArray() { - const valid = gen.name("valid"); - gen.forRange("i", 0, len, (i) => { - cxt.subschema({ - keyword: "items", - dataProp: i, - dataPropType: subschema_1.Type.Num, - strictSchema: it.strictSchema, - }, valid); - if (!it.allErrors) - gen.if(codegen_1.not(valid), () => gen.break()); - }); - cxt.ok(valid); - } }, }; function fullTupleSchema(len, sch) { diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/patternProperties.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/patternProperties.js index 25e9e4f5fbaf88..5b188c240256f4 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/patternProperties.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/patternProperties.js @@ -52,7 +52,6 @@ const def = { schemaProp: pat, dataProp: key, dataPropType: subschema_1.Type.Str, - strictSchema: it.strictSchema, }, valid); if (it.opts.unevaluated && props !== true) { gen.assign(codegen_1._ `${props}[${key}]`, true); diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/properties.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/properties.js index 23dadd7b7ce409..12fab3ce281970 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/properties.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/properties.js @@ -42,7 +42,6 @@ const def = { keyword: "properties", schemaProp: prop, dataProp: prop, - strictSchema: it.strictSchema, }, valid); } }, diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/propertyNames.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/propertyNames.js index 9467ce79e18733..d38f9a5eb723d3 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/propertyNames.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/applicator/propertyNames.js @@ -24,7 +24,6 @@ const def = { dataTypes: ["string"], propertyName: key, compositeRule: true, - strictSchema: it.strictSchema, }, valid); gen.if(codegen_1.not(valid), () => { cxt.error(true); diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/code.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/code.js index 7f877151522f51..a019e59b2115b7 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/code.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/code.js @@ -1,8 +1,9 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.usePattern = exports.callValidateCode = exports.schemaProperties = exports.allSchemaProperties = exports.noPropertyInData = exports.propertyInData = exports.reportMissingProp = exports.checkMissingProp = exports.checkReportMissingProp = void 0; +exports.validateUnion = exports.validateArray = exports.usePattern = exports.callValidateCode = exports.schemaProperties = exports.allSchemaProperties = exports.noPropertyInData = exports.propertyInData = exports.reportMissingProp = exports.checkMissingProp = exports.checkReportMissingProp = void 0; const codegen_1 = require("../compile/codegen"); const util_1 = require("../compile/util"); +const subschema_1 = require("../compile/subschema"); const names_1 = require("../compile/names"); function checkReportMissingProp(cxt, prop) { const { gen, data, it } = cxt; @@ -64,4 +65,54 @@ function usePattern(gen, pattern) { }); } exports.usePattern = usePattern; +function validateArray(cxt) { + const { gen, data, keyword, it } = cxt; + const valid = gen.name("valid"); + if (it.allErrors) { + const validArr = gen.let("valid", true); + validateItems(() => gen.assign(validArr, false)); + return validArr; + } + gen.var(valid, true); + validateItems(() => gen.break()); + return valid; + function validateItems(notValid) { + const len = gen.const("len", codegen_1._ `${data}.length`); + gen.forRange("i", 0, len, (i) => { + cxt.subschema({ + keyword, + dataProp: i, + dataPropType: subschema_1.Type.Num, + }, valid); + gen.if(codegen_1.not(valid), notValid); + }); + } +} +exports.validateArray = validateArray; +function validateUnion(cxt) { + const { gen, schema, keyword, it } = cxt; + /* istanbul ignore if */ + if (!Array.isArray(schema)) + throw new Error("ajv implementation error"); + const alwaysValid = schema.some((sch) => util_1.alwaysValidSchema(it, sch)); + if (alwaysValid && !it.opts.unevaluated) + return; + const valid = gen.let("valid", false); + const schValid = gen.name("_valid"); + gen.block(() => schema.forEach((_sch, i) => { + const schCxt = cxt.subschema({ + keyword, + schemaProp: i, + compositeRule: true, + }, schValid); + gen.assign(valid, codegen_1._ `${valid} || ${schValid}`); + const merged = cxt.mergeValidEvaluated(schCxt, schValid); + // can short-circuit if `unevaluatedProperties/Items` not supported (opts.unevaluated !== true) + // or if all properties and items were evaluated (it.props === true && it.items === true) + if (!merged) + gen.if(codegen_1.not(valid)); + })); + cxt.result(valid, () => cxt.reset(), () => cxt.error(true)); +} +exports.validateUnion = validateUnion; //# sourceMappingURL=code.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/core/index.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/core/index.js index d3981d4b58dcdb..87656d7436f4ff 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/core/index.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/core/index.js @@ -7,6 +7,7 @@ const core = [ "$id", "$defs", "$vocabulary", + { keyword: "$comment" }, "definitions", id_1.default, ref_1.default, diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/core/ref.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/core/ref.js index b56fbcc511710d..10e68389de0122 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/core/ref.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/core/ref.js @@ -38,7 +38,6 @@ const def = { const valid = gen.name("valid"); const schCxt = cxt.subschema({ schema: sch, - strictSchema: true, dataTypes: [], schemaPath: codegen_1.nil, topSchemaRef: schName, diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/discriminator.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/discriminator.js new file mode 100644 index 00000000000000..ca5d4d0ad8ba33 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/discriminator.js @@ -0,0 +1,38 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const codegen_1 = require("../../compile/codegen"); +const metadata_1 = require("./metadata"); +const nullable_1 = require("./nullable"); +const def = { + keyword: "discriminator", + schemaType: "string", + implements: ["mapping"], + code(cxt) { + metadata_1.checkMetadata(cxt); + const { gen, data, schema, parentSchema } = cxt; + const [valid, cond] = nullable_1.checkNullableObject(cxt, data); + gen.if(cond, () => { + const tag = gen.const("tag", codegen_1._ `${data}${codegen_1.getProperty(schema)}`); + gen.if(codegen_1._ `typeof ${tag} == "string"`, () => { + gen.if(false); + for (const tagValue in parentSchema.mapping) { + gen.elseIf(codegen_1._ `${tag} === ${tagValue}`); + gen.assign(valid, applyTagSchema(tagValue)); + } + gen.endIf(); + }); + }); + cxt.pass(valid); + function applyTagSchema(schemaProp) { + const _valid = gen.name("valid"); + cxt.subschema({ + keyword: "mapping", + schemaProp, + jtdDiscriminator: schema, + }, _valid); + return _valid; + } + }, +}; +exports.default = def; +//# sourceMappingURL=discriminator.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/elements.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/elements.js new file mode 100644 index 00000000000000..77a46ca11dd73a --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/elements.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const util_1 = require("../../compile/util"); +const code_1 = require("../code"); +const codegen_1 = require("../../compile/codegen"); +const metadata_1 = require("./metadata"); +const nullable_1 = require("./nullable"); +const def = { + keyword: "elements", + schemaType: "object", + code(cxt) { + metadata_1.checkMetadata(cxt); + const { gen, data, schema, it } = cxt; + if (util_1.alwaysValidSchema(it, schema)) + return; + const [valid, cond] = nullable_1.checkNullable(cxt, codegen_1.nil); + gen.if(codegen_1.and(cond, codegen_1._ `Array.isArray(${data})`), () => gen.assign(valid, code_1.validateArray(cxt))); + cxt.pass(valid); + }, +}; +exports.default = def; +//# sourceMappingURL=elements.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/enum.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/enum.js new file mode 100644 index 00000000000000..2995909048ab59 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/enum.js @@ -0,0 +1,41 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const codegen_1 = require("../../compile/codegen"); +const metadata_1 = require("./metadata"); +const def = { + keyword: "enum", + schemaType: "array", + code(cxt) { + metadata_1.checkMetadata(cxt); + const { gen, data, schema, schemaValue, parentSchema, it } = cxt; + if (schema.length === 0) + throw new Error("enum must have non-empty array"); + if (schema.length !== new Set(schema).size) + throw new Error("enum items must be unique"); + let valid; + if (schema.length >= it.opts.loopEnum) { + if (parentSchema.nullable) { + valid = gen.let("valid", codegen_1._ `${data} === null`); + gen.if(codegen_1.not(valid), loopEnum); + } + else { + valid = gen.let("valid", false); + loopEnum(); + } + } + else { + /* istanbul ignore if */ + if (!Array.isArray(schema)) + throw new Error("ajv implementation error"); + valid = codegen_1.or(...schema.map((value) => codegen_1._ `${data} === ${value}`)); + if (parentSchema.nullable) + valid = codegen_1.or(codegen_1._ `${data} === null`, valid); + } + cxt.pass(valid); + function loopEnum() { + gen.forOf("v", schemaValue, (v) => gen.if(codegen_1._ `${valid} = ${data} === ${v}`, () => gen.break())); + } + }, +}; +exports.default = def; +//# sourceMappingURL=enum.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/index.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/index.js new file mode 100644 index 00000000000000..f0ba74daf1086b --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/index.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +// import definitions from "./definitions" +const ref_1 = require("./ref"); +const type_1 = require("./type"); +const enum_1 = require("./enum"); +const elements_1 = require("./elements"); +const properties_1 = require("./properties"); +const optionalProperties_1 = require("./optionalProperties"); +const discriminator_1 = require("./discriminator"); +const values_1 = require("./values"); +const union_1 = require("./union"); +const metadata_1 = require("./metadata"); +const jtdVocabulary = [ + "definitions", + ref_1.default, + type_1.default, + enum_1.default, + elements_1.default, + properties_1.default, + optionalProperties_1.default, + discriminator_1.default, + values_1.default, + union_1.default, + metadata_1.default, + { keyword: "additionalProperties", schemaType: "boolean" }, + { keyword: "nullable", schemaType: "boolean" }, +]; +exports.default = jtdVocabulary; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/metadata.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/metadata.js new file mode 100644 index 00000000000000..acd00ffcad7b58 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/metadata.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.checkMetadata = void 0; +const util_1 = require("../../compile/util"); +const def = { + keyword: "metadata", + schemaType: "object", + code(cxt) { + checkMetadata(cxt); + const { gen, schema, it } = cxt; + if (util_1.alwaysValidSchema(it, schema)) + return; + const valid = gen.name("valid"); + cxt.subschema({ keyword: "metadata", jtdMetadata: true }, valid); + cxt.ok(valid); + }, +}; +function checkMetadata({ it, keyword }, metadata) { + if (it.jtdMetadata !== metadata) { + throw new Error(`JTD: "${keyword}" cannot be used in this schema location`); + } +} +exports.checkMetadata = checkMetadata; +exports.default = def; +//# sourceMappingURL=metadata.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/nullable.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/nullable.js new file mode 100644 index 00000000000000..ee2e6935ebe8a6 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/nullable.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.checkNullableObject = exports.checkNullable = void 0; +const codegen_1 = require("../../compile/codegen"); +function checkNullable({ gen, data, parentSchema }, cond) { + const valid = gen.name("valid"); + if (parentSchema.nullable) { + gen.let(valid, codegen_1._ `${data} === null`); + cond = codegen_1.not(valid); + } + else { + gen.let(valid, false); + } + return [valid, cond]; +} +exports.checkNullable = checkNullable; +function checkNullableObject(cxt, cond) { + const [valid, cond_] = checkNullable(cxt, cond); + return [valid, codegen_1._ `${cond_} && typeof ${cxt.data} == "object" && !Array.isArray(${cxt.data})`]; +} +exports.checkNullableObject = checkNullableObject; +//# sourceMappingURL=nullable.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/optionalProperties.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/optionalProperties.js new file mode 100644 index 00000000000000..c9058251d36cf4 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/optionalProperties.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const properties_1 = require("./properties"); +const def = { + keyword: "optionalProperties", + schemaType: "object", + code(cxt) { + if (cxt.parentSchema.properties) + return; + properties_1.validateProperties(cxt); + }, +}; +exports.default = def; +//# sourceMappingURL=optionalProperties.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/properties.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/properties.js new file mode 100644 index 00000000000000..c9a29a01c5fec2 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/properties.js @@ -0,0 +1,123 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.validateProperties = void 0; +const code_1 = require("../code"); +const util_1 = require("../../compile/util"); +const codegen_1 = require("../../compile/codegen"); +const metadata_1 = require("./metadata"); +const nullable_1 = require("./nullable"); +const def = { + keyword: "properties", + schemaType: "object", + code: validateProperties, +}; +function validateProperties(cxt) { + metadata_1.checkMetadata(cxt); + const { gen, data, parentSchema, it } = cxt; + const { additionalProperties, nullable } = parentSchema; + if (it.jtdDiscriminator && nullable) + throw new Error("JTD: nullable inside discriminator mapping"); + if (commonProperties()) { + throw new Error("JTD: properties and optionalProperties have common members"); + } + const [allProps, properties] = schemaProperties("properties"); + const [allOptProps, optProperties] = schemaProperties("optionalProperties"); + if (properties.length === 0 && optProperties.length === 0 && additionalProperties) { + return; + } + const [valid, cond] = it.jtdDiscriminator === undefined + ? nullable_1.checkNullableObject(cxt, data) + : [gen.let("valid", false), true]; + gen.if(cond, () => gen.assign(valid, true).block(() => { + validateProps(properties, "properties", true); + validateProps(optProperties, "optionalProperties"); + if (!additionalProperties) + validateAdditional(); + })); + cxt.pass(valid); + function commonProperties() { + const props = parentSchema.properties; + const optProps = parentSchema.optionalProperties; + if (!(props && optProps)) + return false; + for (const p in props) { + if (Object.prototype.hasOwnProperty.call(optProps, p)) + return true; + } + return false; + } + function schemaProperties(keyword) { + const schema = parentSchema[keyword]; + const allPs = schema ? code_1.allSchemaProperties(schema) : []; + if (it.jtdDiscriminator && allPs.some((p) => p === it.jtdDiscriminator)) { + throw new Error(`JTD: discriminator tag used in ${keyword}`); + } + const ps = allPs.filter((p) => !util_1.alwaysValidSchema(it, schema[p])); + return [allPs, ps]; + } + function validateProps(props, keyword, required) { + const _valid = gen.var("valid"); + for (const prop of props) { + gen.if(code_1.propertyInData(data, prop, it.opts.ownProperties), () => applyPropertySchema(prop, keyword, _valid), missingProperty); + cxt.ok(_valid); + } + function missingProperty() { + if (required) { + gen.assign(_valid, false); + cxt.error(); + } + else { + gen.assign(_valid, true); + } + } + } + function applyPropertySchema(prop, keyword, _valid) { + cxt.subschema({ + keyword, + schemaProp: prop, + dataProp: prop, + }, _valid); + } + function validateAdditional() { + gen.forIn("key", data, (key) => { + const _allProps = it.jtdDiscriminator === undefined ? allProps : [it.jtdDiscriminator].concat(allProps); + const addProp = isAdditional(key, _allProps, "properties"); + const addOptProp = isAdditional(key, allOptProps, "optionalProperties"); + const extra = addProp === true ? addOptProp : addOptProp === true ? addProp : codegen_1.and(addProp, addOptProp); + gen.if(extra, () => { + if (it.opts.removeAdditional) { + gen.code(codegen_1._ `delete ${data}[${key}]`); + } + else { + // cxt.setParams({additionalProperty: key}) + cxt.error(); + if (!it.opts.allErrors) + gen.break(); + } + }); + }); + } + function isAdditional(key, props, keyword) { + let additional; + if (props.length > 8) { + // TODO maybe an option instead of hard-coded 8? + const propsSchema = util_1.schemaRefOrVal(it, parentSchema[keyword], keyword); + const hasProp = gen.scopeValue("func", { + // eslint-disable-next-line @typescript-eslint/unbound-method + ref: Object.prototype.hasOwnProperty, + code: codegen_1._ `Object.prototype.hasOwnProperty`, + }); + additional = codegen_1._ `!${hasProp}.call(${propsSchema}, ${key})`; + } + else if (props.length) { + additional = codegen_1.and(...props.map((p) => codegen_1._ `${key} !== ${p}`)); + } + else { + additional = true; + } + return additional; + } +} +exports.validateProperties = validateProperties; +exports.default = def; +//# sourceMappingURL=properties.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/ref.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/ref.js new file mode 100644 index 00000000000000..acfd31748dae6f --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/ref.js @@ -0,0 +1,64 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const compile_1 = require("../../compile"); +const codegen_1 = require("../../compile/codegen"); +const error_classes_1 = require("../../compile/error_classes"); +const names_1 = require("../../compile/names"); +const ref_1 = require("../core/ref"); +const metadata_1 = require("./metadata"); +const def = { + keyword: "ref", + schemaType: "string", + code(cxt) { + metadata_1.checkMetadata(cxt); + const { gen, data, schema: ref, parentSchema, it } = cxt; + const { schemaEnv: { root }, } = it; + const valid = gen.name("valid"); + if (parentSchema.nullable) { + gen.var(valid, codegen_1._ `${data} === null`); + gen.if(codegen_1.not(valid), validateJtdRef); + } + else { + gen.var(valid, false); + validateJtdRef(); + } + cxt.ok(valid); + function validateJtdRef() { + var _a; + const refSchema = (_a = root.schema.definitions) === null || _a === void 0 ? void 0 : _a[ref]; + if (!refSchema) + throw new error_classes_1.MissingRefError("", ref, `No definition ${ref}`); + if (hasRef(refSchema) || !it.opts.inlineRefs) + callValidate(refSchema); + else + inlineRefSchema(refSchema); + } + function callValidate(schema) { + const sch = compile_1.compileSchema.call(it.self, new compile_1.SchemaEnv({ schema, root })); + const v = ref_1.getValidate(cxt, sch); + const errsCount = gen.const("_errs", names_1.default.errors); + ref_1.callRef(cxt, v, sch, sch.$async); + gen.assign(valid, codegen_1._ `${errsCount} === ${names_1.default.errors}`); + } + function inlineRefSchema(schema) { + const schName = gen.scopeValue("schema", it.opts.code.source === true ? { ref: schema, code: codegen_1.stringify(schema) } : { ref: schema }); + cxt.subschema({ + schema, + dataTypes: [], + schemaPath: codegen_1.nil, + topSchemaRef: schName, + errSchemaPath: `/definitions/${ref}`, + }, valid); + } + function hasRef(schema) { + for (const key in schema) { + let sch; + if (key === "ref" || (typeof (sch = schema[key]) == "object" && hasRef(sch))) + return true; + } + return false; + } + }, +}; +exports.default = def; +//# sourceMappingURL=ref.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/type.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/type.js new file mode 100644 index 00000000000000..1eedbb86480e3c --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/type.js @@ -0,0 +1,47 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const codegen_1 = require("../../compile/codegen"); +const timestamp_1 = require("../../compile/timestamp"); +const metadata_1 = require("./metadata"); +const intRange = { + int8: [-128, 127], + uint8: [0, 255], + int16: [-32768, 32767], + uint16: [0, 65535], + int32: [-2147483648, 2147483647], + uint32: [0, 4294967295], +}; +const def = { + keyword: "type", + schemaType: "string", + code(cxt) { + metadata_1.checkMetadata(cxt); + const { gen, data, schema, parentSchema } = cxt; + let cond; + switch (schema) { + case "boolean": + case "string": + cond = codegen_1._ `typeof ${data} == ${schema}`; + break; + case "timestamp": { + const vts = gen.scopeValue("func", { + ref: timestamp_1.default, + code: codegen_1._ `require("ajv/dist/compile/timestamp").default`, + }); + cond = codegen_1._ `${data} instanceof Date || (typeof ${data} == "string" && ${vts}(${data}))`; + break; + } + case "float32": + case "float64": + cond = codegen_1._ `typeof ${data} == "number"`; + break; + default: { + const [min, max] = intRange[schema]; + cond = codegen_1._ `typeof ${data} == "number" && isFinite(${data}) && ${data} >= ${min} && ${data} <= ${max} && !(${data} % 1)`; + } + } + cxt.pass(parentSchema.nullable ? codegen_1.or(codegen_1._ `${data} === null`, cond) : cond); + }, +}; +exports.default = def; +//# sourceMappingURL=type.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/union.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/union.js new file mode 100644 index 00000000000000..e3bc5033e1bb62 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/union.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const code_1 = require("../code"); +const def = { + keyword: "union", + schemaType: "array", + trackErrors: true, + code: code_1.validateUnion, +}; +exports.default = def; +//# sourceMappingURL=union.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/values.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/values.js new file mode 100644 index 00000000000000..68682ef1199476 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/jtd/values.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const subschema_1 = require("../../compile/subschema"); +const util_1 = require("../../compile/util"); +const codegen_1 = require("../../compile/codegen"); +const metadata_1 = require("./metadata"); +const nullable_1 = require("./nullable"); +const def = { + keyword: "values", + schemaType: "object", + code(cxt) { + metadata_1.checkMetadata(cxt); + const { gen, data, schema, it } = cxt; + if (util_1.alwaysValidSchema(it, schema)) + return; + const [valid, cond] = nullable_1.checkNullableObject(cxt, data); + gen.if(cond, () => gen.assign(valid, validateMap())); + cxt.pass(valid); + function validateMap() { + const _valid = gen.name("valid"); + if (it.allErrors) { + const validMap = gen.let("valid", true); + validateValues(() => gen.assign(validMap, false)); + return validMap; + } + gen.var(_valid, true); + validateValues(() => gen.break()); + return _valid; + function validateValues(notValid) { + gen.forIn("key", data, (key) => { + cxt.subschema({ + keyword: "values", + dataProp: key, + dataPropType: subschema_1.Type.Str, + }, _valid); + gen.if(codegen_1.not(_valid), notValid); + }); + } + } + }, +}; +exports.default = def; +//# sourceMappingURL=values.js.map \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedProperties.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedProperties.js index ce77b261cab7ec..6ab14c01a59f61 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedProperties.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedProperties.js @@ -44,7 +44,6 @@ const def = { keyword: "unevaluatedProperties", dataProp: key, dataPropType: subschema_1.Type.Str, - strictSchema: it.strictSchema, }, valid); if (!allErrors) gen.if(codegen_1.not(valid), () => gen.break()); diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/validation/index.js b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/validation/index.js index 9a7b711c1b2ca1..7b56b4e45359da 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/validation/index.js +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/dist/vocabularies/validation/index.js @@ -24,6 +24,7 @@ const validation = [ limitItems_1.default, uniqueItems_1.default, // any + { keyword: "type", schemaType: ["string", "array"] }, { keyword: "nullable", schemaType: "boolean" }, const_1.default, enum_1.default, diff --git a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/package.json b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/package.json index 032498f33b03b8..bace75fe97ae76 100644 --- a/tools/node_modules/eslint/node_modules/table/node_modules/ajv/package.json +++ b/tools/node_modules/eslint/node_modules/table/node_modules/ajv/package.json @@ -33,7 +33,7 @@ "eslint": "^7.8.1", "eslint-config-prettier": "^7.0.0", "glob": "^7.0.0", - "husky": "^4.2.5", + "husky": "^5.0.9", "if-node-version": "^1.0.0", "js-beautify": "^1.7.3", "json-schema-test": "^2.0.0", @@ -98,8 +98,8 @@ "url": "git+https://github.com/ajv-validator/ajv.git" }, "scripts": { - "build": "rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts", - "bundle": "rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019", + "build": "rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/jtd-schema.ts", + "bundle": "rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD", "eslint": "eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite", "json-tests": "rm -rf spec/_json/*.js && node scripts/jsontests", "prepublish": "npm run build", @@ -117,5 +117,5 @@ }, "tonicExampleFilename": ".tonic_example.js", "types": "dist/ajv.d.ts", - "version": "7.0.3" + "version": "7.1.0" } \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/which/package.json b/tools/node_modules/eslint/node_modules/which/package.json index 9620a99a29e14c..32eaa57575d680 100644 --- a/tools/node_modules/eslint/node_modules/which/package.json +++ b/tools/node_modules/eslint/node_modules/which/package.json @@ -5,7 +5,7 @@ "url": "http://blog.izs.me" }, "bin": { - "node-which": "./bin/node-which" + "node-which": "bin/node-which" }, "bugs": { "url": "https://github.com/isaacs/node-which/issues" diff --git a/tools/node_modules/eslint/package.json b/tools/node_modules/eslint/package.json index 24c8bc57f61b9f..a2977ce5896b2b 100644 --- a/tools/node_modules/eslint/package.json +++ b/tools/node_modules/eslint/package.json @@ -11,7 +11,7 @@ }, "bundleDependencies": false, "dependencies": { - "@babel/code-frame": "^7.0.0", + "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.3.0", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -24,7 +24,7 @@ "eslint-utils": "^2.1.0", "eslint-visitor-keys": "^2.0.0", "espree": "^7.3.1", - "esquery": "^1.2.0", + "esquery": "^1.4.0", "esutils": "^2.0.2", "file-entry-cache": "^6.0.0", "functional-red-black-tree": "^1.0.1", @@ -154,5 +154,5 @@ "test:cli": "mocha", "webpack": "node Makefile.js webpack" }, - "version": "7.19.0" + "version": "7.20.0" } \ No newline at end of file From 88d3f74c85eaa62b4d721a880cb6bc8ea2237bc3 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Mon, 1 Feb 2021 15:53:36 -0800 Subject: [PATCH 098/108] fs: add fsPromises.watch() An alternative to `fs.watch()` that returns an `AsyncIterator` ```js const { watch } = require('fs/promises'); (async () => { const ac = new AbortController(); const { signal } = ac; setTimeout(() => ac.abort(), 10000); const watcher = watch('file.txt', { signal }); for await (const { eventType, filename } of watcher) { console.log(eventType, filename); } })() ``` Signed-off-by: James M Snell PR-URL: https://github.com/nodejs/node/pull/37179 Reviewed-By: Benjamin Gruenbaum --- doc/api/fs.md | 53 ++++++++++- lib/internal/fs/promises.js | 2 + lib/internal/fs/watchers.js | 119 +++++++++++++++++++++++- test/parallel/test-bootstrap-modules.js | 3 + test/parallel/test-fs-promises-watch.js | 115 +++++++++++++++++++++++ 5 files changed, 285 insertions(+), 7 deletions(-) create mode 100644 test/parallel/test-fs-promises-watch.js diff --git a/doc/api/fs.md b/doc/api/fs.md index 34cb626dfad797..5e7521ce7c8e36 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -1189,6 +1189,55 @@ The `atime` and `mtime` arguments follow these rules: * If the value can not be converted to a number, or is `NaN`, `Infinity` or `-Infinity`, an `Error` will be thrown. +### `fsPromises.watch(filename[, options])` + + +* `filename` {string|Buffer|URL} +* `options` {string|Object} + * `persistent` {boolean} Indicates whether the process should continue to run + as long as files are being watched. **Default:** `true`. + * `recursive` {boolean} Indicates whether all subdirectories should be + watched, or only the current directory. This applies when a directory is + specified, and only on supported platforms (See [caveats][]). **Default:** + `false`. + * `encoding` {string} Specifies the character encoding to be used for the + filename passed to the listener. **Default:** `'utf8'`. + * `signal` {AbortSignal} An {AbortSignal} used to signal when the watcher + should stop. +* Returns: {AsyncIterator} of objects with the properties: + * `eventType` {string} The type of change + * `filename` {string|Buffer} The name of the file changed. + +Returns an async iterator that watches for changes on `filename`, where `filename` +is either a file or a directory. + +```js +const { watch } = require('fs/promises'); + +const ac = new AbortController(); +const { signal } = ac; +setTimeout(() => ac.abort(), 10000); + +(async () => { + try { + const watcher = watch(__filename, { signal }); + for await (const event of watcher) + console.log(event); + } catch (err) { + if (err.name === 'AbortError') + return; + throw err; + } +})(); +``` + +On most platforms, `'rename'` is emitted whenever a filename appears or +disappears in the directory. + +All the [caveats][] for `fs.watch()` also apply to `fsPromises.watch()`. + ### `fsPromises.writeFile(file, data[, options])` ' + - '

    Describe Something in more detail here.

    ' + '

    Describe Something in more detail here.

    ' }, { file: fixtures.path('sample_document.md'), @@ -110,16 +113,18 @@ const testData = [ file: fixtures.path('document_with_links.md'), html: '

    Usage and Example#' + - '

    Usage

    Usage#

    node \\[options\\] index.js' + '

    Please see the' + - 'Command Line Optionsdocument for more information.

    ' + + 'Command Line Optionsdocument for more information.

    ' + + '

    ' + 'Example' + '#

    An example of a' + 'webserverwritten with Node.js which responds with' + - '\'Hello, World!\':

    See also:

    ' + + '

    See also#

    Check' + - 'out alsothis guide

    ' + 'out alsothis guide

    ' }, { file: fixtures.path('document_with_special_heading.md'), From 51336594337ed19d0826e480d0e7e024c55bbeb2 Mon Sep 17 00:00:00 2001 From: Danielle Adams Date: Tue, 16 Feb 2021 16:00:34 -0500 Subject: [PATCH 108/108] 2021-02-16, Version 15.9.0 (Current) Notable Changes: * crypto: * add keyObject.export() 'jwk' format option (Filip Skokan) https://github.com/nodejs/node/pull/37081 * deps: * upgrade to libuv 1.41.0 (Colin Ihrig) https://github.com/nodejs/node/pull/37360 * doc: * add dmabupt to collaborators (Xu Meng) https://github.com/nodejs/node/pull/37377 * refactor fs docs structure (James M Snell) https://github.com/nodejs/node/pull/37170 * fs: * add fsPromises.watch() (James M Snell) https://github.com/nodejs/node/pull/37179 * use a default callback for fs.close() (James M Snell) https://github.com/nodejs/node/pull/37174 * add AbortSignal support to watch (Benjamin Gruenbaum) https://github.com/nodejs/node/pull/37190 * perf_hooks: * introduce createHistogram (James M Snell) https://github.com/nodejs/node/pull/37155 * stream: * improve Readable.from error handling (Benjamin Gruenbaum) https://github.com/nodejs/node/pull/37158 * timers: * introduce setInterval async iterator (linkgoron) https://github.com/nodejs/node/pull/37153 * tls: * add ability to get cert/peer cert as X509Certificate object (James M Snell) https://github.com/nodejs/node/pull/37070 --- CHANGELOG.md | 3 +- doc/api/crypto.md | 4 +- doc/api/fs.md | 6 +- doc/api/n-api.md | 2 +- doc/api/perf_hooks.md | 8 +- doc/api/timers.md | 2 +- doc/api/tls.md | 4 +- doc/api/vm.md | 2 +- doc/api/webcrypto.md | 4 +- doc/api/worker_threads.md | 2 +- doc/changelogs/CHANGELOG_V15.md | 136 ++++++++++++++++++++++++++++++++ src/node_version.h | 6 +- 12 files changed, 158 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4079b2f21294ff..0dc6061fc0f33a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,7 +32,8 @@ release. -15.8.0
    +15.9.0
    +15.8.0
    15.7.0
    15.6.0
    15.5.1
    diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 2ef2f74320c5dd..fa2694d0fe3872 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -1381,7 +1381,7 @@ keys. @@ -1844,7 +1844,7 @@ The issuer identification included in this certificate. ### `x509.issuerCertificate` * Type: {X509Certificate} diff --git a/doc/api/fs.md b/doc/api/fs.md index 5e7521ce7c8e36..a4d4b07e80ebce 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -1191,7 +1191,7 @@ The `atime` and `mtime` arguments follow these rules: ### `fsPromises.watch(filename[, options])` * `filename` {string|Buffer|URL} @@ -1699,7 +1699,7 @@ See the POSIX chown(2) documentation for more detail. > Stability: 1 - Experimental diff --git a/doc/api/perf_hooks.md b/doc/api/perf_hooks.md index 12777fbd694e52..3c627b11aea6c2 100644 --- a/doc/api/perf_hooks.md +++ b/doc/api/perf_hooks.md @@ -655,7 +655,7 @@ performance.mark('meow'); ## `perf_hooks.createHistogram([options])` * `options` {Object} @@ -814,19 +814,19 @@ implement the `enable()` and `disable()` methods. ## Class: `RecordableHistogram extends Histogram` ### `histogram.record(val)` * `val` {number|bigint} The amount to record in the histogram. ### `histogram.recordDelta()` Calculates the amount of time (in nanoseconds) that has passed since the diff --git a/doc/api/timers.md b/doc/api/timers.md index fe8f70f5572a93..ee7162ea7be270 100644 --- a/doc/api/timers.md +++ b/doc/api/timers.md @@ -365,7 +365,7 @@ added: v15.0.0 ### `timersPromises.setInterval([delay[, value[, options]]])` Returns an async iterator that generates values in an interval of `delay` ms. diff --git a/doc/api/tls.md b/doc/api/tls.md index 376c9318fccfc8..f8a3a1aa36b4cc 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -1150,7 +1150,7 @@ to implement the `tls-unique` channel binding from [RFC 5929][]. ### `tlsSocket.getPeerX509Certificate()` * Returns: {X509Certificate} @@ -1227,7 +1227,7 @@ See [Session Resumption][] for more information. ### `tlsSocket.getX509Certificate()` * Returns: {X509Certificate} diff --git a/doc/api/vm.md b/doc/api/vm.md index cb97cda7d791c0..bf74fb505d4f98 100644 --- a/doc/api/vm.md +++ b/doc/api/vm.md @@ -813,7 +813,7 @@ const vm = require('vm'); @@ -697,7 +697,7 @@ The {CryptoKey} (secret key) generating algorithms supported include: diff --git a/doc/api/worker_threads.md b/doc/api/worker_threads.md index 95167da0a91666..42e263f1beddd2 100644 --- a/doc/api/worker_threads.md +++ b/doc/api/worker_threads.md @@ -474,7 +474,7 @@ are part of the channel.