diff --git a/.eslintrc.js b/.eslintrc.js index f46a64bcbf2acd..8b462e0777c5d4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -361,5 +361,6 @@ module.exports = { WritableStream: 'readable', WritableStreamDefaultWriter: 'readable', WritableStreamDefaultController: 'readable', + WebSocket: 'readable', }, }; diff --git a/benchmark/misc/hidestackframes.js b/benchmark/error/hidestackframes.js similarity index 100% rename from benchmark/misc/hidestackframes.js rename to benchmark/error/hidestackframes.js diff --git a/benchmark/error/node-error-instantiation.js b/benchmark/error/node-error-instantiation.js new file mode 100644 index 00000000000000..333087b9195894 --- /dev/null +++ b/benchmark/error/node-error-instantiation.js @@ -0,0 +1,66 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); + +const bench = common.createBenchmark(main, { + n: [1e6], + code: [ + 'built-in', + 'ERR_HTTP2_STREAM_SELF_DEPENDENCY', + 'ERR_INVALID_STATE', + 'ERR_INVALID_URL', + ], + stackTraceLimit: [0, 10], +}, { + flags: ['--expose-internals'], +}); + +function getErrorFactory(code) { + const { + ERR_HTTP2_STREAM_SELF_DEPENDENCY, + ERR_INVALID_STATE, + ERR_INVALID_URL, + } = require('internal/errors').codes; + + switch (code) { + case 'built-in': + return (n) => new Error(); + case 'ERR_HTTP2_STREAM_SELF_DEPENDENCY': + return (n) => new ERR_HTTP2_STREAM_SELF_DEPENDENCY(); + case 'ERR_INVALID_STATE': + return (n) => new ERR_INVALID_STATE(n + ''); + case 'ERR_INVALID_URL': + return (n) => new ERR_INVALID_URL({ input: n + '' }); + default: + throw new Error(`${code} not supported`); + } +} + +function main({ n, code, stackTraceLimit }) { + const getError = getErrorFactory(code); + + Error.stackTraceLimit = stackTraceLimit; + + // Warm up. + const length = 1024; + const array = []; + for (let i = 0; i < length; ++i) { + array.push(getError(i)); + } + + bench.start(); + + for (let i = 0; i < n; ++i) { + const index = i % length; + array[index] = getError(index); + } + + bench.end(n); + + // Verify the entries to prevent dead code elimination from making + // the benchmark invalid. + for (let i = 0; i < length; ++i) { + assert.strictEqual(typeof array[i], 'object'); + } +} diff --git a/benchmark/error/node-error-stack.js b/benchmark/error/node-error-stack.js new file mode 100644 index 00000000000000..06319ccd17105f --- /dev/null +++ b/benchmark/error/node-error-stack.js @@ -0,0 +1,62 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); + +const bench = common.createBenchmark(main, { + n: [1e6], + code: [ + 'built-in', + 'ERR_HTTP2_STREAM_SELF_DEPENDENCY', + 'ERR_INVALID_STATE', + ], + stackTraceLimit: [0, 10], +}, { + flags: ['--expose-internals'], +}); + +function getErrorStackFactory(code) { + const { + ERR_INVALID_STATE, + ERR_HTTP2_STREAM_SELF_DEPENDENCY, + } = require('internal/errors').codes; + + switch (code) { + case 'built-in': + return (n) => new Error().stack; + case 'ERR_HTTP2_STREAM_SELF_DEPENDENCY': + return (n) => new ERR_HTTP2_STREAM_SELF_DEPENDENCY().stack; + case 'ERR_INVALID_STATE': + return (n) => new ERR_INVALID_STATE(n + '').stack; + default: + throw new Error(`${code} not supported`); + } +} + +function main({ n, code, stackTraceLimit }) { + const getStack = getErrorStackFactory(code); + + Error.stackTraceLimit = stackTraceLimit; + + // Warm up. + const length = 1024; + const array = []; + for (let i = 0; i < length; ++i) { + array.push(getStack(i)); + } + + bench.start(); + + for (let i = 0; i < n; ++i) { + const index = i % length; + array[index] = getStack(index); + } + + bench.end(n); + + // Verify the entries to prevent dead code elimination from making + // the benchmark invalid. + for (let i = 0; i < length; ++i) { + assert.strictEqual(typeof array[i], 'string'); + } +} diff --git a/benchmark/error/node-error.js b/benchmark/error/node-error.js deleted file mode 100644 index 3a0aef91f04a06..00000000000000 --- a/benchmark/error/node-error.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -const common = require('../common'); - -const bench = common.createBenchmark(main, { - n: [1e7], -}, { - flags: ['--expose-internals'], -}); - -function main({ n }) { - const { - codes: { - ERR_INVALID_STATE, - }, - } = require('internal/errors'); - bench.start(); - for (let i = 0; i < n; ++i) - new ERR_INVALID_STATE.TypeError('test'); - bench.end(n); -} diff --git a/common.gypi b/common.gypi index 14f05fcf9ccb8d..909d09934a1b25 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.18', + 'v8_embedder_string': '-node.19', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-base.cc b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-base.cc index e0602edc7e1c6a..e4ca7bfdacb11c 100644 --- a/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-base.cc +++ b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-base.cc @@ -130,7 +130,8 @@ EmbeddedTargetOs ToEmbeddedTargetOs(const char* s) { } std::string string(s); - if (string == "aix") { + // Python 3.9+ on IBM i returns os400 as sys.platform instead of aix + if (string == "aix" || string == "os400") { return EmbeddedTargetOs::kAIX; } else if (string == "chromeos") { return EmbeddedTargetOs::kChromeOS; diff --git a/doc/api/cli.md b/doc/api/cli.md index 1da38c1739126b..013256d776bac7 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -738,6 +738,14 @@ added: v12.3.0 Enable experimental WebAssembly module support. +### `--experimental-websocket` + + + +Enable experimental [`WebSocket`][] support. + ### `--force-context-aware` + +> Stability: 1 - Experimental. + +A browser-compatible implementation of [`WebSocket`][]. Enable this API +with the [`--experimental-websocket`][] CLI flag. + ## Class: `WritableStream` diff --git a/lib/internal/blob.js b/lib/internal/blob.js index a54adb615fbc17..b68037612ab8b3 100644 --- a/lib/internal/blob.js +++ b/lib/internal/blob.js @@ -24,6 +24,9 @@ const { concat, getDataObject, } = internalBinding('blob'); +const { + kMaxLength, +} = internalBinding('buffer'); const { TextDecoder, @@ -62,7 +65,6 @@ const { } = require('internal/errors'); const { - isUint32, validateDictionary, } = require('internal/validators'); @@ -160,8 +162,8 @@ class Blob { return src; }); - if (!isUint32(length)) - throw new ERR_BUFFER_TOO_LARGE(0xFFFFFFFF); + if (length > kMaxLength) + throw new ERR_BUFFER_TOO_LARGE(kMaxLength); this[kHandle] = _createBlob(sources_, length); this[kLength] = length; diff --git a/lib/internal/crypto/hkdf.js b/lib/internal/crypto/hkdf.js index 7f0fe5534ee843..cf3c39e8d9da5a 100644 --- a/lib/internal/crypto/hkdf.js +++ b/lib/internal/crypto/hkdf.js @@ -57,7 +57,7 @@ const validateParameters = hideStackFrames((hash, key, salt, info, length) => { validateInteger(length, 'length', 0, kMaxLength); if (info.byteLength > 1024) { - throw ERR_OUT_OF_RANGE( + throw new ERR_OUT_OF_RANGE( 'info', 'must not contain more than 1024 bytes', info.byteLength); diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 4e332e1ce18d16..6bba8ec095e86e 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -175,9 +175,10 @@ const aggregateErrors = hideStackFrames((errors, message, code) => { return err; }); +const assert = require('internal/assert'); + // Lazily loaded let util; -let assert; let internalUtil = null; function lazyInternalUtil() { @@ -371,42 +372,103 @@ function makeSystemErrorWithCode(key) { } function makeNodeErrorWithCode(Base, key) { - return function NodeError(...args) { - const limit = Error.stackTraceLimit; - if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = 0; - const error = new Base(); - // Reset the limit and setting the name property. - if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = limit; - const message = getMessage(key, args, error); - ObjectDefineProperties(error, { - [kIsNodeError]: { - __proto__: null, - value: true, - enumerable: false, - writable: false, - configurable: true, - }, - message: { - __proto__: null, - value: message, - enumerable: false, - writable: true, - configurable: true, - }, - toString: { - __proto__: null, - value() { + const msg = messages.get(key); + const expectedLength = typeof msg !== 'string' ? -1 : getExpectedArgumentLength(msg); + + switch (expectedLength) { + case 0: { + class NodeError extends Base { + code = key; + + constructor(...args) { + assert( + args.length === 0, + `Code: ${key}; The provided arguments length (${args.length}) does not ` + + `match the required ones (${expectedLength}).`, + ); + super(msg); + } + + // This is a workaround for wpt tests that expect that the error + // constructor has a `name` property of the base class. + get ['constructor']() { + return Base; + } + + get [kIsNodeError]() { + return true; + } + + toString() { return `${this.name} [${key}]: ${this.message}`; - }, - enumerable: false, - writable: true, - configurable: true, - }, - }); - captureLargerStackTrace(error); - error.code = key; - return error; - }; + } + } + return NodeError; + } + case -1: { + class NodeError extends Base { + code = key; + + constructor(...args) { + super(); + ObjectDefineProperty(this, 'message', { + __proto__: null, + value: getMessage(key, args, this), + enumerable: false, + writable: true, + configurable: true, + }); + } + + // This is a workaround for wpt tests that expect that the error + // constructor has a `name` property of the base class. + get ['constructor']() { + return Base; + } + + get [kIsNodeError]() { + return true; + } + + toString() { + return `${this.name} [${key}]: ${this.message}`; + } + } + return NodeError; + } + default: { + + class NodeError extends Base { + code = key; + + constructor(...args) { + assert( + args.length === expectedLength, + `Code: ${key}; The provided arguments length (${args.length}) does not ` + + `match the required ones (${expectedLength}).`, + ); + + ArrayPrototypeUnshift(args, msg); + super(ReflectApply(lazyInternalUtilInspect().format, null, args)); + } + + // This is a workaround for wpt tests that expect that the error + // constructor has a `name` property of the base class. + get ['constructor']() { + return Base; + } + + get [kIsNodeError]() { + return true; + } + + toString() { + return `${this.name} [${key}]: ${this.message}`; + } + } + return NodeError; + } + } } /** @@ -443,11 +505,16 @@ function E(sym, val, def, ...otherClasses) { codes[sym] = def; } +function getExpectedArgumentLength(msg) { + let expectedLength = 0; + const regex = /%[dfijoOs]/g; + while (RegExpPrototypeExec(regex, msg) !== null) expectedLength++; + return expectedLength; +} + function getMessage(key, args, self) { const msg = messages.get(key); - assert ??= require('internal/assert'); - if (typeof msg === 'function') { assert( msg.length <= args.length, // Default options do not count. @@ -457,9 +524,7 @@ function getMessage(key, args, self) { return ReflectApply(msg, self, args); } - const regex = /%[dfijoOs]/g; - let expectedLength = 0; - while (RegExpPrototypeExec(regex, msg) !== null) expectedLength++; + const expectedLength = getExpectedArgumentLength(msg); assert( expectedLength === args.length, `Code: ${key}; The provided arguments length (${args.length}) does not ` + @@ -1476,8 +1541,7 @@ E('ERR_NETWORK_IMPORT_DISALLOWED', "import of '%s' by %s is not supported: %s", Error); E('ERR_NOT_BUILDING_SNAPSHOT', 'Operation cannot be invoked when not building startup snapshot', Error); -E('ERR_NOT_SUPPORTED_IN_SNAPSHOT', - '%s is not supported in startup snapshot', Error); +E('ERR_NOT_SUPPORTED_IN_SNAPSHOT', '%s is not supported in startup snapshot', Error); E('ERR_NO_CRYPTO', 'Node.js is not compiled with OpenSSL crypto support', Error); E('ERR_NO_ICU', diff --git a/lib/internal/fs/streams.js b/lib/internal/fs/streams.js index c317f3b9202af9..6a213693342b94 100644 --- a/lib/internal/fs/streams.js +++ b/lib/internal/fs/streams.js @@ -143,8 +143,8 @@ function importFd(stream, options) { return options.fd.fd; } - throw ERR_INVALID_ARG_TYPE('options.fd', - ['number', 'FileHandle'], options.fd); + throw new ERR_INVALID_ARG_TYPE('options.fd', + ['number', 'FileHandle'], options.fd); } function ReadStream(path, options) { diff --git a/lib/internal/modules/esm/hooks.js b/lib/internal/modules/esm/hooks.js index 8ad4d00bbfe06f..8dd81ca52c5318 100644 --- a/lib/internal/modules/esm/hooks.js +++ b/lib/internal/modules/esm/hooks.js @@ -407,7 +407,7 @@ class Hooks { !isAnyArrayBuffer(source) && !isArrayBufferView(source) ) { - throw ERR_INVALID_RETURN_PROPERTY_VALUE( + throw new ERR_INVALID_RETURN_PROPERTY_VALUE( 'a string, an ArrayBuffer, or a TypedArray', hookErrIdentifier, 'source', @@ -599,7 +599,7 @@ class HooksProxy { if (status === 'error') { if (body == null || typeof body !== 'object') { throw body; } if (body.serializationFailed || body.serialized == null) { - throw ERR_WORKER_UNSERIALIZABLE_ERROR(); + throw new ERR_WORKER_UNSERIALIZABLE_ERROR(); } // eslint-disable-next-line no-restricted-syntax diff --git a/lib/internal/navigator.js b/lib/internal/navigator.js index 3b8343cd7ed6f8..5971891ea73cc9 100644 --- a/lib/internal/navigator.js +++ b/lib/internal/navigator.js @@ -27,7 +27,7 @@ class Navigator { if (arguments[0] === kInitialize) { return; } - throw ERR_ILLEGAL_CONSTRUCTOR(); + throw new ERR_ILLEGAL_CONSTRUCTOR(); } /** diff --git a/lib/internal/process/pre_execution.js b/lib/internal/process/pre_execution.js index 1f4a08515b5ae9..f120f371d9b634 100644 --- a/lib/internal/process/pre_execution.js +++ b/lib/internal/process/pre_execution.js @@ -78,7 +78,7 @@ function prepareExecution(options) { setupTraceCategoryState(); setupInspectorHooks(); setupWarningHandler(); - setupFetch(); + setupUndici(); setupWebCrypto(); setupCustomEvent(); setupCodeCoverage(); @@ -262,9 +262,9 @@ function setupWarningHandler() { } // https://fetch.spec.whatwg.org/ -function setupFetch() { - if (getEmbedderOptions().noBrowserGlobals || - getOptionValue('--no-experimental-fetch')) { +// https://websockets.spec.whatwg.org/ +function setupUndici() { + if (getEmbedderOptions().noBrowserGlobals) { return; } @@ -278,12 +278,6 @@ function setupFetch() { return undici; } - async function fetch(input, init = undefined) { - return lazyUndici().fetch(input, init); - } - - defineOperation(globalThis, 'fetch', fetch); - function lazyInterface(name) { return { configurable: true, @@ -297,17 +291,31 @@ function setupFetch() { }; } - ObjectDefineProperties(globalThis, { - FormData: lazyInterface('FormData'), - Headers: lazyInterface('Headers'), - Request: lazyInterface('Request'), - Response: lazyInterface('Response'), - }); + if (!getOptionValue('--no-experimental-fetch')) { + async function fetch(input, init = undefined) { + return lazyUndici().fetch(input, init); + } - // The WebAssembly Web API: https://webassembly.github.io/spec/web-api - internalBinding('wasm_web_api').setImplementation((streamState, source) => { - require('internal/wasm_web_api').wasmStreamingCallback(streamState, source); - }); + defineOperation(globalThis, 'fetch', fetch); + + ObjectDefineProperties(globalThis, { + FormData: lazyInterface('FormData'), + Headers: lazyInterface('Headers'), + Request: lazyInterface('Request'), + Response: lazyInterface('Response'), + }); + + // The WebAssembly Web API: https://webassembly.github.io/spec/web-api + internalBinding('wasm_web_api').setImplementation((streamState, source) => { + require('internal/wasm_web_api').wasmStreamingCallback(streamState, source); + }); + } + + if (getOptionValue('--experimental-websocket')) { + ObjectDefineProperties(globalThis, { + WebSocket: lazyInterface('WebSocket'), + }); + } } // TODO(aduh95): move this to internal/bootstrap/web/* when the CLI flag is diff --git a/lib/internal/url.js b/lib/internal/url.js index 13a9e287ffc47a..ca41c48582b19d 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -855,7 +855,7 @@ class URL { set href(value) { value = `${value}`; const href = bindingUrl.update(this.#context.href, updateActions.kHref, value); - if (!href) { throw ERR_INVALID_URL(value); } + if (!href) { throw new ERR_INVALID_URL(value); } this.#updateContext(href); } diff --git a/lib/stream.js b/lib/stream.js index 9a09401e7d016a..cdbc1fe0380694 100644 --- a/lib/stream.js +++ b/lib/stream.js @@ -64,7 +64,7 @@ for (const key of ObjectKeys(streamReturningOperators)) { const op = streamReturningOperators[key]; function fn(...args) { if (new.target) { - throw ERR_ILLEGAL_CONSTRUCTOR(); + throw new ERR_ILLEGAL_CONSTRUCTOR(); } return Stream.Readable.from(ReflectApply(op, this, args)); } @@ -82,7 +82,7 @@ for (const key of ObjectKeys(promiseReturningOperators)) { const op = promiseReturningOperators[key]; function fn(...args) { if (new.target) { - throw ERR_ILLEGAL_CONSTRUCTOR(); + throw new ERR_ILLEGAL_CONSTRUCTOR(); } return ReflectApply(op, this, args); } diff --git a/src/node_options.cc b/src/node_options.cc index b544f1209143c0..0285f422dfd62c 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -370,6 +370,11 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { &EnvironmentOptions::experimental_fetch, kAllowedInEnvvar, true); + AddOption("--experimental-websocket", + "experimental WebSocket API", + &EnvironmentOptions::experimental_websocket, + kAllowedInEnvvar, + true); AddOption("--experimental-global-customevent", "expose experimental CustomEvent on the global scope", &EnvironmentOptions::experimental_global_customevent, diff --git a/src/node_options.h b/src/node_options.h index bc18a45e681a3c..2b9f3d3084651a 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -111,6 +111,7 @@ class EnvironmentOptions : public Options { std::string dns_result_order; bool enable_source_maps = false; bool experimental_fetch = true; + bool experimental_websocket = false; bool experimental_global_customevent = true; bool experimental_global_web_crypto = true; bool experimental_https_modules = false; diff --git a/test/common/globals.js b/test/common/globals.js index f18b358e657a55..8b9b6b34f6abaf 100644 --- a/test/common/globals.js +++ b/test/common/globals.js @@ -123,6 +123,7 @@ const webIdlExposedWindow = new Set([ 'Headers', 'Request', 'Response', + 'WebSocket', ]); const nodeGlobals = new Set([ diff --git a/test/common/index.js b/test/common/index.js index c10dea59319264..9d8accf939a1ff 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -370,6 +370,9 @@ if (global.ReadableStream) { global.DecompressionStream, ); } +if (global.WebSocket) { + knownGlobals.push(WebSocket); +} function allowGlobals(...allowlist) { knownGlobals = knownGlobals.concat(allowlist); @@ -720,9 +723,8 @@ function expectsError(validator, exact) { assert.fail(`Expected one argument, got ${inspect(args)}`); } const error = args.pop(); - const descriptor = Object.getOwnPropertyDescriptor(error, 'message'); // The error message should be non-enumerable - assert.strictEqual(descriptor.enumerable, false); + assert.strictEqual(Object.prototype.propertyIsEnumerable.call(error, 'message'), false); assert.throws(() => { throw error; }, validator); return true; diff --git a/test/fixtures/test-runner/output/junit_reporter.snapshot b/test/fixtures/test-runner/output/junit_reporter.snapshot index 6516387e7ed582..e0a4c331dd5c22 100644 --- a/test/fixtures/test-runner/output/junit_reporter.snapshot +++ b/test/fixtures/test-runner/output/junit_reporter.snapshot @@ -10,6 +10,7 @@ [Error [ERR_TEST_FAILURE]: thrown from sync fail todo] { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: Error: thrown from sync fail todo * @@ -18,8 +19,7 @@ * * * - at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), - code: 'ERR_TEST_FAILURE' + * } @@ -27,6 +27,7 @@ [Error [ERR_TEST_FAILURE]: thrown from sync fail todo with message] { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: Error: thrown from sync fail todo with message * @@ -35,8 +36,7 @@ * * * - at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), - code: 'ERR_TEST_FAILURE' + * } @@ -51,6 +51,7 @@ [Error [ERR_TEST_FAILURE]: thrown from sync throw fail] { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: Error: thrown from sync throw fail * @@ -59,8 +60,7 @@ * * * - at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), - code: 'ERR_TEST_FAILURE' + * } @@ -71,6 +71,7 @@ [Error [ERR_TEST_FAILURE]: thrown from async throw fail] { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: Error: thrown from async throw fail * @@ -79,8 +80,7 @@ * * * - at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), - code: 'ERR_TEST_FAILURE' + * } @@ -88,6 +88,7 @@ [Error [ERR_TEST_FAILURE]: thrown from async throw fail] { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: Error: thrown from async throw fail * @@ -96,8 +97,7 @@ * * * - at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), - code: 'ERR_TEST_FAILURE' + * } @@ -107,6 +107,7 @@ true !== false ] { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: @@ -124,8 +125,7 @@ true !== false actual: true, expected: false, operator: 'strictEqual' - }, - code: 'ERR_TEST_FAILURE' + } } @@ -133,6 +133,7 @@ true !== false [Error [ERR_TEST_FAILURE]: rejected from reject fail] { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: Error: rejected from reject fail * @@ -141,8 +142,7 @@ true !== false * * * - at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), - code: 'ERR_TEST_FAILURE' + * } @@ -156,6 +156,7 @@ true !== false Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail * { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: Error: thrown from subtest sync throw fail * @@ -167,8 +168,7 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail * * * - at Test.postRun (node:internal/test_runner/test:715:19), - code: 'ERR_TEST_FAILURE' + * } @@ -176,7 +176,7 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail -[Error [ERR_TEST_FAILURE]: Symbol(thrown symbol from sync throw non-error fail)] { failureType: 'testCodeFailure', cause: Symbol(thrown symbol from sync throw non-error fail), code: 'ERR_TEST_FAILURE' } +[Error [ERR_TEST_FAILURE]: Symbol(thrown symbol from sync throw non-error fail)] { code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: Symbol(thrown symbol from sync throw non-error fail) } @@ -188,7 +188,7 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail -[Error [ERR_TEST_FAILURE]: test did not finish before its parent and was cancelled] { failureType: 'cancelledByParent', cause: 'test did not finish before its parent and was cancelled', code: 'ERR_TEST_FAILURE' } +[Error [ERR_TEST_FAILURE]: test did not finish before its parent and was cancelled] { code: 'ERR_TEST_FAILURE', failureType: 'cancelledByParent', cause: 'test did not finish before its parent and was cancelled' } @@ -205,6 +205,7 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail [Error [ERR_TEST_FAILURE]: this should be executed] { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: Error: this should be executed * @@ -213,8 +214,7 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail * * * - at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), - code: 'ERR_TEST_FAILURE' + * } @@ -236,11 +236,11 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail [Error [ERR_TEST_FAILURE]: callback failure] { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: Error: callback failure * - at process.processImmediate (node:internal/timers:478:21), - code: 'ERR_TEST_FAILURE' + * } @@ -249,12 +249,13 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail -[Error [ERR_TEST_FAILURE]: passed a callback but also returned a Promise] { failureType: 'callbackAndPromisePresent', cause: 'passed a callback but also returned a Promise', code: 'ERR_TEST_FAILURE' } +[Error [ERR_TEST_FAILURE]: passed a callback but also returned a Promise] { code: 'ERR_TEST_FAILURE', failureType: 'callbackAndPromisePresent', cause: 'passed a callback but also returned a Promise' } [Error [ERR_TEST_FAILURE]: thrown from callback throw] { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: Error: thrown from callback throw * @@ -263,8 +264,7 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail * * * - at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), - code: 'ERR_TEST_FAILURE' + * } @@ -273,9 +273,9 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail Error [ERR_TEST_FAILURE]: callback invoked multiple times * * { + code: 'ERR_TEST_FAILURE', failureType: 'multipleCallbackInvocations', - cause: 'callback invoked multiple times', - code: 'ERR_TEST_FAILURE' + cause: 'callback invoked multiple times' } @@ -284,14 +284,14 @@ Error [ERR_TEST_FAILURE]: callback invoked multiple times Error [ERR_TEST_FAILURE]: callback invoked multiple times * { + code: 'ERR_TEST_FAILURE', failureType: 'uncaughtException', cause: Error [ERR_TEST_FAILURE]: callback invoked multiple times * { + code: 'ERR_TEST_FAILURE', failureType: 'multipleCallbackInvocations', - cause: 'callback invoked multiple times', - code: 'ERR_TEST_FAILURE' - }, - code: 'ERR_TEST_FAILURE' + cause: 'callback invoked multiple times' + } } @@ -299,11 +299,11 @@ Error [ERR_TEST_FAILURE]: callback invoked multiple times Error [ERR_TEST_FAILURE]: thrown from callback async throw * { + code: 'ERR_TEST_FAILURE', failureType: 'uncaughtException', cause: Error: thrown from callback async throw * - at process.processImmediate (node:internal/timers:478:21), - code: 'ERR_TEST_FAILURE' + * } @@ -319,7 +319,7 @@ Error [ERR_TEST_FAILURE]: thrown from callback async throw -[Error [ERR_TEST_FAILURE]: customized] { failureType: 'testCodeFailure', cause: customized, code: 'ERR_TEST_FAILURE' } +[Error [ERR_TEST_FAILURE]: customized] { code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: customized } @@ -328,9 +328,9 @@ Error [ERR_TEST_FAILURE]: thrown from callback async throw foo: 1, [Symbol(nodejs.util.inspect.custom)]: [Function: [nodejs.util.inspect.custom]] }] { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', - cause: { foo: 1, [Symbol(nodejs.util.inspect.custom)]: [Function: [nodejs.util.inspect.custom]] }, - code: 'ERR_TEST_FAILURE' + cause: { foo: 1, [Symbol(nodejs.util.inspect.custom)]: [Function: [nodejs.util.inspect.custom]] } } @@ -339,6 +339,7 @@ Error [ERR_TEST_FAILURE]: thrown from callback async throw Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fails at first * { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: Error: thrown from subtest sync throw fails at first * @@ -350,8 +351,7 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fails at first * * * - at Test.postRun (node:internal/test_runner/test:715:19), - code: 'ERR_TEST_FAILURE' + * } @@ -359,6 +359,7 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fails at first Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fails at second * { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: Error: thrown from subtest sync throw fails at second * @@ -370,20 +371,19 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fails at second * * * - at async Test.run (node:internal/test_runner/test:632:9), - code: 'ERR_TEST_FAILURE' + * } -[Error [ERR_TEST_FAILURE]: test timed out after 5ms] { failureType: 'testTimeoutFailure', cause: 'test timed out after 5ms', code: 'ERR_TEST_FAILURE' } +[Error [ERR_TEST_FAILURE]: test timed out after 5ms] { code: 'ERR_TEST_FAILURE', failureType: 'testTimeoutFailure', cause: 'test timed out after 5ms' } -[Error [ERR_TEST_FAILURE]: test timed out after 5ms] { failureType: 'testTimeoutFailure', cause: 'test timed out after 5ms', code: 'ERR_TEST_FAILURE' } +[Error [ERR_TEST_FAILURE]: test timed out after 5ms] { code: 'ERR_TEST_FAILURE', failureType: 'testTimeoutFailure', cause: 'test timed out after 5ms' } @@ -391,19 +391,19 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fails at second -[Error [ERR_TEST_FAILURE]: custom error] { failureType: 'testCodeFailure', cause: 'custom error', code: 'ERR_TEST_FAILURE' } +[Error [ERR_TEST_FAILURE]: custom error] { code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: 'custom error' } Error [ERR_TEST_FAILURE]: foo * { + code: 'ERR_TEST_FAILURE', failureType: 'uncaughtException', cause: Error: foo * * - at process.processTimers (node:internal/timers:514:7), - code: 'ERR_TEST_FAILURE' + * } @@ -411,12 +411,12 @@ Error [ERR_TEST_FAILURE]: foo Error [ERR_TEST_FAILURE]: bar * { + code: 'ERR_TEST_FAILURE', failureType: 'unhandledRejection', cause: Error: bar * * - at process.processTimers (node:internal/timers:514:7), - code: 'ERR_TEST_FAILURE' + * } @@ -435,6 +435,7 @@ should loosely deep-equal bar: 2, c: [Circular *1] }] { + code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: AssertionError [ERR_ASSERTION]: Expected values to be loosely deep-equal: @@ -455,8 +456,7 @@ should loosely deep-equal actual: [Object], expected: [Object], operator: 'deepEqual' - }, - code: 'ERR_TEST_FAILURE' + } } @@ -464,9 +464,9 @@ should loosely deep-equal Error [ERR_TEST_FAILURE]: test could not be started because its parent finished * { + code: 'ERR_TEST_FAILURE', failureType: 'parentAlreadyFinished', - cause: 'test could not be started because its parent finished', - code: 'ERR_TEST_FAILURE' + cause: 'test could not be started because its parent finished' } diff --git a/test/fixtures/test-runner/output/spec_reporter.snapshot b/test/fixtures/test-runner/output/spec_reporter.snapshot index 5dc05d5b43c12d..8f14dc7fc9bade 100644 --- a/test/fixtures/test-runner/output/spec_reporter.snapshot +++ b/test/fixtures/test-runner/output/spec_reporter.snapshot @@ -178,9 +178,9 @@ callback called twice in future tick (*ms) Error [ERR_TEST_FAILURE]: callback invoked multiple times * { + code: 'ERR_TEST_FAILURE', failureType: 'multipleCallbackInvocations', - cause: 'callback invoked multiple times', - code: 'ERR_TEST_FAILURE' + cause: 'callback invoked multiple times' } callback async throw (*ms) @@ -449,9 +449,9 @@ callback called twice in future tick (*ms) Error [ERR_TEST_FAILURE]: callback invoked multiple times * { + code: 'ERR_TEST_FAILURE', failureType: 'multipleCallbackInvocations', - cause: 'callback invoked multiple times', - code: 'ERR_TEST_FAILURE' + cause: 'callback invoked multiple times' } * diff --git a/test/fixtures/test-runner/output/spec_reporter_cli.snapshot b/test/fixtures/test-runner/output/spec_reporter_cli.snapshot index 25c22069c3b8e7..a9b70560d905b2 100644 --- a/test/fixtures/test-runner/output/spec_reporter_cli.snapshot +++ b/test/fixtures/test-runner/output/spec_reporter_cli.snapshot @@ -178,9 +178,9 @@ callback called twice in future tick (*ms) Error [ERR_TEST_FAILURE]: callback invoked multiple times * { + code: 'ERR_TEST_FAILURE', failureType: 'multipleCallbackInvocations', - cause: 'callback invoked multiple times', - code: 'ERR_TEST_FAILURE' + cause: 'callback invoked multiple times' } callback async throw (*ms) @@ -449,9 +449,9 @@ callback called twice in future tick (*ms) Error [ERR_TEST_FAILURE]: callback invoked multiple times * { + code: 'ERR_TEST_FAILURE', failureType: 'multipleCallbackInvocations', - cause: 'callback invoked multiple times', - code: 'ERR_TEST_FAILURE' + cause: 'callback invoked multiple times' } * diff --git a/test/message/internal_assert.out b/test/message/internal_assert.out index bd25c879478083..197b863bf6ae69 100644 --- a/test/message/internal_assert.out +++ b/test/message/internal_assert.out @@ -5,7 +5,6 @@ node:internal/assert:* Error [ERR_INTERNAL_ASSERTION]: This is caused by either a bug in Node.js or incorrect usage of Node.js internals. Please open an issue with this stack trace at https://github.com/nodejs/node/issues - at new NodeError (node:internal/errors:*:*) at assert (node:internal/assert:*:*) at * (*test*message*internal_assert.js:7:1) at * diff --git a/test/message/internal_assert_fail.out b/test/message/internal_assert_fail.out index 408d6d3364470d..e6895691cda9c1 100644 --- a/test/message/internal_assert_fail.out +++ b/test/message/internal_assert_fail.out @@ -6,7 +6,6 @@ Error [ERR_INTERNAL_ASSERTION]: Unreachable! This is caused by either a bug in Node.js or incorrect usage of Node.js internals. Please open an issue with this stack trace at https://github.com/nodejs/node/issues - at new NodeError (node:internal/errors:*:*) at Function.fail (node:internal/assert:*:*) at * (*test*message*internal_assert_fail.js:7:8) at * diff --git a/test/parallel/test-blob-buffer-too-large.js b/test/parallel/test-blob-buffer-too-large.js index 2fd8b8754bd593..a9cf53b025bbff 100644 --- a/test/parallel/test-blob-buffer-too-large.js +++ b/test/parallel/test-blob-buffer-too-large.js @@ -3,17 +3,17 @@ const common = require('../common'); const assert = require('assert'); -const { Blob } = require('buffer'); +const { Blob, kMaxLength } = require('buffer'); if (common.isFreeBSD) common.skip('Oversized buffer make the FreeBSD CI runner crash'); try { - new Blob([new Uint8Array(0xffffffff), [1]]); + new Blob([new Uint8Array(kMaxLength), [1]]); } catch (e) { if ( e.message === 'Array buffer allocation failed' || - e.message === 'Invalid typed array length: 4294967295' + e.message === `Invalid typed array length: ${kMaxLength}` ) { common.skip( 'Insufficient memory on this platform for oversized buffer test.' diff --git a/test/parallel/test-buffer-alloc.js b/test/parallel/test-buffer-alloc.js index c6b728027057ec..aad9c6bcab69e9 100644 --- a/test/parallel/test-buffer-alloc.js +++ b/test/parallel/test-buffer-alloc.js @@ -4,13 +4,16 @@ const common = require('../common'); const assert = require('assert'); const vm = require('vm'); -const SlowBuffer = require('buffer').SlowBuffer; +const { + SlowBuffer, + kMaxLength, +} = require('buffer'); // Verify the maximum Uint8Array size. There is no concrete limit by spec. The // internal limits should be updated if this fails. assert.throws( - () => new Uint8Array(2 ** 32 + 1), - { message: 'Invalid typed array length: 4294967297' } + () => new Uint8Array(kMaxLength + 1), + { message: `Invalid typed array length: ${kMaxLength + 1}` }, ); const b = Buffer.allocUnsafe(1024); diff --git a/test/parallel/test-buffer-over-max-length.js b/test/parallel/test-buffer-over-max-length.js index d2df358cc00ca4..f29d6b62d4aa40 100644 --- a/test/parallel/test-buffer-over-max-length.js +++ b/test/parallel/test-buffer-over-max-length.js @@ -12,18 +12,8 @@ const bufferMaxSizeMsg = { name: 'RangeError', }; -assert.throws(() => Buffer((-1 >>> 0) + 2), bufferMaxSizeMsg); -assert.throws(() => SlowBuffer((-1 >>> 0) + 2), bufferMaxSizeMsg); -assert.throws(() => Buffer.alloc((-1 >>> 0) + 2), bufferMaxSizeMsg); -assert.throws(() => Buffer.allocUnsafe((-1 >>> 0) + 2), bufferMaxSizeMsg); -assert.throws(() => Buffer.allocUnsafeSlow((-1 >>> 0) + 2), bufferMaxSizeMsg); - assert.throws(() => Buffer(kMaxLength + 1), bufferMaxSizeMsg); assert.throws(() => SlowBuffer(kMaxLength + 1), bufferMaxSizeMsg); assert.throws(() => Buffer.alloc(kMaxLength + 1), bufferMaxSizeMsg); assert.throws(() => Buffer.allocUnsafe(kMaxLength + 1), bufferMaxSizeMsg); assert.throws(() => Buffer.allocUnsafeSlow(kMaxLength + 1), bufferMaxSizeMsg); - -// issue GH-4331 -assert.throws(() => Buffer.allocUnsafe(0x100000001), bufferMaxSizeMsg); -assert.throws(() => Buffer.allocUnsafe(0xFFFFFFFFF), bufferMaxSizeMsg); diff --git a/test/parallel/test-buffer-tostring-rangeerror.js b/test/parallel/test-buffer-tostring-rangeerror.js index d2e1e0d6e46438..0ebea759b5c42b 100644 --- a/test/parallel/test-buffer-tostring-rangeerror.js +++ b/test/parallel/test-buffer-tostring-rangeerror.js @@ -1,17 +1,22 @@ 'use strict'; require('../common'); -// This test ensures that Node.js throws a RangeError when trying to convert a -// gigantic buffer into a string. +// This test ensures that Node.js throws an Error when trying to convert a +// large buffer into a string. // Regression test for https://github.com/nodejs/node/issues/649. const assert = require('assert'); -const SlowBuffer = require('buffer').SlowBuffer; +const { + SlowBuffer, + constants: { + MAX_STRING_LENGTH, + }, +} = require('buffer'); -const len = 1422561062959; +const len = MAX_STRING_LENGTH + 1; const message = { - code: 'ERR_OUT_OF_RANGE', - name: 'RangeError', + code: 'ERR_STRING_TOO_LONG', + name: 'Error', }; assert.throws(() => Buffer(len).toString('utf8'), message); assert.throws(() => SlowBuffer(len).toString('utf8'), message); diff --git a/test/parallel/test-repl-top-level-await.js b/test/parallel/test-repl-top-level-await.js index 1abcca75f1e2a0..c8bc26fad62e5c 100644 --- a/test/parallel/test-repl-top-level-await.js +++ b/test/parallel/test-repl-top-level-await.js @@ -207,8 +207,8 @@ async function ctrlCTest() { assert.deepStrictEqual(output.slice(0, 3), [ 'await new Promise(() => {})\r', 'Uncaught:', - 'Error [ERR_SCRIPT_EXECUTION_INTERRUPTED]: ' + - 'Script execution was interrupted by `SIGINT`', + '[Error [ERR_SCRIPT_EXECUTION_INTERRUPTED]: ' + + 'Script execution was interrupted by `SIGINT`] {', ]); assert.deepStrictEqual(output.slice(-2), [ '}', diff --git a/test/parallel/test-websocket.js b/test/parallel/test-websocket.js new file mode 100644 index 00000000000000..2a7069ccf3b739 --- /dev/null +++ b/test/parallel/test-websocket.js @@ -0,0 +1,7 @@ +// Flags: --experimental-websocket +'use strict'; + +require('../common'); +const assert = require('assert'); + +assert.strictEqual(typeof WebSocket, 'function'); diff --git a/tools/doc/allhtml.mjs b/tools/doc/allhtml.mjs index cdf7140f728469..ccf3a10ea7f95b 100644 --- a/tools/doc/allhtml.mjs +++ b/tools/doc/allhtml.mjs @@ -27,7 +27,7 @@ for (const link of toc.match(//g)) { const data = fs.readFileSync(new URL(`./${href}`, source), 'utf8'); // Split the doc. - const match = /(<\/ul>\s*)?<\/\w+>\s*<\w+ id="apicontent">/.exec(data); + const match = /(<\/ul>\s*)?<\/\w+>\s*<\w+ role="main" id="apicontent">/.exec(data); // Get module name const moduleName = href.replace(/\.html$/, ''); @@ -89,7 +89,7 @@ all = all.slice(0, tocStart.index + tocStart[0].length) + all.slice(tocStart.index + tocStart[0].length); // Replace apicontent with the concatenated set of apicontents from each source. -const apiStart = /<\w+ id="apicontent">\s*/.exec(all); +const apiStart = /<\w+ role="main" id="apicontent">\s*/.exec(all); const apiEnd = all.lastIndexOf(''); all = all.slice(0, apiStart.index + apiStart[0].length) .replace( diff --git a/tools/doc/html.mjs b/tools/doc/html.mjs index 168f68c1b03f21..95782efe03d554 100644 --- a/tools/doc/html.mjs +++ b/tools/doc/html.mjs @@ -467,7 +467,7 @@ export function buildToc({ filename, apilinks }) { .use(htmlStringify) .processSync(toc).toString(); - file.toc = `
Table of contents${inner}
`; + file.toc = ``; file.tocPicker = `
${inner}
`; } else { file.toc = file.tocPicker = ''; diff --git a/tools/github_reporter/index.js b/tools/github_reporter/index.js index 3b22136ab5260a..e9cf741b2ddc86 100644 --- a/tools/github_reporter/index.js +++ b/tools/github_reporter/index.js @@ -1621,7 +1621,7 @@ var require_oidc_utils = __commonJS({ Error Code : ${error.statusCode} - Error Message: ${error.result.message}`); + Error Message: ${error.message}`); }); const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; if (!id_token) { diff --git a/tools/github_reporter/package.json b/tools/github_reporter/package.json index ff8ac3ec813d20..a4606a05892ced 100644 --- a/tools/github_reporter/package.json +++ b/tools/github_reporter/package.json @@ -1,7 +1,8 @@ { "name": "@reporters/github", - "version": "1.5.2", + "version": "1.5.3", "description": "A github actions reporter for `node:test`", + "type": "commonjs", "keywords": [ "github actions", "node:test", diff --git a/tools/osx-notarize.sh b/tools/osx-notarize.sh index 31c92c2ca426f3..beea7041793cdf 100755 --- a/tools/osx-notarize.sh +++ b/tools/osx-notarize.sh @@ -1,34 +1,87 @@ #!/bin/sh -# Uses gon, from https://github.com/mitchellh/gon, to notarize a generated node-.pkg file -# with Apple for installation on macOS Catalina and later as validated by Gatekeeper. +# Notarize a generated node-.pkg file as an Apple requirement for installation on macOS Catalina and later, as validated by Gatekeeper. +# Uses gon (Xcode version < 13.0) or notarytool (Xcode >= 13.0). -set -e - -gon_version="0.2.2" -gon_exe="${HOME}/.gon/gon_${gon_version}" +version() { + echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }' || echo "0" +} +xcode_version=$(xcodebuild -version | awk '/Xcode/ {print $2}') +xcode_version_result=$(version "$xcode_version") +xcode_version_threshold=$(version "13.0") pkgid="$1" -[ -z "$pkgid" ] && \ - echo "Usage: $0 " \ +if [ -z "$pkgid" ]; then + echo "Usage: $0 " exit 1 +fi # shellcheck disable=SC2154 -[ -z "$NOTARIZATION_ID" ] && \ - echo "No NOTARIZATION_ID environment var. Skipping notarization." \ +if [ -z "$NOTARIZATION_ID" ]; then + echo "No NOTARIZATION_ID environment variable. Skipping notarization." exit 0 +fi -set -x - -mkdir -p "${HOME}/.gon/" +if [ -z "$NOTARIZATION_PASSWORD" ]; then + echo "No NOTARIZATION_PASSWORD environment variable. Skipping notarization." + exit 0 +fi -if [ ! -f "${gon_exe}" ]; then - curl -sL "https://github.com/mitchellh/gon/releases/download/v${gon_version}/gon_${gon_version}_macos.zip" -o "${gon_exe}.zip" - (cd "${HOME}/.gon/" && rm -f gon && unzip "${gon_exe}.zip" && mv gon "${gon_exe}") +if [ -z "$NOTARIZATION_TEAM_ID" ]; then + echo "No NOTARIZATION_TEAM_ID environment variable. Skipping notarization." + exit 0 fi -sed -e "s/{{appleid}}/${NOTARIZATION_ID}/" -e "s/{{pkgid}}/${pkgid}/" tools/osx-gon-config.json.tmpl \ - > gon-config.json +# TODO(@ulisesGascon): remove support for gon +# when https://github.com/nodejs/build/issues/3385#issuecomment-1729281269 is ready +if [ "$xcode_version_result" -lt "$xcode_version_threshold" ]; then + echo "Notarization process is done with gon." + set -x + + gon_version="0.2.2" + gon_exe="${HOME}/.gon/gon_${gon_version}" -"${gon_exe}" -log-level=info gon-config.json + mkdir -p "${HOME}/.gon/" + + if [ ! -f "${gon_exe}" ]; then + curl -sL "https://github.com/mitchellh/gon/releases/download/v${gon_version}/gon_${gon_version}_macos.zip" -o "${gon_exe}.zip" + (cd "${HOME}/.gon/" && rm -f gon && unzip "${gon_exe}.zip" && mv gon "${gon_exe}") + fi + + sed -e "s/{{appleid}}/${NOTARIZATION_ID}/" -e "s/{{pkgid}}/${pkgid}/" tools/osx-gon-config.json.tmpl \ + > gon-config.json + + "${gon_exe}" -log-level=info gon-config.json + +else + echo "Notarization process is done with Notarytool." + + if ! command -v xcrun notarytool > /dev/null + then + echo "Notarytool is not present in the system. Notarization has failed." + exit 1 + fi + + # Submit the package for notarization + # TODO(@ulisesGascon): refactor to use --keychain-profile + # when https://github.com/nodejs/build/issues/3385#issuecomment-1729281269 is ready + notarization_output=$( + xcrun notarytool submit \ + --apple-id "$NOTARIZATION_ID" \ + --password "$NOTARIZATION_PASSWORD" \ + --team-id "$NOTARIZATION_TEAM_ID" \ + --wait \ + "node-$pkgid.pkg" 2>&1 + ) + + if [ $? -eq 0 ]; then + # Extract the operation ID from the output + operation_id=$(echo "$notarization_output" | awk '/RequestUUID/ {print $NF}') + echo "Notarization submitted. Operation ID: $operation_id" + exit 0 + else + echo "Notarization failed. Error: $notarization_output" + exit 1 + fi +fi