/
githubmirror
/
deno
Обзор
Документация
Войти
/
githubmirror
/
deno
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
ext/node/polyfills/util.ts
468 строк
12 KB
Bartek Iwańczuk
fix(ext/node): implement util.diff (#36289)
24 июл 2026, 16:42
Не верифицирован
24 июл 2026, 16:42
04dcb7e
Код
Авторство
О чём код?
// Copyright 2018-2026 the Deno authors. MIT license. (function () { const { core, internals, primordials } = __bootstrap; const { op_node_call_is_from_dependency } = core.ops; const { ArrayIsArray, ArrayPrototypeJoin, ArrayPrototypeMap, ArrayPrototypeReverse, Date, DatePrototypeGetDate, DatePrototypeGetHours, DatePrototypeGetMinutes, DatePrototypeGetMonth, DatePrototypeGetSeconds, ErrorCaptureStackTrace, NumberPrototypeToString, ObjectCreate, ObjectDefineProperty, ObjectGetOwnPropertyDescriptor, ObjectKeys, ObjectSetPrototypeOf, ReflectApply, ReflectConstruct, SafeFinalizationRegistry, SafeSet, SafeWeakRef, SetPrototypeAdd, SetPrototypeHas, StringPrototypeIsWellFormed, StringPrototypePadStart, StringPrototypeToWellFormed, PromiseResolve, PromiseWithResolvers, WeakRefPrototypeDeref, } = primordials; const { promisify } = core.loadExtScript("ext:deno_node/internal/util.mjs"); const { callbackify } = core.loadExtScript( "ext:deno_node/_util/_util_callbackify.js", ); const { debuglog } = core.loadExtScript( "ext:deno_node/internal/util/debuglog.ts", ); const { format, formatWithOptions, inspect, stripVTControlCharacters, styleText, } = core.loadExtScript("ext:deno_node/internal/util/inspect.mjs"); const { codes } = core.loadExtScript("ext:deno_node/internal/error_codes.ts"); const types = core.loadExtScript("ext:deno_node/internal/util/types.ts"); const { isDeepStrictEqual } = core.loadExtScript( "ext:deno_node/internal/util/comparisons.ts", ); const { validateAbortSignal, validateBoolean, validateNumber, validateObject, validateString, validateStringArray, } = core.loadExtScript("ext:deno_node/internal/validators.mjs"); const { myersDiff } = core.loadExtScript( "ext:deno_node/internal/assert/myers_diff.js", ); const { parseArgs } = core.loadExtScript( "ext:deno_node/internal/util/parse_args/parse_args.js", ); const { MIMEParams, MIMEType } = core.loadExtScript( "ext:deno_node/internal/mime.ts", ); const abortSignal = core.loadExtScript("ext:deno_web/03_abort_signal.js"); const { ERR_INVALID_ARG_TYPE, ERR_WORKER_UNSUPPORTED_OPERATION } = core .loadExtScript( "ext:deno_node/internal/errors.ts", ); const { default: binding } = core.loadExtScript( "ext:deno_node/internal_binding/util.ts", ); const { validateOneOf } = core.loadExtScript( "ext:deno_node/internal/validators.mjs", ); const lazyV8 = core.createLazyLoader("node:v8"); const { os: osConstants } = core.loadExtScript( "ext:deno_node/internal_binding/constants.ts", ); const abortedRegistry = new SafeFinalizationRegistry((heldValue) => { const signal = WeakRefPrototypeDeref(heldValue.signal); if (signal !== undefined) { signal[abortSignal.remove](heldValue.algorithm); } }); let process; const lazyLoadProcess = core.createLazyLoader("node:process"); /** @deprecated - use `Array.isArray()` instead. */ const isArray = ArrayIsArray; /** @deprecated Use Object.assign() instead. */ function _extend(target, source) { // Don't do anything if source isn't an object if (source === null || typeof source !== "object") return target; const keys = ObjectKeys(source); let i = keys.length; while (i--) { target[keys[i]] = source[keys[i]]; } return target; } /** * https://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor * @param ctor Constructor function which needs to inherit the prototype. * @param superCtor Constructor function to inherit prototype from. */ function inherits(ctor, superCtor) { if (ctor === undefined || ctor === null) { throw new codes.ERR_INVALID_ARG_TYPE("ctor", "Function", ctor); } if (superCtor === undefined || superCtor === null) { throw new codes.ERR_INVALID_ARG_TYPE("superCtor", "Function", superCtor); } if (superCtor.prototype === undefined) { throw new codes.ERR_INVALID_ARG_TYPE( "superCtor.prototype", "Object", superCtor.prototype, ); } ObjectDefineProperty(ctor, "super_", { __proto__: null, value: superCtor, writable: true, configurable: true, }); ObjectSetPrototypeOf(ctor.prototype, superCtor.prototype); } const { _TextDecoder, _TextEncoder, getSystemErrorMap, getSystemErrorMessage, getSystemErrorName, } = core.loadExtScript("ext:deno_node/_utils.ts"); /** The global TextDecoder */ const TextDecoder = _TextDecoder; /** The global TextEncoder */ const TextEncoder = _TextEncoder; function toUSVString(str) { if (StringPrototypeIsWellFormed(str)) { return str; } return StringPrototypeToWellFormed(str); } function pad(n) { return StringPrototypePadStart(NumberPrototypeToString(n), 2, "0"); } const months = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ]; /** * @returns 26 Feb 16:19:34 */ function timestamp() { const d = new Date(); const t = ArrayPrototypeJoin([ pad(DatePrototypeGetHours(d)), pad(DatePrototypeGetMinutes(d)), pad(DatePrototypeGetSeconds(d)), ], ":"); return `${DatePrototypeGetDate(d)} ${months[DatePrototypeGetMonth(d)]} ${t}`; } /** * Log is just a thin wrapper to console.log that prepends a timestamp * @deprecated */ function log(...args) { // deno-lint-ignore no-console console.log("%s - %s", timestamp(), ReflectApply(format, undefined, args)); } // Keep a list of deprecation codes that have been warned on so we only warn on // each one once. const codesWarned = new SafeSet(); // Mark that a method should not be used. // Returns a modified function which warns once by default. // If --no-deprecation is set, then it is a no-op. function deprecate( fn, msg, code, { modifyPrototype = true } = { __proto__: null, }, ) { // Note: `process` is loaded lazily on first invocation of `deprecated`, // not here. Loading it eagerly during `deprecate()` is enough to deadlock // snapshot evaluation when `deprecate` is called from a module body that // is itself in `process.ts`'s transitive load chain (e.g. assert.ts). if (code !== undefined) { validateString(code, "code"); } let warned = false; function deprecated(...args) { process ??= lazyLoadProcess(); if (process.noDeprecation === true) { return ReflectApply(fn, this, args); } if (!warned && !op_node_call_is_from_dependency()) { warned = true; if (code !== undefined) { if (!SetPrototypeHas(codesWarned, code)) { process.emitWarning(msg, "DeprecationWarning", code, deprecated); SetPrototypeAdd(codesWarned, code); } } else { process.emitWarning(msg, "DeprecationWarning", deprecated); } } if (new.target) { return ReflectConstruct(fn, args, new.target); } return ReflectApply(fn, this, args); } if (modifyPrototype) { // The wrapper will keep the same prototype as fn to maintain prototype chain ObjectSetPrototypeOf(deprecated, fn); if (fn.prototype) { // Setting this (rather than using Object.setPrototype, as above) ensures // that calling the unwrapped constructor gives an instanceof the wrapped // constructor. deprecated.prototype = fn.prototype; } ObjectDefineProperty(deprecated, "length", { __proto__: null, ...ObjectGetOwnPropertyDescriptor(fn, "length"), }); } return deprecated; } // deno-lint-ignore require-await async function aborted( signal, resource, ) { if (signal === undefined) { throw new ERR_INVALID_ARG_TYPE("signal", "AbortSignal", signal); } validateAbortSignal(signal, "signal"); validateObject(resource, "resource", { allowArray: true, allowFunction: true, }); if (signal.aborted) { return PromiseResolve(); } const abortPromise = PromiseWithResolvers(); const resourceRef = new SafeWeakRef(resource); const algorithm = () => { abortedRegistry.unregister(algorithm); if (WeakRefPrototypeDeref(resourceRef) !== undefined) { abortPromise.resolve(); } }; signal[abortSignal.add](algorithm); abortedRegistry.register(resource, { __proto__: null, signal: new SafeWeakRef(signal), algorithm, }, algorithm); return abortPromise.promise; } function prepareStackTrace(_error, stackTraces) { return ArrayPrototypeMap(stackTraces, (stack) => { return ({ functionName: stack.getFunctionName() ?? "", // TODO(kt3k): This needs to be script's id scriptId: "0", scriptName: stack.getFileName(), lineNumber: stack.getLineNumber(), column: stack.getColumnNumber(), columnNumber: stack.getColumnNumber(), }); }); } const kDefaultMaxCallStackSizeToCapture = 200; /** * Returns the call sites of the current call stack * @param frameCount The limit of the number of frames to return * @param _options The options * @returns The call sites */ function getCallSites( frameCount = 10, options = { __proto__: null }, ) { validateNumber( frameCount, "frameCount", 0, kDefaultMaxCallStackSizeToCapture, ); if (options) { validateObject(options, "options"); } const target = {}; // deno-lint-ignore deno-internal/prefer-primordials const original = Error.prepareStackTrace; // deno-lint-ignore deno-internal/prefer-primordials const limitOriginal = Error.stackTraceLimit; // deno-lint-ignore deno-internal/prefer-primordials Error.stackTraceLimit = frameCount; // deno-lint-ignore deno-internal/prefer-primordials Error.prepareStackTrace = prepareStackTrace; ErrorCaptureStackTrace(target, getCallSites); const capturedTraces = target.stack; // deno-lint-ignore deno-internal/prefer-primordials Error.prepareStackTrace = original; // deno-lint-ignore deno-internal/prefer-primordials Error.stackTraceLimit = limitOriginal; return capturedTraces; } function parseEnv(input) { validateString(input, "content"); const parsed = binding.parseEnv(input); const result = ObjectCreate(null); const keys = ObjectKeys(parsed); for (let i = 0; i < keys.length; i++) { result[keys[i]] = parsed[keys[i]]; } return result; } function setTraceSigInt(enabled) { validateBoolean(enabled, "enabled"); if (internals.__isWorkerThread) { throw new ERR_WORKER_UNSUPPORTED_OPERATION("Setting trace SIGINT"); } // No-op on the main thread: Deno does not implement Node's SIGINT trace // facility, but the call should succeed so user code can opt in/out. } // https://nodejs.org/api/util.html#utilqueryobjectsconstructor-options // Mirrors `v8.queryObjects` - see ext/node/polyfills/v8.ts for the limitations. function queryObjects(ctor, options) { return lazyV8().queryObjects(ctor, options); } // Deno's AbortSignal is not yet structured-cloneable, so transfer is a no-op: // the returned signal/controller can still be used in-process. This mirrors // Node's API surface so user code calling these does not throw. function transferableAbortSignal(signal) { if ( signal === null || typeof signal !== "object" || typeof signal.aborted !== "boolean" ) { throw new ERR_INVALID_ARG_TYPE("signal", "AbortSignal", signal); } return signal; } function transferableAbortController() { return new AbortController(); } function convertProcessSignalToExitCode(signalCode) { const { signals } = osConstants; validateOneOf(signalCode, "signalCode", ObjectKeys(signals)); return 128 + signals[signalCode]; } function validateDiffInput(value, name) { if (!ArrayIsArray(value)) { validateString(value, name); return; } validateStringArray(value, name); } // https://nodejs.org/api/util.html#utildiffactual-expected function diff(actual, expected) { if (actual === expected) { return []; } validateDiffInput(actual, "actual"); validateDiffInput(expected, "expected"); return ArrayPrototypeReverse(myersDiff(actual, expected)); } return { callbackify, diff, debuglog, debug: debuglog, format, formatWithOptions, inspect, MIMEParams, MIMEType, parseArgs, promisify, stripVTControlCharacters, styleText, types, isArray, _extend, inherits, TextDecoder, TextEncoder, toUSVString, log, deprecate, aborted, getCallSites, parseEnv, queryObjects, setTraceSigInt, transferableAbortController, transferableAbortSignal, convertProcessSignalToExitCode, getSystemErrorMap, getSystemErrorMessage, getSystemErrorName, isDeepStrictEqual, }; })();