diff options
Diffstat (limited to 'src/js/node')
-rw-r--r-- | src/js/node/assert.js | 36 | ||||
-rw-r--r-- | src/js/node/async_hooks.ts | 127 | ||||
-rw-r--r-- | src/js/node/child_process.js | 109 | ||||
-rw-r--r-- | src/js/node/crypto.js | 573 | ||||
-rw-r--r-- | src/js/node/diagnostics_channel.js | 2 | ||||
-rw-r--r-- | src/js/node/dns.js | 23 | ||||
-rw-r--r-- | src/js/node/domain.ts | 8 | ||||
-rw-r--r-- | src/js/node/events.js | 66 | ||||
-rw-r--r-- | src/js/node/fs.js | 109 | ||||
-rw-r--r-- | src/js/node/fs.promises.ts | 107 | ||||
-rw-r--r-- | src/js/node/http.ts | 95 | ||||
-rw-r--r-- | src/js/node/net.js | 164 | ||||
-rw-r--r-- | src/js/node/os.ts | 3 | ||||
-rw-r--r-- | src/js/node/querystring.js | 6 | ||||
-rw-r--r-- | src/js/node/readline.js | 191 | ||||
-rw-r--r-- | src/js/node/stream.js | 86 | ||||
-rw-r--r-- | src/js/node/tls.js | 83 | ||||
-rw-r--r-- | src/js/node/tty.js | 39 | ||||
-rw-r--r-- | src/js/node/url.js | 5 | ||||
-rw-r--r-- | src/js/node/util.js | 356 | ||||
-rw-r--r-- | src/js/node/worker_threads.ts | 6 | ||||
-rw-r--r-- | src/js/node/zlib.js | 22 |
22 files changed, 1259 insertions, 957 deletions
diff --git a/src/js/node/assert.js b/src/js/node/assert.js index 475f72006..75b7057b3 100644 --- a/src/js/node/assert.js +++ b/src/js/node/assert.js @@ -79,7 +79,7 @@ var require_errors = __commonJS({ _classCallCheck(this, NodeError2), (_this = _possibleConstructorReturn( this, - _getPrototypeOf(NodeError2).call(this, getMessage(arg1, arg2, arg3)), + _getPrototypeOf(NodeError2).$call(this, getMessage(arg1, arg2, arg3)), )), (_this.code = code), _this @@ -298,7 +298,7 @@ var require_assertion_error = __commonJS({ if (typeof Reflect == "undefined" || !Reflect.construct || Reflect.construct.sham) return !1; if (typeof Proxy == "function") return !0; try { - return Date.prototype.toString.call(Reflect.construct(Date, [], function () {})), !0; + return Date.prototype.toString.$call(Reflect.construct(Date, [], function () {})), !0; } catch { return !1; } @@ -309,16 +309,16 @@ var require_assertion_error = __commonJS({ ? (_construct = Reflect.construct) : (_construct = function (Parent2, args2, Class2) { var a = [null]; - a.push.apply(a, args2); - var Constructor = Function.bind.apply(Parent2, a), + a.push.$apply(a, args2); + var Constructor = Function.bind.$apply(Parent2, a), instance = new Constructor(); return Class2 && _setPrototypeOf(instance, Class2.prototype), instance; }), - _construct.apply(null, arguments) + _construct.$apply(null, arguments) ); } function _isNativeFunction(fn) { - return Function.toString.call(fn).indexOf("[native code]") !== -1; + return Function.toString.$call(fn).indexOf("[native code]") !== -1; } function _setPrototypeOf(o, p) { return ( @@ -663,7 +663,7 @@ var require_assertion_error = __commonJS({ expected = options.expected, limit = Error.stackTraceLimit; if (((Error.stackTraceLimit = 0), message != null)) - _this = _possibleConstructorReturn(this, _getPrototypeOf(AssertionError2).call(this, String(message))); + _this = _possibleConstructorReturn(this, _getPrototypeOf(AssertionError2).$call(this, String(message))); else if ( (process.stderr && process.stderr.isTTY && @@ -683,7 +683,7 @@ var require_assertion_error = __commonJS({ ) _this = _possibleConstructorReturn( this, - _getPrototypeOf(AssertionError2).call(this, createErrDiff(actual, expected, operator)), + _getPrototypeOf(AssertionError2).$call(this, createErrDiff(actual, expected, operator)), ); else if (operator === "notDeepStrictEqual" || operator === "notStrictEqual") { var base = kReadableOperator[operator], @@ -700,11 +700,11 @@ var require_assertion_error = __commonJS({ res.length === 1 ? (_this = _possibleConstructorReturn( this, - _getPrototypeOf(AssertionError2).call(this, "".concat(base, " ").concat(res[0])), + _getPrototypeOf(AssertionError2).$call(this, "".concat(base, " ").concat(res[0])), )) : (_this = _possibleConstructorReturn( this, - _getPrototypeOf(AssertionError2).call( + _getPrototypeOf(AssertionError2).$call( this, "" .concat( @@ -757,7 +757,7 @@ should equal : (other = " ".concat(operator, " ").concat(other))), (_this = _possibleConstructorReturn( this, - _getPrototypeOf(AssertionError2).call(this, "".concat(_res).concat(other)), + _getPrototypeOf(AssertionError2).$call(this, "".concat(_res).concat(other)), )); } return ( @@ -902,7 +902,7 @@ var require_assert = __commonJS({ function ok() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) args[_key] = arguments[_key]; - innerOk.apply(void 0, [ok, args.length].concat(args)); + innerOk.$apply(void 0, [ok, args.length].concat(args)); } assert.ok = ok; assert.equal = function equal(actual, expected, message) { @@ -1071,7 +1071,7 @@ var require_assert = __commonJS({ ? !0 : Error.isPrototypeOf(expected) ? !1 - : expected.call({}, actual) === !0; + : expected.$call({}, actual) === !0; } function getActual(fn) { if (typeof fn != "function") throw new ERR_INVALID_ARG_TYPE("fn", "Function", fn); @@ -1168,25 +1168,25 @@ var require_assert = __commonJS({ assert.throws = function throws(promiseFn) { for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) args[_key2 - 1] = arguments[_key2]; - expectsError.apply(void 0, [throws, getActual(promiseFn)].concat(args)); + expectsError.$apply(void 0, [throws, getActual(promiseFn)].concat(args)); }; assert.rejects = function rejects(promiseFn) { for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) args[_key3 - 1] = arguments[_key3]; return waitForActual(promiseFn).then(function (result) { - return expectsError.apply(void 0, [rejects, result].concat(args)); + return expectsError.$apply(void 0, [rejects, result].concat(args)); }); }; assert.doesNotThrow = function doesNotThrow(fn) { for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) args[_key4 - 1] = arguments[_key4]; - expectsNoError.apply(void 0, [doesNotThrow, getActual(fn)].concat(args)); + expectsNoError.$apply(void 0, [doesNotThrow, getActual(fn)].concat(args)); }; assert.doesNotReject = function doesNotReject(fn) { for (var _len5 = arguments.length, args = new Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) args[_key5 - 1] = arguments[_key5]; return waitForActual(fn).then(function (result) { - return expectsNoError.apply(void 0, [doesNotReject, result].concat(args)); + return expectsNoError.$apply(void 0, [doesNotReject, result].concat(args)); }); }; assert.ifError = function ifError(err) { @@ -1240,7 +1240,7 @@ var require_assert = __commonJS({ function strict() { for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) args[_key6] = arguments[_key6]; - innerOk.apply(void 0, [strict, args.length].concat(args)); + innerOk.$apply(void 0, [strict, args.length].concat(args)); } assert.strict = objectAssign(strict, assert, { equal: assert.strictEqual, diff --git a/src/js/node/async_hooks.ts b/src/js/node/async_hooks.ts index ef77b79f7..20d82f5e5 100644 --- a/src/js/node/async_hooks.ts +++ b/src/js/node/async_hooks.ts @@ -10,7 +10,7 @@ // // This means context tracking is *kind-of* manual. If we recieve a callback in native code // - In Zig, call jsValue.withAsyncContextIfNeeded(); which returns another JSValue. Store that and -// then run .call() on it later. +// then run .$call() on it later. // - In C++, call AsyncContextFrame::withAsyncContextIfNeeded(jsValue). Then to call it, // use AsyncContextFrame:: call(...) instead of JSC:: call. // @@ -19,17 +19,55 @@ // use. But the nature of this approach makes the implementation *itself* very low-impact on performance. // // AsyncContextData is an immutable array managed in here, formatted [key, value, key, value] where -// each key is an AsyncLocalStorage object and the value is the associated value. +// each key is an AsyncLocalStorage object and the value is the associated value. There are a ton of +// calls to $assert which will verify this invariant (only during bun-debug) // const { cleanupLater, setAsyncHooksEnabled } = $lazy("async_hooks"); +// Only run during debug +function assertValidAsyncContextArray(array: unknown): array is ReadonlyArray<any> | undefined { + // undefined is OK + if (array === undefined) return true; + // Otherwise, it must be an array + $assert( + Array.isArray(array), + "AsyncContextData must be an array or undefined, got", + Bun.inspect(array, { depth: 1 }), + ); + // the array has to be even + $assert(array.length % 2 === 0, "AsyncContextData should be even-length, got", Bun.inspect(array, { depth: 1 })); + // if it is zero-length, use undefined instead + $assert(array.length > 0, "AsyncContextData should be undefined if empty, got", Bun.inspect(array, { depth: 1 })); + for (var i = 0; i < array.length; i += 2) { + $assert( + array[i] instanceof AsyncLocalStorage, + `Odd indexes in AsyncContextData should be an array of AsyncLocalStorage\nIndex %s was %s`, + i, + array[i], + ); + } + return true; +} + +// Only run during debug +function debugFormatContextValue(value: ReadonlyArray<any> | undefined) { + if (value === undefined) return "undefined"; + let str = "{\n"; + for (var i = 0; i < value.length; i += 2) { + str += ` ${value[i].__id__}: typeof = ${typeof value[i + 1]}\n`; + } + str += "}"; + return str; +} + function get(): ReadonlyArray<any> | undefined { - $debug("get", $getInternalField($asyncContext, 0)); + $debug("get", debugFormatContextValue($getInternalField($asyncContext, 0))); return $getInternalField($asyncContext, 0); } function set(contextValue: ReadonlyArray<any> | undefined) { - $debug("set", contextValue); + $assert(assertValidAsyncContextArray(contextValue)); + $debug("set", debugFormatContextValue(contextValue)); return $putInternalField($asyncContext, 0, contextValue); } @@ -38,6 +76,16 @@ class AsyncLocalStorage { constructor() { setAsyncHooksEnabled(true); + + // In debug mode assign every AsyncLocalStorage a unique ID + if (IS_BUN_DEVELOPMENT) { + const uid = Math.random().toString(36).slice(2, 8); + const source = require("bun:jsc").callerSourceOrigin(); + + (this as any).__id__ = uid + "@" + require("node:path").basename(source); + + $debug("new AsyncLocalStorage uid=", (this as any).__id__, source); + } } static bind(fn, ...args: any) { @@ -67,8 +115,11 @@ class AsyncLocalStorage { return; } var { length } = context; + $assert(length > 0); + $assert(length % 2 === 0); for (var i = 0; i < length; i += 2) { if (context[i] === this) { + $assert(length > i + 1); const clone = context.slice(); clone[i + 1] = store; set(clone); @@ -76,33 +127,43 @@ class AsyncLocalStorage { } } set(context.concat(this, store)); + $assert(this.getStore() === store); } exit(cb, ...args) { return this.run(undefined, cb, ...args); } - run(store, callback, ...args) { + // This function is literred with $asserts to ensure that everything that + // is assumed to be true is *actually* true. + run(store_value, callback, ...args) { + $debug("run " + (this as any).__id__); var context = get() as any[]; // we make sure to .slice() before mutating var hasPrevious = false; - var previous; + var previous_value; var i = 0; - var contextWasInit = !context; - if (contextWasInit) { - set((context = [this, store])); + var contextWasAlreadyInit = !context; + if (contextWasAlreadyInit) { + set((context = [this, store_value])); } else { // it's safe to mutate context now that it was cloned context = context!.slice(); i = context.indexOf(this); if (i > -1) { + $assert(i % 2 === 0); hasPrevious = true; - previous = context[i + 1]; - context[i + 1] = store; + previous_value = context[i + 1]; + context[i + 1] = store_value; } else { - context.push(this, store); + i = context.length; + context.push(this, store_value); + $assert(i % 2 === 0); + $assert(context.length % 2 === 0); } set(context); } + $assert(i > -1, "i was not set"); + $assert(this.getStore() === store_value, "run: store_value was not set"); try { return callback(...args); } catch (e) { @@ -111,24 +172,36 @@ class AsyncLocalStorage { // Note: early `return` will prevent `throw` above from working. I think... // Set AsyncContextFrame to undefined if we are out of context values if (!this.#disableCalled) { - var context2 = get()! as any[]; - if (context2 === context && contextWasInit) { + var context2 = get()! as any[]; // we make sure to .slice() before mutating + if (context2 === context && contextWasAlreadyInit) { + $assert(context2.length === 2, "context was mutated without copy"); set(undefined); } else { context2 = context2.slice(); // array is cloned here + $assert(context2[i] === this); if (hasPrevious) { - context2[i + 1] = previous; + context2[i + 1] = previous_value; set(context2); } else { + // i wonder if this is a fair assert to make context2.splice(i, 2); + $assert(context2.length % 2 === 0); set(context2.length ? context2 : undefined); } } + $assert( + this.getStore() === previous_value, + "run: previous_value", + Bun.inspect(previous_value), + "was not restored, i see", + this.getStore(), + ); } } } disable() { + $debug("disable " + (this as any).__id__); // In this case, we actually do want to mutate the context state if (!this.#disableCalled) { var context = get() as any[]; @@ -147,6 +220,7 @@ class AsyncLocalStorage { } getStore() { + $debug("getStore " + (this as any).__id__); var context = get(); if (!context) return; var { length } = context; @@ -156,11 +230,21 @@ class AsyncLocalStorage { } } +if (IS_BUN_DEVELOPMENT) { + AsyncLocalStorage.prototype[Bun.inspect.custom] = function (depth, options) { + if (depth < 0) return `AsyncLocalStorage { ${Bun.inspect((this as any).__id__, options)} }`; + return `AsyncLocalStorage { [${options.stylize("debug id", "special")}]: ${Bun.inspect( + (this as any).__id__, + options, + )} }`; + }; +} + class AsyncResource { type; #snapshot; - constructor(type, options) { + constructor(type, options?) { if (typeof type !== "string") { throw new TypeError('The "type" argument must be of type string. Received type ' + typeof type); } @@ -193,13 +277,22 @@ class AsyncResource { var prev = get(); set(this.#snapshot); try { - return fn.apply(thisArg, args); + return fn.$apply(thisArg, args); } catch (error) { throw error; } finally { set(prev); } } + + bind(fn, thisArg) { + return this.runInAsyncScope.bind(this, fn, thisArg ?? this); + } + + static bind(fn, type, thisArg) { + type = type || fn.name; + return new AsyncResource(type || "bound-anonymous-fn").bind(fn, thisArg); + } } // The rest of async_hooks is not implemented and is stubbed with no-ops and warnings. diff --git a/src/js/node/child_process.js b/src/js/node/child_process.js index 859e01aa7..8840a59b1 100644 --- a/src/js/node/child_process.js +++ b/src/js/node/child_process.js @@ -286,12 +286,12 @@ function execFile(file, args, options, callback) { let stdout; let stderr; if (encoding || (child.stdout && readableEncoding)) { - stdout = ArrayPrototypeJoin.call(_stdout, ""); + stdout = ArrayPrototypeJoin.$call(_stdout, ""); } else { stdout = BufferConcat(_stdout); } if (encoding || (child.stderr && readableEncoding)) { - stderr = ArrayPrototypeJoin.call(_stderr, ""); + stderr = ArrayPrototypeJoin.$call(_stderr, ""); } else { stderr = BufferConcat(_stderr); } @@ -301,7 +301,7 @@ function execFile(file, args, options, callback) { return; } - if (args?.length) cmd += ` ${ArrayPrototypeJoin.call(args, " ")}`; + if (args?.length) cmd += ` ${ArrayPrototypeJoin.$call(args, " ")}`; if (!ex) { let message = `Command failed: ${cmd}`; if (stderr) message += `\n${stderr}`; @@ -353,7 +353,7 @@ function execFile(file, args, options, callback) { "data", maxBuffer === Infinity ? function onUnlimitedSizeBufferedData(chunk) { - ArrayPrototypePush.call(_stdout, chunk); + ArrayPrototypePush.$call(_stdout, chunk); } : encoding ? function onChildStdoutEncoded(chunk) { @@ -370,12 +370,12 @@ function execFile(file, args, options, callback) { encodedStdoutLen += actualLen; } const truncatedLen = maxBuffer - (encodedStdoutLen - actualLen); - ArrayPrototypePush.call(_stdout, StringPrototypeSlice.apply(chunk, 0, truncatedLen)); + ArrayPrototypePush.$call(_stdout, StringPrototypeSlice.$apply(chunk, 0, truncatedLen)); ex = new ERR_CHILD_PROCESS_STDIO_MAXBUFFER("stdout"); kill(); } else { - ArrayPrototypePush.call(_stdout, chunk); + ArrayPrototypePush.$call(_stdout, chunk); } } : function onChildStdoutRaw(chunk) { @@ -383,12 +383,12 @@ function execFile(file, args, options, callback) { if (stdoutLen > maxBuffer) { const truncatedLen = maxBuffer - (stdoutLen - chunk.length); - ArrayPrototypePush.call(_stdout, chunk.slice(0, truncatedLen)); + ArrayPrototypePush.$call(_stdout, chunk.slice(0, truncatedLen)); ex = new ERR_CHILD_PROCESS_STDIO_MAXBUFFER("stdout"); kill(); } else { - ArrayPrototypePush.call(_stdout, chunk); + ArrayPrototypePush.$call(_stdout, chunk); } }, ); @@ -401,7 +401,7 @@ function execFile(file, args, options, callback) { "data", maxBuffer === Infinity ? function onUnlimitedSizeBufferedData(chunk) { - ArrayPrototypePush.call(_stderr, chunk); + ArrayPrototypePush.$call(_stderr, chunk); } : encoding ? function onChildStderrEncoded(chunk) { @@ -418,12 +418,12 @@ function execFile(file, args, options, callback) { encodedStderrLen += actualLen; } const truncatedLen = maxBuffer - (encodedStderrLen - actualLen); - ArrayPrototypePush.call(_stderr, StringPrototypeSlice.call(chunk, 0, truncatedLen)); + ArrayPrototypePush.$call(_stderr, StringPrototypeSlice.$call(chunk, 0, truncatedLen)); ex = new ERR_CHILD_PROCESS_STDIO_MAXBUFFER("stderr"); kill(); } else { - ArrayPrototypePush.call(_stderr, chunk); + ArrayPrototypePush.$call(_stderr, chunk); } } : function onChildStderrRaw(chunk) { @@ -431,12 +431,12 @@ function execFile(file, args, options, callback) { if (stderrLen > maxBuffer) { const truncatedLen = maxBuffer - (stderrLen - chunk.length); - ArrayPrototypePush.call(_stderr, StringPrototypeSlice.call(chunk, 0, truncatedLen)); + ArrayPrototypePush.$call(_stderr, StringPrototypeSlice.$call(chunk, 0, truncatedLen)); ex = new ERR_CHILD_PROCESS_STDIO_MAXBUFFER("stderr"); kill(); } else { - ArrayPrototypePush.call(_stderr, chunk); + ArrayPrototypePush.$call(_stderr, chunk); } }, ); @@ -595,7 +595,7 @@ function spawnSync(file, args, options) { if (!success) { result.error = new SystemError(result.output[2], options.file, "spawnSync", -1, result.status); - result.error.spawnargs = ArrayPrototypeSlice.call(options.args, 1); + result.error.spawnargs = ArrayPrototypeSlice.$call(options.args, 1); } return result; @@ -630,7 +630,7 @@ function execFileSync(file, args, options) { // if (inheritStderr && ret.stderr) process.stderr.write(ret.stderr); const errArgs = [options.argv0 || file]; - ArrayPrototypePush.apply(errArgs, args); + ArrayPrototypePush.$apply(errArgs, args); const err = checkExecSyncError(ret, errArgs); if (err) throw err; @@ -679,16 +679,16 @@ function stdioStringToArray(stdio, channel) { case "ignore": case "overlapped": case "pipe": - ArrayPrototypePush.call(options, stdio, stdio, stdio); + ArrayPrototypePush.$call(options, stdio, stdio, stdio); break; case "inherit": - ArrayPrototypePush.call(options, 0, 1, 2); + ArrayPrototypePush.$call(options, 0, 1, 2); break; default: throw new ERR_INVALID_ARG_VALUE("stdio", stdio); } - if (channel) ArrayPrototypePush.call(options, channel); + if (channel) ArrayPrototypePush.$call(options, channel); return options; } @@ -738,19 +738,19 @@ function fork(modulePath, args = [], options) { validateArgumentNullCheck(options.execPath, "options.execPath"); // Prepare arguments for fork: - execArgv = options.execArgv || process.execArgv; - validateArgumentsNullCheck(execArgv, "options.execArgv"); - - if (execArgv === process.execArgv && process._eval != null) { - const index = ArrayPrototypeLastIndexOf.call(execArgv, process._eval); - if (index > 0) { - // Remove the -e switch to avoid fork bombing ourselves. - execArgv = ArrayPrototypeSlice.call(execArgv); - ArrayPrototypeSplice.call(execArgv, index - 1, 2); - } - } + // execArgv = options.execArgv || process.execArgv; + // validateArgumentsNullCheck(execArgv, "options.execArgv"); + + // if (execArgv === process.execArgv && process._eval != null) { + // const index = ArrayPrototypeLastIndexOf.$call(execArgv, process._eval); + // if (index > 0) { + // // Remove the -e switch to avoid fork bombing ourselves. + // execArgv = ArrayPrototypeSlice.$call(execArgv); + // ArrayPrototypeSplice.$call(execArgv, index - 1, 2); + // } + // } - args = [...execArgv, modulePath, ...args]; + args = [/*...execArgv,*/ modulePath, ...args]; if (typeof options.stdio === "string") { options.stdio = stdioStringToArray(options.stdio, "ipc"); @@ -758,7 +758,7 @@ function fork(modulePath, args = [], options) { // Use a separate fd=3 for the IPC channel. Inherit stdin, stdout, // and stderr from the parent if silent isn't set. options.stdio = stdioStringToArray(options.silent ? "pipe" : "inherit", "ipc"); - } else if (!ArrayPrototypeIncludes.call(options.stdio, "ipc")) { + } else if (!ArrayPrototypeIncludes.$call(options.stdio, "ipc")) { throw new ERR_CHILD_PROCESS_IPC_REQUIRED("options.stdio"); } @@ -772,7 +772,7 @@ function convertToValidSignal(signal) { if (typeof signal === "number" && getSignalsToNamesMapping()[signal]) return signal; if (typeof signal === "string") { - const signalName = signals[StringPrototypeToUpperCase.call(signal)]; + const signalName = signals[StringPrototypeToUpperCase.$call(signal)]; if (signalName) return signalName; } @@ -801,7 +801,7 @@ function getSignalsToNamesMapping() { function normalizeExecFileArgs(file, args, options, callback) { if (ArrayIsArray(args)) { - args = ArrayPrototypeSlice.call(args); + args = ArrayPrototypeSlice.$call(args); } else if (args != null && typeof args === "object") { callback = options; options = args; @@ -866,7 +866,7 @@ function normalizeSpawnArguments(file, args, options) { if (file.length === 0) throw new ERR_INVALID_ARG_VALUE("file", file, "cannot be empty"); if (ArrayIsArray(args)) { - args = ArrayPrototypeSlice.call(args); + args = ArrayPrototypeSlice.$call(args); } else if (args == null) { args = []; } else if (typeof args !== "object") { @@ -912,7 +912,7 @@ function normalizeSpawnArguments(file, args, options) { // Handle shell if (options.shell) { validateArgumentNullCheck(options.shell, "options.shell"); - const command = ArrayPrototypeJoin.call([file, ...args], " "); + const command = ArrayPrototypeJoin.$call([file, ...args], " "); // TODO: Windows moment // Set the shell, switches, and commands. // if (process.platform === "win32") { @@ -935,9 +935,9 @@ function normalizeSpawnArguments(file, args, options) { // Handle argv0 if (typeof options.argv0 === "string") { - ArrayPrototypeUnshift.call(args, options.argv0); + ArrayPrototypeUnshift.$call(args, options.argv0); } else { - ArrayPrototypeUnshift.call(args, file); + ArrayPrototypeUnshift.$call(args, file); } const env = options.env || process.env; @@ -959,7 +959,7 @@ function checkExecSyncError(ret, args, cmd) { ObjectAssign(err, ret); } else if (ret.status !== 0) { let msg = "Command failed: "; - msg += cmd || ArrayPrototypeJoin.call(args, " "); + msg += cmd || ArrayPrototypeJoin.$call(args, " "); if (ret.stderr && ret.stderr.length > 0) msg += `\n${ret.stderr.toString()}`; err = genericNodeError(msg, ret); } @@ -1019,7 +1019,7 @@ class ChildProcess extends EventEmitter { if (this.spawnfile) err.path = this.spawnfile; - err.spawnargs = ArrayPrototypeSlice.call(this.spawnargs, 1); + err.spawnargs = ArrayPrototypeSlice.$call(this.spawnargs, 1); this.emit("error", err); } else { this.emit("exit", this.exitCode, this.signalCode); @@ -1132,8 +1132,8 @@ class ChildProcess extends EventEmitter { // if (options.envPairs === undefined) options.envPairs = []; // else validateArray(options.envPairs, "options.envPairs"); - // ArrayPrototypePush.call(options.envPairs, `NODE_CHANNEL_FD=${ipcFd}`); - // ArrayPrototypePush.call( + // ArrayPrototypePush.$call(options.envPairs, `NODE_CHANNEL_FD=${ipcFd}`); + // ArrayPrototypePush.$call( // options.envPairs, // `NODE_CHANNEL_SERIALIZATION_MODE=${serialization}` // ); @@ -1174,6 +1174,7 @@ class ChildProcess extends EventEmitter { env: env || process.env, detached: typeof detachedOption !== "undefined" ? !!detachedOption : false, onExit: (handle, exitCode, signalCode, err) => { + $debug("ChildProcess: onExit", exitCode, signalCode, err, this.pid); this.#handle = handle; this.pid = this.#handle.pid; @@ -1189,6 +1190,8 @@ class ChildProcess extends EventEmitter { }); this.pid = this.#handle.pid; + $debug("ChildProcess: spawn", this.pid, spawnargs); + onSpawnNT(this); if (ipc) { @@ -1298,7 +1301,7 @@ function nodeToBun(item) { return item; } else { const result = nodeToBunLookup[item]; - if (result === undefined) throw new Error("Invalid stdio option"); + if (result === undefined) throw new Error(`Invalid stdio option "${item}"`); return result; } } @@ -1430,7 +1433,7 @@ function validateMaxBuffer(maxBuffer) { } function validateArgumentNullCheck(arg, propName) { - if (typeof arg === "string" && StringPrototypeIncludes.call(arg, "\u0000")) { + if (typeof arg === "string" && StringPrototypeIncludes.$call(arg, "\u0000")) { throw new ERR_INVALID_ARG_VALUE(propName, arg, "must be a string without null bytes"); } } @@ -1487,9 +1490,9 @@ const validateAbortSignal = (signal, name) => { /** @type {validateOneOf} */ const validateOneOf = (value, name, oneOf) => { // const validateOneOf = hideStackFrames((value, name, oneOf) => { - if (!ArrayPrototypeIncludes.call(oneOf, value)) { - const allowed = ArrayPrototypeJoin.call( - ArrayPrototypeMap.call(oneOf, v => (typeof v === "string" ? `'${v}'` : String(v))), + if (!ArrayPrototypeIncludes.$call(oneOf, value)) { + const allowed = ArrayPrototypeJoin.$call( + ArrayPrototypeMap.$call(oneOf, v => (typeof v === "string" ? `'${v}'` : String(v))), ", ", ); const reason = "must be one of: " + allowed; @@ -1516,7 +1519,7 @@ const validateObject = (value, name, options = null) => { const nullable = options?.nullable ?? false; if ( (!nullable && value === null) || - (!allowArray && ArrayIsArray.call(value)) || + (!allowArray && ArrayIsArray.$call(value)) || (typeof value !== "object" && (!allowFunction || typeof value !== "function")) ) { throw new ERR_INVALID_ARG_TYPE(name, "object", value); @@ -1562,8 +1565,8 @@ function nullCheck(path, propName, throwError = true) { // We can only perform meaningful checks on strings and Uint8Arrays. if ( (!pathIsString && !pathIsUint8Array) || - (pathIsString && !StringPrototypeIncludes.call(path, "\u0000")) || - (pathIsUint8Array && !Uint8ArrayPrototypeIncludes.call(path, 0)) + (pathIsString && !StringPrototypeIncludes.$call(path, "\u0000")) || + (pathIsUint8Array && !Uint8ArrayPrototypeIncludes.$call(path, 0)) ) { return; } @@ -1698,7 +1701,7 @@ function genericNodeError(message, options) { // typeof value === "string", // "All expected entries have to be of type string" // ); -// if (ArrayPrototypeIncludes.call(kTypes, value)) { +// if (ArrayPrototypeIncludes.$call(kTypes, value)) { // ArrayPrototypePush(types, StringPrototypeToLowerCase(value)); // } else if (RegExpPrototypeExec(classRegExp, value) !== null) { // ArrayPrototypePush(instances, value); @@ -1716,8 +1719,8 @@ function genericNodeError(message, options) { // if (instances.length > 0) { // const pos = ArrayPrototypeIndexOf(types, "object"); // if (pos !== -1) { -// ArrayPrototypeSplice.call(types, pos, 1); -// ArrayPrototypePush.call(instances, "Object"); +// ArrayPrototypeSplice.$call(types, pos, 1); +// ArrayPrototypePush.$call(instances, "Object"); // } // } @@ -1752,7 +1755,7 @@ function genericNodeError(message, options) { // if (other.length > 0) { // if (other.length > 2) { // const last = ArrayPrototypePop(other); -// msg += `one of ${ArrayPrototypeJoin.call(other, ", ")}, or ${last}`; +// msg += `one of ${ArrayPrototypeJoin.$call(other, ", ")}, or ${last}`; // } else if (other.length === 2) { // msg += `one of ${other[0]} or ${other[1]}`; // } else { diff --git a/src/js/node/crypto.js b/src/js/node/crypto.js index a7b628ef8..ae7e24655 100644 --- a/src/js/node/crypto.js +++ b/src/js/node/crypto.js @@ -10,7 +10,40 @@ var Buffer = globalThis.Buffer; const EMPTY_BUFFER = Buffer.alloc(0); const { isAnyArrayBuffer, isArrayBufferView } = require("node:util/types"); +function exportIfKeyObject(key) { + if (key instanceof KeyObject) { + key = key.export(); + } else if (key instanceof CryptoKey) { + key = KeyObject.from(key).export(); + } + return key; +} +function getKeyFrom(key, type) { + if (key instanceof KeyObject) { + key = key.export(); + } else if (key instanceof CryptoKey) { + key = KeyObject.from(key).export(); + } else if (!Buffer.isBuffer(key) && typeof key === "object") { + if ((typeof key.format === "string" || typeof key.passphrase === "string") && typeof key.key !== "undefined") { + key = type === "public" ? _createPublicKey(key).export() : _createPrivateKey(key).export(); + } + } else if (typeof key === "string" && type === "public") { + // make public key from non encrypted private PEM + key.indexOf("PRIVATE KEY-----") !== -1 && (key = _createPublicKey(key).export()); + } + return key; +} function getArrayBufferOrView(buffer, name, encoding) { + if (buffer instanceof KeyObject) { + if (buffer.type !== "secret") { + const error = new TypeError( + `ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Invalid key object type ${key.type}, expected secret`, + ); + error.code = "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE"; + throw error; + } + buffer = buffer.export(); + } if (isAnyArrayBuffer(buffer)) return buffer; if (typeof buffer === "string") { if (encoding === "buffer") encoding = "utf8"; @@ -135,7 +168,7 @@ var require_hash_base = __commonJS({ throw new TypeError(prefix + " must be a string or a buffer"); } function HashBase(blockSize) { - StreamModule.Transform.call(this), + StreamModule.Transform.$call(this), (this._block = Buffer2.allocUnsafe(blockSize)), (this._blockSize = blockSize), (this._blockOffset = 0), @@ -202,7 +235,7 @@ var require_md5 = __commonJS({ Buffer2 = require_safe_buffer().Buffer, ARRAY16 = new Array(16); function MD5() { - HashBase.call(this, 64), + HashBase.$call(this, 64), (this._a = 1732584193), (this._b = 4023233417), (this._c = 2562383102), @@ -350,7 +383,7 @@ var require_ripemd160 = __commonJS({ hl = [0, 1518500249, 1859775393, 2400959708, 2840853838], hr = [1352829926, 1548603684, 1836072691, 2053994217, 0]; function RIPEMD160() { - HashBase.call(this, 64), + HashBase.$call(this, 64), (this._a = 1732584193), (this._b = 4023233417), (this._c = 2562383102), @@ -508,7 +541,7 @@ var require_sha = __commonJS({ K = [1518500249, 1859775393, -1894007588, -899497514], W = new Array(80); function Sha() { - this.init(), (this._w = W), Hash.call(this, 64, 56); + this.init(), (this._w = W), Hash.$call(this, 64, 56); } inherits(Sha, Hash); Sha.prototype.init = function () { @@ -573,7 +606,7 @@ var require_sha1 = __commonJS({ K = [1518500249, 1859775393, -1894007588, -899497514], W = new Array(80); function Sha1() { - this.init(), (this._w = W), Hash.call(this, 64, 56); + this.init(), (this._w = W), Hash.$call(this, 64, 56); } inherits(Sha1, Hash); Sha1.prototype.init = function () { @@ -650,7 +683,7 @@ var require_sha256 = __commonJS({ ], W = new Array(64); function Sha256() { - this.init(), (this._w = W), Hash.call(this, 64, 56); + this.init(), (this._w = W), Hash.$call(this, 64, 56); } inherits(Sha256, Hash); Sha256.prototype.init = function () { @@ -742,7 +775,7 @@ var require_sha224 = __commonJS({ Buffer2 = require_safe_buffer().Buffer, W = new Array(64); function Sha224() { - this.init(), (this._w = W), Hash.call(this, 64, 56); + this.init(), (this._w = W), Hash.$call(this, 64, 56); } inherits(Sha224, Sha256); Sha224.prototype.init = function () { @@ -803,7 +836,7 @@ var require_sha512 = __commonJS({ ], W = new Array(160); function Sha512() { - this.init(), (this._w = W), Hash.call(this, 128, 112); + this.init(), (this._w = W), Hash.$call(this, 128, 112); } inherits(Sha512, Hash); Sha512.prototype.init = function () { @@ -985,7 +1018,7 @@ var require_sha384 = __commonJS({ Buffer2 = require_safe_buffer().Buffer, W = new Array(160); function Sha384() { - this.init(), (this._w = W), Hash.call(this, 128, 112); + this.init(), (this._w = W), Hash.$call(this, 128, 112); } inherits(Sha384, SHA512); Sha384.prototype.init = function () { @@ -1052,15 +1085,17 @@ var require_cipher_base = __commonJS({ var Buffer2 = require_safe_buffer().Buffer, inherits = require_inherits_browser(); function CipherBase(hashMode) { - StreamModule.Transform.call(this), + StreamModule.Transform.$call(this), (this.hashMode = typeof hashMode == "string"), this.hashMode ? (this[hashMode] = this._finalOrDigest) : (this.final = this._finalOrDigest), this._final && ((this.__final = this._final), (this._final = null)), (this._decoder = null), (this._encoding = null); + this._finalized = !1; } inherits(CipherBase, StreamModule.Transform); CipherBase.prototype.update = function (data, inputEnc, outputEnc) { + if (outputEnc === "buffer") outputEnc = undefined; typeof data == "string" && (data = Buffer2.from(data, inputEnc)); var outData = this._update(data); return this.hashMode ? this : (outputEnc && (outData = this._toString(outData, outputEnc)), outData); @@ -1095,6 +1130,13 @@ var require_cipher_base = __commonJS({ done(err); }; CipherBase.prototype._finalOrDigest = function (outputEnc) { + if (outputEnc === "buffer") outputEnc = undefined; + if (this._finalized) { + if (!this._encoding) return Buffer2.alloc(0); + return ""; + } + + this._finalized = !0; var outData = this.__final() || Buffer2.alloc(0); return outputEnc && (outData = this._toString(outData, outputEnc, !0)), outData; }; @@ -1247,7 +1289,7 @@ var require_browser2 = __commonJS({ Object.defineProperty(LazyHash.prototype, method, { get() { Object.setPrototypeOf(this, lazyHashFullInitProto); - StreamModule.Transform.call(this, this._options); + StreamModule.Transform.$call(this, this._options); return this[method]; }, enumerable: false, @@ -1274,7 +1316,9 @@ var require_legacy = __commonJS({ ZEROS = Buffer2.alloc(128), blocksize = 64; function Hmac(alg, key) { - Base.call(this, "digest"), + key = exportIfKeyObject(key); + + Base.$call(this, "digest"), typeof key == "string" && (key = Buffer2.from(key)), (this._alg = alg), (this._key = key), @@ -1327,7 +1371,9 @@ var require_browser3 = __commonJS({ var sha = require_sha2(); var ZEROS = Buffer2.alloc(128); function Hmac(alg, key) { - Base.call(this, "digest"), typeof key == "string" && (key = Buffer2.from(key)); + key = exportIfKeyObject(key); + + Base.$call(this, "digest"), typeof key == "string" && (key = Buffer2.from(key)); var blocksize = alg === "sha512" || alg === "sha384" ? 128 : 64; if (((this._alg = alg), (this._key = key), key.length > blocksize)) { var hash = alg === "rmd160" ? new RIPEMD160() : sha(alg); @@ -1350,9 +1396,11 @@ var require_browser3 = __commonJS({ Hmac.prototype._final = function () { var h = this._hash.digest(), hash = this._alg === "rmd160" ? new RIPEMD160() : sha(this._alg); + return hash.update(this._opad).update(h).digest(); }; module.exports = function (alg, key) { + key = exportIfKeyObject(key); return ( (alg = alg.toLowerCase()), alg === "rmd160" || alg === "ripemd160" @@ -1419,23 +1467,28 @@ var require_algorithms = __commonJS({ hash: "sha1", id: "", }, + sha1: { + sign: "ecdsa/rsa", + hash: "sha1", + id: "", + }, sha256: { - sign: "ecdsa", + sign: "ecdsa/rsa", hash: "sha256", id: "", }, sha224: { - sign: "ecdsa", + sign: "ecdsa/rsa", hash: "sha224", id: "", }, sha384: { - sign: "ecdsa", + sign: "ecdsa/rsa", hash: "sha384", id: "", }, sha512: { - sign: "ecdsa", + sign: "ecdsa/rsa", hash: "sha512", id: "", }, @@ -1593,6 +1646,7 @@ var require_sync_browser = __commonJS({ ripemd160: 20, }; function Hmac(alg, key, saltLen) { + key = exportIfKeyObject(key); var hash = getDigest(alg), blocksize = alg === "sha512" || alg === "sha384" ? 128 : 64; key.length > blocksize @@ -2007,7 +2061,7 @@ var require_des = __commonJS({ (this.tmp = new Array(2)), (this.keys = null); } function DES(options) { - Cipher.call(this, options); + Cipher.$call(this, options); var state = new DESState(); (this._desState = state), this.deriveKeys(state, options.key); } @@ -2089,7 +2143,7 @@ var require_cbc = __commonJS({ } function instantiate(Base) { function CBC(options) { - Base.call(this, options), this._cbcInit(); + Base.$call(this, options), this._cbcInit(); } inherits(CBC, Base); for (var keys = Object.keys(proto), i = 0; i < keys.length; i++) { @@ -2114,10 +2168,10 @@ var require_cbc = __commonJS({ iv = state.iv; if (this.type === "encrypt") { for (var i = 0; i < this.blockSize; i++) iv[i] ^= inp[inOff + i]; - superProto._update.call(this, iv, 0, out, outOff); + superProto._update.$call(this, iv, 0, out, outOff); for (var i = 0; i < this.blockSize; i++) iv[i] = out[outOff + i]; } else { - superProto._update.call(this, inp, inOff, out, outOff); + superProto._update.$call(this, inp, inOff, out, outOff); for (var i = 0; i < this.blockSize; i++) out[outOff + i] ^= iv[i]; for (var i = 0; i < this.blockSize; i++) iv[i] = inp[inOff + i]; } @@ -2151,7 +2205,7 @@ var require_ede = __commonJS({ ]); } function EDE(options) { - Cipher.call(this, options); + Cipher.$call(this, options); var state = new EDEState(this.type, this.options.key); this._edeState = state; } @@ -2203,7 +2257,7 @@ var require_browserify_des = __commonJS({ module.exports = DES; inherits(DES, CipherBase); function DES(opts) { - CipherBase.call(this); + CipherBase.$call(this); var modeName = opts.mode.toLowerCase(), mode = modes[modeName], type; @@ -2628,6 +2682,11 @@ var require_aes = __commonJS({ "node_modules/browserify-aes/aes.js"(exports, module) { var Buffer2 = require_safe_buffer().Buffer; function asUInt32Array(buf) { + if (buf instanceof KeyObject) { + buf = buf.export(); + } else if (buf instanceof CryptoKey) { + buf = KeyObject.from(buf).export(); + } Buffer2.isBuffer(buf) || (buf = Buffer2.from(buf)); for (var len = (buf.length / 4) | 0, out = new Array(len), i = 0; i < len; i++) out[i] = buf.readUInt32BE(i * 4); return out; @@ -2919,7 +2978,7 @@ var require_authCipher = __commonJS({ return incr32(out), out; } function StreamCipher(mode, key, iv, decrypt) { - Transform.call(this); + Transform.$call(this); var h = Buffer2.alloc(4, 0); this._cipher = new aes.AES(key); var ck = this._cipher.encryptBlock(h); @@ -2977,7 +3036,7 @@ var require_streamCipher = __commonJS({ Transform = require_cipher_base(), inherits = require_inherits_browser(); function StreamCipher(mode, key, iv, decrypt) { - Transform.call(this), + Transform.$call(this), (this._cipher = new aes.AES(key)), (this._prev = Buffer2.from(iv)), (this._cache = Buffer2.allocUnsafe(0)), @@ -3043,7 +3102,7 @@ var require_encrypter = __commonJS({ ebtk = require_evp_bytestokey(), inherits = require_inherits_browser(); function Cipher(mode, key, iv) { - Transform.call(this), + Transform.$call(this), (this._cache = new Splitter()), (this._cipher = new aes.AES(key)), (this._prev = Buffer2.from(iv)), @@ -3133,7 +3192,7 @@ var require_decrypter = __commonJS({ ebtk = require_evp_bytestokey(), inherits = require_inherits_browser(); function Decipher(mode, key, iv) { - Transform.call(this), + Transform.$call(this), (this._cache = new Splitter()), (this._last = void 0), (this._cipher = new aes.AES(key)), @@ -5072,7 +5131,7 @@ var require_bn = __commonJS({ return num.imul(this.k); }); function K256() { - MPrime.call(this, "k256", "ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f"); + MPrime.$call(this, "k256", "ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f"); } inherits(K256, MPrime), (K256.prototype.split = function (input, output) { @@ -5102,15 +5161,15 @@ var require_bn = __commonJS({ ); }); function P224() { - MPrime.call(this, "p224", "ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001"); + MPrime.$call(this, "p224", "ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001"); } inherits(P224, MPrime); function P192() { - MPrime.call(this, "p192", "ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff"); + MPrime.$call(this, "p192", "ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff"); } inherits(P192, MPrime); function P25519() { - MPrime.call(this, "25519", "7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed"); + MPrime.$call(this, "25519", "7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed"); } inherits(P25519, MPrime), (P25519.prototype.imulK = function (num) { @@ -5256,7 +5315,7 @@ var require_bn = __commonJS({ return new Mont(num); }); function Mont(m) { - Red.call(this, m), + Red.$call(this, m), (this.shift = this.m.bitLength()), this.shift % 26 !== 0 && (this.shift += 26 - (this.shift % 26)), (this.r = new BN(1).iushln(this.shift)), @@ -5849,11 +5908,16 @@ var require_utils3 = __commonJS({ function cachedProperty(obj, name, computer) { var key = "_" + name; obj.prototype[name] = function () { - return this[key] !== void 0 ? this[key] : (this[key] = computer.call(this)); + return this[key] !== void 0 ? this[key] : (this[key] = computer.$call(this)); }; } utils.cachedProperty = cachedProperty; function parseBytes(bytes) { + if (bytes instanceof KeyObject) { + bytes = bytes.export(); + } else if (bytes instanceof CryptoKey) { + bytes = KeyObject.from(bytes).export(); + } return typeof bytes == "string" ? utils.toArray(bytes, "hex") : bytes; } utils.parseBytes = parseBytes; @@ -6104,7 +6168,7 @@ var require_short = __commonJS({ Base = require_base(), assert = utils.assert; function ShortCurve(conf) { - Base.call(this, "short", conf), + Base.$call(this, "short", conf), (this.a = new BN(conf.a, 16).toRed(this.red)), (this.b = new BN(conf.b, 16).toRed(this.red)), (this.tinv = this.two.redInvm()), @@ -6247,7 +6311,7 @@ var require_short = __commonJS({ return res; }; function Point(curve, x, y, isRed) { - Base.BasePoint.call(this, curve, "affine"), + Base.BasePoint.$call(this, curve, "affine"), x === null && y === null ? ((this.x = null), (this.y = null), (this.inf = !0)) : ((this.x = new BN(x, 16)), @@ -6425,7 +6489,7 @@ var require_short = __commonJS({ return res; }; function JPoint(curve, x, y, z) { - Base.BasePoint.call(this, curve, "jacobian"), + Base.BasePoint.$call(this, curve, "jacobian"), x === null && y === null && z === null ? ((this.x = this.curve.one), (this.y = this.curve.one), (this.z = new BN(0))) : ((this.x = new BN(x, 16)), (this.y = new BN(y, 16)), (this.z = new BN(z, 16))), @@ -6688,7 +6752,7 @@ var require_mont = __commonJS({ Base = require_base(), utils = require_utils3(); function MontCurve(conf) { - Base.call(this, "mont", conf), + Base.$call(this, "mont", conf), (this.a = new BN(conf.a, 16).toRed(this.red)), (this.b = new BN(conf.b, 16).toRed(this.red)), (this.i4 = new BN(4).toRed(this.red).redInvm()), @@ -6705,7 +6769,7 @@ var require_mont = __commonJS({ return y.redSqr().cmp(rhs) === 0; }; function Point(curve, x, z) { - Base.BasePoint.call(this, curve, "projective"), + Base.BasePoint.$call(this, curve, "projective"), x === null && z === null ? ((this.x = this.curve.one), (this.z = this.curve.zero)) : ((this.x = new BN(x, 16)), @@ -6804,7 +6868,7 @@ var require_edwards = __commonJS({ (this.twisted = (conf.a | 0) !== 1), (this.mOneA = this.twisted && (conf.a | 0) === -1), (this.extended = this.mOneA), - Base.call(this, "edwards", conf), + Base.$call(this, "edwards", conf), (this.a = new BN(conf.a, 16).umod(this.red.m)), (this.a = this.a.toRed(this.red)), (this.c = new BN(conf.c, 16).toRed(this.red)), @@ -6860,7 +6924,7 @@ var require_edwards = __commonJS({ return lhs.cmp(rhs) === 0; }; function Point(curve, x, y, z, t) { - Base.BasePoint.call(this, curve, "projective"), + Base.BasePoint.$call(this, curve, "projective"), x === null && y === null && z === null ? ((this.x = this.curve.zero), (this.y = this.curve.one), @@ -7398,7 +7462,7 @@ var require__ = __commonJS({ sha1_K = [1518500249, 1859775393, 2400959708, 3395469782]; function SHA1() { if (!(this instanceof SHA1)) return new SHA1(); - BlockHash.call(this), + BlockHash.$call(this), (this.h = [1732584193, 4023233417, 2562383102, 271733878, 3285377520]), (this.W = new Array(80)); } @@ -7463,7 +7527,7 @@ var require__2 = __commonJS({ ]; function SHA256() { if (!(this instanceof SHA256)) return new SHA256(); - BlockHash.call(this), + BlockHash.$call(this), (this.h = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]), (this.k = sha256_K), (this.W = new Array(64)); @@ -7513,7 +7577,7 @@ var require__3 = __commonJS({ SHA256 = require__2(); function SHA224() { if (!(this instanceof SHA224)) return new SHA224(); - SHA256.call(this), + SHA256.$call(this), (this.h = [3238371032, 914150663, 812702999, 4144912697, 4290775857, 1750603025, 1694076839, 3204075428]); } utils.inherits(SHA224, SHA256); @@ -7569,7 +7633,7 @@ var require__4 = __commonJS({ ]; function SHA512() { if (!(this instanceof SHA512)) return new SHA512(); - BlockHash.call(this), + BlockHash.$call(this), (this.h = [ 1779033703, 4089235720, 3144134277, 2227873595, 1013904242, 4271175723, 2773480762, 1595750129, 1359893119, 2917565137, 2600822924, 725511199, 528734635, 4215389547, 1541459225, 327033209, @@ -7749,7 +7813,7 @@ var require__5 = __commonJS({ SHA512 = require__4(); function SHA384() { if (!(this instanceof SHA384)) return new SHA384(); - SHA512.call(this), + SHA512.$call(this), (this.h = [ 3418070365, 3238371032, 1654270250, 914150663, 2438529370, 812702999, 355462360, 4144912697, 1731405415, 4290775857, 2394180231, 1750603025, 3675008525, 1694076839, 1203062813, 3204075428, @@ -7792,7 +7856,7 @@ var require_ripemd = __commonJS({ BlockHash = common.BlockHash; function RIPEMD160() { if (!(this instanceof RIPEMD160)) return new RIPEMD160(); - BlockHash.call(this), + BlockHash.$call(this), (this.h = [1732584193, 4023233417, 2562383102, 271733878, 3285377520]), (this.endian = "little"); } @@ -7888,6 +7952,8 @@ var require_hmac = __commonJS({ var utils = require_utils4(), assert = require_minimalistic_assert(); function Hmac(hash, key, enc) { + key = exportIfKeyObject(key); + if (!(this instanceof Hmac)) return new Hmac(hash, key, enc); (this.Hash = hash), (this.blockSize = hash.blockSize / 8), @@ -9132,7 +9198,7 @@ var require_ec = __commonJS({ function EC(options) { if (!(this instanceof EC)) return new EC(options); typeof options == "string" && - (assert(Object.prototype.hasOwnProperty.call(curves, options), "Unknown curve " + options), + (assert(Object.prototype.hasOwnProperty.$call(curves, options), "Unknown curve " + options), (options = curves[options])), options instanceof curves.PresetCurve && (options = { curve: options }), (this.curve = options.curve.curve), @@ -9633,7 +9699,7 @@ var require_buffer = __commonJS({ Reporter = require_reporter().Reporter, Buffer2 = require_safer().Buffer; function DecoderBuffer(base, options) { - if ((Reporter.call(this, options), !Buffer2.isBuffer(base))) { + if ((Reporter.$call(this, options), !Buffer2.isBuffer(base))) { this.error("Input not Buffer"); return; } @@ -9659,7 +9725,7 @@ var require_buffer = __commonJS({ DecoderBuffer.prototype.save = function () { return { offset: this.offset, - reporter: Reporter.prototype.save.call(this), + reporter: Reporter.prototype.save.$call(this), }; }; DecoderBuffer.prototype.restore = function (save) { @@ -9668,7 +9734,7 @@ var require_buffer = __commonJS({ (res.offset = save.offset), (res.length = this.offset), (this.offset = save.offset), - Reporter.prototype.restore.call(this, save.reporter), + Reporter.prototype.restore.$call(this, save.reporter), res ); }; @@ -9858,14 +9924,14 @@ var require_node = __commonJS({ methods.forEach(function (method) { this[method] = function () { let clone = new this.constructor(this); - return state.children.push(clone), clone[method].apply(clone, arguments); + return state.children.push(clone), clone[method].$apply(clone, arguments); }; }, this); }; Node.prototype._init = function (body) { let state = this._baseState; assert(state.parent === null), - body.call(this), + body.$call(this), (state.children = state.children.filter(function (child) { return child._baseState.parent === this; }, this)), @@ -9910,7 +9976,7 @@ var require_node = __commonJS({ tags.forEach(function (tag) { Node.prototype[tag] = function () { let state = this._baseState, - args = Array.prototype.slice.call(arguments); + args = Array.prototype.slice.$call(arguments); return assert(state.tag === null), (state.tag = tag), this._useArgs(args), this; }; }); @@ -9937,7 +10003,7 @@ var require_node = __commonJS({ }; Node.prototype.obj = function () { let state = this._baseState, - args = Array.prototype.slice.call(arguments); + args = Array.prototype.slice.$call(arguments); return (state.obj = !0), args.length !== 0 && this._useArgs(args), this; }; Node.prototype.key = function (newKey) { @@ -10264,7 +10330,7 @@ var require_der2 = __commonJS({ return this.tree._encode(data, reporter).join(); }; function DERNode(parent) { - Node.call(this, "der", parent); + Node.$call(this, "der", parent); } inherits(DERNode, Node); DERNode.prototype._encodeComposite = function (tag, primitive, cls, content) { @@ -10431,12 +10497,12 @@ var require_pem = __commonJS({ var inherits = require_inherits_browser(), DEREncoder = require_der2(); function PEMEncoder(entity) { - DEREncoder.call(this, entity), (this.enc = "pem"); + DEREncoder.$call(this, entity), (this.enc = "pem"); } inherits(PEMEncoder, DEREncoder); module.exports = PEMEncoder; PEMEncoder.prototype.encode = function (data, options) { - let p = DEREncoder.prototype.encode.call(this, data).toString("base64"), + let p = DEREncoder.prototype.encode.$call(this, data).toString("base64"), out = ["-----BEGIN " + options.label + "-----"]; for (let i = 0; i < p.length; i += 64) out.push(p.slice(i, i + 64)); return ( @@ -10483,7 +10549,7 @@ var require_der3 = __commonJS({ ); }; function DERNode(parent) { - Node.call(this, "der", parent); + Node.$call(this, "der", parent); } inherits(DERNode, Node); DERNode.prototype._peekTag = function (buffer, tag, any) { @@ -10671,7 +10737,7 @@ var require_pem2 = __commonJS({ Buffer2 = require_safer().Buffer, DERDecoder = require_der3(); function PEMDecoder(entity) { - DERDecoder.call(this, entity), (this.enc = "pem"); + DERDecoder.$call(this, entity), (this.enc = "pem"); } inherits(PEMDecoder, DERDecoder); module.exports = PEMDecoder; @@ -10697,7 +10763,7 @@ var require_pem2 = __commonJS({ let base64 = lines.slice(start + 1, end).join(""); base64.replace(/[^a-z0-9+/=]+/gi, ""); let input = Buffer2.from(base64, "base64"); - return DERDecoder.prototype.decode.call(this, input, options); + return DERDecoder.prototype.decode.$call(this, input, options); }; }, }); @@ -10735,7 +10801,7 @@ var require_api = __commonJS({ return ( inherits(Generated, Base), (Generated.prototype._initNamed = function (entity, name2) { - Base.call(this, entity, name2); + Base.$call(this, entity, name2); }), new Generated(this) ); @@ -11042,8 +11108,67 @@ var require_parse_asn1 = __commonJS({ module.exports = parseKeys; function parseKeys(buffer) { var password; - typeof buffer == "object" && !Buffer2.isBuffer(buffer) && ((password = buffer.passphrase), (buffer = buffer.key)), - typeof buffer == "string" && (buffer = Buffer2.from(buffer)); + if (buffer instanceof KeyObject) { + buffer = buffer.export(); + } else if (buffer instanceof CryptoKey) { + buffer = KeyObject.from(buffer).export(); + } else { + if (typeof buffer == "object" && !Buffer2.isBuffer(buffer)) { + password = buffer.passphrase; + buffer = buffer.key; + + if (buffer instanceof KeyObject) { + var options; + switch (buffer.type) { + case "secret": + options = { + format: "buffer", + }; + break; + case "public": + options = { + format: "pem", + type: "spki", + passphrase: password, + }; + break; + case "private": + options = { + format: "pem", + type: "pkcs8", + passphrase: password, + }; + break; + } + buffer = buffer.export(options); + } else if (buffer instanceof CryptoKey) { + var options; + switch (buffer.type) { + case "secret": + options = { + format: "buffer", + }; + break; + case "public": + options = { + format: "pem", + type: "spki", + passphrase: password, + }; + break; + case "private": + options = { + format: "pem", + type: "pkcs8", + passphrase: password, + }; + break; + } + buffer = KeyObject.from(buffer).export(options); + } + } + } + typeof buffer == "string" && (buffer = Buffer2.from(buffer)); var stripped = fixProc(buffer, password), type = stripped.tag, data = stripped.data, @@ -11165,7 +11290,8 @@ var require_sign = __commonJS({ parseKeys = require_parse_asn1(), curves = require_curves2(); function sign(hash, key, hashType, signType, tag) { - var priv = parseKeys(key); + var priv = parseKeys(getKeyFrom(key, "private")); + if (priv.curve) { if (signType !== "ecdsa" && signType !== "ecdsa/rsa") throw new Error("wrong private key type"); return ecSign(hash, priv); @@ -11291,7 +11417,7 @@ var require_verify = __commonJS({ parseKeys = require_parse_asn1(), curves = require_curves2(); function verify(sig, hash, key, signType, tag) { - var pub = parseKeys(key); + var pub = parseKeys(getKeyFrom(key, "public")); if (pub.type === "ec") { if (signType !== "ecdsa" && signType !== "ecdsa/rsa") throw new Error("wrong public key type"); return ecVerify(sig, hash, pub); @@ -11362,7 +11488,10 @@ var require_browser8 = __commonJS({ (algorithms[key].id = Buffer2.from(algorithms[key].id, "hex")), (algorithms[key.toLowerCase()] = algorithms[key]); }); function Sign(algorithm) { - StreamModule.Writable.call(this); + if (typeof algorithm === "string") { + algorithm = algorithm.toLowerCase(); + } + StreamModule.Writable.$call(this); var data = algorithms[algorithm]; if (!data) throw new Error("Unknown message digest"); (this._hashType = data.hash), @@ -11384,7 +11513,10 @@ var require_browser8 = __commonJS({ return enc ? sig.toString(enc) : sig; }; function Verify(algorithm) { - StreamModule.Writable.call(this); + StreamModule.Writable.$call(this); + if (typeof algorithm === "string") { + algorithm = algorithm.toLowerCase(); + } var data = algorithms[algorithm]; if (!data) throw new Error("Unknown message digest"); (this._hash = createHash(data.hash)), (this._tag = data.id), (this._signType = data.sign); @@ -11682,13 +11814,19 @@ var require_privateDecrypt = __commonJS({ // node_modules/public-encrypt/browser.js var require_browser10 = __commonJS({ "node_modules/public-encrypt/browser.js"(exports) { - exports.publicEncrypt = require_publicEncrypt(); - exports.privateDecrypt = require_privateDecrypt(); + var publicEncrypt = require_publicEncrypt(); + exports.publicEncrypt = function (key, buf, options) { + return publicEncrypt(getKeyFrom(key, "public"), buf, options); + }; + var privateDecrypt = require_privateDecrypt(); + exports.privateDecrypt = function (key, buf, options) { + return privateDecrypt(getKeyFrom(key, "private"), buf, options); + }; exports.privateEncrypt = function (key, buf) { - return exports.publicEncrypt(key, buf, !0); + return publicEncrypt(getKeyFrom(key, "private"), buf, !0); }; exports.publicDecrypt = function (key, buf) { - return exports.privateDecrypt(key, buf, !0); + return privateDecrypt(getKeyFrom(key, "public"), buf, !0); }; }, }); @@ -11888,6 +12026,299 @@ const harcoded_curves = [ function getCurves() { return harcoded_curves; } +const { + symmetricKeySize, + asymmetricKeyDetails, + asymmetricKeyType, + equals, + exports, + createSecretKey, + createPublicKey, + createPrivateKey, + generateKeySync, + generateKeyPairSync, +} = $lazy("internal/crypto"); + +const kCryptoKey = Symbol.for("::bunKeyObjectCryptoKey::"); +class KeyObject { + [kCryptoKey]; + constructor(key) { + // TODO: check why this is fails + // if(!(key instanceof CryptoKey)) { + // throw new TypeError("The \"key\" argument must be an instance of CryptoKey."); + // } + if (typeof key !== "object") { + throw new TypeError('The "key" argument must be an instance of CryptoKey.'); + } + this[kCryptoKey] = key; + } + toString() { + return "[object KeyObject]"; + } + + static from(key) { + if (key instanceof KeyObject) { + key = key[kCryptoKey]; + } + return new KeyObject(key); + } + + get asymmetricKeyDetails() { + return asymmetricKeyDetails(this[kCryptoKey]); + } + + get symmetricKeySize() { + return symmetricKeySize(this[kCryptoKey]); + } + + get asymmetricKeyType() { + return asymmetricKeyType(this[kCryptoKey]); + } + + ["export"](options) { + switch (arguments.length) { + case 0: + switch (this.type) { + case "secret": + options = { + format: "buffer", + }; + break; + case "public": + options = { + format: "pem", + type: "spki", + }; + break; + case "private": + options = { + format: "pem", + type: "pkcs8", + }; + break; + } + break; + case 1: + if (typeof options === "object" && !options.format) { + switch (this.type) { + case "secret": + options.format = "buffer"; + break; + default: + options.format = "pem"; + break; + } + } + } + return exports(this[kCryptoKey], options); + } + + equals(otherKey) { + if (!(otherKey instanceof KeyObject)) { + throw new TypeError("otherKey must be a KeyObject"); + } + return equals(this[kCryptoKey], otherKey[kCryptoKey]); + } + + get type() { + return this[kCryptoKey].type; + } +} + +crypto_exports.generateKeySync = function (algorithm, options) { + return KeyObject.from(generateKeySync(algorithm, options?.length)); +}; + +crypto_exports.generateKey = function (algorithm, options, callback) { + try { + const key = KeyObject.from(generateKeySync(algorithm, options?.length)); + typeof callback === "function" && callback(null, KeyObject.from(key)); + } catch (err) { + typeof callback === "function" && callback(err); + } +}; + +function _generateKeyPairSync(algorithm, options) { + const result = generateKeyPairSync(algorithm, options); + if (result) { + const publicKeyEncoding = options?.publicKeyEncoding; + const privateKeyEncoding = options?.privateKeyEncoding; + result.publicKey = publicKeyEncoding + ? KeyObject.from(result.publicKey).export(publicKeyEncoding) + : KeyObject.from(result.publicKey); + result.privateKey = privateKeyEncoding + ? KeyObject.from(result.privateKey).export(privateKeyEncoding) + : KeyObject.from(result.privateKey); + } + return result; +} +crypto_exports.generateKeyPairSync = _generateKeyPairSync; + +crypto_exports.generateKeyPair = function (algorithm, options, callback) { + try { + const result = _generateKeyPairSync(algorithm, options); + typeof callback === "function" && callback(null, result.publicKey, result.privateKey); + } catch (err) { + typeof callback === "function" && callback(err); + } +}; + +crypto_exports.createSecretKey = function (key, encoding) { + if (key instanceof KeyObject || key instanceof CryptoKey) { + if (key.type !== "secret") { + const error = new TypeError( + `ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Invalid key object type ${key.type}, expected secret`, + ); + error.code = "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE"; + throw error; + } + return KeyObject.from(key); + } + + const buffer = getArrayBufferOrView(key, encoding || "utf8"); + return KeyObject.from(createSecretKey(buffer)); +}; + +function _createPrivateKey(key) { + if (typeof key === "string") { + key = Buffer.from(key, "utf8"); + return KeyObject.from(createPrivateKey({ key, format: "pem" })); + } else if (isAnyArrayBuffer(key) || isArrayBufferView(key)) { + return KeyObject.from(createPrivateKey({ key, format: "pem" })); + } else if (typeof key === "object") { + if (key instanceof KeyObject || key instanceof CryptoKey) { + const error = new TypeError(`ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Invalid key object type ${key.type}`); + error.code = "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE"; + throw error; + } else { + let actual_key = key.key; + if (typeof actual_key === "string") { + actual_key = Buffer.from(actual_key, key.encoding || "utf8"); + key.key = actual_key; + } else if (actual_key instanceof KeyObject || actual_key instanceof CryptoKey) { + const error = new TypeError(`ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Invalid key object type ${key.type}`); + error.code = "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE"; + throw error; + } + if (!isAnyArrayBuffer(actual_key) && !isArrayBufferView(actual_key) && typeof actual_key !== "object") { + var error = new TypeError( + `ERR_INVALID_ARG_TYPE: The "key" argument must be of type string or an instance of ArrayBuffer, Buffer, TypedArray, DataView or object. Received ` + + actual_key, + ); + error.code = "ERR_INVALID_ARG_TYPE"; + throw error; + } + if (!key.format) { + key.format = "pem"; + } + return KeyObject.from(createPrivateKey(key)); + } + } else { + var error = new TypeError( + `ERR_INVALID_ARG_TYPE: The "key" argument must be of type string or an instance of ArrayBuffer, Buffer, TypedArray, DataView or object. Received ` + + key, + ); + error.code = "ERR_INVALID_ARG_TYPE"; + throw error; + } +} +crypto_exports.createPrivateKey = _createPrivateKey; + +function _createPublicKey(key) { + if (typeof key === "string") { + key = Buffer.from(key, "utf8"); + return KeyObject.from(createPublicKey({ key, format: "pem" })); + } else if (isAnyArrayBuffer(key) || isArrayBufferView(key)) { + return KeyObject.from(createPublicKey({ key, format: "pem" })); + } else if (typeof key === "object") { + if (key instanceof KeyObject || key instanceof CryptoKey) { + if (key.type === "private") { + return KeyObject.from(createPublicKey({ key: key[kCryptoKey] || key, format: "" })); + } + const error = new TypeError( + `ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Invalid key object type ${key.type}, expected private`, + ); + error.code = "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE"; + throw error; + } else { + // must be an encrypted private key (this option is not documented at all) + if (key.passphrase) { + //TODO: handle encrypted keys in one native call + let actual_key = key.key; + if (typeof actual_key === "string") { + actual_key = Buffer.from(actual_key, key.encoding || "utf8"); + } + return KeyObject.from( + createPublicKey({ + key: createPrivateKey({ key: actual_key, format: key.format, passphrase: key.passphrase }), + format: "", + }), + ); + } + let actual_key = key.key; + if (typeof actual_key === "string") { + actual_key = Buffer.from(actual_key, key.encoding || "utf8"); + key.key = actual_key; + } else if (actual_key instanceof KeyObject || actual_key instanceof CryptoKey) { + if (actual_key.type === "private") { + return KeyObject.from(createPublicKey({ key: actual_key[kCryptoKey] || actual_key, format: "" })); + } + const error = new TypeError( + `ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Invalid key object type ${actual_key.type}, expected private`, + ); + error.code = "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE"; + throw error; + } + if (!isAnyArrayBuffer(actual_key) && !isArrayBufferView(actual_key) && typeof actual_key !== "object") { + var error = new TypeError( + `ERR_INVALID_ARG_TYPE: The "key" argument must be of type string or an instance of ArrayBuffer, Buffer, TypedArray, DataView or object. Received ` + + key, + ); + error.code = "ERR_INVALID_ARG_TYPE"; + throw error; + } + if (!key.format) { + key.format = "pem"; + } + return KeyObject.from(createPublicKey(key)); + } + } else { + var error = new TypeError( + `ERR_INVALID_ARG_TYPE: The "key" argument must be of type string or an instance of ArrayBuffer, Buffer, TypedArray, DataView or object. Received ` + + key, + ); + error.code = "ERR_INVALID_ARG_TYPE"; + throw error; + } +} +crypto_exports.createPublicKey = _createPublicKey; +crypto_exports.KeyObject = KeyObject; +const _createSign = crypto_exports.createSign; +crypto_exports.sign = function (algorithm, data, key, encoding, callback) { + if (typeof callback === "function") { + try { + const result = _createSign(algorithm).update(data, encoding).sign(key, encoding); + callback(null, result); + } catch (err) { + callback(err); + } + } else { + return _createSign(algorithm).update(data, encoding).sign(key, encoding); + } +}; +const _createVerify = crypto_exports.createVerify; +crypto_exports.verify = function (algorithm, data, key, signature, callback) { + if (typeof callback === "function") { + try { + const result = _createVerify(algorithm).update(data).verify(key, signature); + callback(null, result); + } catch (err) { + callback(err); + } + } else { + return _createVerify(algorithm).update(data).verify(key, signature); + } +}; var webcrypto = crypto; __export(crypto_exports, { diff --git a/src/js/node/diagnostics_channel.js b/src/js/node/diagnostics_channel.js index 664c80693..5a9ee620b 100644 --- a/src/js/node/diagnostics_channel.js +++ b/src/js/node/diagnostics_channel.js @@ -10,7 +10,7 @@ const ArrayPrototypeSplice = (array, start, deleteCount) => array.splice(start, const ObjectGetPrototypeOf = Object.getPrototypeOf; const ObjectSetPrototypeOf = Object.setPrototypeOf; const SymbolHasInstance = Symbol.hasInstance; -const ReflectApply = Reflect.apply; +const ReflectApply = $getByIdDirect(Reflect, "apply"); const PromiseResolve = Promise.resolve; const PromiseReject = Promise.reject; const PromisePrototypeThen = (promise, onFulfilled, onRejected) => promise.then(onFulfilled, onRejected); diff --git a/src/js/node/dns.js b/src/js/node/dns.js index a6de07351..e82e6a4b5 100644 --- a/src/js/node/dns.js +++ b/src/js/node/dns.js @@ -1,5 +1,5 @@ // Hardcoded module "node:dns" -// only resolve4, resolve, lookup, resolve6 and resolveSrv are implemented. +// only resolve4, resolve, lookup, resolve6, resolveSrv, and reverse are implemented. const dns = Bun.dns; function getServers() { @@ -19,6 +19,16 @@ function lookup(domain, options, callback) { options = { family: options }; } + if (domain !== domain || (typeof domain !== "number" && !domain)) { + console.warn( + `DeprecationWarning: The provided hostname "${String( + domain, + )}" is not a valid hostname, and is supported in the dns module solely for compatibility.`, + ); + callback(null, null, 4); + return; + } + dns.lookup(domain, options).then( res => { res.sort((a, b) => a.family - b.family); @@ -176,7 +186,14 @@ function lookupService(address, port, callback) { throw new TypeError("callback must be a function"); } - callback(null, address, port); + dns.lookupService(address, port, callback).then( + results => { + callback(null, ...results); + }, + error => { + callback(error); + }, + ); } function reverse(ip, callback) { @@ -517,7 +534,7 @@ const promises = { }, lookupService(address, port) { - return Promise.resolve([]); + return dns.lookupService(address, port); }, resolve(hostname, rrtype) { diff --git a/src/js/node/domain.ts b/src/js/node/domain.ts index b03367ff4..7bed189e5 100644 --- a/src/js/node/domain.ts +++ b/src/js/node/domain.ts @@ -18,9 +18,9 @@ domain.createDomain = domain.create = function () { }; d.bind = function (fn) { return function () { - var args = Array.prototype.slice.call(arguments); + var args = Array.prototype.slice.$call(arguments); try { - fn.apply(null, args); + fn.$apply(null, args); } catch (err) { emitError(err); } @@ -31,9 +31,9 @@ domain.createDomain = domain.create = function () { if (err) { emitError(err); } else { - var args = Array.prototype.slice.call(arguments, 1); + var args = Array.prototype.slice.$call(arguments, 1); try { - fn.apply(null, args); + fn.$apply(null, args); } catch (err) { emitError(err); } diff --git a/src/js/node/events.js b/src/js/node/events.js index bd79dd3ae..0c7434518 100644 --- a/src/js/node/events.js +++ b/src/js/node/events.js @@ -14,7 +14,7 @@ const ArrayPrototypeSlice = Array.prototype.slice; var defaultMaxListeners = 10; -// EventEmitter must be a standard function because some old code will do weird tricks like `EventEmitter.apply(this)`. +// EventEmitter must be a standard function because some old code will do weird tricks like `EventEmitter.$apply(this)`. const EventEmitter = function EventEmitter(opts) { if (this._events === undefined || this._events === this.__proto__._events) { this._events = { __proto__: null }; @@ -49,14 +49,14 @@ function emitError(emitter, args) { if (!events) throw args[0]; var errorMonitor = events[kErrorMonitor]; if (errorMonitor) { - for (var handler of ArrayPrototypeSlice.call(errorMonitor)) { - handler.apply(emitter, args); + for (var handler of ArrayPrototypeSlice.$call(errorMonitor)) { + handler.$apply(emitter, args); } } var handlers = events.error; if (!handlers) throw args[0]; - for (var handler of ArrayPrototypeSlice.call(handlers)) { - handler.apply(emitter, args); + for (var handler of ArrayPrototypeSlice.$call(handlers)) { + handler.$apply(emitter, args); } return true; } @@ -92,9 +92,30 @@ const emitWithoutRejectionCapture = function emit(type, ...args) { if (events === undefined) return false; var handlers = events[type]; if (handlers === undefined) return false; - - for (var handler of [...handlers]) { - handler.apply(this, args); + // Clone handlers array if necessary since handlers can be added/removed during the loop. + // Cloning is skipped for performance reasons in the case of exactly one attached handler + // since array length changes have no side-effects in a for-loop of length 1. + const maybeClonedHandlers = handlers.length > 1 ? handlers.slice() : handlers; + for (let i = 0, { length } = maybeClonedHandlers; i < length; i++) { + const handler = maybeClonedHandlers[i]; + // For performance reasons Function.call(...) is used whenever possible. + switch (args.length) { + case 0: + handler.$call(this); + break; + case 1: + handler.$call(this, args[0]); + break; + case 2: + handler.$call(this, args[0], args[1]); + break; + case 3: + handler.$call(this, args[0], args[1], args[2]); + break; + default: + handler.$apply(this, args); + break; + } } return true; }; @@ -107,8 +128,31 @@ const emitWithRejectionCapture = function emit(type, ...args) { if (events === undefined) return false; var handlers = events[type]; if (handlers === undefined) return false; - for (var handler of [...handlers]) { - var result = handler.apply(this, args); + // Clone handlers array if necessary since handlers can be added/removed during the loop. + // Cloning is skipped for performance reasons in the case of exactly one attached handler + // since array length changes have no side-effects in a for-loop of length 1. + const maybeClonedHandlers = handlers.length > 1 ? handlers.slice() : handlers; + for (let i = 0, { length } = maybeClonedHandlers; i < length; i++) { + const handler = maybeClonedHandlers[i]; + let result; + // For performance reasons Function.call(...) is used whenever possible. + switch (args.length) { + case 0: + result = handler.$call(this); + break; + case 1: + result = handler.$call(this, args[0]); + break; + case 2: + result = handler.$call(this, args[0], args[1]); + break; + case 3: + result = handler.$call(this, args[0], args[1], args[2]); + break; + default: + result = handler.$apply(this, args); + break; + } if (result !== undefined && $isPromise(result)) { addCatch(this, result, type, args); } @@ -181,7 +225,7 @@ function overflowWarning(emitter, type, handlers) { function onceWrapper(type, listener, ...args) { this.removeListener(type, listener); - listener.apply(this, args); + listener.$apply(this, args); } EventEmitterPrototype.once = function once(type, fn) { diff --git a/src/js/node/fs.js b/src/js/node/fs.js index b4165311f..39c257c9f 100644 --- a/src/js/node/fs.js +++ b/src/js/node/fs.js @@ -109,73 +109,86 @@ class StatWatcher extends EventEmitter { } var access = function access(...args) { - callbackify(fs.accessSync, args); + callbackify(fs.access, args); }, appendFile = function appendFile(...args) { - callbackify(fs.appendFileSync, args); + callbackify(fs.appendFile, args); }, close = function close(...args) { - callbackify(fs.closeSync, args); + callbackify(fs.close, args); }, rm = function rm(...args) { - callbackify(fs.rmSync, args); + callbackify(fs.rm, args); }, rmdir = function rmdir(...args) { - callbackify(fs.rmdirSync, args); + callbackify(fs.rmdir, args); }, copyFile = function copyFile(...args) { const callback = args[args.length - 1]; if (typeof callback !== "function") { - // TODO: set code - throw new TypeError("Callback must be a function"); + const err = new TypeError("Callback must be a function"); + err.code = "ERR_INVALID_ARG_TYPE"; + throw err; } fs.copyFile(...args).then(result => callback(null, result), callback); }, - exists = function exists(...args) { - callbackify(fs.existsSync, args); + exists = function exists(path, callback) { + if (typeof callback !== "function") { + const err = new TypeError("Callback must be a function"); + err.code = "ERR_INVALID_ARG_TYPE"; + throw err; + } + try { + fs.exists.$apply(fs, [path]).then( + existed => callback(existed), + _ => callback(false), + ); + } catch (e) { + callback(false); + } }, chown = function chown(...args) { - callbackify(fs.chownSync, args); + callbackify(fs.chown, args); }, chmod = function chmod(...args) { - callbackify(fs.chmodSync, args); + callbackify(fs.chmod, args); }, fchmod = function fchmod(...args) { - callbackify(fs.fchmodSync, args); + callbackify(fs.fchmod, args); }, fchown = function fchown(...args) { - callbackify(fs.fchownSync, args); + callbackify(fs.fchown, args); }, fstat = function fstat(...args) { - callbackify(fs.fstatSync, args); + callbackify(fs.fstat, args); }, fsync = function fsync(...args) { - callbackify(fs.fsyncSync, args); + callbackify(fs.fsync, args); }, ftruncate = function ftruncate(...args) { - callbackify(fs.ftruncateSync, args); + callbackify(fs.ftruncate, args); }, futimes = function futimes(...args) { - callbackify(fs.futimesSync, args); + callbackify(fs.futimes, args); }, lchmod = function lchmod(...args) { - callbackify(fs.lchmodSync, args); + callbackify(fs.lchmod, args); }, lchown = function lchown(...args) { - callbackify(fs.lchownSync, args); + callbackify(fs.lchown, args); }, link = function link(...args) { - callbackify(fs.linkSync, args); + callbackify(fs.link, args); }, mkdir = function mkdir(...args) { - callbackify(fs.mkdirSync, args); + callbackify(fs.mkdir, args); }, mkdtemp = function mkdtemp(...args) { - callbackify(fs.mkdtempSync, args); + callbackify(fs.mkdtemp, args); }, open = function open(...args) { - callbackify(fs.openSync, args); + callbackify(fs.open, args); }, read = function read(fd, buffer, offsetOrOptions, length, position, callback) { let offset = offsetOrOptions; @@ -210,7 +223,7 @@ var access = function access(...args) { }); }, write = function write(...args) { - callbackify(fs.writeSync, args); + callbackify(fs.write, args); }, readdir = function readdir(...args) { const callback = args[args.length - 1]; @@ -231,10 +244,10 @@ var access = function access(...args) { fs.readFile(...args).then(result => callback(null, result), callback); }, writeFile = function writeFile(...args) { - callbackify(fs.writeFileSync, args); + callbackify(fs.writeFile, args); }, readlink = function readlink(...args) { - callbackify(fs.readlinkSync, args); + callbackify(fs.readlink, args); }, realpath = function realpath(...args) { const callback = args[args.length - 1]; @@ -246,7 +259,7 @@ var access = function access(...args) { fs.realpath(...args).then(result => callback(null, result), callback); }, rename = function rename(...args) { - callbackify(fs.renameSync, args); + callbackify(fs.rename, args); }, lstat = function lstat(...args) { const callback = args[args.length - 1]; @@ -267,19 +280,19 @@ var access = function access(...args) { fs.stat(...args).then(result => callback(null, result), callback); }, symlink = function symlink(...args) { - callbackify(fs.symlinkSync, args); + callbackify(fs.symlink, args); }, truncate = function truncate(...args) { - callbackify(fs.truncateSync, args); + callbackify(fs.truncate, args); }, unlink = function unlink(...args) { - callbackify(fs.unlinkSync, args); + callbackify(fs.unlink, args); }, utimes = function utimes(...args) { - callbackify(fs.utimesSync, args); + callbackify(fs.utimes, args); }, lutimes = function lutimes(...args) { - callbackify(fs.lutimesSync, args); + callbackify(fs.lutimes, args); }, accessSync = fs.accessSync.bind(fs), appendFileSync = fs.appendFileSync.bind(fs), @@ -406,16 +419,18 @@ function unwatchFile(filename, listener) { } function callbackify(fsFunction, args) { + const callback = args[args.length - 1]; try { - const result = fsFunction.apply(fs, args.slice(0, args.length - 1)); - const callback = args[args.length - 1]; - if (typeof callback === "function") { - queueMicrotask(() => callback(null, result)); - } + var result = fsFunction.$apply(fs, args.slice(0, args.length - 1)); + result.then( + (...args) => callback(null, ...args), + err => callback(err), + ); } catch (e) { - const callback = args[args.length - 1]; if (typeof callback === "function") { - queueMicrotask(() => callback(e)); + callback(e); + } else { + throw e; } } } @@ -874,7 +889,7 @@ var WriteStreamClass = (WriteStream = function WriteStream(path, options = defau tempThis.fd = fs.openSync(path, flags, mode); } - NativeWritable.call(this, tempThis.fd, { + NativeWritable.$call(this, tempThis.fd, { ...options, decodeStrings: false, autoDestroy, @@ -978,7 +993,7 @@ WriteStreamPrototype[writeStreamPathFastPathCallSymbol] = function WriteStreamPa }, err => { readStream[kIoDone] = this[kIoDone] = true; - WriteStream_errorOrDestroy.call(this, err); + WriteStream_errorOrDestroy.$call(this, err); readStream.emit("error", err); }, ); @@ -994,7 +1009,7 @@ WriteStreamPrototype.disableBunFastPath = function disableBunFastPath() { function WriteStream_handleWrite(er, bytes) { if (er) { - return WriteStream_errorOrDestroy.call(this, er); + return WriteStream_errorOrDestroy.$call(this, er); } this.bytesWritten += bytes; @@ -1026,11 +1041,11 @@ WriteStreamPrototype._destroy = function _destroy(err, cb) { } if (this[kIoDone]) { - this.once(kIoDone, () => WriteStream_internalClose.call(this, err, cb)); + this.once(kIoDone, () => WriteStream_internalClose.$call(this, err, cb)); return; } - WriteStream_internalClose.call(this, err, cb); + WriteStream_internalClose.$call(this, err, cb); }; WriteStreamPrototype.close = function close(cb) { @@ -1065,7 +1080,7 @@ WriteStreamPrototype.write = function write(chunk, encoding, cb) { const callback = native ? (err, bytes) => { this[kIoDone] = false; - WriteStream_handleWrite.call(this, err, bytes); + WriteStream_handleWrite.$call(this, err, bytes); this.emit(kIoDone); if (cb) !err ? cb() : cb(err); } @@ -1074,7 +1089,7 @@ WriteStreamPrototype.write = function write(chunk, encoding, cb) { if (this._write) { return this._write(chunk, encoding, callback); } else { - return NativeWritable.prototype.write.call(this, chunk, encoding, callback, native); + return NativeWritable.prototype.write.$call(this, chunk, encoding, callback, native); } }; @@ -1084,7 +1099,7 @@ WriteStreamPrototype._writev = undefined; WriteStreamPrototype.end = function end(chunk, encoding, cb) { var native = this.pos === undefined; - return NativeWritable.prototype.end.call(this, chunk, encoding, cb, native); + return NativeWritable.prototype.end.$call(this, chunk, encoding, cb, native); }; WriteStreamPrototype._destroy = function _destroy(err, cb) { diff --git a/src/js/node/fs.promises.ts b/src/js/node/fs.promises.ts index 8921e42d3..91566d155 100644 --- a/src/js/node/fs.promises.ts +++ b/src/js/node/fs.promises.ts @@ -9,14 +9,6 @@ var fs = Bun.fs(); // in some cases, node swaps around arguments or makes small tweaks to the return type // this is just better than nothing. const notrace = "::bunternal::"; -var promisify = { - [notrace]: fsFunction => { - return async function (...args) { - await 1; - return fsFunction.apply(fs, args); - }; - }, -}[notrace]; function watch( filename: string | Buffer | URL, @@ -139,72 +131,57 @@ async function opendir(dir: string) { } export default { - access: promisify(fs.accessSync), - appendFile: promisify(fs.appendFileSync), - close: promisify(fs.closeSync), + access: fs.access.bind(fs), + appendFile: fs.appendFile.bind(fs), + close: fs.close.bind(fs), copyFile: fs.copyFile.bind(fs), cp, - exists: promisify(fs.existsSync), - chown: promisify(fs.chownSync), - chmod: promisify(fs.chmodSync), - fchmod: promisify(fs.fchmodSync), - fchown: promisify(fs.fchownSync), - fstat: promisify(fs.fstatSync), - fsync: promisify(fs.fsyncSync), - ftruncate: promisify(fs.ftruncateSync), - futimes: promisify(fs.futimesSync), - lchmod: promisify(fs.lchmodSync), - lchown: promisify(fs.lchownSync), - link: promisify(fs.linkSync), + exists: fs.exists.bind(fs), + chown: fs.chown.bind(fs), + chmod: fs.chmod.bind(fs), + fchmod: fs.fchmod.bind(fs), + fchown: fs.fchown.bind(fs), + fstat: fs.fstat.bind(fs), + fsync: fs.fsync.bind(fs), + ftruncate: fs.ftruncate.bind(fs), + futimes: fs.futimes.bind(fs), + lchmod: fs.lchmod.bind(fs), + lchown: fs.lchown.bind(fs), + link: fs.link.bind(fs), lstat: fs.lstat.bind(fs), - mkdir: promisify(fs.mkdirSync), - mkdtemp: promisify(fs.mkdtempSync), - open: promisify(fs.openSync), - read: promisify(fs.readSync), - write: promisify(fs.writeSync), + mkdir: fs.mkdir.bind(fs), + mkdtemp: fs.mkdtemp.bind(fs), + open: fs.open.bind(fs), + read: fs.read.bind(fs), + write: fs.write.bind(fs), readdir: fs.readdir.bind(fs), readFile: fs.readFile.bind(fs), - writeFile: promisify(fs.writeFileSync), - readlink: promisify(fs.readlinkSync), + writeFile: fs.writeFile.bind(fs), + readlink: fs.readlink.bind(fs), realpath: fs.realpath.bind(fs), - rename: promisify(fs.renameSync), + rename: fs.rename.bind(fs), stat: fs.stat.bind(fs), - symlink: promisify(fs.symlinkSync), - truncate: promisify(fs.truncateSync), - unlink: promisify(fs.unlinkSync), - utimes: promisify(fs.utimesSync), - lutimes: promisify(fs.lutimesSync), - rm: promisify(fs.rmSync), - rmdir: promisify(fs.rmdirSync), - writev: (fd, buffers, position) => { - return new Promise((resolve, reject) => { - try { - var bytesWritten = fs.writevSync(fd, buffers, position); - } catch (err) { - reject(err); - return; - } - - resolve({ - bytesWritten, - buffers, - }); - }); + symlink: fs.symlink.bind(fs), + truncate: fs.truncate.bind(fs), + unlink: fs.unlink.bind(fs), + utimes: fs.utimes.bind(fs), + lutimes: fs.lutimes.bind(fs), + rm: fs.rm.bind(fs), + rmdir: fs.rmdir.bind(fs), + writev: async (fd, buffers, position) => { + var bytesWritten = await fs.writev(fd, buffers, position); + return { + bytesWritten, + buffers, + }; }, - readv: (fd, buffers, position) => { - return new Promise((resolve, reject) => { - try { - var bytesRead = fs.readvSync(fd, buffers, position); - } catch (err) { - reject(err); - return; - } + readv: async (fd, buffers, position) => { + var bytesRead = await fs.readv(fd, buffers, position); - resolve({ - bytesRead, - buffers, - }); - }); + return { + bytesRead, + buffers, + }; }, constants, watch, diff --git a/src/js/node/http.ts b/src/js/node/http.ts index 70ee6cead..27dab8c3d 100644 --- a/src/js/node/http.ts +++ b/src/js/node/http.ts @@ -2,6 +2,7 @@ const EventEmitter = require("node:events"); const { isTypedArray } = require("node:util/types"); const { Duplex, Readable, Writable } = require("node:stream"); +const { getHeader, setHeader } = $lazy("http"); const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/; /** @@ -11,7 +12,7 @@ const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/; * field-vchar = VCHAR / obs-text */ function checkInvalidHeaderChar(val: string) { - return RegExpPrototypeExec.call(headerCharRegex, val) !== null; + return RegExpPrototypeExec.$call(headerCharRegex, val) !== null; } const validateHeaderName = (name, label) => { @@ -75,13 +76,9 @@ const searchParamsSymbol = Symbol.for("query"); // This is the symbol used in No const StringPrototypeSlice = String.prototype.slice; const StringPrototypeStartsWith = String.prototype.startsWith; const StringPrototypeToUpperCase = String.prototype.toUpperCase; -const StringPrototypeIncludes = String.prototype.includes; -const StringPrototypeCharCodeAt = String.prototype.charCodeAt; -const StringPrototypeIndexOf = String.prototype.indexOf; const ArrayIsArray = Array.isArray; const RegExpPrototypeExec = RegExp.prototype.exec; const ObjectAssign = Object.assign; -const ObjectPrototypeHasOwnProperty = Object.prototype.hasOwnProperty; const INVALID_PATH_REGEX = /[^\u0021-\u00ff]/; const NODE_HTTP_WARNING = @@ -126,30 +123,20 @@ function validateFunction(callable: any, field: string) { return callable; } -function getHeader(headers, name) { - if (!headers) return; - const result = headers.get(name); - return result == null ? undefined : result; -} - type FakeSocket = InstanceType<typeof FakeSocket>; var FakeSocket = class Socket extends Duplex { - [kInternalSocketData]: any; + [kInternalSocketData]!: [import("bun").Server, OutgoingMessage, Request]; bytesRead = 0; bytesWritten = 0; connecting = false; - remoteAddress: string | null = null; - remotePort; timeout = 0; - isServer = false; + #address; address() { - return { - address: this.localAddress, - family: this.localFamily, - port: this.localPort, - }; + // Call server.requestIP() without doing any propety getter twice. + var internalData; + return (this.#address ??= (internalData = this[kInternalSocketData])?.[0]?.requestIP(internalData[2]) ?? {}); } get bufferSize() { @@ -193,8 +180,31 @@ var FakeSocket = class Socket extends Duplex { ref() {} + get remoteAddress() { + return this.address()?.address; + } + + set remoteAddress(val) { + // initialize the object so that other properties wouldn't be lost + this.address().address = val; + } + + get remotePort() { + return this.address()?.port; + } + + set remotePort(val) { + // initialize the object so that other properties wouldn't be lost + this.address().port = val; + } + get remoteFamily() { - return "IPv4"; + return this.address()?.family; + } + + set remoteFamily(val) { + // initialize the object so that other properties wouldn't be lost + this.address().family = val; } resetAndDestroy() {} @@ -437,13 +447,7 @@ class Server extends EventEmitter { address() { if (!this.#server) return null; - - const address = this.#server.hostname; - return { - address, - family: isIPv6(address) ? "IPv6" : "IPv4", - port: this.#server.port, - }; + return this.#server.address; } listen(port, host, backlog, onListen) { @@ -521,14 +525,14 @@ class Server extends EventEmitter { const http_req = new RequestClass(req); const http_res = new ResponseClass({ reply, req: http_req }); + http_req.socket[kInternalSocketData] = [_server, http_res, req]; + http_req.once("error", err => reject(err)); http_res.once("error", err => reject(err)); const upgrade = req.headers.get("upgrade"); if (upgrade) { - const socket = http_req.socket; - socket[kInternalSocketData] = [_server, http_res, req]; - server.emit("upgrade", http_req, socket, kEmptyBuffer); + server.emit("upgrade", http_req, http_req.socket, kEmptyBuffer); } else { server.emit("request", http_req, http_res); } @@ -549,7 +553,7 @@ class Server extends EventEmitter { }); setTimeout(emitListeningNextTick, 1, this, onListen, null, this.#server.hostname, this.#server.port); } catch (err) { - setTimeout(emitListeningNextTick, 1, this, onListen, err); + server.emit("error", err); } return this; @@ -608,12 +612,11 @@ class IncomingMessage extends Readable { this.#bodyStream = undefined; const socket = new FakeSocket(); - socket.remoteAddress = url.hostname; - socket.remotePort = url.port; + if (url.protocol === "https:") socket.encrypted = true; this.#fakeSocket = socket; this.url = url.pathname + url.search; - this.#nodeReq = this.req = nodeReq; + this.req = nodeReq; assignHeaders(this, req); } @@ -628,7 +631,6 @@ class IncomingMessage extends Readable { #req; url; #type; - #nodeReq; _construct(callback) { // TODO: streaming @@ -654,7 +656,7 @@ class IncomingMessage extends Readable { if (this.#aborted) return; if (done) { this.push(null); - this.destroy(); + process.nextTick(destroyBodyStreamNT, this); break; } for (var v of value) { @@ -958,8 +960,11 @@ let OriginalWriteHeadFn, OriginalImplicitHeadFn; class ServerResponse extends Writable { declare _writableState: any; - constructor({ req, reply }) { + constructor(c) { super(); + if (!c) c = {}; + var req = c.req || {}; + var reply = c.reply; this.req = req; this._reply = reply; this.sendDate = true; @@ -1174,7 +1179,7 @@ class ServerResponse extends Writable { setHeader(name, value) { var headers = (this.#headers ??= new Headers()); - headers.set(name, value); + setHeader(headers, name, value); return this; } @@ -1391,7 +1396,7 @@ class ClientRequest extends OutgoingMessage { if (options.path) { const path = String(options.path); - if (RegExpPrototypeExec.call(INVALID_PATH_REGEX, path) !== null) { + if (RegExpPrototypeExec.$call(INVALID_PATH_REGEX, path) !== null) { $debug('Path contains unescaped characters: "%s"', path); throw new Error("Path contains unescaped characters"); // throw new ERR_UNESCAPED_CHARACTERS("Request path"); @@ -1438,7 +1443,7 @@ class ClientRequest extends OutgoingMessage { // throw new ERR_INVALID_HTTP_TOKEN("Method", method); throw new Error("ERR_INVALID_HTTP_TOKEN: Method"); } - method = this.#method = StringPrototypeToUpperCase.call(method); + method = this.#method = StringPrototypeToUpperCase.$call(method); } else { method = this.#method = "GET"; } @@ -1515,7 +1520,7 @@ class ClientRequest extends OutgoingMessage { // // For the Host header, ensure that IPv6 addresses are enclosed // // in square brackets, as defined by URI formatting // // https://tools.ietf.org/html/rfc3986#section-3.2.2 - // const posColon = StringPrototypeIndexOf.call(hostHeader, ":"); + // const posColon = StringPrototypeIndexOf.$call(hostHeader, ":"); // if ( // posColon !== -1 && // StringPrototypeIncludes(hostHeader, ":", posColon + 1) && @@ -1614,8 +1619,8 @@ function urlToHttpOptions(url) { return { protocol, hostname: - typeof hostname === "string" && StringPrototypeStartsWith.call(hostname, "[") - ? StringPrototypeSlice.call(hostname, 1, -1) + typeof hostname === "string" && StringPrototypeStartsWith.$call(hostname, "[") + ? StringPrototypeSlice.$call(hostname, 1, -1) : hostname, hash, search, @@ -1646,7 +1651,7 @@ const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/; * See https://tools.ietf.org/html/rfc7230#section-3.2.6 */ function checkIsHttpToken(val) { - return RegExpPrototypeExec.call(tokenRegExp, val) !== null; + return RegExpPrototypeExec.$call(tokenRegExp, val) !== null; } // Copyright Joyent, Inc. and other Node contributors. diff --git a/src/js/node/net.js b/src/js/node/net.js index f0873ae22..56b0f9ced 100644 --- a/src/js/node/net.js +++ b/src/js/node/net.js @@ -66,6 +66,14 @@ const bunSocketServerOptions = Symbol.for("::bunnetserveroptions::"); const bunSocketInternal = Symbol.for("::bunnetsocketinternal::"); const bunTLSConnectOptions = Symbol.for("::buntlsconnectoptions::"); +function closeNT(self) { + self.emit("close"); +} +function endNT(socket, callback, err) { + socket.end(); + callback(err); +} + var SocketClass; const Socket = (function (InternalSocket) { SocketClass = InternalSocket; @@ -74,17 +82,15 @@ const Socket = (function (InternalSocket) { enumerable: false, }); - return Object.defineProperty( - function Socket(options) { - return new InternalSocket(options); - }, - Symbol.hasInstance, - { - value(instance) { - return instance instanceof InternalSocket; - }, + function Socket(options) { + return new InternalSocket(options); + } + Socket.prototype = InternalSocket.prototype; + return Object.defineProperty(Socket, Symbol.hasInstance, { + value(instance) { + return instance instanceof InternalSocket; }, - ); + }); })( class Socket extends Duplex { static #Handlers = { @@ -317,7 +323,7 @@ const Socket = (function (InternalSocket) { this._parent = this; this._parentWrap = this; this.#pendingRead = undefined; - this.#upgraded = false; + this.#upgraded = null; if (socket instanceof Socket) { this.#socket = socket; } @@ -352,6 +358,14 @@ const Socket = (function (InternalSocket) { Socket.#Drain(socket); } + #closeRawConnection() { + const connection = this.#upgraded; + connection[bunSocketInternal] = null; + connection.unref(); + connection.destroy(); + process.nextTick(closeNT, connection); + } + connect(port, host, connectListener) { var path; var connection = this.#socket; @@ -412,7 +426,7 @@ const Socket = (function (InternalSocket) { var tls = undefined; if (typeof bunTLS === "function") { - tls = bunTLS.call(this, port, host, true); + tls = bunTLS.$call(this, port, host, true); // Client always request Cert this._requestCert = true; this._rejectUnauthorized = rejectUnauthorized; @@ -446,90 +460,97 @@ const Socket = (function (InternalSocket) { } else if (connectListener) this.on("connect", connectListener); // start using existing connection - if (connection) { - const socket = connection[bunSocketInternal]; - - if (socket) { - this.connecting = true; - this.#upgraded = true; - const result = socket.upgradeTLS({ - data: this, - tls, - socket: Socket.#Handlers, - }); - if (result) { - const [raw, tls] = result; - // replace socket - connection[bunSocketInternal] = raw; - raw.timeout(raw.timeout); - raw.connecting = false; - this[bunSocketInternal] = tls; - } else { - this[bunSocketInternal] = null; - throw new Error("Invalid socket"); - } - } else { - // wait to be connected - connection.once("connect", () => { - const socket = connection[bunSocketInternal]; - if (!socket) return; + try { + if (connection) { + const socket = connection[bunSocketInternal]; + if (socket) { this.connecting = true; - this.#upgraded = true; + this.#upgraded = connection; const result = socket.upgradeTLS({ data: this, tls, socket: Socket.#Handlers, }); - if (result) { const [raw, tls] = result; // replace socket connection[bunSocketInternal] = raw; raw.timeout(raw.timeout); + this.once("end", this.#closeRawConnection); raw.connecting = false; this[bunSocketInternal] = tls; } else { this[bunSocketInternal] = null; throw new Error("Invalid socket"); } + } else { + // wait to be connected + connection.once("connect", () => { + const socket = connection[bunSocketInternal]; + if (!socket) return; + + this.connecting = true; + this.#upgraded = connection; + const result = socket.upgradeTLS({ + data: this, + tls, + socket: Socket.#Handlers, + }); + + if (result) { + const [raw, tls] = result; + // replace socket + connection[bunSocketInternal] = raw; + raw.timeout(raw.timeout); + this.once("end", this.#closeRawConnection); + raw.connecting = false; + this[bunSocketInternal] = tls; + } else { + this[bunSocketInternal] = null; + throw new Error("Invalid socket"); + } + }); + } + } else if (path) { + // start using unix socket + bunConnect({ + data: this, + unix: path, + socket: Socket.#Handlers, + tls, + }).catch(error => { + this.emit("error", error); + this.emit("close"); + }); + } else { + // default start + bunConnect({ + data: this, + hostname: host || "localhost", + port: port, + socket: Socket.#Handlers, + tls, + }).catch(error => { + this.emit("error", error); + this.emit("close"); }); } - } else if (path) { - // start using unix socket - bunConnect({ - data: this, - unix: path, - socket: Socket.#Handlers, - tls, - }).catch(error => { - this.emit("error", error); - this.emit("close"); - }); - } else { - // default start - bunConnect({ - data: this, - hostname: host || "localhost", - port: port, - socket: Socket.#Handlers, - tls, - }).catch(error => { - this.emit("error", error); - this.emit("close"); - }); + } catch (error) { + process.nextTick(emitErrorAndCloseNextTick, this, error); } return this; } _destroy(err, callback) { - this[bunSocketInternal]?.end(); - callback(err); + const socket = this[bunSocketInternal]; + socket && process.nextTick(endNT, socket, callback, err); } _final(callback) { this[bunSocketInternal]?.end(); callback(); + process.nextTick(closeNT, this); } get localAddress() { @@ -552,8 +573,10 @@ const Socket = (function (InternalSocket) { const queue = this.#readQueue; let chunk; while ((chunk = queue.peek())) { - if (!this.push(chunk)) return; + const can_continue = !this.push(chunk); + // always remove from queue push will queue it internally if needed queue.shift(); + if (!can_continue) break; } } @@ -815,7 +838,7 @@ class Server extends EventEmitter { const options = this[bunSocketServerOptions]; if (typeof bunTLS === "function") { - [tls, TLSSocketClass] = bunTLS.call(this, port, hostname, false); + [tls, TLSSocketClass] = bunTLS.$call(this, port, hostname, false); options.servername = tls.serverName; options.InternalSocketClass = TLSSocketClass; } else { @@ -864,6 +887,11 @@ function emitErrorNextTick(self, error) { self.emit("error", error); } +function emitErrorAndCloseNextTick(self, error) { + self.emit("error", error); + self.emit("close"); +} + function emitListeningNextTick(self, onListen) { if (typeof onListen === "function") { try { diff --git a/src/js/node/os.ts b/src/js/node/os.ts index c5b202444..744131bb6 100644 --- a/src/js/node/os.ts +++ b/src/js/node/os.ts @@ -77,6 +77,9 @@ function lazyCpus({ cpus }) { function bound(obj) { return { + availableParallelism: () => { + return navigator.hardwareConcurrency; + }, arch: obj.arch.bind(obj), cpus: lazyCpus(obj), endianness: obj.endianness.bind(obj), diff --git a/src/js/node/querystring.js b/src/js/node/querystring.js index 232bdac75..d7104cfcd 100644 --- a/src/js/node/querystring.js +++ b/src/js/node/querystring.js @@ -27,13 +27,13 @@ var require_object_keys = __commonJS((exports, module) => { var prop; var i; for (prop in obj) { - if (hasOwnProperty.call(obj, prop)) { + if (hasOwnProperty.$call(obj, prop)) { result.push(prop); } } if (hasDontEnumBug) { for (i = 0; i < dontEnumsLength; i++) { - if (hasOwnProperty.call(obj, dontEnums[i])) { + if (hasOwnProperty.$call(obj, dontEnums[i])) { result.push(dontEnums[i]); } } @@ -345,7 +345,7 @@ var require_src = __commonJS((exports, module) => { decode: parse, }); var objectKeys = require_object_keys(); - var isArray = arg => Object.prototype.toString.call(arg) === "[object Array]"; + var isArray = arg => Object.prototype.toString.$call(arg) === "[object Array]"; var indexOf = (arr, searchElement, fromIndex) => { var k; if (arr == null) { diff --git a/src/js/node/readline.js b/src/js/node/readline.js index 6b3cddd80..16f4e1995 100644 --- a/src/js/node/readline.js +++ b/src/js/node/readline.js @@ -74,12 +74,11 @@ var NumberMIN_SAFE_INTEGER = Number.MIN_SAFE_INTEGER; var MathCeil = Math.ceil; var MathFloor = Math.floor; var MathMax = Math.max; -var MathMaxApply = Math.max.apply; var DateNow = Date.now; var FunctionPrototype = Function.prototype; var StringPrototype = String.prototype; var StringPrototypeSymbolIterator = StringPrototype[SymbolIterator]; -var StringIteratorPrototypeNext = StringPrototypeSymbolIterator.call("").next; +var StringIteratorPrototypeNext = StringPrototypeSymbolIterator.$call("").next; var ObjectSetPrototypeOf = Object.setPrototypeOf; var ObjectDefineProperty = Object.defineProperty; var ObjectDefineProperties = Object.defineProperties; @@ -93,10 +92,10 @@ var createSafeIterator = (factory, next) => { class SafeIterator { #iterator; constructor(iterable) { - this.#iterator = factory.call(iterable); + this.#iterator = factory.$call(iterable); } next() { - return next.call(this.#iterator); + return next.$call(this.#iterator); } [SymbolIterator]() { return this; @@ -178,9 +177,9 @@ var getStringWidth = function getStringWidth(str, removeControlChars = true) { var width = 0; if (removeControlChars) str = stripVTControlCharacters(str); - str = StringPrototypeNormalize.call(str, "NFC"); + str = StringPrototypeNormalize.$call(str, "NFC"); for (var char of new SafeStringIterator(str)) { - var code = StringPrototypeCodePointAt.call(char, 0); + var code = StringPrototypeCodePointAt.$call(char, 0); if (isFullWidthCodePoint(code)) { width += 2; } else if (!isZeroWidthCodePoint(code)) { @@ -207,7 +206,7 @@ var ansi = new RegExp(ansiPattern, "g"); */ function stripVTControlCharacters(str) { validateString(str, "str"); - return RegExpPrototypeSymbolReplace.call(ansi, str, ""); + return RegExpPrototypeSymbolReplace.$call(ansi, str, ""); } // Promisify @@ -238,7 +237,7 @@ function promisify(original) { function fn(...args) { return new Promise((resolve, reject) => { - ArrayPrototypePush.call(args, (err, ...values) => { + ArrayPrototypePush.$call(args, (err, ...values) => { if (err) { return reject(err); } @@ -449,7 +448,7 @@ function validateObject(value, name, options = null) { var nullable = options?.nullable ?? false; if ( (!nullable && value === null) || - (!allowArray && ArrayIsArray.call(value)) || + (!allowArray && ArrayIsArray.$call(value)) || (typeof value !== "object" && (!allowFunction || typeof value !== "function")) ) { throw new ERR_INVALID_ARG_TYPE(name, "object", value); @@ -518,8 +517,8 @@ CSI.kClearToLineEnd = kClearToLineEnd = CSI`0K`; function charLengthLeft(str, i) { if (i <= 0) return 0; if ( - (i > 1 && StringPrototypeCodePointAt.call(str, i - 2) >= kUTF16SurrogateThreshold) || - StringPrototypeCodePointAt.call(str, i - 1) >= kUTF16SurrogateThreshold + (i > 1 && StringPrototypeCodePointAt.$call(str, i - 2) >= kUTF16SurrogateThreshold) || + StringPrototypeCodePointAt.$call(str, i - 1) >= kUTF16SurrogateThreshold ) { return 2; } @@ -532,7 +531,7 @@ function charLengthAt(str, i) { // moving to the right. return 1; } - return StringPrototypeCodePointAt.call(str, i) >= kUTF16SurrogateThreshold ? 2 : 1; + return StringPrototypeCodePointAt.$call(str, i) >= kUTF16SurrogateThreshold ? 2 : 1; } /* @@ -670,13 +669,13 @@ function* emitKeys(stream) { * We buffered enough data, now trying to extract code * and modifier from it */ - var cmd = StringPrototypeSlice.call(s, cmdStart); + var cmd = StringPrototypeSlice.$call(s, cmdStart); var match; - if ((match = RegExpPrototypeExec.call(/^(\d\d?)(;(\d))?([~^$])$/, cmd))) { + if ((match = RegExpPrototypeExec.$call(/^(\d\d?)(;(\d))?([~^$])$/, cmd))) { code += match[1] + match[4]; modifier = (match[3] || 1) - 1; - } else if ((match = RegExpPrototypeExec.call(/^((\d;)?(\d))?([A-Za-z])$/, cmd))) { + } else if ((match = RegExpPrototypeExec.$call(/^((\d;)?(\d))?([A-Za-z])$/, cmd))) { code += match[4]; modifier = (match[3] || 1) - 1; } else { @@ -985,12 +984,12 @@ function* emitKeys(stream) { keyMeta = escaped; } else if (!escaped && ch <= "\x1a") { // ctrl+letter - keyName = StringFromCharCode(StringPrototypeCharCodeAt.call(ch) + StringPrototypeCharCodeAt.call("a") - 1); + keyName = StringFromCharCode(StringPrototypeCharCodeAt.$call(ch) + StringPrototypeCharCodeAt.$call("a") - 1); keyCtrl = true; - } else if (RegExpPrototypeExec.call(/^[0-9A-Za-z]$/, ch) !== null) { + } else if (RegExpPrototypeExec.$call(/^[0-9A-Za-z]$/, ch) !== null) { // Letter, number, shift+letter - keyName = StringPrototypeToLowerCase.call(ch); - keyShift = RegExpPrototypeExec.call(/^[A-Z]$/, ch) !== null; + keyName = StringPrototypeToLowerCase.$call(ch); + keyShift = RegExpPrototypeExec.$call(/^[A-Z]$/, ch) !== null; keyMeta = escaped; } else if (escaped) { // Escape sequence timeout @@ -1034,12 +1033,12 @@ function commonPrefix(strings) { if (strings.length === 1) { return strings[0]; } - var sorted = ArrayPrototypeSort.call(ArrayPrototypeSlice.call(strings)); + var sorted = ArrayPrototypeSort.$call(ArrayPrototypeSlice.$call(strings)); var min = sorted[0]; var max = sorted[sorted.length - 1]; for (var i = 0; i < min.length; i++) { if (min[i] !== max[i]) { - return StringPrototypeSlice.call(min, 0, i); + return StringPrototypeSlice.$call(min, 0, i); } } return min; @@ -1402,7 +1401,7 @@ function onKeyPress(s, key) { // If the keySeq is half of a surrogate pair // (>= 0xd800 and <= 0xdfff), refresh the line so // the character is displayed appropriately. - var ch = StringPrototypeCodePointAt.call(key.sequence, 0); + var ch = StringPrototypeCodePointAt.$call(key.sequence, 0); if (ch >= 0xd800 && ch <= 0xdfff) this[kRefreshLine](); } } @@ -1416,7 +1415,7 @@ function InterfaceConstructor(input, output, completer, terminal) { return new InterfaceConstructor(input, output, completer, terminal); } - EventEmitter.call(this); + EventEmitter.$call(this); this[kOnSelfCloseWithoutTerminal] = onSelfCloseWithoutTerminal.bind(this); this[kOnSelfCloseWithTerminal] = onSelfCloseWithTerminal.bind(this); @@ -1613,7 +1612,7 @@ var _Interface = class Interface extends InterfaceConstructor { var setRawMode = this.input.setRawMode; if (typeof setRawMode === "function") { - setRawMode.call(this.input, mode); + setRawMode.$call(this.input, mode); } return wasInRawMode; @@ -1686,19 +1685,19 @@ var _Interface = class Interface extends InterfaceConstructor { if (this.historySize === 0) return this.line; // If the trimmed line is empty then return the line - if (StringPrototypeTrim.call(this.line).length === 0) return this.line; + if (StringPrototypeTrim.$call(this.line).length === 0) return this.line; if (this.history.length === 0 || this.history[0] !== this.line) { if (this.removeHistoryDuplicates) { // Remove older history line if identical to new one - var dupIndex = ArrayPrototypeIndexOf.call(this.history, this.line); - if (dupIndex !== -1) ArrayPrototypeSplice.call(this.history, dupIndex, 1); + var dupIndex = ArrayPrototypeIndexOf.$call(this.history, this.line); + if (dupIndex !== -1) ArrayPrototypeSplice.$call(this.history, dupIndex, 1); } - ArrayPrototypeUnshift.call(this.history, this.line); + ArrayPrototypeUnshift.$call(this.history, this.line); // Only store so many - if (this.history.length > this.historySize) ArrayPrototypePop.call(this.history); + if (this.history.length > this.historySize) ArrayPrototypePop.$call(this.history); } this.historyIndex = -1; @@ -1819,30 +1818,30 @@ var _Interface = class Interface extends InterfaceConstructor { } var string = this[kDecoder].write(b); if (this[kSawReturnAt] && DateNow() - this[kSawReturnAt] <= this.crlfDelay) { - if (StringPrototypeCodePointAt.call(string) === 10) string = StringPrototypeSlice.call(string, 1); + if (StringPrototypeCodePointAt.$call(string) === 10) string = StringPrototypeSlice.$call(string, 1); this[kSawReturnAt] = 0; } // Run test() on the new string chunk, not on the entire line buffer. - var newPartContainsEnding = RegExpPrototypeExec.call(lineEnding, string); + var newPartContainsEnding = RegExpPrototypeExec.$call(lineEnding, string); if (newPartContainsEnding !== null) { if (this[kLine_buffer]) { string = this[kLine_buffer] + string; this[kLine_buffer] = null; - newPartContainsEnding = RegExpPrototypeExec.call(lineEnding, string); + newPartContainsEnding = RegExpPrototypeExec.$call(lineEnding, string); } - this[kSawReturnAt] = StringPrototypeEndsWith.call(string, "\r") ? DateNow() : 0; + this[kSawReturnAt] = StringPrototypeEndsWith.$call(string, "\r") ? DateNow() : 0; var indexes = [0, newPartContainsEnding.index, lineEnding.lastIndex]; var nextMatch; - while ((nextMatch = RegExpPrototypeExec.call(lineEnding, string)) !== null) { - ArrayPrototypePush.call(indexes, nextMatch.index, lineEnding.lastIndex); + while ((nextMatch = RegExpPrototypeExec.$call(lineEnding, string)) !== null) { + ArrayPrototypePush.$call(indexes, nextMatch.index, lineEnding.lastIndex); } var lastIndex = indexes.length - 1; // Either '' or (conceivably) the unfinished portion of the next line - this[kLine_buffer] = StringPrototypeSlice.call(string, indexes[lastIndex]); + this[kLine_buffer] = StringPrototypeSlice.$call(string, indexes[lastIndex]); for (var i = 1; i < lastIndex; i += 2) { - this[kOnLine](StringPrototypeSlice.call(string, indexes[i - 1], indexes[i])); + this[kOnLine](StringPrototypeSlice.$call(string, indexes[i - 1], indexes[i])); } } else if (string) { // No newlines this time, save what we have for next time @@ -1857,8 +1856,8 @@ var _Interface = class Interface extends InterfaceConstructor { [kInsertString](c) { this[kBeforeEdit](this.line, this.cursor); if (this.cursor < this.line.length) { - var beg = StringPrototypeSlice.call(this.line, 0, this.cursor); - var end = StringPrototypeSlice.call(this.line, this.cursor, this.line.length); + var beg = StringPrototypeSlice.$call(this.line, 0, this.cursor); + var end = StringPrototypeSlice.$call(this.line, this.cursor, this.line.length); this.line = beg + c + end; this.cursor += c.length; this[kRefreshLine](); @@ -1878,7 +1877,7 @@ var _Interface = class Interface extends InterfaceConstructor { async [kTabComplete](lastKeypressWasTab) { this.pause(); - var string = StringPrototypeSlice.call(this.line, 0, this.cursor); + var string = StringPrototypeSlice.$call(this.line, 0, this.cursor); var value; try { value = await this.completer(string); @@ -1899,15 +1898,15 @@ var _Interface = class Interface extends InterfaceConstructor { } // If there is a common prefix to all matches, then apply that portion. - var prefix = commonPrefix(ArrayPrototypeFilter.call(completions, e => e !== "")); - if (StringPrototypeStartsWith.call(prefix, completeOn) && prefix.length > completeOn.length) { - this[kInsertString](StringPrototypeSlice.call(prefix, completeOn.length)); + var prefix = commonPrefix(ArrayPrototypeFilter.$call(completions, e => e !== "")); + if (StringPrototypeStartsWith.$call(prefix, completeOn) && prefix.length > completeOn.length) { + this[kInsertString](StringPrototypeSlice.$call(prefix, completeOn.length)); return; - } else if (!StringPrototypeStartsWith.call(completeOn, prefix)) { + } else if (!StringPrototypeStartsWith.$call(completeOn, prefix)) { this.line = - StringPrototypeSlice.call(this.line, 0, this.cursor - completeOn.length) + + StringPrototypeSlice.$call(this.line, 0, this.cursor - completeOn.length) + prefix + - StringPrototypeSlice.call(this.line, this.cursor, this.line.length); + StringPrototypeSlice.$call(this.line, this.cursor, this.line.length); this.cursor = this.cursor - completeOn.length + prefix.length; this._refreshLine(); return; @@ -1920,8 +1919,8 @@ var _Interface = class Interface extends InterfaceConstructor { this[kBeforeEdit](this.line, this.cursor); // Apply/show completions. - var completionsWidth = ArrayPrototypeMap.call(completions, e => getStringWidth(e)); - var width = MathMaxApply(completionsWidth) + 2; // 2 space padding + var completionsWidth = ArrayPrototypeMap.$call(completions, e => getStringWidth(e)); + var width = MathMax.$apply(completionsWidth) + 2; // 2 space padding var maxColumns = MathFloor(this.columns / width) || 1; if (maxColumns === Infinity) { maxColumns = 1; @@ -1936,7 +1935,7 @@ var _Interface = class Interface extends InterfaceConstructor { lineIndex = 0; whitespace = 0; } else { - output += StringPrototypeRepeat.call(" ", whitespace); + output += StringPrototypeRepeat.$call(" ", whitespace); } if (completion !== "") { output += completion; @@ -1957,17 +1956,17 @@ var _Interface = class Interface extends InterfaceConstructor { if (this.cursor > 0) { // Reverse the string and match a word near beginning // to avoid quadratic time complexity - var leading = StringPrototypeSlice.call(this.line, 0, this.cursor); - var reversed = ArrayPrototypeJoin.call(ArrayPrototypeReverse.call(ArrayFrom(leading)), ""); - var match = RegExpPrototypeExec.call(/^\s*(?:[^\w\s]+|\w+)?/, reversed); + var leading = StringPrototypeSlice.$call(this.line, 0, this.cursor); + var reversed = ArrayPrototypeJoin.$call(ArrayPrototypeReverse.$call(ArrayFrom(leading)), ""); + var match = RegExpPrototypeExec.$call(/^\s*(?:[^\w\s]+|\w+)?/, reversed); this[kMoveCursor](-match[0].length); } } [kWordRight]() { if (this.cursor < this.line.length) { - var trailing = StringPrototypeSlice.call(this.line, this.cursor); - var match = RegExpPrototypeExec.call(/^(?:\s+|[^\w\s]+|\w+)\s*/, trailing); + var trailing = StringPrototypeSlice.$call(this.line, this.cursor); + var match = RegExpPrototypeExec.$call(/^(?:\s+|[^\w\s]+|\w+)\s*/, trailing); this[kMoveCursor](match[0].length); } } @@ -1978,8 +1977,8 @@ var _Interface = class Interface extends InterfaceConstructor { // The number of UTF-16 units comprising the character to the left var charSize = charLengthLeft(this.line, this.cursor); this.line = - StringPrototypeSlice.call(this.line, 0, this.cursor - charSize) + - StringPrototypeSlice.call(this.line, this.cursor, this.line.length); + StringPrototypeSlice.$call(this.line, 0, this.cursor - charSize) + + StringPrototypeSlice.$call(this.line, this.cursor, this.line.length); this.cursor -= charSize; this[kRefreshLine](); @@ -1992,8 +1991,8 @@ var _Interface = class Interface extends InterfaceConstructor { // The number of UTF-16 units comprising the character to the left var charSize = charLengthAt(this.line, this.cursor); this.line = - StringPrototypeSlice.call(this.line, 0, this.cursor) + - StringPrototypeSlice.call(this.line, this.cursor + charSize, this.line.length); + StringPrototypeSlice.$call(this.line, 0, this.cursor) + + StringPrototypeSlice.$call(this.line, this.cursor + charSize, this.line.length); this[kRefreshLine](); } } @@ -2003,11 +2002,11 @@ var _Interface = class Interface extends InterfaceConstructor { this[kBeforeEdit](this.line, this.cursor); // Reverse the string and match a word near beginning // to avoid quadratic time complexity - var leading = StringPrototypeSlice.call(this.line, 0, this.cursor); - var reversed = ArrayPrototypeJoin.call(ArrayPrototypeReverse.call(ArrayFrom(leading)), ""); - var match = RegExpPrototypeExec.call(/^\s*(?:[^\w\s]+|\w+)?/, reversed); - leading = StringPrototypeSlice.call(leading, 0, leading.length - match[0].length); - this.line = leading + StringPrototypeSlice.call(this.line, this.cursor, this.line.length); + var leading = StringPrototypeSlice.$call(this.line, 0, this.cursor); + var reversed = ArrayPrototypeJoin.$call(ArrayPrototypeReverse.$call(ArrayFrom(leading)), ""); + var match = RegExpPrototypeExec.$call(/^\s*(?:[^\w\s]+|\w+)?/, reversed); + leading = StringPrototypeSlice.$call(leading, 0, leading.length - match[0].length); + this.line = leading + StringPrototypeSlice.$call(this.line, this.cursor, this.line.length); this.cursor = leading.length; this[kRefreshLine](); } @@ -2016,18 +2015,18 @@ var _Interface = class Interface extends InterfaceConstructor { [kDeleteWordRight]() { if (this.cursor < this.line.length) { this[kBeforeEdit](this.line, this.cursor); - var trailing = StringPrototypeSlice.call(this.line, this.cursor); - var match = RegExpPrototypeExec.call(/^(?:\s+|\W+|\w+)\s*/, trailing); + var trailing = StringPrototypeSlice.$call(this.line, this.cursor); + var match = RegExpPrototypeExec.$call(/^(?:\s+|\W+|\w+)\s*/, trailing); this.line = - StringPrototypeSlice.call(this.line, 0, this.cursor) + StringPrototypeSlice.call(trailing, match[0].length); + StringPrototypeSlice.$call(this.line, 0, this.cursor) + StringPrototypeSlice.$call(trailing, match[0].length); this[kRefreshLine](); } } [kDeleteLineLeft]() { this[kBeforeEdit](this.line, this.cursor); - var del = StringPrototypeSlice.call(this.line, 0, this.cursor); - this.line = StringPrototypeSlice.call(this.line, this.cursor); + var del = StringPrototypeSlice.$call(this.line, 0, this.cursor); + this.line = StringPrototypeSlice.$call(this.line, this.cursor); this.cursor = 0; this[kPushToKillRing](del); this[kRefreshLine](); @@ -2035,17 +2034,17 @@ var _Interface = class Interface extends InterfaceConstructor { [kDeleteLineRight]() { this[kBeforeEdit](this.line, this.cursor); - var del = StringPrototypeSlice.call(this.line, this.cursor); - this.line = StringPrototypeSlice.call(this.line, 0, this.cursor); + var del = StringPrototypeSlice.$call(this.line, this.cursor); + this.line = StringPrototypeSlice.$call(this.line, 0, this.cursor); this[kPushToKillRing](del); this[kRefreshLine](); } [kPushToKillRing](del) { if (!del || del === this[kKillRing][0]) return; - ArrayPrototypeUnshift.call(this[kKillRing], del); + ArrayPrototypeUnshift.$call(this[kKillRing], del); this[kKillRingCursor] = 0; - while (this[kKillRing].length > kMaxLengthOfKillRing) ArrayPrototypePop.call(this[kKillRing]); + while (this[kKillRing].length > kMaxLengthOfKillRing) ArrayPrototypePop.$call(this[kKillRing]); } [kYank]() { @@ -2066,8 +2065,8 @@ var _Interface = class Interface extends InterfaceConstructor { this[kKillRingCursor] = 0; } var currentYank = this[kKillRing][this[kKillRingCursor]]; - var head = StringPrototypeSlice.call(this.line, 0, this.cursor - lastYank.length); - var tail = StringPrototypeSlice.call(this.line, this.cursor); + var head = StringPrototypeSlice.$call(this.line, 0, this.cursor - lastYank.length); + var tail = StringPrototypeSlice.$call(this.line, this.cursor); this.line = head + currentYank + tail; this.cursor = head.length + currentYank.length; this[kRefreshLine](); @@ -2091,20 +2090,20 @@ var _Interface = class Interface extends InterfaceConstructor { } [kPushToUndoStack](text, cursor) { - if (ArrayPrototypePush.call(this[kUndoStack], { text, cursor }) > kMaxUndoRedoStackSize) { - ArrayPrototypeShift.call(this[kUndoStack]); + if (ArrayPrototypePush.$call(this[kUndoStack], { text, cursor }) > kMaxUndoRedoStackSize) { + ArrayPrototypeShift.$call(this[kUndoStack]); } } [kUndo]() { if (this[kUndoStack].length <= 0) return; - ArrayPrototypePush.call(this[kRedoStack], { + ArrayPrototypePush.$call(this[kRedoStack], { text: this.line, cursor: this.cursor, }); - var entry = ArrayPrototypePop.call(this[kUndoStack]); + var entry = ArrayPrototypePop.$call(this[kUndoStack]); this.line = entry.text; this.cursor = entry.cursor; @@ -2114,12 +2113,12 @@ var _Interface = class Interface extends InterfaceConstructor { [kRedo]() { if (this[kRedoStack].length <= 0) return; - ArrayPrototypePush.call(this[kUndoStack], { + ArrayPrototypePush.$call(this[kUndoStack], { text: this.line, cursor: this.cursor, }); - var entry = ArrayPrototypePop.call(this[kRedoStack]); + var entry = ArrayPrototypePop.$call(this[kRedoStack]); this.line = entry.text; this.cursor = entry.cursor; @@ -2133,7 +2132,7 @@ var _Interface = class Interface extends InterfaceConstructor { var index = this.historyIndex - 1; while ( index >= 0 && - (!StringPrototypeStartsWith.call(this.history[index], search) || this.line === this.history[index]) + (!StringPrototypeStartsWith.$call(this.history[index], search) || this.line === this.history[index]) ) { index--; } @@ -2155,7 +2154,7 @@ var _Interface = class Interface extends InterfaceConstructor { var index = this.historyIndex + 1; while ( index < this.history.length && - (!StringPrototypeStartsWith.call(this.history[index], search) || this.line === this.history[index]) + (!StringPrototypeStartsWith.$call(this.history[index], search) || this.line === this.history[index]) ) { index++; } @@ -2213,7 +2212,7 @@ var _Interface = class Interface extends InterfaceConstructor { * }} */ getCursorPos() { - var strBeforeCursor = this[kPrompt] + StringPrototypeSlice.call(this.line, 0, this.cursor); + var strBeforeCursor = this[kPrompt] + StringPrototypeSlice.$call(this.line, 0, this.cursor); return this[kGetDisplayPos](strBeforeCursor); } @@ -2259,7 +2258,7 @@ var _Interface = class Interface extends InterfaceConstructor { // Activate or deactivate substring search. if ((keyName === "up" || keyName === "down") && !keyCtrl && !keyMeta && !keyShift) { if (this[kSubstringSearch] === null) { - this[kSubstringSearch] = StringPrototypeSlice.call(this.line, 0, this.cursor); + this[kSubstringSearch] = StringPrototypeSlice.$call(this.line, 0, this.cursor); } } else if (this[kSubstringSearch] !== null) { this[kSubstringSearch] = null; @@ -2271,7 +2270,7 @@ var _Interface = class Interface extends InterfaceConstructor { // Undo & Redo if (typeof keySeq === "string") { - switch (StringPrototypeCodePointAt.call(keySeq, 0)) { + switch (StringPrototypeCodePointAt.$call(keySeq, 0)) { case 0x1f: this[kUndo](); return; @@ -2497,13 +2496,13 @@ var _Interface = class Interface extends InterfaceConstructor { // falls through default: if (typeof s === "string" && s) { - var nextMatch = RegExpPrototypeExec.call(lineEnding, s); + var nextMatch = RegExpPrototypeExec.$call(lineEnding, s); if (nextMatch !== null) { - this[kInsertString](StringPrototypeSlice.call(s, 0, nextMatch.index)); + this[kInsertString](StringPrototypeSlice.$call(s, 0, nextMatch.index)); var { lastIndex } = lineEnding; - while ((nextMatch = RegExpPrototypeExec.call(lineEnding, s)) !== null) { + while ((nextMatch = RegExpPrototypeExec.$call(lineEnding, s)) !== null) { this[kLine](); - this[kInsertString](StringPrototypeSlice.call(s, lastIndex, nextMatch.index)); + this[kInsertString](StringPrototypeSlice.$call(s, lastIndex, nextMatch.index)); ({ lastIndex } = lineEnding); } if (lastIndex === s.length) this[kLine](); @@ -2549,7 +2548,7 @@ function Interface(input, output, completer, terminal) { completer = (v, cb) => cb(null, realCompleter(v)); } - InterfaceConstructor.call(this, input, output, completer, terminal); + InterfaceConstructor.$call(this, input, output, completer, terminal); // TODO: Test this if (process.env.TERM === "dumb") { @@ -2879,7 +2878,7 @@ Interface.prototype._tabComplete = function (lastKeypressWasTab) { // Overriding parent method because `this.completer` in the legacy // implementation takes a callback instead of being an async function. this.pause(); - var string = StringPrototypeSlice.call(this.line, 0, this.cursor); + var string = StringPrototypeSlice.$call(this.line, 0, this.cursor); this.completer(string, (err, value) => { this.resume(); @@ -2980,7 +2979,7 @@ class Readline { var data = y == null ? CSI`${x + 1}G` : CSI`${y + 1};${x + 1}H`; if (this.#autoCommit) process.nextTick(() => this.#stream.write(data)); - else ArrayPrototypePush.call(this.#todo, data); + else ArrayPrototypePush.$call(this.#todo, data); return this; } @@ -3010,7 +3009,7 @@ class Readline { data += CSI`${dy}B`; } if (this.#autoCommit) process.nextTick(() => this.#stream.write(data)); - else ArrayPrototypePush.call(this.#todo, data); + else ArrayPrototypePush.$call(this.#todo, data); } return this; } @@ -3028,7 +3027,7 @@ class Readline { var data = dir < 0 ? kClearToLineBeginning : dir > 0 ? kClearToLineEnd : kClearLine; if (this.#autoCommit) process.nextTick(() => this.#stream.write(data)); - else ArrayPrototypePush.call(this.#todo, data); + else ArrayPrototypePush.$call(this.#todo, data); return this; } @@ -3040,7 +3039,7 @@ class Readline { if (this.#autoCommit) { process.nextTick(() => this.#stream.write(kClearScreenDown)); } else { - ArrayPrototypePush.call(this.#todo, kClearScreenDown); + ArrayPrototypePush.$call(this.#todo, kClearScreenDown); } return this; } @@ -3053,7 +3052,7 @@ class Readline { */ commit() { return new Promise(resolve => { - this.#stream.write(ArrayPrototypeJoin.call(this.#todo, ""), resolve); + this.#stream.write(ArrayPrototypeJoin.$call(this.#todo, ""), resolve); this.#todo = []; }); } diff --git a/src/js/node/stream.js b/src/js/node/stream.js index f9d4377b5..5297c033c 100644 --- a/src/js/node/stream.js +++ b/src/js/node/stream.js @@ -106,10 +106,10 @@ var require_primordials = __commonJS({ }, Error, FunctionPrototypeCall(fn, thisArgs, ...args) { - return fn.call(thisArgs, ...args); + return fn.$call(thisArgs, ...args); }, FunctionPrototypeSymbolHasInstance(self, instance) { - return Function.prototype[Symbol.hasInstance].call(self, instance); + return Function.prototype[Symbol.hasInstance].$call(self, instance); }, MathFloor: Math.floor, Number, @@ -143,7 +143,7 @@ var require_primordials = __commonJS({ PromiseReject(err) { return Promise.reject(err); }, - ReflectApply: Reflect.apply, + ReflectApply: $getByIdDirect(Reflect, "apply"), RegExpPrototypeTest(self, value) { return self.test(value); }, @@ -210,7 +210,7 @@ var require_util = __commonJS({ return; } called = true; - callback.apply(this, args); + callback.$apply(this, args); }; }, createDeferredPromise: function () { @@ -1161,7 +1161,7 @@ var require_end_of_stream = __commonJS({ return; } if (!readable || readableFinished) { - callback.call(stream); + callback.$call(stream); } }; let readableFinished = isReadableFinished(stream, false); @@ -1174,26 +1174,26 @@ var require_end_of_stream = __commonJS({ return; } if (!writable || writableFinished) { - callback.call(stream); + callback.$call(stream); } }; const onerror = err => { - callback.call(stream, err); + callback.$call(stream, err); }; let closed = isClosed(stream); const onclose = () => { closed = true; const errored = isWritableErrored(stream) || isReadableErrored(stream); if (errored && typeof errored !== "boolean") { - return callback.call(stream, errored); + return callback.$call(stream, errored); } if (readable && !readableFinished && isReadableNodeStream(stream, true)) { - if (!isReadableFinished(stream, false)) return callback.call(stream, new ERR_STREAM_PREMATURE_CLOSE()); + if (!isReadableFinished(stream, false)) return callback.$call(stream, new ERR_STREAM_PREMATURE_CLOSE()); } if (writable && !writableFinished) { - if (!isWritableFinished(stream, false)) return callback.call(stream, new ERR_STREAM_PREMATURE_CLOSE()); + if (!isWritableFinished(stream, false)) return callback.$call(stream, new ERR_STREAM_PREMATURE_CLOSE()); } - callback.call(stream); + callback.$call(stream); }; const onrequest = () => { stream.req.on("finish", onfinish); @@ -1263,7 +1263,7 @@ var require_end_of_stream = __commonJS({ const abort = () => { const endCallback = callback; cleanup(); - endCallback.call( + endCallback.$call( stream, new AbortError(void 0, { cause: options.signal.reason, @@ -1276,7 +1276,7 @@ var require_end_of_stream = __commonJS({ const originalCallback = callback; callback = once((...args) => { options.signal.removeEventListener("abort", abort); - originalCallback.apply(stream, args); + originalCallback.$apply(stream, args); }); options.signal.addEventListener("abort", abort); } @@ -1450,7 +1450,7 @@ var require_operators = __commonJS({ resume = null; } } - }.call(this); + }.$call(this); } function asIndexedPairs(options = void 0) { if (options != null) { @@ -1476,10 +1476,10 @@ var require_operators = __commonJS({ } yield [index++, val]; } - }.call(this); + }.$call(this); } async function some(fn, options = void 0) { - for await (const unused of filter.call(this, fn, options)) { + for await (const unused of filter.$call(this, fn, options)) { return true; } return false; @@ -1488,7 +1488,7 @@ var require_operators = __commonJS({ if (typeof fn !== "function") { throw new ERR_INVALID_ARG_TYPE("fn", ["Function", "AsyncFunction"], fn); } - return !(await some.call( + return !(await some.$call( this, async (...args) => { return !(await fn(...args)); @@ -1497,7 +1497,7 @@ var require_operators = __commonJS({ )); } async function find(fn, options) { - for await (const result of filter.call(this, fn, options)) { + for await (const result of filter.$call(this, fn, options)) { return result; } return void 0; @@ -1510,7 +1510,7 @@ var require_operators = __commonJS({ await fn(value, options2); return kEmpty; } - for await (const unused of map.call(this, forEachFn, options)); + for await (const unused of map.$call(this, forEachFn, options)); } function filter(fn, options) { if (typeof fn !== "function") { @@ -1522,7 +1522,7 @@ var require_operators = __commonJS({ } return kEmpty; } - return map.call(this, filterFn, options); + return map.$call(this, filterFn, options); } var ReduceAwareErrMissingArgs = class extends ERR_MISSING_ARGS { constructor() { @@ -1622,12 +1622,12 @@ var require_operators = __commonJS({ return result; } function flatMap(fn, options) { - const values = map.call(this, fn, options); + const values = map.$call(this, fn, options); return async function* flatMap2() { for await (const val of values) { yield* val; } - }.call(this); + }.$call(this); } function toIntegerOrInfinity(number) { number = Number2(number); @@ -1673,7 +1673,7 @@ var require_operators = __commonJS({ yield val; } } - }.call(this); + }.$call(this); } function take(number, options = void 0) { if (options != null) { @@ -1711,7 +1711,7 @@ var require_operators = __commonJS({ return; } } - }.call(this); + }.$call(this); } module.exports.streamReturningOperators = { asIndexedPairs, @@ -2001,7 +2001,7 @@ var require_legacy = __commonJS({ function Stream(options) { if (!(this instanceof Stream)) return new Stream(options); - EE.call(this, options); + EE.$call(this, options); } Stream.prototype = {}; ObjectSetPrototypeOf(Stream.prototype, EE.prototype); @@ -2274,7 +2274,7 @@ var require_readable = __commonJS({ if (typeof construct === "function") this._construct = construct; if (signal && !isDuplex) addAbortSignal(signal, this); } - Stream.call(this, options); + Stream.$call(this, options); destroyImpl.construct(this, () => { if (this._readableState.needReadable) { @@ -2287,7 +2287,7 @@ var require_readable = __commonJS({ ObjectSetPrototypeOf(Readable, Stream); Readable.prototype.on = function (ev, fn) { - const res = Stream.prototype.on.call(this, ev, fn); + const res = Stream.prototype.on.$call(this, ev, fn); const state = this._readableState; if (ev === "data") { state.readableListening = this.listenerCount("readable") > 0; @@ -2975,7 +2975,7 @@ var require_readable = __commonJS({ }; Readable.prototype.addListener = Readable.prototype.on; Readable.prototype.removeListener = function (ev, fn) { - const res = Stream.prototype.removeListener.call(this, ev, fn); + const res = Stream.prototype.removeListener.$call(this, ev, fn); if (ev === "readable") { runOnNextTick(updateReadableListening, this); } @@ -2983,7 +2983,7 @@ var require_readable = __commonJS({ }; Readable.prototype.off = Readable.prototype.removeListener; Readable.prototype.removeAllListeners = function (ev) { - const res = Stream.prototype.removeAllListeners.apply(this, arguments); + const res = Stream.prototype.removeAllListeners.$apply(this, arguments); if (ev === "readable" || ev === void 0) { runOnNextTick(updateReadableListening, this); } @@ -3433,7 +3433,7 @@ var require_writable = __commonJS({ if (typeof options.construct === "function") this._construct = options.construct; if (options.signal) addAbortSignal(options.signal, this); } - Stream.call(this, options); + Stream.$call(this, options); destroyImpl.construct(this, () => { const state = this._writableState; @@ -4003,7 +4003,7 @@ var require_writable = __commonJS({ if (!state.destroyed && (state.bufferedIndex < state.buffered.length || state[kOnFinished].length)) { runOnNextTick(errorBuffer, state); } - destroy.call(this, err, cb); + destroy.$call(this, err, cb); return this; }; Writable.prototype._undestroy = destroyImpl.undestroy; @@ -4387,8 +4387,8 @@ var require_duplex = __commonJS({ function Duplex(options) { if (!(this instanceof Duplex)) return new Duplex(options); - Readable.call(this, options); - Writable.call(this, options); + Readable.$call(this, options); + Writable.$call(this, options); if (options) { this.allowHalfOpen = options.allowHalfOpen !== false; @@ -4473,7 +4473,7 @@ var require_transform = __commonJS({ var Duplex = require_duplex(); function Transform(options) { if (!(this instanceof Transform)) return new Transform(options); - Duplex.call(this, options); + Duplex.$call(this, options); this._readableState.sync = false; this[kCallback] = null; @@ -4519,7 +4519,7 @@ var require_transform = __commonJS({ } function prefinish() { if (this._final !== final) { - final.call(this); + final.$call(this); } } Transform.prototype._final = final; @@ -4570,7 +4570,7 @@ var require_passthrough = __commonJS({ function PassThrough(options) { if (!(this instanceof PassThrough)) return new PassThrough(options); - Transform.call(this, options); + Transform.$call(this, options); } PassThrough.prototype = {}; @@ -4643,7 +4643,7 @@ var require_pipeline = __commonJS({ if (!Readable) { Readable = require_readable(); } - yield* Readable.prototype[SymbolAsyncIterator].call(val); + yield* Readable.prototype[SymbolAsyncIterator].$call(val); } async function pump(iterable, writable, finish, { end }) { let error; @@ -4806,7 +4806,7 @@ var require_pipeline = __commonJS({ const then = (_ret = ret) === null || _ret === void 0 ? void 0 : _ret.then; if (typeof then === "function") { finishCount++; - then.call( + then.$call( ret, val => { value = val; @@ -5478,7 +5478,7 @@ const _fileSink = Symbol("fileSink"); const _native = Symbol("native"); function NativeWritable(pathOrFdOrSink, options = {}) { - Writable.call(this, options); + Writable.$call(this, options); this[_native] = true; @@ -5521,7 +5521,7 @@ const WritablePrototypeWrite = Writable.prototype.write; NativeWritable.prototype.write = function NativeWritablePrototypeWrite(chunk, encoding, cb, native) { if (!(native ?? this[_native])) { this[_native] = false; - return WritablePrototypeWrite.call(this, chunk, encoding, cb); + return WritablePrototypeWrite.$call(this, chunk, encoding, cb); } var fileSink = this[_fileSink] ?? NativeWritable_lazyConstruct(this); @@ -5540,13 +5540,17 @@ NativeWritable.prototype.write = function NativeWritablePrototypeWrite(chunk, en return false; } fileSink.flush(true); + + if (typeof encoding === "function") { + cb = encoding; + } // TODO: Should we just have a calculation based on encoding and length of chunk? if (cb) cb(null, chunk.byteLength); return true; }; const WritablePrototypeEnd = Writable.prototype.end; NativeWritable.prototype.end = function end(chunk, encoding, cb, native) { - return WritablePrototypeEnd.call(this, chunk, encoding, cb, native ?? this[_native]); + return WritablePrototypeEnd.$call(this, chunk, encoding, cb, native ?? this[_native]); }; function NativeWritable_internalDestroy(error, cb) { diff --git a/src/js/node/tls.js b/src/js/node/tls.js index bdf06faac..ef9232d7b 100644 --- a/src/js/node/tls.js +++ b/src/js/node/tls.js @@ -42,16 +42,16 @@ function isValidTLSArray(obj) { } function unfqdn(host) { - return RegExpPrototypeSymbolReplace.call(/[.]$/, host, ""); + return RegExpPrototypeSymbolReplace.$call(/[.]$/, host, ""); } // String#toLowerCase() is locale-sensitive so we use // a conservative version that only lowercases A-Z. function toLowerCase(c) { - return StringFromCharCode.call(32 + StringPrototypeCharCodeAt.call(c, 0)); + return StringFromCharCode.$call(32 + StringPrototypeCharCodeAt.$call(c, 0)); } function splitHost(host) { - return StringPrototypeSplit.call(RegExpPrototypeSymbolReplace.call(/[A-Z]/g, unfqdn(host), toLowerCase), "."); + return StringPrototypeSplit.$call(RegExpPrototypeSymbolReplace.$call(/[A-Z]/g, unfqdn(host), toLowerCase), "."); } function check(hostParts, pattern, wildcards) { @@ -63,14 +63,14 @@ function check(hostParts, pattern, wildcards) { if (hostParts.length !== patternParts.length) return false; // Pattern has empty components, e.g. "bad..example.com". - if (ArrayPrototypeIncludes.call(patternParts, "")) return false; + if (ArrayPrototypeIncludes.$call(patternParts, "")) return false; // RFC 6125 allows IDNA U-labels (Unicode) in names but we have no // good way to detect their encoding or normalize them so we simply // reject them. Control characters and blanks are rejected as well // because nothing good can come from accepting them. - const isBad = s => RegExpPrototypeExec.call(/[^\u0021-\u007F]/u, s) !== null; - if (ArrayPrototypeSome.call(patternParts, isBad)) return false; + const isBad = s => RegExpPrototypeExec.$call(/[^\u0021-\u007F]/u, s) !== null; + if (ArrayPrototypeSome.$call(patternParts, isBad)) return false; // Check host parts from right to left first. for (let i = hostParts.length - 1; i > 0; i -= 1) { @@ -79,12 +79,12 @@ function check(hostParts, pattern, wildcards) { const hostSubdomain = hostParts[0]; const patternSubdomain = patternParts[0]; - const patternSubdomainParts = StringPrototypeSplit.call(patternSubdomain, "*"); + const patternSubdomainParts = StringPrototypeSplit.$call(patternSubdomain, "*"); // Short-circuit when the subdomain does not contain a wildcard. // RFC 6125 does not allow wildcard substitution for components // containing IDNA A-labels (Punycode) so match those verbatim. - if (patternSubdomainParts.length === 1 || StringPrototypeIncludes.call(patternSubdomain, "xn--")) + if (patternSubdomainParts.length === 1 || StringPrototypeIncludes.$call(patternSubdomain, "xn--")) return hostSubdomain === patternSubdomain; if (!wildcards) return false; @@ -99,9 +99,9 @@ function check(hostParts, pattern, wildcards) { if (prefix.length + suffix.length > hostSubdomain.length) return false; - if (!StringPrototypeStartsWith.call(hostSubdomain, prefix)) return false; + if (!StringPrototypeStartsWith.$call(hostSubdomain, prefix)) return false; - if (!StringPrototypeEndsWith.call(hostSubdomain, suffix)) return false; + if (!StringPrototypeEndsWith.$call(hostSubdomain, suffix)) return false; return true; } @@ -118,12 +118,12 @@ function splitEscapedAltNames(altNames) { let currentToken = ""; let offset = 0; while (offset !== altNames.length) { - const nextSep = StringPrototypeIndexOf.call(altNames, ", ", offset); - const nextQuote = StringPrototypeIndexOf.call(altNames, '"', offset); + const nextSep = StringPrototypeIndexOf.$call(altNames, ", ", offset); + const nextQuote = StringPrototypeIndexOf.$call(altNames, '"', offset); if (nextQuote !== -1 && (nextSep === -1 || nextQuote < nextSep)) { // There is a quote character and there is no separator before the quote. - currentToken += StringPrototypeSubstring.call(altNames, offset, nextQuote); - const match = RegExpPrototypeExec.call(jsonStringPattern, StringPrototypeSubstring.call(altNames, nextQuote)); + currentToken += StringPrototypeSubstring.$call(altNames, offset, nextQuote); + const match = RegExpPrototypeExec.$call(jsonStringPattern, StringPrototypeSubstring.$call(altNames, nextQuote)); if (!match) { let error = new SyntaxError("ERR_TLS_CERT_ALTNAME_FORMAT: Invalid subject alternative name string"); error.name = ERR_TLS_CERT_ALTNAME_FORMAT; @@ -133,16 +133,16 @@ function splitEscapedAltNames(altNames) { offset = nextQuote + match[0].length; } else if (nextSep !== -1) { // There is a separator and no quote before it. - currentToken += StringPrototypeSubstring.call(altNames, offset, nextSep); - ArrayPrototypePush.call(result, currentToken); + currentToken += StringPrototypeSubstring.$call(altNames, offset, nextSep); + ArrayPrototypePush.$call(result, currentToken); currentToken = ""; offset = nextSep + 2; } else { - currentToken += StringPrototypeSubstring.call(altNames, offset); + currentToken += StringPrototypeSubstring.$call(altNames, offset); offset = altNames.length; } } - ArrayPrototypePush.call(result, currentToken); + ArrayPrototypePush.$call(result, currentToken); return result; } @@ -155,14 +155,14 @@ function checkServerIdentity(hostname, cert) { hostname = "" + hostname; if (altNames) { - const splitAltNames = StringPrototypeIncludes.call(altNames, '"') + const splitAltNames = StringPrototypeIncludes.$call(altNames, '"') ? splitEscapedAltNames(altNames) - : StringPrototypeSplit.call(altNames, ", "); - ArrayPrototypeForEach.call(splitAltNames, name => { - if (StringPrototypeStartsWith.call(name, "DNS:")) { - ArrayPrototypePush.call(dnsNames, StringPrototypeSlice.call(name, 4)); - } else if (StringPrototypeStartsWith.call(name, "IP Address:")) { - ArrayPrototypePush.call(ips, canonicalizeIP(StringPrototypeSlice.call(name, 11))); + : StringPrototypeSplit.$call(altNames, ", "); + ArrayPrototypeForEach.$call(splitAltNames, name => { + if (StringPrototypeStartsWith.$call(name, "DNS:")) { + ArrayPrototypePush.$call(dnsNames, StringPrototypeSlice.$call(name, 4)); + } else if (StringPrototypeStartsWith.$call(name, "IP Address:")) { + ArrayPrototypePush.$call(ips, canonicalizeIP(StringPrototypeSlice.$call(name, 11))); } }); } @@ -172,20 +172,20 @@ function checkServerIdentity(hostname, cert) { hostname = unfqdn(hostname); // Remove trailing dot for error messages. if (net.isIP(hostname)) { - valid = ArrayPrototypeIncludes.call(ips, canonicalizeIP(hostname)); - if (!valid) reason = `IP: ${hostname} is not in the cert's list: ` + ArrayPrototypeJoin.call(ips, ", "); + valid = ArrayPrototypeIncludes.$call(ips, canonicalizeIP(hostname)); + if (!valid) reason = `IP: ${hostname} is not in the cert's list: ` + ArrayPrototypeJoin.$call(ips, ", "); } else if (dnsNames.length > 0 || subject?.CN) { const hostParts = splitHost(hostname); const wildcard = pattern => check(hostParts, pattern, true); if (dnsNames.length > 0) { - valid = ArrayPrototypeSome.call(dnsNames, wildcard); + valid = ArrayPrototypeSome.$call(dnsNames, wildcard); if (!valid) reason = `Host: ${hostname}. is not in the cert's altnames: ${altNames}`; } else { // Match against Common Name only if no supported identifiers exist. const cn = subject.CN; - if (Array.isArray(cn)) valid = ArrayPrototypeSome.call(cn, wildcard); + if (Array.isArray(cn)) valid = ArrayPrototypeSome.$call(cn, wildcard); else if (cn) valid = wildcard(cn); if (!valid) reason = `Host: ${hostname}. is not cert's CN: ${cn}`; @@ -281,7 +281,7 @@ function translatePeerCertificate(c) { const info = c.infoAccess; c.infoAccess = { __proto__: null }; // XXX: More key validation? - RegExpPrototypeSymbolReplace.call(/([^\n:]*):([^\n]*)(?:\n|$)/g, info, (all, key, val) => { + RegExpPrototypeSymbolReplace.$call(/([^\n:]*):([^\n]*)(?:\n|$)/g, info, (all, key, val) => { if (val.charCodeAt(0) === 0x22) { // The translatePeerCertificate function is only // used on internally created legacy certificate @@ -290,7 +290,7 @@ function translatePeerCertificate(c) { // so this should never throw. val = JSONParse(val); } - if (key in c.infoAccess) ArrayPrototypePush.call(c.infoAccess[key], val); + if (key in c.infoAccess) ArrayPrototypePush.$call(c.infoAccess[key], val); else c.infoAccess[key] = [val]; }); } @@ -306,18 +306,15 @@ const TLSSocket = (function (InternalTLSSocket) { value: "TLSSocket", enumerable: false, }); - - return Object.defineProperty( - function Socket(options) { - return new InternalTLSSocket(options); - }, - Symbol.hasInstance, - { - value(instance) { - return instance instanceof InternalTLSSocket; - }, + function Socket(options) { + return new InternalTLSSocket(options); + } + Socket.prototype = InternalTLSSocket.prototype; + return Object.defineProperty(Socket, Symbol.hasInstance, { + value(instance) { + return instance instanceof InternalTLSSocket; }, - ); + }); })( class TLSSocket extends InternalTCPSocket { #secureContext; @@ -630,7 +627,7 @@ function getCiphers() { function convertProtocols(protocols) { const lens = new Array(protocols.length); const buff = Buffer.allocUnsafe( - ArrayPrototypeReduce.call( + ArrayPrototypeReduce.$call( protocols, (p, c, i) => { const len = Buffer.byteLength(c); diff --git a/src/js/node/tty.js b/src/js/node/tty.js index d5645c6da..6e138b0cf 100644 --- a/src/js/node/tty.js +++ b/src/js/node/tty.js @@ -1,36 +1,43 @@ const { ttySetMode, isatty, getWindowSize: _getWindowSize } = $lazy("tty"); +// primordials +const NumberIsInteger = Number.isInteger; + function ReadStream(fd) { if (!(this instanceof ReadStream)) return new ReadStream(fd); if (fd >> 0 !== fd || fd < 0) throw new RangeError("fd must be a positive integer"); - const stream = require("node:fs").ReadStream.call(this, "", { + const stream = require("node:fs").ReadStream.$call(this, "", { fd, }); + Object.setPrototypeOf(stream, ReadStream.prototype); stream.isRaw = false; - stream.isTTY = isatty(stream.fd); + stream.isTTY = true; + + $assert(stream instanceof ReadStream); return stream; } Object.defineProperty(ReadStream, "prototype", { get() { - const Real = require("node:fs").ReadStream.prototype; + const Prototype = Object.create(require("node:fs").ReadStream.prototype); - Object.defineProperty(ReadStream, "prototype", { value: Real }); - ReadStream.prototype.setRawMode = function (flag) { + Prototype.setRawMode = function (flag) { const mode = flag ? 1 : 0; const err = ttySetMode(this.fd, mode); if (err) { - this.emit("error", new Error("setRawMode failed with errno:", err)); + this.emit("error", new Error("setRawMode failed with errno: " + err)); return this; } this.isRaw = flag; return this; }; - return Real; + Object.defineProperty(ReadStream, "prototype", { value: Prototype }); + + return Prototype; }, enumerable: true, configurable: true, @@ -95,7 +102,7 @@ function WriteStream(fd) { if (!(this instanceof WriteStream)) return new WriteStream(fd); if (fd >> 0 !== fd || fd < 0) throw new RangeError("fd must be a positive integer"); - const stream = require("node:fs").WriteStream.call(this, "", { + const stream = require("node:fs").WriteStream.$call(this, "", { fd, }); @@ -185,7 +192,7 @@ Object.defineProperty(WriteStream, "prototype", { // Lazy load for startup performance. if (OSRelease === undefined) { const { release } = require("node:os"); - OSRelease = StringPrototypeSplit(release(), "."); + OSRelease = release().split("."); } // Windows 10 build 10586 is the first Windows release that supports 256 // colors. Windows 10 build 14931 is the first release that supports @@ -216,14 +223,12 @@ Object.defineProperty(WriteStream, "prototype", { } if ("TEAMCITY_VERSION" in env) { - return RegExpPrototypeExec(/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/, env.TEAMCITY_VERSION) !== null - ? COLORS_16 - : COLORS_2; + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? COLORS_16 : COLORS_2; } switch (env.TERM_PROGRAM) { case "iTerm.app": - if (!env.TERM_PROGRAM_VERSION || RegExpPrototypeExec(/^[0-2]\./, env.TERM_PROGRAM_VERSION) !== null) { + if (!env.TERM_PROGRAM_VERSION || /^[0-2]\./.test(env.TERM_PROGRAM_VERSION)) { return COLORS_256; } return COLORS_16m; @@ -239,16 +244,16 @@ Object.defineProperty(WriteStream, "prototype", { } if (env.TERM) { - if (RegExpPrototypeExec(/^xterm-256/, env.TERM) !== null) { + if (/^xterm-256/.test(env.TERM) !== null) { return COLORS_256; } - const termEnv = StringPrototypeToLowerCase(env.TERM); + const termEnv = env.TERM.toLowerCase(); if (TERM_ENVS[termEnv]) { return TERM_ENVS[termEnv]; } - if (ArrayPrototypeSome(TERM_ENVS_REG_EXP, term => RegExpPrototypeExec(term, termEnv) !== null)) { + if (TERM_ENVS_REG_EXP.some(term => term.test(termEnv))) { return COLORS_16; } } @@ -286,7 +291,7 @@ Object.defineProperty(WriteStream, "prototype", { var validateInteger = (value, name, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) => { if (typeof value !== "number") throw new ERR_INVALID_ARG_TYPE(name, "number", value); - if (!Number.isInteger(value)) throw new ERR_OUT_OF_RANGE(name, "an integer", value); + if (!NumberIsInteger(value)) throw new ERR_OUT_OF_RANGE(name, "an integer", value); if (value < min || value > max) throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value); }; diff --git a/src/js/node/url.js b/src/js/node/url.js index 3b6b57ac2..f5823cdc2 100644 --- a/src/js/node/url.js +++ b/src/js/node/url.js @@ -370,7 +370,8 @@ Url.prototype.parse = function (url, parseQueryString, slashesDenoteHost) { this.search = rest.substr(qm); this.query = rest.substr(qm + 1); if (parseQueryString) { - this.query = new URLSearchParams(this.query); + const query = this.query; + this.query = new URLSearchParams(query).toJSON(); } rest = rest.slice(0, qm); } else if (parseQueryString) { @@ -409,7 +410,7 @@ function urlFormat(obj) { obj = urlParse(obj); } if (!(obj instanceof Url)) { - return Url.prototype.format.call(obj); + return Url.prototype.format.$call(obj); } return obj.format(); } diff --git a/src/js/node/util.js b/src/js/node/util.js index 10dc95e2e..dae341448 100644 --- a/src/js/node/util.js +++ b/src/js/node/util.js @@ -1,20 +1,13 @@ // Hardcoded module "node:util" const types = require("node:util/types"); +/** @type {import('node-inspect-extracted')} */ +const utl = require("internal/util/inspect"); var cjs_exports = {}; -function isBufferInterface({ copy, fill, readUint8 }) { - return typeof copy === "function" && typeof fill === "function" && typeof readUint8 === "function"; -} - function isBuffer(value) { - return ( - Buffer.isBuffer(value) || - // incase it ends up as a browserify buffer - (typeof value === "object" && isBufferInterface(value || {})) - ); + return Buffer.isBuffer(value); } - function isFunction(value) { return typeof value === "function"; } @@ -22,55 +15,11 @@ function isFunction(value) { const deepEquals = Bun.deepEquals; const isDeepStrictEqual = (a, b) => deepEquals(a, b, true); var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors; -var formatRegExp = /%[sdjfoc%]/g; -// This function is nowhere near what Node.js does but it is close enough of a shim. -function formatWithOptions(inspectOptions, f) { - if (!isString(f)) { - var objects = []; - for (var i = 0; i < arguments.length; i++) { - objects.push(inspect(arguments[i], inspectOptions)); - } - return objects.join(" "); - } - var i = 2; - var args = arguments; - var len = args.length; - var str = String(f).replace(formatRegExp, function (x2) { - if (x2 === "%%") return "%"; - if (i >= len) return x2; - switch (x2) { - case "%s": - return String(args[i++]); - case "%f": - return Number(args[i++]); - case "%d": - return Math.round(Number(args[i++])); - case "%j": - try { - return JSON.stringify(args[i++]); - } catch (_) { - return "[Circular]"; - } - case "%o": - return inspect(args[i++], { showHidden: true, showProxy: true, ...inspectOptions }); - case "%O": - return inspect(args[i++], { showHidden: true, showProxy: true, ...inspectOptions }); - default: - return x2; - } - }); - for (var x = args[i]; i < len; x = args[++i]) { - if (isNull(x) || !isObject(x)) { - str += " " + x; - } else { - str += " " + inspect(x, inspectOptions); - } - } - return str; -} -function format(...args) { - return formatWithOptions({}, ...args); -} + +const inspect = utl.inspect; +const formatWithOptions = utl.formatWithOptions; +const format = utl.format; +const stripVTControlCharacters = utl.stripVTControlCharacters; function deprecate(fn, msg, code) { if (process.noDeprecation === true) { @@ -91,7 +40,7 @@ function deprecate(fn, msg, code) { } warned = true; } - return fn.apply(this, arguments); + return fn.$apply(this, arguments); } return deprecated; } @@ -114,7 +63,7 @@ function debuglog(set) { if (debugEnvRegex.test(set)) { var pid = process.pid; debugs[set] = function () { - var msg = format.apply(cjs_exports, arguments); + var msg = format.$apply(cjs_exports, arguments); console.error("%s %d: %s", set, pid, msg); }; } else { @@ -123,277 +72,6 @@ function debuglog(set) { } return debugs[set]; } -var kInspectCustom = Symbol.for("nodejs.util.inspect.custom"); -function inspect(obj, opts) { - var ctx = { - seen: [], - stylize: stylizeNoColor, - }; - if (arguments.length >= 3) ctx.depth = arguments[2]; - if (arguments.length >= 4) ctx.colors = arguments[3]; - if (isBoolean(opts)) { - ctx.showHidden = opts; - } else if (opts) { - _extend(ctx, opts); - } - if (isUndefined(ctx.showHidden)) ctx.showHidden = false; - if (isUndefined(ctx.depth)) ctx.depth = 2; - if (isUndefined(ctx.colors)) ctx.colors = false; - if (isUndefined(ctx.customInspect)) ctx.customInspect = true; - if (ctx.colors) ctx.stylize = stylizeWithColor; - return formatValue(ctx, obj, ctx.depth); -} -inspect.colors = { - bold: [1, 22], - italic: [3, 23], - underline: [4, 24], - inverse: [7, 27], - white: [37, 39], - grey: [90, 39], - black: [30, 39], - blue: [34, 39], - cyan: [36, 39], - green: [32, 39], - magenta: [35, 39], - red: [31, 39], - yellow: [33, 39], -}; -inspect.styles = { - special: "cyan", - number: "yellow", - boolean: "yellow", - undefined: "grey", - null: "bold", - string: "green", - date: "magenta", - regexp: "red", -}; -inspect.custom = kInspectCustom; -// JS polyfill doesnt support all these options -inspect.defaultOptions = { - showHidden: false, - depth: 2, - colors: false, - customInspect: true, - showProxy: false, - maxArrayLength: 100, - maxStringLength: 10000, - breakLength: 80, - compact: 3, - sorted: false, - getters: false, - numericSeparator: false, -}; -function stylizeWithColor(str, styleType) { - const style = inspect.styles[styleType]; - if (style !== undefined) { - const color = inspect.colors[style]; - if (color !== undefined) return `\u001b[${color[0]}m${str}\u001b[${color[1]}m`; - } - return str; -} -function stylizeNoColor(str, styleType) { - return str; -} -function arrayToHash(array) { - var hash = {}; - array.forEach(function (val, idx) { - hash[val] = true; - }); - return hash; -} -function formatValue(ctx, value, recurseTimes) { - if (ctx.customInspect && value) { - const customInspect = value[kInspectCustom]; - if (isFunction(customInspect)) { - var ret = customInspect.call(value, recurseTimes, ctx, inspect); - if (!isString(ret)) { - ret = formatValue(ctx, ret, recurseTimes); - } - return ret; - } - } - var primitive = formatPrimitive(ctx, value); - if (primitive) { - return primitive; - } - var keys = Object.keys(value).concat(Object.getOwnPropertySymbols(value)); - var visibleKeys = arrayToHash(keys); - if (ctx.showHidden) { - keys = Object.getOwnPropertyNames(value); - } - if (isError(value) && (keys.indexOf("message") >= 0 || keys.indexOf("description") >= 0)) { - return formatError(value); - } - if (keys.length === 0) { - if (isFunction(value)) { - var name = value.name ? ": " + value.name : ""; - return ctx.stylize("[Function" + name + "]", "special"); - } - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), "regexp"); - } - if (isDate(value)) { - return ctx.stylize(Date.prototype.toString.call(value), "date"); - } - if (isError(value)) { - return formatError(value); - } - } - var base = "", - array = false, - braces = ["{", "}"]; - if ($isArray(value)) { - array = true; - braces = ["[", "]"]; - } - if (isFunction(value)) { - var n = value.name ? ": " + value.name : ""; - base = " [Function" + n + "]"; - } - if (isRegExp(value)) { - base = " " + RegExp.prototype.toString.call(value); - } - if (isDate(value)) { - base = " " + Date.prototype.toUTCString.call(value); - } - if (isError(value)) { - base = " " + formatError(value); - } - if (keys.length === 0 && (!array || value.length == 0)) { - return braces[0] + base + braces[1]; - } - if (recurseTimes < 0) { - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), "regexp"); - } else { - return ctx.stylize("[Object]", "special"); - } - } - ctx.seen.push(value); - var output; - if (array) { - output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); - } else { - output = keys.map(function (key) { - return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); - }); - } - ctx.seen.pop(); - return reduceToSingleString(output, base, braces); -} -function formatPrimitive(ctx, value) { - if (isUndefined(value)) return ctx.stylize("undefined", "undefined"); - if (isString(value)) { - var simple = "'" + JSON.stringify(value).replace(/^"|"$/g, "").replace(/'/g, "\\'").replace(/\\"/g, '"') + "'"; - return ctx.stylize(simple, "string"); - } - if (isNumber(value)) return ctx.stylize("" + value, "number"); - if (isBoolean(value)) return ctx.stylize("" + value, "boolean"); - if (isNull(value)) return ctx.stylize("null", "null"); -} -function formatError(value) { - return "[" + Error.prototype.toString.call(value) + "]"; -} -function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { - var output = []; - for (var i = 0, l = value.length; i < l; ++i) { - if (hasOwnProperty(value, String(i))) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true)); - } else { - output.push(""); - } - } - keys.forEach(function (key) { - if (!key.match(/^\d+$/)) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)); - } - }); - return output; -} -function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { - var name, str, desc; - desc = Object.getOwnPropertyDescriptor(value, key) || { - value: value[key], - }; - if (desc.get) { - if (desc.set) { - str = ctx.stylize("[Getter/Setter]", "special"); - } else { - str = ctx.stylize("[Getter]", "special"); - } - } else { - if (desc.set) { - str = ctx.stylize("[Setter]", "special"); - } - } - if (!hasOwnProperty(visibleKeys, key)) { - name = "[" + (typeof key === "symbol" ? key.description : key) + "]"; - } - if (typeof key === "symbol") { - name = "[" + ctx.stylize(`Symbol(${key.description})`, "string") + "]"; - } - if (!str) { - if (ctx.seen.indexOf(desc.value) < 0) { - if (isNull(recurseTimes)) { - str = formatValue(ctx, desc.value, null); - } else { - str = formatValue(ctx, desc.value, recurseTimes - 1); - } - if (str.indexOf("\n") > -1) { - if (array) { - str = str - .split("\n") - .map(function (line) { - return " " + line; - }) - .join("\n") - .substr(2); - } else { - str = - "\n" + - str - .split("\n") - .map(function (line) { - return " " + line; - }) - .join("\n"); - } - } - } else { - str = ctx.stylize("[Circular]", "special"); - } - } - if (isUndefined(name)) { - if (array && key.match(/^\d+$/)) { - return str; - } - name = JSON.stringify("" + key); - if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { - name = name.substr(1, name.length - 2); - name = ctx.stylize(name, "name"); - } else { - name = name - .replace(/'/g, "\\'") - .replace(/\\"/g, '"') - .replace(/(^"|"$)/g, "'"); - name = ctx.stylize(name, "string"); - } - } - return name + ": " + str; -} -function reduceToSingleString(output, base, braces) { - var numLinesEst = 0; - var length = output.reduce(function (prev, cur) { - numLinesEst++; - if (cur.indexOf("\n") >= 0) numLinesEst++; - return prev + cur.replace(/\u001b\[\d\d?m/g, "").length + 1; - }, 0); - if (length > 60) { - return braces[0] + (base === "" ? "" : base + "\n ") + " " + output.join(",\n ") + " " + braces[1]; - } - return braces[0] + base + " " + output.join(", ") + " " + braces[1]; -} function isBoolean(arg) { return typeof arg === "boolean"; @@ -447,7 +125,7 @@ function timestamp() { return [d.getDate(), months[d.getMonth()], time].join(" "); } var log = function log() { - console.log("%s - %s", timestamp(), format.apply(cjs_exports, arguments)); + console.log("%s - %s", timestamp(), format.$apply(cjs_exports, arguments)); }; var inherits = function inherits(ctor, superCtor) { ctor.super_ = superCtor; @@ -469,9 +147,6 @@ var _extend = function (origin, add) { } return origin; }; -function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -} var kCustomPromisifiedSymbol = Symbol.for("util.promisify.custom"); var promisify = function promisify(original) { if (typeof original !== "function") throw new TypeError('The "original" argument must be of type Function'); @@ -506,7 +181,7 @@ var promisify = function promisify(original) { } }); try { - original.apply(this, args); + original.$apply(this, args); } catch (err) { promiseReject(err); } @@ -537,16 +212,16 @@ function callbackify(original) { throw new TypeError('The "original" argument must be of type Function'); } function callbackified() { - var args = Array.prototype.slice.call(arguments); + var args = Array.prototype.slice.$call(arguments); var maybeCb = args.pop(); if (typeof maybeCb !== "function") { throw new TypeError("The last argument must be of type Function"); } var self = this; var cb = function () { - return maybeCb.apply(self, arguments); + return maybeCb.$apply(self, arguments); }; - original.apply(this, args).then( + original.$apply(this, args).then( function (ret) { process.nextTick(cb, null, ret); }, @@ -566,6 +241,7 @@ var toUSVString = input => { export default Object.assign(cjs_exports, { format, formatWithOptions, + stripVTControlCharacters, deprecate, debuglog, _extend, diff --git a/src/js/node/worker_threads.ts b/src/js/node/worker_threads.ts index f1f15b64e..df9b5bdf4 100644 --- a/src/js/node/worker_threads.ts +++ b/src/js/node/worker_threads.ts @@ -224,6 +224,10 @@ class Worker extends EventEmitter { this.#worker.addEventListener("open", this.#onOpen.bind(this)); } + get threadId() { + return this.#worker.threadId; + } + ref() { this.#worker.ref(); } @@ -261,7 +265,7 @@ class Worker extends EventEmitter { } terminate() { - var onExitPromise = this.#onExitPromise; + const onExitPromise = this.#onExitPromise; if (onExitPromise) { return $isPromise(onExitPromise) ? onExitPromise : Promise.resolve(onExitPromise); } diff --git a/src/js/node/zlib.js b/src/js/node/zlib.js index 06c523b85..407fac4e4 100644 --- a/src/js/node/zlib.js +++ b/src/js/node/zlib.js @@ -43,10 +43,10 @@ var require_common = __commonJS({ var TYPED_OK = typeof Uint8Array !== "undefined" && typeof Uint16Array !== "undefined" && typeof Int32Array !== "undefined"; function _has(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); + return Object.prototype.hasOwnProperty.$call(obj, key); } exports.assign = function (obj) { - var sources = Array.prototype.slice.call(arguments, 1); + var sources = Array.prototype.slice.$call(arguments, 1); while (sources.length) { var source = sources.shift(); if (!source) { @@ -106,7 +106,7 @@ var require_common = __commonJS({ } }, flattenChunks: function (chunks) { - return [].concat.apply([], chunks); + return [].concat.$apply([], chunks); }, }; exports.setTyped = function (on) { @@ -4111,31 +4111,31 @@ var require_lib = __commonJS({ } function Deflate(opts) { if (!(this instanceof Deflate)) return new Deflate(opts); - Zlib.call(this, opts, binding.DEFLATE); + Zlib.$call(this, opts, binding.DEFLATE); } function Inflate(opts) { if (!(this instanceof Inflate)) return new Inflate(opts); - Zlib.call(this, opts, binding.INFLATE); + Zlib.$call(this, opts, binding.INFLATE); } function Gzip(opts) { if (!(this instanceof Gzip)) return new Gzip(opts); - Zlib.call(this, opts, binding.GZIP); + Zlib.$call(this, opts, binding.GZIP); } function Gunzip(opts) { if (!(this instanceof Gunzip)) return new Gunzip(opts); - Zlib.call(this, opts, binding.GUNZIP); + Zlib.$call(this, opts, binding.GUNZIP); } function DeflateRaw(opts) { if (!(this instanceof DeflateRaw)) return new DeflateRaw(opts); - Zlib.call(this, opts, binding.DEFLATERAW); + Zlib.$call(this, opts, binding.DEFLATERAW); } function InflateRaw(opts) { if (!(this instanceof InflateRaw)) return new InflateRaw(opts); - Zlib.call(this, opts, binding.INFLATERAW); + Zlib.$call(this, opts, binding.INFLATERAW); } function Unzip(opts) { if (!(this instanceof Unzip)) return new Unzip(opts); - Zlib.call(this, opts, binding.UNZIP); + Zlib.$call(this, opts, binding.UNZIP); } function isValidFlushFlag(flag) { return ( @@ -4151,7 +4151,7 @@ var require_lib = __commonJS({ var _this = this; this._opts = opts = opts || {}; this._chunkSize = opts.chunkSize || exports.Z_DEFAULT_CHUNK; - Transform.call(this, opts); + Transform.$call(this, opts); if (opts.flush && !isValidFlushFlag(opts.flush)) { throw new Error("Invalid flush flag: " + opts.flush); } |