{ "schemaVersion": 1, "title": "OpenContainers Node.js compatibility matrix", "sources": [ { "label": "Bun Node.js compatibility", "url": "https://bun.com/docs/runtime/nodejs-compat" }, { "label": "Node.js API documentation", "url": "https://nodejs.org/api/" } ], "statuses": { "full": "Implemented with behavioral test coverage for the tracked surface.", "partial": "Implemented for the browser-safe subset, with known gaps tracked.", "stubbed": "Resolvable for package probes; behavior is no-op or deliberately narrow.", "blocked": "Resolvable, but faithful behavior is blocked by browser or security limits.", "missing": "Not implemented yet." }, "modules": [ { "specifier": "node:assert", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Native-shaped CommonJS export order, AssertionError metadata, helper metadata/prototypes, Assert facade metadata/prototype order, strict facade identity, matching/async helpers and match argument validation, partialDeepStrictEqual, and loose deepEqual behavior are covered.", "probe": "const assert = require('node:assert'); const strict = require('node:assert/strict'); const keys = 'AssertionError,ok,fail,equal,notEqual,deepEqual,notDeepEqual,deepStrictEqual,notDeepStrictEqual,strictEqual,notStrictEqual,partialDeepStrictEqual,match,doesNotMatch,throws,rejects,doesNotThrow,doesNotReject,ifError,strict,Assert'; const helperNames = ['ok','fail','equal','notEqual','deepEqual','notDeepEqual','deepStrictEqual','notDeepStrictEqual','strictEqual','notStrictEqual','partialDeepStrictEqual','match','doesNotMatch','throws','rejects','doesNotThrow','doesNotReject','ifError']; const helperMeta = (namespace) => helperNames.map((name) => name + ':' + namespace[name].name + ':' + namespace[name].length + ':' + Object.hasOwn(namespace[name], 'prototype')).join('|'); const prototypeKeys = Object.keys(assert.Assert.prototype).join(','); const assertionErrorPrototype = assert.AssertionError.prototype; const assertionErrorToString = Object.getOwnPropertyDescriptor(assertionErrorPrototype, 'toString'); const assertionError = new assert.AssertionError({ message: 'm', actual: 1, expected: 2, operator: '===' }); let invalidAssertionErrorCode; try { new assert.AssertionError(); } catch (error) { invalidAssertionErrorCode = error.code; } const assertionErrorMeta = [assert.AssertionError.name, assert.AssertionError.length, assert.AssertionError === strict.AssertionError, Object.getOwnPropertyNames(assertionErrorPrototype).join(','), Object.keys(assertionErrorPrototype).join(','), assertionErrorToString.value.name, assertionErrorToString.value.length, assertionErrorToString.enumerable, assertionErrorToString.configurable, assertionErrorToString.writable, Object.hasOwn(assertionErrorToString.value, 'prototype')].join(':'); const assertionErrorInstance = [assertionError.generatedMessage, assertionError.diff, Object.keys(assertionError).join(','), Object.getOwnPropertyNames(assertionError).filter((name) => name !== 'stack').join(','), assertionError.toString(), invalidAssertionErrorCode].join(':'); const invalidMatchRows = [() => assert.match(123, /123/), () => assert.doesNotMatch(123, /zzz/), () => strict.match(123, /123/), () => strict.doesNotMatch(123, /zzz/)].map((action) => { try { action(); return 'ok'; } catch (error) { return [error.name, error.code, error.operator].join(':'); } }).join('|'); if (Object.keys(assert).join(',') !== keys || assert.name !== 'assert' || assert.length !== 0 || assert.ok === assert || strict.name !== 'strict' || strict.length !== 0 || strict.strict !== strict || assert.Assert.length !== 1 || assertionErrorMeta !== 'AssertionError:1:true:constructor,toString::toString:0:false:true:true:false' || assertionErrorInstance !== 'false:simple:generatedMessage,code,actual,expected,operator,diff:message,generatedMessage,name,code,actual,expected,operator,diff:AssertionError [ERR_ASSERTION]: m:ERR_INVALID_ARG_TYPE' || prototypeKeys !== 'fail,ok,equal,notEqual,deepEqual,notDeepEqual,deepStrictEqual,notDeepStrictEqual,strictEqual,notStrictEqual,partialDeepStrictEqual,throws,rejects,doesNotThrow,doesNotReject,ifError,match,doesNotMatch' || invalidMatchRows !== 'AssertionError:ERR_ASSERTION:match|AssertionError:ERR_ASSERTION:doesNotMatch|AssertionError:ERR_ASSERTION:match|AssertionError:ERR_ASSERTION:doesNotMatch' || helperMeta(assert) !== 'ok:ok:0:true|fail:fail:1:true|equal:equal:2:true|notEqual:notEqual:2:true|deepEqual:deepEqual:2:true|notDeepEqual:notDeepEqual:2:true|deepStrictEqual:deepStrictEqual:2:true|notDeepStrictEqual:notDeepStrictEqual:2:true|strictEqual:strictEqual:2:true|notStrictEqual:notStrictEqual:2:true|partialDeepStrictEqual:partialDeepStrictEqual:2:true|match:match:2:true|doesNotMatch:doesNotMatch:2:true|throws:throws:1:true|rejects:rejects:1:false|doesNotThrow:doesNotThrow:1:true|doesNotReject:doesNotReject:1:false|ifError:ifError:1:true' || helperMeta(strict) !== 'ok:ok:0:true|fail:fail:1:true|equal:strictEqual:2:true|notEqual:notStrictEqual:2:true|deepEqual:deepStrictEqual:2:true|notDeepEqual:notDeepStrictEqual:2:true|deepStrictEqual:deepStrictEqual:2:true|notDeepStrictEqual:notDeepStrictEqual:2:true|strictEqual:strictEqual:2:true|notStrictEqual:notStrictEqual:2:true|partialDeepStrictEqual:partialDeepStrictEqual:2:true|match:match:2:true|doesNotMatch:doesNotMatch:2:true|throws:throws:1:true|rejects:rejects:1:false|doesNotThrow:doesNotThrow:1:true|doesNotReject:doesNotReject:1:false|ifError:ifError:1:true') throw new Error('assert metadata failed'); assert.equal(1, '1'); assert.deepEqual({ a: 1, b: ['2'] }, { a: '1', b: [2] }); assert.partialDeepStrictEqual({ a: 1, b: { c: 2 } }, { b: { c: 2 } }); new assert.Assert({ strict: false }).equal(1, '1'); new assert.Assert({ strict: false }).deepEqual({ a: 1 }, { a: '1' })" }, { "specifier": "node:assert/strict", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Native-shaped CommonJS export order, AssertionError metadata, strict facade metadata, helper aliases, Assert facade metadata/prototype order, strict equality behavior, match argument validation, and partialDeepStrictEqual are covered.", "probe": "const assert = require('node:assert/strict'); const keys = 'AssertionError,ok,fail,equal,notEqual,deepEqual,notDeepEqual,deepStrictEqual,notDeepStrictEqual,strictEqual,notStrictEqual,partialDeepStrictEqual,match,doesNotMatch,throws,rejects,doesNotThrow,doesNotReject,ifError,Assert,strict'; const helperNames = ['ok','fail','equal','notEqual','deepEqual','notDeepEqual','deepStrictEqual','notDeepStrictEqual','strictEqual','notStrictEqual','partialDeepStrictEqual','match','doesNotMatch','throws','rejects','doesNotThrow','doesNotReject','ifError']; const helperMeta = helperNames.map((name) => name + ':' + assert[name].name + ':' + assert[name].length + ':' + Object.hasOwn(assert[name], 'prototype')).join('|'); const assertionErrorPrototype = assert.AssertionError.prototype; const assertionErrorToString = Object.getOwnPropertyDescriptor(assertionErrorPrototype, 'toString'); const assertionErrorMeta = [assert.AssertionError.name, assert.AssertionError.length, Object.getOwnPropertyNames(assertionErrorPrototype).join(','), Object.keys(assertionErrorPrototype).join(','), assertionErrorToString.value.name, assertionErrorToString.value.length, assertionErrorToString.enumerable, assertionErrorToString.configurable, assertionErrorToString.writable, Object.hasOwn(assertionErrorToString.value, 'prototype')].join(':'); const invalidMatchRows = [() => assert.match(123, /123/), () => assert.doesNotMatch(123, /zzz/)].map((action) => { try { action(); return 'ok'; } catch (error) { return [error.name, error.code, error.operator].join(':'); } }).join('|'); if (Object.keys(assert).join(',') !== keys || assert.name !== 'strict' || assert.length !== 0 || assert.strict !== assert || assert.Assert.length !== 1 || assertionErrorMeta !== 'AssertionError:1:constructor,toString::toString:0:false:true:true:false' || Object.keys(assert.Assert.prototype).join(',') !== 'fail,ok,equal,notEqual,deepEqual,notDeepEqual,deepStrictEqual,notDeepStrictEqual,strictEqual,notStrictEqual,partialDeepStrictEqual,throws,rejects,doesNotThrow,doesNotReject,ifError,match,doesNotMatch' || invalidMatchRows !== 'AssertionError:ERR_ASSERTION:match|AssertionError:ERR_ASSERTION:doesNotMatch' || helperMeta !== 'ok:ok:0:true|fail:fail:1:true|equal:strictEqual:2:true|notEqual:notStrictEqual:2:true|deepEqual:deepStrictEqual:2:true|notDeepEqual:notDeepStrictEqual:2:true|deepStrictEqual:deepStrictEqual:2:true|notDeepStrictEqual:notDeepStrictEqual:2:true|strictEqual:strictEqual:2:true|notStrictEqual:notStrictEqual:2:true|partialDeepStrictEqual:partialDeepStrictEqual:2:true|match:match:2:true|doesNotMatch:doesNotMatch:2:true|throws:throws:1:true|rejects:rejects:1:false|doesNotThrow:doesNotThrow:1:true|doesNotReject:doesNotReject:1:false|ifError:ifError:1:true') throw new Error('assert/strict metadata failed'); assert.deepEqual({ ok: true }, { ok: true }); assert.partialDeepStrictEqual({ a: 1, b: { c: 2 } }, { b: { c: 2 } }); try { assert.equal(1, '1'); throw new Error('strict assert failed') } catch (error) { if (error.message === 'strict assert failed') throw error }" }, { "specifier": "node:buffer", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Native-shaped CommonJS export order, absence of non-native SlowBuffer/OpenContainersBuffer public exports, accessor INSPECT_MAX_BYTES metadata, read-only constants descriptors, Node v26 max-length probe constants, base64 helpers, UTF validation helpers, Blob/File fallbacks, and object URL resolution are covered.", "probe": "const buffer = require('node:buffer'); const keys = 'Buffer,transcode,isUtf8,isAscii,kMaxLength,kStringMaxLength,btoa,atob,constants,INSPECT_MAX_BYTES,Blob,resolveObjectURL,File'; const descriptorRows = ['constants','INSPECT_MAX_BYTES','kMaxLength','kStringMaxLength','SlowBuffer','OpenContainersBuffer'].map((key) => { const descriptor = Object.getOwnPropertyDescriptor(buffer, key); if (!descriptor) return key + ':missing'; return [key, descriptor.enumerable, descriptor.configurable, 'writable' in descriptor ? descriptor.writable : '', descriptor.get?.name ?? '', descriptor.set?.name ?? '', typeof descriptor.value].join(':') }).join('|'); const constantRows = ['MAX_LENGTH','MAX_STRING_LENGTH'].map((key) => { const descriptor = Object.getOwnPropertyDescriptor(buffer.constants, key); return [key, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value].join(':') }).join('|'); const originalInspectMaxBytes = buffer.INSPECT_MAX_BYTES; buffer.INSPECT_MAX_BYTES = 123; const inspectMaxBytesOk = buffer.INSPECT_MAX_BYTES === 123; buffer.INSPECT_MAX_BYTES = originalInspectMaxBytes; if (Object.hasOwn(buffer, 'default') || Object.keys(buffer).includes('default') || Object.keys(buffer).join(',') !== keys || Object.getOwnPropertyNames(buffer).join(',') !== keys || descriptorRows !== 'constants:true:false:false:::object|INSPECT_MAX_BYTES:true:true::get:set:undefined|kMaxLength:true:true:true:::number|kStringMaxLength:true:true:true:::number|SlowBuffer:missing|OpenContainersBuffer:missing' || constantRows !== 'MAX_LENGTH:true:false:false:9007199254740991|MAX_STRING_LENGTH:true:false:false:536870888' || Object.getPrototypeOf(buffer.constants) !== Object.prototype || Object.isFrozen(buffer.constants) || !Object.isExtensible(buffer.constants) || buffer.kMaxLength !== 9007199254740991 || buffer.constants.MAX_LENGTH !== 9007199254740991 || buffer.kStringMaxLength !== 536870888 || buffer.constants.MAX_STRING_LENGTH !== 536870888 || !inspectMaxBytesOk || buffer.Buffer.from('ok').toString('base64') !== 'b2s=' || typeof buffer.SlowBuffer !== 'undefined' || typeof buffer.OpenContainersBuffer !== 'undefined' || !buffer.isAscii(Buffer.from('abc')) || !buffer.isUtf8(Buffer.from('abc')) || buffer.isAscii(Buffer.from([0xff])) || buffer.isUtf8(Buffer.from([0xc3, 0x28])) || !buffer.isUtf8(Buffer.from([0xc3, 0xa9]))) throw new Error('buffer failed'); const url = URL.createObjectURL(new buffer.Blob(['ok'])); const blob = buffer.resolveObjectURL(url); if (!(blob instanceof buffer.Blob) || blob.size !== 2) throw new Error('resolveObjectURL failed'); URL.revokeObjectURL(url); if (buffer.resolveObjectURL(url) !== undefined || buffer.resolveObjectURL(new URL('blob:opencontainers:test')) !== undefined) throw new Error('resolveObjectURL invalid failed')" }, { "specifier": "node:console", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Native-shaped CommonJS export order, hidden own-property descriptor/order parity, Console constructor metadata, Console.prototype order/enumerable descriptors, context/createTask helpers, grouped output, counters, timers, color mode, ignored write errors, and sys alias resolution are covered.", "probe": "const consoleModule = require('node:console'); const { Console } = consoleModule; const consolePrototypeRow = (name) => { const descriptor = Object.getOwnPropertyDescriptor(Console.prototype, name); return descriptor ? [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype')].join(':') : name + ':missing' }; const consolePrototypeMeta = [Object.getOwnPropertyNames(Console.prototype).join(','), Object.keys(Console.prototype).join(','), ['log','trace','table','dirxml','groupCollapsed','timeStamp','profile','profileEnd'].map(consolePrototypeRow).join('|')].join(';'); const consoleOwnNames = Object.getOwnPropertyNames(consoleModule).join(','); const hiddenConsoleRows = ['_stdoutErrorHandler','_stderrErrorHandler','_ignoreErrors','_times','_stdout','_stderr'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(consoleModule, name); if ('value' in descriptor) return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value, descriptor.value?.name ?? '', descriptor.value?.length ?? '', Object.hasOwn(descriptor.value ?? {}, 'prototype'), descriptor.value?.constructor?.name ?? ''].join(':'); return [name, descriptor.enumerable, descriptor.configurable, 'accessor', descriptor.get.name, descriptor.get.length, Object.hasOwn(descriptor.get, 'prototype'), descriptor.set.name, descriptor.set.length, Object.hasOwn(descriptor.set, 'prototype')].join(':'); }).join('|'); const hiddenWrites = []; const previousStdout = consoleModule._stdout; consoleModule._stdout = { write: (chunk) => hiddenWrites.push(chunk) }; consoleModule.log('hidden stdout'); consoleModule._stdout = previousStdout; const chunks = []; const c = new Console({ stdout: { write: chunk => chunks.push(chunk) }, groupIndentation: 4, inspectOptions: { colors: false }, ignoreErrors: true }); c.group('g'); c.log({ ok: true }); c.dirxml('xml'); c.count('x'); c.count('x'); new Console({ stdout: { write() { throw new Error('ignored') } }, ignoreErrors: true }).log('ok'); if (Object.keys(consoleModule).join(',') !== 'log,info,debug,warn,error,dir,time,timeEnd,timeLog,trace,assert,clear,count,countReset,group,groupEnd,table,dirxml,groupCollapsed,Console,profile,profileEnd,timeStamp,context,createTask' || Object.hasOwn(consoleModule, 'default') || Console.length !== 1 || consoleOwnNames !== 'log,info,debug,warn,error,dir,time,timeEnd,timeLog,trace,assert,clear,count,countReset,group,groupEnd,table,dirxml,groupCollapsed,_stdoutErrorHandler,_stderrErrorHandler,_ignoreErrors,_times,Console,profile,profileEnd,timeStamp,context,createTask,_stdout,_stderr' || hiddenConsoleRows !== '_stdoutErrorHandler:false:true:true:function::1:false:Function|_stderrErrorHandler:false:true:true:function::1:false:Function|_ignoreErrors:false:true:true:boolean:::false:Boolean|_times:false:true:true:object:::false:Map|_stdout:false:true:accessor:get:0:false:set:1:false|_stderr:false:true:accessor:get:0:false:set:1:false' || hiddenWrites.join('').trim() !== 'hidden stdout' || consolePrototypeMeta !== \"constructor,log,info,debug,warn,error,dir,time,timeEnd,timeLog,trace,assert,clear,count,countReset,group,groupEnd,table,dirxml,groupCollapsed;log,info,debug,warn,error,dir,time,timeEnd,timeLog,trace,assert,clear,count,countReset,group,groupEnd,table,dirxml,groupCollapsed;log:true:true:true:log:0:false|trace:true:true:true:trace:0:true|table:true:true:true:table:2:false|dirxml:true:true:true:log:0:false|groupCollapsed:true:true:true:group:0:false|timeStamp:missing|profile:missing|profileEnd:missing\" || consoleModule.log.name !== 'log' || consoleModule.context.length !== 1 || !chunks.join('').includes('x: 2') || !chunks.join('').includes(' { ok: true }') || typeof console.timeLog !== 'function' || typeof consoleModule.context('probe').log !== 'function' || consoleModule.createTask('probe').run(() => 42) !== 42) throw new Error('console failed')" }, { "specifier": "node:diagnostics_channel", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Native-shaped export order, channel constructor metadata, prototype order and method metadata, bounded/tracing helpers, invalid channel-name validation, subscriber validation, bounded channel instance shape, and sync tracing are covered.", "probe": "const dc = require('node:diagnostics_channel'); const channelProto = dc.Channel.prototype; const boundedProto = dc.BoundedChannel.prototype; const constructorMeta = ['Channel','BoundedChannel'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(dc[name], 'length'); return [name, dc[name].name, dc[name].length, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value].join(':') }).join('|'); const channelProtoMeta = ['subscribe','unsubscribe','bindStore','unbindStore','hasSubscribers','publish','runStores','withStoreScope'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(channelProto, name); const detail = 'value' in descriptor ? descriptor.value.name + ':' + descriptor.value.length + ':' + descriptor.writable : descriptor.get.name + ':' + descriptor.get.length + ':' + typeof descriptor.set; return [name, descriptor.enumerable, descriptor.configurable, detail].join(':') }).join('|'); const boundedProtoMeta = ['hasSubscribers','subscribe','unsubscribe','withScope','run'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(boundedProto, name); const detail = 'value' in descriptor ? descriptor.value.name + ':' + descriptor.value.length + ':' + descriptor.writable : descriptor.get.name + ':' + descriptor.get.length + ':' + typeof descriptor.set; return [name, descriptor.enumerable, descriptor.configurable, detail].join(':') }).join('|'); if (Object.keys(dc).join(',') !== 'channel,hasSubscribers,subscribe,tracingChannel,unsubscribe,boundedChannel,Channel,BoundedChannel' || constructorMeta !== 'Channel:Channel:1:false:true:false:1|BoundedChannel:BoundedChannel:1:false:true:false:1' || Object.getOwnPropertyNames(channelProto).join(',') !== 'constructor,subscribe,unsubscribe,bindStore,unbindStore,hasSubscribers,publish,runStores,withStoreScope' || Object.keys(channelProto).join(',') !== '' || channelProtoMeta !== 'subscribe:false:true:subscribe:1:true|unsubscribe:false:true:unsubscribe:0:true|bindStore:false:true:bindStore:2:true|unbindStore:false:true:unbindStore:0:true|hasSubscribers:false:true:get hasSubscribers:0:undefined|publish:false:true:publish:0:true|runStores:false:true:runStores:3:true|withStoreScope:false:true:withStoreScope:0:true' || Object.getOwnPropertyNames(boundedProto).join(',') !== 'constructor,hasSubscribers,subscribe,unsubscribe,withScope,run' || Object.keys(boundedProto).join(',') !== '' || boundedProtoMeta !== 'hasSubscribers:false:true:get hasSubscribers:0:undefined|subscribe:false:true:subscribe:1:true|unsubscribe:false:true:unsubscribe:1:true|withScope:false:true:withScope:0:true|run:false:true:run:3:true') throw new Error('diagnostics_channel metadata failed'); const invalidChannelRows = [() => dc.channel({ toString() { return 'bad'; } }), () => dc.subscribe({ toString() { return 'bad'; } }, () => {}), () => dc.unsubscribe({ toString() { return 'bad'; } }, () => {})].map((action) => { try { action(); return 'ok'; } catch (error) { return error.name + ':' + error.code; } }).join('|'); const ch = dc.channel('probe'); let value = 0; ch.subscribe((message) => { value = message.value; }); ch.publish({ value: 1 }); const bounded = dc.boundedChannel('probe-bounded'); const boundedEvents = []; const boundedSubscriber = { start(message, name) { boundedEvents.push(`${String(name)}:${message.value}`); }, end(message, name) { boundedEvents.push(`${String(name)}:${message.value}`); } }; bounded.subscribe(boundedSubscriber); const boundedResult = bounded.run({ value: 2 }, (a, b) => a + b, null, 3, 4); const tracing = dc.tracingChannel('probe-trace'); const traced = []; tracing.subscribe({ start(message, name) { traced.push(`${String(name)}:${message.result ?? message.value}`); }, end(message, name) { traced.push(`${String(name)}:${message.result ?? message.value}`); } }); const tracedResult = tracing.traceSync((a, b) => a * b, { value: 'ctx' }, null, 2, 5); if (value !== 1 || invalidChannelRows !== 'TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE' || dc.hasSubscribers({ toString() { return 'bad'; } }) !== false || !(ch instanceof dc.Channel) || !(bounded instanceof dc.BoundedChannel) || Object.keys(bounded).length !== 0 || Object.getOwnPropertyNames(bounded).join(',') !== 'start,end' || boundedResult !== 7 || boundedEvents.join('|') !== 'tracing:probe-bounded:start:2|tracing:probe-bounded:end:2' || Object.keys(tracing).length !== 0 || Object.getOwnPropertyNames(tracing).join(',') !== 'error' || tracedResult !== 10 || traced.join('|') !== 'tracing:probe-trace:start:ctx|tracing:probe-trace:end:10') throw new Error('diagnostics_channel failed')" }, { "specifier": "node:dns", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/net-builtin.test.mjs", "limitation": "Virtual loopback and IPv4-mapped literal-IP lookup, PTR/reverse records, Resolver instances, Resolver constructor option validation, Resolver#setLocalAddress validation, native-shaped invalid rrtype validation, native-shaped Resolver cancellation for pending virtual queries, native-aligned verbatim default result order and verbatim false IPv4-first override, TTL records, DNS server validation/normalization, malformed IPv6 rejection, Node-shaped CommonJS export order, native-shaped promises accessor identity, Node-shaped function names/arities, native-shaped top-level helper function prototype metadata, native enumerable Resolver query-method prototype order and function prototype metadata, resolver-instance method shape, promise rejection timing for deferred lookup/reverse validation, synchronous lookupService port validation and invalid lookupService port type rejection, common lookupService port-to-service-name mapping, and stable DNS argument/error probes are supported; real DNS is constrained by browser networking.", "probe": "const dns = require('node:dns'); const promises = require('node:dns/promises'); const keys = 'lookup,lookupService,Resolver,getDefaultResultOrder,setDefaultResultOrder,setServers,ADDRCONFIG,ALL,V4MAPPED,NODATA,FORMERR,SERVFAIL,NOTFOUND,NOTIMP,REFUSED,BADQUERY,BADNAME,BADFAMILY,BADRESP,CONNREFUSED,TIMEOUT,EOF,FILE,NOMEM,DESTRUCTION,BADSTR,BADFLAGS,NONAME,BADHINTS,NOTINITIALIZED,LOADIPHLPAPI,ADDRGETNETWORKPARAMS,CANCELLED,getServers,resolve,resolve4,resolve6,resolveAny,resolveCaa,resolveCname,resolveMx,resolveNaptr,resolveNs,resolvePtr,resolveSoa,resolveSrv,resolveTlsa,resolveTxt,reverse,promises'; const resolverKeys = 'resolveAny,resolve4,resolve6,resolveCaa,resolveCname,resolveMx,resolveNs,resolveTlsa,resolveTxt,resolveSrv,resolvePtr,resolveNaptr,resolveSoa,reverse,resolve'; const descriptor = Object.getOwnPropertyDescriptor(dns, 'promises'); const resolver = new dns.Resolver(); const helperNames = 'lookup,lookupService,getDefaultResultOrder,setDefaultResultOrder,setServers,getServers,resolve,resolve4,resolve6,resolveAny,resolveCaa,resolveCname,resolveMx,resolveNaptr,resolveNs,resolvePtr,resolveSoa,resolveSrv,resolveTlsa,resolveTxt,reverse'.split(','); const helperFunctionPrototypeMeta = helperNames.map((name) => { const fn = dns[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, Object.hasOwn(fn, 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(',')].join(':') }).join('|'); const expectedHelperFunctionPrototypeMeta = helperNames.slice(0, 5).map((name) => name + ':true:false:false:true:constructor').concat(helperNames.slice(5).map((name) => name + ':false::::')).join('|'); const queryFunctionPrototypeMeta = resolverKeys.split(',').map((name) => { const fn = dns.Resolver.prototype[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, Object.hasOwn(fn, 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(',')].join(':') }).join('|'); const expectedQueryFunctionPrototypeMeta = resolverKeys.split(',').map((name) => name + ':true:false:false:true:constructor').join('|'); if (Object.hasOwn(dns, 'default') || Object.keys(dns).join(',') !== keys || !descriptor?.get || descriptor.set !== undefined || !descriptor.enumerable || !descriptor.configurable || dns.promises !== promises || dns.getDefaultResultOrder() !== 'verbatim' || dns.ADDRCONFIG !== 1024 || dns.ALL !== 256 || dns.V4MAPPED !== 2048 || dns.NOTFOUND !== 'ENOTFOUND' || dns.lookup.length !== 3 || dns.lookupService.length !== 3 || dns.resolve.length !== 3 || dns.resolve4.length !== 2 || dns.resolve6.length !== 2 || dns.resolveAny.length !== 2 || dns.reverse.length !== 2 || dns.Resolver.length !== 0 || dns.resolve.name !== 'bound resolve' || dns.resolve4.name !== 'bound queryA' || dns.resolveAny.name !== 'bound queryAny' || dns.reverse.name !== 'bound getHostByAddr' || helperFunctionPrototypeMeta !== expectedHelperFunctionPrototypeMeta || Object.keys(dns.Resolver.prototype).join(',') !== resolverKeys || queryFunctionPrototypeMeta !== expectedQueryFunctionPrototypeMeta || dns.Resolver.prototype.resolve4.name !== 'queryA' || dns.Resolver.prototype.resolve4.length !== 2 || dns.Resolver.prototype.reverse.name !== 'getHostByAddr' || dns.Resolver.prototype.reverse.length !== 2) throw new Error('dns metadata failed'); const assertResolverOptions = (Ctor, label) => { const inheritedOptions = Object.create({ timeout: 'bad', tries: 0 }); const accessorOptions = {}; Object.defineProperty(accessorOptions, 'timeout', { get() { throw new Error(label + ' getter called') } }); for (const options of [undefined, null, 42, 'ignored', [], { timeout: -1 }, { timeout: 0 }, { timeout: 2147483647, tries: 1 }, { tries: 2147483647 }, inheritedOptions, accessorOptions]) new Ctor(options); for (const [options, code] of [[{ timeout: '100' }, 'ERR_INVALID_ARG_TYPE'], [{ timeout: NaN }, 'ERR_OUT_OF_RANGE'], [{ timeout: 1.5 }, 'ERR_OUT_OF_RANGE'], [{ timeout: -2 }, 'ERR_OUT_OF_RANGE'], [{ timeout: 2147483648 }, 'ERR_OUT_OF_RANGE'], [{ tries: '2' }, 'ERR_INVALID_ARG_TYPE'], [{ tries: NaN }, 'ERR_OUT_OF_RANGE'], [{ tries: 1.5 }, 'ERR_OUT_OF_RANGE'], [{ tries: 0 }, 'ERR_OUT_OF_RANGE'], [{ tries: 2147483648 }, 'ERR_OUT_OF_RANGE']]) { try { new Ctor(options); throw new Error(label + ' option validation missing') } catch (error) { if (error.message === label + ' option validation missing' || error.code !== code) throw error } } }; assertResolverOptions(dns.Resolver, 'dns Resolver'); dns.setServers(['127.0.0.1', '[::1]:53', '8.8.8.8:5353']); if (dns.getServers().join(',') !== '127.0.0.1,::1,8.8.8.8:5353') throw new Error('dns servers failed'); try { dns.setServers(['dns.example.com']); throw new Error('dns setServers validation missing') } catch (error) { if (error.message === 'dns setServers validation missing' || error.code !== 'ERR_INVALID_IP_ADDRESS') throw error } try { dns.setServers([':::::']); throw new Error('dns IPv6 validation missing') } catch (error) { if (error.message === 'dns IPv6 validation missing' || error.code !== 'ERR_INVALID_IP_ADDRESS') throw error } try { dns.lookupService(':::', 80, () => {}); throw new Error('dns lookupService IPv6 validation missing') } catch (error) { if (error.message === 'dns lookupService IPv6 validation missing' || error.code !== 'ERR_INVALID_ARG_VALUE') throw error } try { dns.reverse(':::', () => {}); throw new Error('dns reverse IPv6 validation missing') } catch (error) { if (error.message === 'dns reverse IPv6 validation missing' || error.code !== 'EINVAL' || error.syscall !== 'getHostByAddr') throw error } dns.setDefaultResultOrder('ipv6first'); const lookup = await new Promise((resolve, reject) => dns.lookup('localhost', { all: true }, (error, records) => error ? reject(error) : resolve(records))); const literal4 = await new Promise((resolve, reject) => dns.lookup('8.8.8.8', { family: 6 }, (error, address, family) => error ? reject(error) : resolve(address + ':' + family))); const literal6 = await new Promise((resolve, reject) => dns.lookup('2001:db8::1', { all: true, family: 4 }, (error, records) => error ? reject(error) : resolve(records.map((record) => record.address + ':' + record.family).join(',')))); const literalMapped = await new Promise((resolve, reject) => dns.lookup('::ffff:127.0.0.1', { all: true, order: 'ipv4first' }, (error, records) => error ? reject(error) : resolve(records.map((record) => record.address + ':' + record.family).join(',')))); const service = await new Promise((resolve, reject) => dns.lookupService('::1', 3000, (error, hostname, port) => error ? reject(error) : resolve(hostname + ':' + port))); const serviceNames = await Promise.all([80,443,22,53,8080,65000].map((port) => new Promise((resolve, reject) => dns.lookupService('127.0.0.1', port, (error, _hostname, service) => error ? reject(error) : resolve(service))))); const servicePortRows = [['callback-null', () => dns.lookupService('127.0.0.1', null, () => {})], ['callback-bool', () => dns.lookupService('127.0.0.1', true, () => {})], ['callback-empty', () => dns.lookupService('127.0.0.1', '', () => {})], ['callback-space', () => dns.lookupService('127.0.0.1', ' ', () => {})], ['promise-null', () => promises.lookupService('127.0.0.1', null)], ['promise-string', () => promises.lookupService('127.0.0.1', '80')]].map(([label, action]) => { try { const result = action(); return label + ':' + (result?.then ? 'promise' : 'ok') } catch (error) { return label + ':' + error.name + ':' + error.code } }).join('|'); const resolved = await new Promise((resolve, reject) => resolver.resolve4('localhost', { ttl: true }, (error, records) => error ? reject(error) : resolve(records))); const resolverLocal = resolver.setLocalAddress('127.0.0.1', '::1'); const resolverMixedLocal = resolver.setLocalAddress('::1', '127.0.0.1'); const promiseResolverLocal = new promises.Resolver().setLocalAddress('2001:db8::1'); if (lookup.map((record) => record.family).join(',') !== '6,4' || literal4 !== '8.8.8.8:4' || literal6 !== '2001:db8::1:6' || literalMapped !== '::ffff:127.0.0.1:6' || service !== 'localhost:3000' || serviceNames.join(',') !== 'http,https,ssh,domain,http-alt,65000' || servicePortRows !== 'callback-null:RangeError:ERR_SOCKET_BAD_PORT|callback-bool:RangeError:ERR_SOCKET_BAD_PORT|callback-empty:RangeError:ERR_SOCKET_BAD_PORT|callback-space:RangeError:ERR_SOCKET_BAD_PORT|promise-null:RangeError:ERR_SOCKET_BAD_PORT|promise-string:promise' || resolved.map((record) => record.address + ':' + record.ttl).join(',') !== '127.0.0.1:0' || resolverLocal !== undefined || resolverMixedLocal !== undefined || promiseResolverLocal !== undefined) throw new Error(serviceNames.join(',') !== 'http,https,ssh,domain,http-alt,65000' ? 'dns service names failed' : servicePortRows.includes('ok') ? 'dns lookupService port validation failed' : 'dns behavior failed'); const assertSyncError = (label, action, name, code, message) => { try { action(); throw new Error(label + ' missing') } catch (error) { if (error.message === label + ' missing' || error.name !== name || error.code !== code || error.message !== message) throw error } }; assertSyncError('dns resolve bad rrtype', () => dns.resolve('localhost', 'BADTYPE', () => {}), 'TypeError', 'ERR_INVALID_ARG_VALUE', \"The argument 'rrtype' is invalid. Received 'BADTYPE'\"); assertSyncError('dns resolve number rrtype', () => dns.resolve('localhost', 1, () => {}), 'TypeError', 'ERR_INVALID_ARG_TYPE', 'The \"rrtype\" argument must be of type string. Received type number (1)'); assertSyncError('dns resolver undefined rrtype', () => resolver.resolve('localhost', undefined, () => {}), 'TypeError', 'ERR_INVALID_ARG_TYPE', 'The \"rrtype\" argument must be of type string. Received undefined'); assertSyncError('dns resolver local address type', () => resolver.setLocalAddress(1), 'TypeError', 'ERR_INVALID_ARG_TYPE', 'The \"ipv4\" argument must be of type string. Received type number (1)'); assertSyncError('dns resolver local address value', () => resolver.setLocalAddress('bad'), 'TypeError', 'ERR_INVALID_ARG_VALUE', 'Invalid IP address.'); assertSyncError('dns promise resolver local address type', () => new promises.Resolver().setLocalAddress('127.0.0.1', null), 'TypeError', 'ERR_INVALID_ARG_TYPE', 'The \"ipv6\" argument must be of type string. Received null'); try { dns.lookup('localhost', { family: 9 }, () => {}); throw new Error('dns validation missing') } catch (error) { if (error.message === 'dns validation missing' || error.code !== 'ERR_INVALID_ARG_VALUE') throw error }" }, { "specifier": "node:dns/promises", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/net-builtin.test.mjs", "limitation": "Promise API follows the same virtual/browser DNS constraints as node:dns, including loopback and IPv4-mapped literal-IP lookup, loopback PTR/reverse records, local Resolver instances, Resolver constructor option validation, Resolver#setLocalAddress validation, native-shaped invalid rrtype validation, native-shaped Resolver cancellation for pending virtual queries, native-aligned verbatim default result order and verbatim false IPv4-first override, DNS server validation/normalization, malformed IPv6 rejection, Node-shaped CommonJS export order, native-shaped parent accessor identity, Node-shaped function names/arities including reverse, native-shaped top-level helper function prototype metadata, native enumerable Resolver query-method prototype order and function prototype metadata, resolver-instance method shape, argument validation, Node-shaped promise rejection timing for lookup/reverse, synchronous lookupService port validation and invalid lookupService port type rejection, common lookupService port-to-service-name mapping, and TTL records.", "probe": "const dns = require('node:dns'); const promises = require('node:dns/promises'); const keys = 'lookup,lookupService,Resolver,getDefaultResultOrder,setDefaultResultOrder,setServers,NODATA,FORMERR,SERVFAIL,NOTFOUND,NOTIMP,REFUSED,BADQUERY,BADNAME,BADFAMILY,BADRESP,CONNREFUSED,TIMEOUT,EOF,FILE,NOMEM,DESTRUCTION,BADSTR,BADFLAGS,NONAME,BADHINTS,NOTINITIALIZED,LOADIPHLPAPI,ADDRGETNETWORKPARAMS,CANCELLED,getServers,resolve,resolve4,resolve6,resolveAny,resolveCaa,resolveCname,resolveMx,resolveNaptr,resolveNs,resolvePtr,resolveSoa,resolveSrv,resolveTlsa,resolveTxt,reverse'; const resolverKeys = 'resolveAny,resolve4,resolve6,resolveCaa,resolveCname,resolveMx,resolveNs,resolveTlsa,resolveTxt,resolveSrv,resolvePtr,resolveNaptr,resolveSoa,reverse,resolve'; const resolver = new promises.Resolver(); const helperNames = 'lookup,lookupService,getDefaultResultOrder,setDefaultResultOrder,setServers,getServers,resolve,resolve4,resolve6,resolveAny,resolveCaa,resolveCname,resolveMx,resolveNaptr,resolveNs,resolvePtr,resolveSoa,resolveSrv,resolveTlsa,resolveTxt,reverse'.split(','); const helperFunctionPrototypeMeta = helperNames.map((name) => { const fn = promises[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, Object.hasOwn(fn, 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(',')].join(':') }).join('|'); const expectedHelperFunctionPrototypeMeta = helperNames.slice(0, 5).map((name) => name + ':true:false:false:true:constructor').concat(helperNames.slice(5).map((name) => name + ':false::::')).join('|'); const queryFunctionPrototypeMeta = resolverKeys.split(',').map((name) => { const fn = promises.Resolver.prototype[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, Object.hasOwn(fn, 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(',')].join(':') }).join('|'); const expectedQueryFunctionPrototypeMeta = resolverKeys.split(',').map((name) => name + ':true:false:false:true:constructor').join('|'); if (Object.hasOwn(promises, 'default') || dns.promises !== promises || Object.keys(promises).join(',') !== keys || promises.NOTFOUND !== 'ENOTFOUND' || promises.lookup.length !== 2 || promises.lookupService.length !== 2 || promises.resolve.length !== 2 || promises.resolve4.length !== 2 || promises.resolve6.length !== 2 || promises.resolveAny.length !== 2 || promises.reverse.length !== 2 || promises.Resolver.length !== 0 || promises.resolve.name !== 'bound resolve' || promises.resolve4.name !== 'bound queryA' || promises.resolveAny.name !== 'bound queryAny' || promises.reverse.name !== 'bound getHostByAddr' || helperFunctionPrototypeMeta !== expectedHelperFunctionPrototypeMeta || Object.keys(promises.Resolver.prototype).join(',') !== resolverKeys || queryFunctionPrototypeMeta !== expectedQueryFunctionPrototypeMeta || promises.Resolver.prototype.resolve.name !== 'resolve' || promises.Resolver.prototype.resolve.length !== 2 || promises.Resolver.prototype.reverse.name !== 'getHostByAddr' || promises.Resolver.prototype.reverse.length !== 2) throw new Error('dns/promises metadata failed'); const assertResolverOptions = (Ctor, label) => { const inheritedOptions = Object.create({ timeout: 'bad', tries: 0 }); const accessorOptions = {}; Object.defineProperty(accessorOptions, 'timeout', { get() { throw new Error(label + ' getter called') } }); for (const options of [undefined, null, 42, 'ignored', [], { timeout: -1 }, { timeout: 0 }, { timeout: 2147483647, tries: 1 }, { tries: 2147483647 }, inheritedOptions, accessorOptions]) new Ctor(options); for (const [options, code] of [[{ timeout: '100' }, 'ERR_INVALID_ARG_TYPE'], [{ timeout: NaN }, 'ERR_OUT_OF_RANGE'], [{ timeout: 1.5 }, 'ERR_OUT_OF_RANGE'], [{ timeout: -2 }, 'ERR_OUT_OF_RANGE'], [{ timeout: 2147483648 }, 'ERR_OUT_OF_RANGE'], [{ tries: '2' }, 'ERR_INVALID_ARG_TYPE'], [{ tries: NaN }, 'ERR_OUT_OF_RANGE'], [{ tries: 1.5 }, 'ERR_OUT_OF_RANGE'], [{ tries: 0 }, 'ERR_OUT_OF_RANGE'], [{ tries: 2147483648 }, 'ERR_OUT_OF_RANGE']]) { try { new Ctor(options); throw new Error(label + ' option validation missing') } catch (error) { if (error.message === label + ' option validation missing' || error.code !== code) throw error } } }; assertResolverOptions(promises.Resolver, 'dns/promises Resolver'); dns.setDefaultResultOrder('ipv6first'); const lookup = await promises.lookup('localhost', { all: true }); const literal4 = await promises.lookup('8.8.8.8', { family: 6 }); const literal6 = await promises.lookup('2001:db8::1', { all: true, family: 4 }); const literalMapped = await promises.lookup('::ffff:127.0.0.1', { all: true, order: 'ipv4first' }); const service = await promises.lookupService('127.0.0.1', 8080); const serviceNames = await Promise.all([80,443,22,53,8080,65000].map((port) => promises.lookupService('127.0.0.1', port).then((result) => result.service))); const servicePortRows = [['null', null], ['bool', true], ['empty', ''], ['space', ' '], ['string', '80']].map(([label, port]) => { try { const result = promises.lookupService('127.0.0.1', port); return label + ':' + (result?.then ? 'promise' : 'ok') } catch (error) { return label + ':' + error.name + ':' + error.code } }).join('|'); const any = await promises.resolve('localhost', 'ANY'); const ttl = await resolver.resolve4('localhost', { ttl: true }); const reverse = await resolver.reverse('::1'); const localAddress = resolver.setLocalAddress('127.0.0.1'); const mixedLocalAddress = resolver.setLocalAddress('::1', '127.0.0.1'); if (lookup.map((record) => record.family).join(',') !== '6,4' || literal4.address !== '8.8.8.8' || literal4.family !== 4 || literal6.map((record) => record.address + ':' + record.family).join(',') !== '2001:db8::1:6' || literalMapped.map((record) => record.address + ':' + record.family).join(',') !== '::ffff:127.0.0.1:6' || service.hostname !== 'localhost' || service.service !== 'http-alt' || serviceNames.join(',') !== 'http,https,ssh,domain,http-alt,65000' || servicePortRows !== 'null:RangeError:ERR_SOCKET_BAD_PORT|bool:RangeError:ERR_SOCKET_BAD_PORT|empty:RangeError:ERR_SOCKET_BAD_PORT|space:RangeError:ERR_SOCKET_BAD_PORT|string:promise' || any.map((record) => record.type + ':' + record.family + ':' + record.ttl).join(',') !== 'AAAA:6:0,A:4:0' || ttl.map((record) => record.address + ':' + record.ttl).join(',') !== '127.0.0.1:0' || reverse.join(',') !== 'localhost' || localAddress !== undefined || mixedLocalAddress !== undefined) throw new Error(serviceNames.join(',') !== 'http,https,ssh,domain,http-alt,65000' ? 'dns/promises service names failed' : servicePortRows.includes(':ok') ? 'dns/promises lookupService port validation failed' : 'dns/promises behavior failed'); const assertSyncError = (label, action, name, code, message) => { try { action(); throw new Error(label + ' missing') } catch (error) { if (error.message === label + ' missing' || error.name !== name || error.code !== code || error.message !== message) throw error } }; assertSyncError('dns/promises resolve lowercase rrtype', () => promises.resolve('localhost', 'a'), 'TypeError', 'ERR_INVALID_ARG_VALUE', \"The argument 'rrtype' is invalid. Received 'a'\"); assertSyncError('dns/promises resolve null rrtype', () => promises.resolve('localhost', null), 'TypeError', 'ERR_INVALID_ARG_TYPE', 'The \"rrtype\" argument must be of type string. Received null'); assertSyncError('dns/promises resolver lowercase rrtype', () => resolver.resolve('localhost', 'a'), 'TypeError', 'ERR_INVALID_ARG_VALUE', \"The argument 'rrtype' is invalid. Received 'a'\"); assertSyncError('dns/promises resolver local missing', () => resolver.setLocalAddress(), 'TypeError', 'ERR_INVALID_ARG_TYPE', 'The \"ipv4\" argument must be of type string. Received undefined'); assertSyncError('dns/promises resolver local value', () => resolver.setLocalAddress('127.0.0.999'), 'TypeError', 'ERR_INVALID_ARG_VALUE', 'Invalid IP address.'); try { await promises.reverse(':::'); throw new Error('dns/promises reverse IPv6 validation missing') } catch (error) { if (error.message === 'dns/promises reverse IPv6 validation missing' || error.code !== 'EINVAL' || error.syscall !== 'getHostByAddr') throw error } try { await promises.lookupService(':::', 80); throw new Error('dns/promises lookupService IPv6 validation missing') } catch (error) { if (error.message === 'dns/promises lookupService IPv6 validation missing' || error.code !== 'ERR_INVALID_ARG_VALUE') throw error } try { await promises.resolve4('missing.invalid'); throw new Error('dns/promises missing failed') } catch (error) { if (error.message === 'dns/promises missing failed' || error.code !== 'ENOTFOUND' || error.syscall !== 'queryA' || error.hostname !== 'missing.invalid') throw error }" }, { "specifier": "node:events", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "EventEmitter behavior, native own instance _events/_eventsCount/_maxListeners plus shape/capture symbols with WeakMap-backed listener storage and no leaked OpenContainers storage symbol, EventTarget once/on support including AbortSignal, direct EventTarget getEventListeners/listenerCount and per-target max-listener state, native-shaped addAbortListener validation and disposable metadata, EventEmitterAsyncResource constructor metadata, validation, own emit() prototype metadata/order, resource-shape probes, and async_hooks execution context preservation, native-shaped CommonJS export order, constructor/helper metadata, static helper validation, static accessor descriptors, hidden EventTarget listener symbols, and EventEmitter prototype metadata/aliases are covered.", "probe": "const events = require('node:events'); const asyncHooks = require('node:async_hooks'); const d = (key) => Object.getOwnPropertyDescriptor(events, key); const pd = (key) => Object.getOwnPropertyDescriptor(events.EventEmitter.prototype, key); const hiddenOk = (descriptor) => descriptor && !descriptor.enumerable && !descriptor.configurable && !descriptor.writable && typeof descriptor.value === 'symbol'; const protoOk = (descriptor, type) => descriptor && descriptor.enumerable && descriptor.configurable && descriptor.writable && typeof descriptor.value === type; const ee = new events.EventEmitter(); const capturedEe = new events.EventEmitter({ captureRejections: true }); const emitterShape = (emitter) => [Reflect.ownKeys(emitter).map(String).join(','), Object.keys(emitter).join(','), emitter._eventsCount, Object.getPrototypeOf(emitter._events) === null, Object.getOwnPropertySymbols(emitter).map((symbol) => String(symbol) + ':' + emitter[symbol]).join(','), Object.hasOwn(emitter, 'captureRejections')].join('|'); const p = events.once(ee, 'ready'); ee.emit('ready', 42); const [value] = await p; const asyncResource = new events.EventEmitterAsyncResource({ name: 'matrix-resource', triggerAsyncId: 7 }); const asyncValidation = [() => new events.EventEmitterAsyncResource(), () => new events.EventEmitterAsyncResource({}), () => new events.EventEmitterAsyncResource({ name: null }), () => new events.EventEmitterAsyncResource({ name: 'x', triggerAsyncId: null }), () => new events.EventEmitterAsyncResource({ name: 'x', triggerAsyncId: '7' }), () => new events.EventEmitterAsyncResource({ name: 'x', triggerAsyncId: 1.5 })].map((action) => { try { action(); return 'ok' } catch (error) { return error.name + ':' + error.code } }).join('|'); const asyncDescriptors = ['asyncId','triggerAsyncId','asyncResource'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(events.EventEmitterAsyncResource.prototype, name); return [name, descriptor.enumerable, descriptor.configurable, descriptor.get.name, descriptor.get.length, typeof descriptor.set].join(':') }).join('|'); const asyncPrototypeNames = Object.getOwnPropertyNames(events.EventEmitterAsyncResource.prototype).join(','); const asyncPrototypeKeys = Object.keys(events.EventEmitterAsyncResource.prototype).join(','); const asyncEmitDescriptor = Object.getOwnPropertyDescriptor(events.EventEmitterAsyncResource.prototype, 'emit'); const asyncEmitMeta = [asyncEmitDescriptor.enumerable, asyncEmitDescriptor.configurable, asyncEmitDescriptor.writable, asyncEmitDescriptor.value.name, asyncEmitDescriptor.value.length, Object.hasOwn(asyncEmitDescriptor.value, 'prototype'), asyncEmitDescriptor.value === events.EventEmitter.prototype.emit].join(':'); const asyncEmitRows = []; asyncResource.on('matrix-ready', function(value) { asyncEmitRows.push((this === asyncResource) + ':' + value) }); const asyncEmitReturn = [asyncResource.emit('matrix-ready', 'ok'), asyncResource.emit('missing'), asyncEmitRows.join('|')].join(':'); const stringResource = new events.EventEmitterAsyncResource('string-resource'); const storage = new asyncHooks.AsyncLocalStorage(); let scopedAsyncResource; const scopedRows = []; storage.run('matrix-store', () => { scopedAsyncResource = new events.EventEmitterAsyncResource({ name: 'matrix-scoped', triggerAsyncId: 11 }); }); scopedAsyncResource.on('scoped', function(value) { scopedRows.push([(this === scopedAsyncResource), value, storage.getStore(), asyncHooks.executionAsyncId() === scopedAsyncResource.asyncId, asyncHooks.triggerAsyncId(), asyncHooks.executionAsyncResource() === scopedAsyncResource.asyncResource].join(':')) }); const scopedEmitReturn = scopedAsyncResource.emit('scoped', 'ok'); const addAbortValidation = [() => events.addAbortListener(), () => events.addAbortListener(null, () => {}), () => events.addAbortListener({}, () => {}), () => events.addAbortListener(new AbortController().signal, 1)].map((action) => { try { action(); return 'ok' } catch (error) { return error.name + ':' + error.code } }).join('|'); const abortController = new AbortController(); const abortDisposable = events.addAbortListener(abortController.signal, () => {}); const abortDescriptor = Object.getOwnPropertyDescriptor(abortDisposable, Symbol.dispose); const abortDisposableShape = JSON.stringify([Object.keys(abortDisposable).join(','), Object.getOwnPropertyNames(abortDisposable).join(','), Object.getOwnPropertySymbols(abortDisposable).map(String).join(','), abortDescriptor.enumerable, abortDescriptor.configurable, abortDescriptor.writable, abortDescriptor.value.name, abortDescriptor.value.length, Object.hasOwn(abortDescriptor.value, 'prototype')]); abortDisposable[Symbol.dispose](); let disposedCalls = 0; const disposedController = new AbortController(); const disposed = events.addAbortListener(disposedController.signal, () => disposedCalls++); disposed[Symbol.dispose](); disposedController.abort('stop'); const staticValidation = [['listener-object', () => events.listenerCount({}, 'x')], ['listener-array', () => events.listenerCount([], 'x')], ['listener-function', () => events.listenerCount(function namedListenerTarget() {}, 'x')], ['get-listeners-function', () => events.getEventListeners(function namedEventTarget() {}, 'x')], ['get-max-function', () => events.getMaxListeners(function namedMaxTarget() {})], ['set-max-function', () => events.setMaxListeners(2, function namedSetTarget() {})]].map(([label, action]) => { try { action(); return label + ':return' } catch (error) { return [label, error.name, error.code, error.message].join(':') } }).join('|'); const targetRows = (() => { const target = new EventTarget(); const calls = []; function first() { calls.push('first') } function onceListener() { calls.push('once') } const objectListener = { handleEvent(event) { calls.push('object:' + (event.target === target)) } }; target.addEventListener('ping', first); target.addEventListener('ping', onceListener, { once: true }); target.addEventListener('ping', objectListener); const listeners = events.getEventListeners(target, 'ping'); const before = [listeners.length, listeners[0] === first, listeners[1] === onceListener, listeners[2] === objectListener, events.listenerCount(target, 'ping')].join(':'); target.removeEventListener('ping', first); const removed = events.getEventListeners(target, 'ping').map((listener) => listener === onceListener ? 'once' : listener === objectListener ? 'object' : '?').join(',') + ':' + events.listenerCount(target, 'ping'); target.dispatchEvent(new Event('ping')); const after = calls.join('|') + ':' + events.getEventListeners(target, 'ping').map((listener) => listener === objectListener ? 'object' : '?').join(',') + ':' + events.listenerCount(target, 'ping'); const captureTarget = new EventTarget(); function captureListener() {} captureTarget.addEventListener('capture', captureListener); captureTarget.addEventListener('capture', captureListener); captureTarget.addEventListener('capture', captureListener, { capture: true }); const duplicate = String(events.getEventListeners(captureTarget, 'capture').length); captureTarget.removeEventListener('capture', captureListener); const captureRemove = String(events.getEventListeners(captureTarget, 'capture').length); captureTarget.removeEventListener('capture', captureListener, { capture: true }); const captureClear = String(events.getEventListeners(captureTarget, 'capture').length); const maxBefore = String(events.getMaxListeners(target)); events.setMaxListeners(7, target); const maxAfter = events.getMaxListeners(target) + ':' + events.defaultMaxListeners; return [before, removed, after, duplicate, captureRemove, captureClear, maxBefore, maxAfter].join(';') })(); if (value !== 42 || emitterShape(ee) !== '_events,_eventsCount,_maxListeners,Symbol(shapeMode),Symbol(kCapture)|_events,_eventsCount,_maxListeners|0|true|Symbol(shapeMode):false,Symbol(kCapture):false|false' || emitterShape(capturedEe) !== '_events,_eventsCount,_maxListeners,Symbol(shapeMode),Symbol(kCapture)|_events,_eventsCount,_maxListeners|0|true|Symbol(shapeMode):false,Symbol(kCapture):true|false' || Object.keys(events).join(',') !== 'addAbortListener,once,on,getEventListeners,getMaxListeners,listenerCount,EventEmitter,usingDomains,captureRejectionSymbol,captureRejections,EventEmitterAsyncResource,errorMonitor,defaultMaxListeners,setMaxListeners,init' || events.EventEmitter.length !== 1 || events.EventEmitterAsyncResource.length !== 0 || events.listenerCount.name !== 'listenerCount' || events.listenerCount.length !== 2 || events.setMaxListeners.name !== '' || events.setMaxListeners.length !== 0 || events.init.name !== '' || events.init.length !== 1 || d('captureRejections').configurable || d('defaultMaxListeners').configurable || d('EventEmitterAsyncResource').get.name !== 'lazyEventEmitterAsyncResource' || asyncValidation !== 'TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE|RangeError:ERR_INVALID_ASYNC_ID|RangeError:ERR_INVALID_ASYNC_ID|RangeError:ERR_INVALID_ASYNC_ID' || asyncDescriptors !== 'asyncId:false:true:get asyncId:0:undefined|triggerAsyncId:false:true:get triggerAsyncId:0:undefined|asyncResource:false:true:get asyncResource:0:undefined' || asyncPrototypeNames !== 'constructor,emit,emitDestroy,asyncId,triggerAsyncId,asyncResource' || asyncPrototypeKeys !== '' || asyncEmitMeta !== 'false:true:true:emit:1:false:false' || asyncEmitReturn !== 'true:false:true:ok' || Object.hasOwn(asyncResource, 'asyncId') || Object.hasOwn(asyncResource, 'triggerAsyncId') || Object.hasOwn(asyncResource, 'asyncResource') || Object.hasOwn(asyncResource, 'destroyed') || asyncResource.triggerAsyncId !== 7 || asyncResource.asyncResource.triggerAsyncId() !== 7 || asyncResource.asyncResource.asyncId() !== asyncResource.asyncId || asyncResource.emitDestroy() !== undefined || scopedEmitReturn !== true || scopedRows.join('|') !== 'true:ok:matrix-store:true:11:true' || stringResource.name !== undefined || stringResource.destroyed !== undefined || addAbortValidation !== 'TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE' || abortDisposableShape !== '[\"\",\"\",\"Symbol(Symbol.dispose)\",true,true,true,\"[Symbol.dispose]\",0,false]' || disposedCalls !== 0 || targetRows !== '3:true:true:true:3;once,object:2;once|object:true:object:1;2;1;0;10;7:10' || staticValidation !== 'listener-object:TypeError:ERR_INVALID_ARG_TYPE:The \"emitter\" argument must be an instance of EventEmitter or EventTarget. Received an instance of Object|listener-array:TypeError:ERR_INVALID_ARG_TYPE:The \"emitter\" argument must be an instance of EventEmitter or EventTarget. Received an instance of Array|listener-function:TypeError:ERR_INVALID_ARG_TYPE:The \"emitter\" argument must be an instance of EventEmitter or EventTarget. Received function namedListenerTarget|get-listeners-function:TypeError:ERR_INVALID_ARG_TYPE:The \"emitter\" argument must be an instance of EventEmitter or EventTarget. Received function namedEventTarget|get-max-function:TypeError:ERR_INVALID_ARG_TYPE:The \"emitter\" argument must be an instance of EventEmitter or EventTarget. Received function namedMaxTarget|set-max-function:TypeError:ERR_INVALID_ARG_TYPE:The \"eventTargets\" argument must be an instance of EventEmitter or EventTarget. Received function namedSetTarget' || !hiddenOk(d('kMaxEventTargetListeners')) || !hiddenOk(d('kMaxEventTargetListenersWarned')) || events.EventEmitter.prototype.on !== events.EventEmitter.prototype.addListener || events.EventEmitter.prototype.off !== events.EventEmitter.prototype.removeListener || events.EventEmitter.prototype.on.name !== 'addListener' || events.EventEmitter.prototype.off.name !== 'removeListener' || !protoOk(pd('_events'), 'undefined') || !protoOk(pd('_eventsCount'), 'number') || pd('_eventsCount').value !== 0 || !protoOk(pd('_maxListeners'), 'undefined')) throw new Error('events failed'); const controller = new AbortController(); const abortPromise = events.once(controller.signal, 'abort'); controller.abort('native-reason'); const [abortEvent] = await abortPromise; const target = new EventTarget(); const iterator = events.on(target, 'message', { close: ['close'] }); target.dispatchEvent(new Event('message')); target.dispatchEvent(new Event('close')); let count = 0; let eventTargetOk = false; for await (const [event] of iterator) { eventTargetOk = event.type === 'message' && event.target === target; count++; } const signal = new AbortController(); const aborted = events.on(new EventTarget(), 'message', { signal: signal.signal }); const abortResult = aborted.next().catch((error) => [error.name, error.code, error.cause].join(':')); signal.abort('stop'); if (abortEvent.type !== 'abort' || abortEvent.target !== controller.signal || controller.signal.reason !== 'native-reason' || !eventTargetOk || count !== 1 || await abortResult !== 'AbortError:ABORT_ERR:stop') throw new Error('events EventTarget failed')" }, { "specifier": "node:fs", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/fs-compat.test.mjs, tests/fs-streams-watch.test.mjs", "limitation": "Virtual filesystem APIs are broad, including native-shaped CommonJS export order, Node-shaped callback helpers, native-shaped top-level helper own-prototype descriptors, native-shaped sync helper arities, native-shaped stream export accessors/prototypes, ReadStream/WriteStream helper own-prototype metadata, and directory class descriptor metadata, native-shaped Dirent constructor/predicate/parentPath own-key shape, read-only native-order fs.constants metadata without top-level fs constant exports, native-shaped Stats own keys/prototype accessors/constructor wrapper plus instant/nanosecond timestamp fields, descriptor metadata/flush helpers, descriptor read/write object option overloads and Node-shaped callback result tuples, encoding-aware file-content and readlink/realpath/readdir/opendir path helpers, recursive readdir traversal, cp filter/existing-destination/timestamp options, stricter unlink/open flag validation, mkdtemp prefix validation, disposable temp directory symbol metadata, encoded path results, and file URL scheme/host/encoded-separator validation plus URL-like object parity, native-shaped openAsBlob promise helper, openAsBlob argument preflight validation, Node-shaped FileHandle async id/prototype metadata and StatWatcher wrappers, direct ReadStream/WriteStream constructors plus FileHandle stream/line helpers, glob helpers, recursive virtual directory filtering/nested relative filenames for FSWatcher, and StatFs instance wrappers without public constructor exports, native-shaped promises accessor identity, _toUnixTimestamp, native-shaped Utf8Stream prototype/accessor/disposal metadata, fd writing, and common AbortSignal behavior, but host OS descriptors and native permission semantics remain limited.", "probe": "const fs = require('node:fs'); const fsp = require('node:fs/promises'); const fsNamespace = await import('node:fs'); const expectedFsKeys = 'appendFile,appendFileSync,access,accessSync,chown,chownSync,chmod,chmodSync,close,closeSync,copyFile,copyFileSync,cp,cpSync,createReadStream,createWriteStream,exists,existsSync,fchown,fchownSync,fchmod,fchmodSync,fdatasync,fdatasyncSync,fstat,fstatSync,fsync,fsyncSync,ftruncate,ftruncateSync,futimes,futimesSync,glob,globSync,lchown,lchownSync,lchmod,lchmodSync,link,linkSync,lstat,lstatSync,lutimes,lutimesSync,mkdir,mkdirSync,mkdtemp,mkdtempSync,mkdtempDisposableSync,open,openSync,openAsBlob,readdir,readdirSync,read,readSync,readv,readvSync,readFile,readFileSync,readlink,readlinkSync,realpath,realpathSync,rename,renameSync,rm,rmSync,rmdir,rmdirSync,stat,statfs,statSync,statfsSync,symlink,symlinkSync,truncate,truncateSync,unwatchFile,unlink,unlinkSync,utimes,utimesSync,watch,watchFile,writeFile,writeFileSync,write,writeSync,writev,writevSync,Dirent,Stats,ReadStream,WriteStream,FileReadStream,FileWriteStream,Utf8Stream,_toUnixTimestamp,Dir,opendir,opendirSync,constants,promises'; const promisesDescriptor = Object.getOwnPropertyDescriptor(fs, 'promises'); const statfsProbe = fs.statfsSync('.'); fs.writeFileSync('fs-stats-probe.txt', 'stats'); const statsProbe = fs.statSync('fs-stats-probe.txt'); const statsBigintProbe = fs.statSync('fs-stats-probe.txt', { bigint: true }); const statsProto = Object.getPrototypeOf(statsProbe); const statsBaseProto = Object.getPrototypeOf(statsProto); const statsDescriptor = Object.getOwnPropertyDescriptor(fs, 'Stats'); const statsAccessorsOk = ['atime','mtime','ctime','birthtime','atimeInstant','mtimeInstant','ctimeInstant','birthtimeInstant'].every((name) => { const descriptor = Object.getOwnPropertyDescriptor(statsProto, name); return descriptor?.enumerable && descriptor.configurable && descriptor.get?.name === 'get' && descriptor.get.length === 0 && descriptor.set?.name === 'set' && descriptor.set.length === 1 }); const statsBaseOk = ['isDirectory','isFile','isBlockDevice','isCharacterDevice','isSymbolicLink','isFIFO','isSocket'].every((name) => { const descriptor = Object.getOwnPropertyDescriptor(statsBaseProto, name); return descriptor?.enumerable && descriptor.configurable && descriptor.writable && descriptor.value?.name === '' && descriptor.value.length === 0 }); const checkModeDescriptor = Object.getOwnPropertyDescriptor(statsProto, '_checkModeProperty'); const statsShapeOk = Object.keys(statsProbe).join(',') === 'dev,mode,nlink,uid,gid,rdev,blksize,ino,size,blocks,atimeMs,mtimeMs,ctimeMs,birthtimeMs' && !Object.hasOwn(statsProbe, 'atime') && !Object.hasOwn(statsProbe, 'atimeInstant') && Object.getOwnPropertyNames(statsProto).join(',') === 'constructor,atime,mtime,ctime,birthtime,atimeInstant,mtimeInstant,ctimeInstant,birthtimeInstant,_checkModeProperty' && Object.keys(statsProto).join(',') === 'atime,mtime,ctime,birthtime,atimeInstant,mtimeInstant,ctimeInstant,birthtimeInstant,_checkModeProperty' && statsAccessorsOk && checkModeDescriptor?.enumerable && checkModeDescriptor.configurable && checkModeDescriptor.writable && checkModeDescriptor.value.name === '' && checkModeDescriptor.value.length === 1 && Object.getOwnPropertyNames(statsBaseProto).join(',') === 'constructor,isDirectory,isFile,isBlockDevice,isCharacterDevice,isSymbolicLink,isFIFO,isSocket' && Object.keys(statsBaseProto).join(',') === 'isDirectory,isFile,isBlockDevice,isCharacterDevice,isSymbolicLink,isFIFO,isSocket' && statsBaseOk && statsDescriptor?.enumerable && statsDescriptor.configurable && statsDescriptor.writable && fs.Stats.name === 'deprecated' && fs.Stats.length === 18 && statsProbe.constructor !== fs.Stats && statsProbe instanceof fs.Stats && statsProbe.isFile() && !statsProbe.isDirectory() && typeof statsProbe.atime?.getTime === 'function' && statsProbe.atimeInstant?.constructor?.name === 'Instant' && Object.keys(statsBigintProbe).join(',') === 'dev,mode,nlink,uid,gid,rdev,blksize,ino,size,blocks,atimeMs,mtimeMs,ctimeMs,birthtimeMs,atimeNs,mtimeNs,ctimeNs,birthtimeNs' && typeof statsBigintProbe.mode === 'bigint' && typeof statsBigintProbe.atimeNs === 'bigint' && statsBigintProbe.isFile() && statsBigintProbe.atimeInstant?.constructor?.name === 'Instant'; const topLevelConstantNames = ['F_OK','R_OK','W_OK','X_OK','COPYFILE_EXCL','O_RDONLY','UV_FS_SYMLINK_DIR','S_IFREG']; const topLevelConstantsAbsent = topLevelConstantNames.every((name) => !Object.hasOwn(fs, name) && fs[name] === undefined && !Object.hasOwn(fsNamespace, name) && !Object.hasOwn(fsNamespace.default, name)); fs.writeFileSync('fs-open-blob.txt', 'blob'); const blobPromise = fs.openAsBlob('fs-open-blob.txt', { type: 'text/plain' }); if (Object.keys(fs).join(',') !== expectedFsKeys || !topLevelConstantsAbsent || !statsShapeOk || typeof fs._toUnixTimestamp !== 'function' || typeof fs.Utf8Stream !== 'function' || fs.openAsBlob.constructor.name !== 'Function' || fs.openAsBlob.name !== 'openAsBlob' || fs.openAsBlob.length !== 1 || !(blobPromise instanceof Promise) || Object.hasOwn(fs, 'FSWatcher') || fs.FSWatcher !== undefined || Object.hasOwn(fs, 'StatFs') || fs.StatFs !== undefined || statfsProbe.constructor.name !== 'StatFs' || fs._toUnixTimestamp(new Date(1000)) !== 1 || typeof promisesDescriptor.get !== 'function' || promisesDescriptor.set !== undefined || fs.promises !== fsp) throw new Error('fs helper shape failed'); const blobProbe = await blobPromise; if (blobProbe.type !== 'text/plain' || await blobProbe.text() !== 'blob') throw new Error('fs openAsBlob failed'); const constantsDescriptor = Object.getOwnPropertyDescriptor(fs, 'constants'); const promisesConstantsDescriptor = Object.getOwnPropertyDescriptor(fsp, 'constants'); const rDescriptor = Object.getOwnPropertyDescriptor(fs.constants, 'R_OK'); const constantKeys = Object.keys(fs.constants); const constantHead = constantKeys.slice(0, 15).join(','); const constantTail = constantKeys.slice(-10).join(','); if (!constantsDescriptor.enumerable || constantsDescriptor.configurable || constantsDescriptor.writable || Object.getPrototypeOf(fs.constants) !== null || !Object.isExtensible(fs.constants) || !rDescriptor.enumerable || rDescriptor.configurable || rDescriptor.writable || rDescriptor.value !== fs.constants.R_OK || !promisesConstantsDescriptor.enumerable || !promisesConstantsDescriptor.configurable || !promisesConstantsDescriptor.writable || fsp.constants !== fs.constants || constantHead !== 'UV_FS_SYMLINK_DIR,UV_FS_SYMLINK_JUNCTION,O_RDONLY,O_WRONLY,O_RDWR,UV_DIRENT_UNKNOWN,UV_DIRENT_FILE,UV_DIRENT_DIR,UV_DIRENT_LINK,UV_DIRENT_FIFO,UV_DIRENT_SOCKET,UV_DIRENT_CHAR,UV_DIRENT_BLOCK,S_IFMT,S_IFREG' || constantTail !== 'F_OK,R_OK,W_OK,X_OK,UV_FS_COPYFILE_EXCL,COPYFILE_EXCL,UV_FS_COPYFILE_FICLONE,COPYFILE_FICLONE,UV_FS_COPYFILE_FICLONE_FORCE,COPYFILE_FICLONE_FORCE') throw new Error('fs constants metadata failed'); fs.writeFileSync('fs-io-overload.txt', 'abcdef'); const ioFd = fs.openSync('fs-io-overload.txt', 'r+'); const ioBuffer = Buffer.alloc(4, '.'); const ioRead = fs.readSync(ioFd, ioBuffer, { offset: 1, length: 2, position: 2 }); const ioWrite = fs.writeSync(ioFd, Buffer.from('XYZ'), { offset: 1, length: 2, position: 1 }); const ioCallback = await new Promise((resolve, reject) => { const callbackBuffer = Buffer.alloc(2); fs.read(ioFd, callbackBuffer, { position: 0 }, (error, bytesRead, buffer) => error ? reject(error) : resolve([bytesRead, buffer === callbackBuffer, callbackBuffer.toString()])); }); fs.closeSync(ioFd); fs.writeFileSync('fs-io-overload.txt', 'abcdef'); const ioHandle = await fsp.open('fs-io-overload.txt', 'r+'); const ioHandleBuffer = Buffer.alloc(4, '.'); const ioHandleRead = await ioHandle.read(ioHandleBuffer, { offset: 1, length: 2, position: 2 }); const ioHandleWrite = await ioHandle.write(Buffer.from('XYZ'), { offset: 1, length: 2, position: 1 }); await ioHandle.close(); if (ioRead !== 2 || ioBuffer.toString() !== '.cd.' || ioWrite !== 2 || ioCallback.join(':') !== '2:true:aY' || ioHandleRead.bytesRead !== 2 || ioHandleRead.buffer !== ioHandleBuffer || ioHandleBuffer.toString() !== '.cd.' || ioHandleWrite.bytesWritten !== 2 || ioHandleWrite.buffer.toString() !== 'XYZ' || fs.readFileSync('fs-io-overload.txt', 'utf8') !== 'aYZdef') throw new Error('fs descriptor overloads failed'); const callbackMetadata = { readFile: 3, writeFile: 4, appendFile: 4, readdir: 3, access: 3, stat: 1, lstat: 1, statfs: 1, utimes: 4, lutimes: 4, mkdir: 3, rm: 3, rmdir: 3, unlink: 2, rename: 3, copyFile: 4, cp: 4, chmod: 3, chown: 4, lchmod: 3, lchown: 4, link: 3, realpath: 3, open: 4, close: 1, read: 6, write: 6, readv: 4, writev: 4, truncate: 3, ftruncate: 1, fstat: 1, fchmod: 3, fchown: 4, futimes: 4, fsync: 2, fdatasync: 2, mkdtemp: 3, opendir: 3, glob: 3, readlink: 3, symlink: 4, exists: 2 }; for (const [name, length] of Object.entries(callbackMetadata)) { const fn = fs[name]; if (typeof fn !== 'function' || fn.name !== name || fn.length !== length) throw new Error('fs callback metadata failed: ' + name + ':' + fn?.name + '/' + fn?.length); } const syncMetadata = { copyFileSync: 3, createReadStream: 2, createWriteStream: 2, openSync: 3, readSync: 5, readvSync: 3, statSync: 1, lstatSync: 1, fstatSync: 1, truncateSync: 2, mkdtempSync: 2, mkdtempDisposableSync: 2, globSync: 2, writevSync: 3, symlinkSync: 3, Dirent: 3, Dir: 3 }; for (const [name, length] of Object.entries(syncMetadata)) { const fn = fs[name]; if (typeof fn !== 'function' || fn.name !== name || fn.length !== length) throw new Error('fs sync metadata failed: ' + name + ':' + fn?.name + '/' + fn?.length); } const syncHelperNames = Object.keys(syncMetadata).filter((name) => name !== 'Dirent' && name !== 'Dir'); for (const name of syncHelperNames) { const descriptor = Object.getOwnPropertyDescriptor(fs[name], 'prototype'); if (!descriptor || descriptor.enumerable || descriptor.configurable || !descriptor.writable || Object.getOwnPropertyNames(descriptor.value).join(',') !== 'constructor' || descriptor.value.constructor !== fs[name]) throw new Error('fs sync prototype metadata failed: ' + name); } try { fs._toUnixTimestamp(undefined); throw new Error('timestamp should fail'); } catch (error) { if (error.code !== 'ERR_INVALID_ARG_TYPE') throw error; } const streamExportMetadata = { ReadStream: ['function', 'function', 'get ReadStream', 'set ReadStream', 'ReadStream', 2], WriteStream: ['function', 'function', 'get WriteStream', 'set WriteStream', 'WriteStream', 2], FileReadStream: ['function', 'function', 'get FileReadStream', 'set FileReadStream', 'ReadStream', 2], FileWriteStream: ['function', 'function', 'get FileWriteStream', 'set FileWriteStream', 'WriteStream', 2], Utf8Stream: ['function', 'undefined', 'get Utf8Stream', undefined, 'Utf8Stream', 0] }; for (const [name, [getter, setter, getterName, setterName, fnName, length]] of Object.entries(streamExportMetadata)) { const descriptor = Object.getOwnPropertyDescriptor(fs, name); if (!descriptor || !descriptor.enumerable || !descriptor.configurable || typeof descriptor.get !== getter || typeof descriptor.set !== setter || descriptor.get?.name !== getterName || descriptor.set?.name !== setterName || fs[name].name !== fnName || fs[name].length !== length) throw new Error('fs stream export metadata failed: ' + name); } if (fs.ReadStream !== fs.FileReadStream || fs.WriteStream !== fs.FileWriteStream) throw new Error('fs stream alias metadata failed'); const originalReadStream = fs.ReadStream; let readReplacementCalled = false; let readReplacementArgs; function ReplacementReadStream() { readReplacementCalled = true; readReplacementArgs = [...arguments]; return { replacement: true }; } fs.ReadStream = ReplacementReadStream; const replacementRead = fs.createReadStream('ignored.txt'); if (fs.ReadStream !== ReplacementReadStream || fs.FileReadStream !== originalReadStream || !readReplacementCalled || replacementRead.replacement !== true || typeof readReplacementArgs[0] !== 'string' || typeof readReplacementArgs[1] !== 'undefined') throw new Error('fs ReadStream setter failed'); fs.ReadStream = originalReadStream; const originalWriteStream = fs.WriteStream; let writeReplacementCalled = false; let writeReplacementArgs; function ReplacementWriteStream() { writeReplacementCalled = true; writeReplacementArgs = [...arguments]; return { replacement: true }; } fs.WriteStream = ReplacementWriteStream; const replacementWrite = fs.createWriteStream('ignored.txt'); if (fs.WriteStream !== ReplacementWriteStream || fs.FileWriteStream !== originalWriteStream || !writeReplacementCalled || replacementWrite.replacement !== true || typeof writeReplacementArgs[0] !== 'string' || typeof writeReplacementArgs[1] !== 'undefined') throw new Error('fs WriteStream setter failed'); fs.WriteStream = originalWriteStream; const readStreamProtoNames = Object.getOwnPropertyNames(fs.ReadStream.prototype).join(','); const readStreamProtoKeys = Object.keys(fs.ReadStream.prototype).join(','); const writeStreamProtoNames = Object.getOwnPropertyNames(fs.WriteStream.prototype).join(','); const writeStreamProtoKeys = Object.keys(fs.WriteStream.prototype).join(','); const describeStreamProto = (prototype, names) => names.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(prototype, name); return [String(name), descriptor?.enumerable, descriptor?.configurable, 'value' in descriptor ? descriptor.writable : typeof descriptor?.set, 'value' in descriptor ? descriptor.value.name + '/' + descriptor.value.length : typeof descriptor?.get].join(':'); }).join('|'); const readStreamDescriptors = describeStreamProto(fs.ReadStream.prototype, ['autoClose', '_construct', '_read', '_destroy', 'close', 'pending']); const writeStreamDescriptors = describeStreamProto(fs.WriteStream.prototype, ['autoClose', '_construct', '_write', '_writev', '_destroy', 'close', 'destroySoon', 'pending']); if (readStreamProtoNames !== 'constructor,autoClose,_construct,_read,_destroy,close,pending' || readStreamProtoKeys !== '_construct,_read,_destroy,close' || readStreamDescriptors !== 'autoClose:false:false:function:function|_construct:true:true:true:_construct/1|_read:true:true:true:/1|_destroy:true:true:true:/2|close:true:true:true:/1|pending:false:true:undefined:function' || writeStreamProtoNames !== 'constructor,autoClose,_construct,_write,_writev,_destroy,close,destroySoon,pending' || writeStreamProtoKeys !== '_construct,_write,_writev,_destroy,close,destroySoon' || writeStreamDescriptors !== 'autoClose:false:false:function:function|_construct:true:true:true:_construct/1|_write:true:true:true:/3|_writev:true:true:true:/2|_destroy:true:true:true:/2|close:true:true:true:/1|destroySoon:true:true:true:/3|pending:false:true:undefined:function') throw new Error('fs stream prototype metadata failed'); const dirProtoNames = Object.getOwnPropertyNames(fs.Dir.prototype).join(','); const dirProtoSymbols = Object.getOwnPropertySymbols(fs.Dir.prototype).map(String).join(','); const dirProtoKeys = Object.keys(fs.Dir.prototype).join(','); const dirDescriptors = ['path', 'read', 'readSync', 'close', 'closeSync', 'entries', Symbol.asyncIterator].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(fs.Dir.prototype, name); return [String(name), descriptor?.enumerable, descriptor?.configurable, 'value' in descriptor ? descriptor.writable : typeof descriptor?.set, 'value' in descriptor ? descriptor.value.name + '/' + descriptor.value.length : typeof descriptor?.get].join(':'); }).join('|'); const direntProtoNames = Object.getOwnPropertyNames(fs.Dirent.prototype).join(','); const direntProtoKeys = Object.keys(fs.Dirent.prototype).join(','); if (dirProtoNames !== 'constructor,path,read,readSync,close,closeSync,entries' || dirProtoSymbols !== 'Symbol(Symbol.dispose),Symbol(Symbol.asyncDispose),Symbol(Symbol.asyncIterator)' || dirProtoKeys !== '' || dirDescriptors !== 'path:false:true:undefined:function|read:false:true:true:read/1|readSync:false:true:true:readSync/0|close:false:true:true:close/1|closeSync:false:true:true:closeSync/0|entries:false:true:true:entries/0|Symbol(Symbol.asyncIterator):false:true:true:entries/0' || direntProtoNames !== 'constructor,isDirectory,isFile,isBlockDevice,isCharacterDevice,isSymbolicLink,isFIFO,isSocket' || direntProtoKeys !== '') throw new Error('fs directory prototype metadata failed'); fs.mkdirSync('fs-dir-probe'); fs.writeFileSync('fs-dir-probe/az', 'x'); const dirBuffer = fs.readdirSync('fs-dir-probe', { encoding: 'buffer' })[0]; const direntBufferEntry = fs.readdirSync('fs-dir-probe', { withFileTypes: true, encoding: 'buffer' })[0]; const direntBuffer = direntBufferEntry.name; const manualDirent = new fs.Dirent('manual', fs.constants.UV_DIRENT_FILE, '/parent'); const stringTypeDirent = new fs.Dirent('manual', 'file', '/parent'); const direntShapeRows = [Object.keys(direntBufferEntry).join(','), Reflect.ownKeys(direntBufferEntry).map(String).join(','), typeof direntBufferEntry.parentPath, String(direntBufferEntry.path), Object.keys(manualDirent).join(','), Reflect.ownKeys(manualDirent).map(String).join(','), manualDirent.parentPath, String(manualDirent.path), manualDirent.isFile(), stringTypeDirent.isFile()].join('|'); if (!Buffer.isBuffer(dirBuffer) || dirBuffer.toString('hex') !== '617a' || !Buffer.isBuffer(direntBuffer) || direntBuffer.toString('hex') !== '617a' || direntShapeRows !== 'name,parentPath|name,parentPath,Symbol(type)|string|undefined|name,parentPath|name,parentPath,Symbol(type)|/parent|undefined|true|false' || fs.readdirSync('fs-dir-probe', { encoding: 'hex' })[0] !== '617a' || fs.readdirSync('fs-dir-probe', 'base64')[0] !== 'YXo=') throw new Error('fs readdir encoding failed'); const encodedDir = fs.opendirSync('fs-dir-probe', { encoding: 'buffer' }); const encodedDirent = encodedDir.readSync(); encodedDir.closeSync(); if (!Buffer.isBuffer(encodedDirent.name) || encodedDirent.name.toString('hex') !== '617a') throw new Error('fs opendir encoding failed'); fs.writeFileSync('fs-probe.txt', 'abcdef'); const chunks = []; const read = new fs.ReadStream('fs-probe.txt', { start: 1, end: 3, encoding: 'utf8' }); await new Promise((resolve, reject) => read.on('data', (chunk) => chunks.push(chunk)).on('error', reject).on('end', resolve)); if (chunks.join('') !== 'bcd' || read.path !== 'fs-probe.txt' || read.bytesRead !== 3) throw new Error('fs ReadStream constructor failed'); await new Promise((resolve, reject) => new fs.WriteStream('fs-out.txt').on('error', reject).on('finish', resolve).end('written')); if (fs.readFileSync('fs-out.txt', 'utf8') !== 'written') throw new Error('fs WriteStream constructor failed'); fs.writeFileSync('/workspace/fs-url-backslash\\\\name', 'url'); if (fs.readFileSync(new URL('file:///workspace/fs-url-backslash%5Cname'), 'utf8') !== 'url') throw new Error('fs file URL encoded backslash failed'); const fsUrlRows = []; for (const [label, action] of [['slash', () => fs.readFileSync(new URL('file:///workspace/a%2Fb'))], ['slash-promise', async () => fsp.stat(new URL('file:///workspace/a%2Fb'))], ['scheme', () => fs.statSync(new URL('https://example.com/a'))], ['host', () => fs.readFileSync(new URL('file://server/workspace/a'))], ['plain-object', () => fs.readFileSync({ protocol: 'file:', pathname: '/workspace/fs-stats-probe.txt' })]]) { try { await action(); fsUrlRows.push(label + ':ok') } catch (error) { fsUrlRows.push(label + ':' + error.name + ':' + error.code) } } if (fsUrlRows.join('|') !== 'slash:TypeError:ERR_INVALID_FILE_URL_PATH|slash-promise:TypeError:ERR_INVALID_FILE_URL_PATH|scheme:TypeError:ERR_INVALID_URL_SCHEME|host:TypeError:ERR_INVALID_FILE_URL_HOST|plain-object:TypeError:ERR_INVALID_ARG_TYPE') throw new Error('fs file URL validation failed');; const fsUrlLike = { href: 'file:///workspace/fs-stats-probe.txt', origin: 'null', protocol: 'file:', username: '', password: '', host: '', hostname: '', port: '', pathname: '/workspace/fs-stats-probe.txt', search: '', hash: '' }; if (fs.readFileSync(fsUrlLike, 'utf8') !== 'stats' || !fs.statSync(fsUrlLike).isFile() || fs.readFileSync(new URL('file://localhost/workspace/fs-stats-probe.txt'), 'utf8') !== 'stats') throw new Error('fs file URL-like object failed'); const fsUrlStatRows = []; for (const [label, action] of [['slash-stat', () => fs.statSync(new URL('file:///workspace/a%2Fb'))], ['scheme-stat', () => fs.statSync(new URL('https://example.com/a'))], ['host-stat', () => fs.statSync(new URL('file://server/workspace/a'))], ['plain-object-stat', () => fs.statSync({ protocol: 'file:', pathname: '/workspace/fs-stats-probe.txt' })], ['url-like-missing-host', () => fs.statSync({ href: 'file:///workspace/fs-stats-probe.txt', protocol: 'file:', pathname: '/workspace/fs-stats-probe.txt' })]]) { try { action(); fsUrlStatRows.push(label + ':ok') } catch (error) { fsUrlStatRows.push(label + ':' + error.name + ':' + error.code) } } if (fsUrlStatRows.join('|') !== 'slash-stat:TypeError:ERR_INVALID_FILE_URL_PATH|scheme-stat:TypeError:ERR_INVALID_URL_SCHEME|host-stat:TypeError:ERR_INVALID_FILE_URL_HOST|plain-object-stat:TypeError:ERR_INVALID_ARG_TYPE|url-like-missing-host:TypeError:ERR_INVALID_FILE_URL_HOST') throw new Error('fs file URL stat validation failed');; const utf8ProtoNames = Object.getOwnPropertyNames(fs.Utf8Stream.prototype).join(','); const utf8ProtoKeys = Object.keys(fs.Utf8Stream.prototype).join(','); const utf8ProtoSymbols = Object.getOwnPropertySymbols(fs.Utf8Stream.prototype).map(String).join(','); const utf8Rows = ['write','flush','flushSync','reopen','end','destroy','mode','file','fd','minLength','maxLength','writing','sync','fsync','append','periodicFlush','contentMode','mkdir',Symbol.dispose].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(fs.Utf8Stream.prototype, name); if (!descriptor) return String(name) + ':missing'; if ('value' in descriptor) return [String(name),'data',descriptor.enumerable,descriptor.configurable,descriptor.writable,descriptor.value.name,descriptor.value.length,Object.hasOwn(descriptor.value,'prototype')].join(':'); return [String(name),'accessor',descriptor.enumerable,descriptor.configurable,descriptor.get.name,descriptor.get.length,Object.hasOwn(descriptor.get,'prototype'),typeof descriptor.set].join(':'); }).join('|'); const expectedUtf8Rows = 'write:data:false:true:true:write:1:false|flush:data:false:true:true:flush:0:false|flushSync:data:false:true:true:flushSync:0:false|reopen:data:false:true:true:reopen:1:false|end:data:false:true:true:end:0:false|destroy:data:false:true:true:destroy:0:false|mode:accessor:false:true:get mode:0:false:undefined|file:accessor:false:true:get file:0:false:undefined|fd:accessor:false:true:get fd:0:false:undefined|minLength:accessor:false:true:get minLength:0:false:undefined|maxLength:accessor:false:true:get maxLength:0:false:undefined|writing:accessor:false:true:get writing:0:false:undefined|sync:accessor:false:true:get sync:0:false:undefined|fsync:accessor:false:true:get fsync:0:false:undefined|append:accessor:false:true:get append:0:false:undefined|periodicFlush:accessor:false:true:get periodicFlush:0:false:undefined|contentMode:accessor:false:true:get contentMode:0:false:undefined|mkdir:accessor:false:true:get mkdir:0:false:undefined|Symbol(Symbol.dispose):data:false:true:true:[Symbol.dispose]:0:false'; fs.writeFileSync('utf8-matrix.txt', ''); const utf8Fd = fs.openSync('utf8-matrix.txt', 'w'); const utf8Stream = new fs.Utf8Stream({ fd: utf8Fd }); const utf8Defaults = JSON.stringify([utf8Stream.file, utf8Stream.mode, utf8Stream.minLength, utf8Stream.maxLength, utf8Stream.writing, utf8Stream.sync, utf8Stream.fsync, utf8Stream.append, utf8Stream.periodicFlush, utf8Stream.contentMode, utf8Stream.mkdir]); let utf8ReopenCode; try { utf8Stream.reopen(); } catch (error) { utf8ReopenCode = error.name + ':' + error.code + ':' + error.message; } const utf8WriteReturn = utf8Stream.write('matrix'); const utf8EndReturn = utf8Stream.end('-ok'); fs.closeSync(utf8Fd); if (utf8ProtoNames !== 'constructor,write,flush,flushSync,reopen,end,destroy,mode,file,fd,minLength,maxLength,writing,sync,fsync,append,periodicFlush,contentMode,mkdir' || utf8ProtoKeys !== '' || utf8ProtoSymbols !== 'Symbol(Symbol.dispose)' || utf8Rows !== expectedUtf8Rows || utf8Defaults !== '[null,null,0,0,false,false,false,true,0,\"utf8\",false]' || utf8ReopenCode !== 'Error:ERR_OPERATION_FAILED:Operation failed: Unable to reopen a file descriptor, you must pass a file to SonicBoom' || utf8WriteReturn !== true || utf8EndReturn !== undefined || fs.readFileSync('utf8-matrix.txt', 'utf8') !== 'matrix-ok') throw new Error('fs Utf8Stream metadata failed'); const fsMetadataDescriptorRow = (target, name) => { const descriptor = Object.getOwnPropertyDescriptor(target, name); if (!descriptor) return String(name) + ':missing'; if (name === 'path') return [String(name),'data',descriptor.enumerable,descriptor.configurable,descriptor.writable,typeof descriptor.value].join(':'); if ('value' in descriptor) return [String(name),'data',descriptor.enumerable,descriptor.configurable,descriptor.writable,descriptor.value.name,descriptor.value.length,Object.hasOwn(descriptor.value,'prototype')].join(':'); return [String(name),'accessor',descriptor.enumerable,descriptor.configurable,descriptor.get.name,descriptor.get.length,typeof descriptor.set,Object.hasOwn(descriptor.get,'prototype')].join(':'); }; fs.writeFileSync('fs-filehandle-matrix.txt', 'abc'); const matrixHandle = await fsp.open('fs-filehandle-matrix.txt', 'r+'); const matrixHandleProto = Object.getPrototypeOf(matrixHandle); const matrixHandleAsyncId = matrixHandle.getAsyncId(); const matrixHandleRows = [Object.getOwnPropertyNames(matrixHandleProto).join(','), Object.keys(matrixHandleProto).join(','), ['getAsyncId','fd','appendFile','read','write','readableWebStream','createReadStream','createWriteStream'].map((name) => fsMetadataDescriptorRow(matrixHandleProto, name)).join('|'), fsMetadataDescriptorRow(matrixHandle, 'close'), fsMetadataDescriptorRow(matrixHandleProto, Symbol.asyncDispose), typeof matrixHandleAsyncId, matrixHandleAsyncId > 0, matrixHandle.getAsyncId() === matrixHandleAsyncId].join('::'); const matrixDetachedClose = matrixHandle.close; await matrixDetachedClose(); const matrixHandleClosedRows = [matrixHandle.fd, matrixHandle.getAsyncId() === matrixHandleAsyncId].join(':'); const matrixSyncTemp = fs.mkdtempDisposableSync('matrix-sync-'); const matrixSyncTempRows = [Object.getPrototypeOf(matrixSyncTemp) === null, Object.keys(matrixSyncTemp).join(','), Object.getOwnPropertySymbols(matrixSyncTemp).map(String).join(','), ['path','remove',Symbol.dispose].map((name) => fsMetadataDescriptorRow(matrixSyncTemp, name)).join('|'), typeof matrixSyncTemp[Symbol.asyncDispose], matrixSyncTemp.remove === matrixSyncTemp[Symbol.dispose]].join('::'); matrixSyncTemp[Symbol.dispose](); const matrixAsyncTemp = await fsp.mkdtempDisposable('matrix-async-'); const matrixAsyncTempRemove = matrixAsyncTemp.remove(); const matrixAsyncTempRows = [Object.getPrototypeOf(matrixAsyncTemp) === null, Object.keys(matrixAsyncTemp).join(','), Object.getOwnPropertySymbols(matrixAsyncTemp).map(String).join(','), ['path','remove',Symbol.asyncDispose].map((name) => fsMetadataDescriptorRow(matrixAsyncTemp, name)).join('|'), typeof matrixAsyncTemp[Symbol.dispose], matrixAsyncTemp.remove === matrixAsyncTemp[Symbol.asyncDispose], matrixAsyncTemp[Symbol.asyncDispose] === matrixAsyncTemp[Symbol.dispose], matrixAsyncTempRemove && typeof matrixAsyncTempRemove.then, matrixAsyncTempRemove.constructor.name].join('::'); await matrixAsyncTempRemove; if (matrixHandleRows !== 'constructor,getAsyncId,fd,appendFile,chmod,chown,datasync,sync,read,readv,readFile,readLines,stat,truncate,utimes,write,writev,writeFile,readableWebStream,createReadStream,createWriteStream::::getAsyncId:data:false:true:true:getAsyncId:0:false|fd:accessor:false:true:get fd:0:undefined:false|appendFile:data:false:true:true:appendFile:2:false|read:data:false:true:true:read:4:false|write:data:false:true:true:write:4:false|readableWebStream:data:false:true:true:readableWebStream:0:false|createReadStream:data:false:true:true:createReadStream:0:false|createWriteStream:data:false:true:true:createWriteStream:0:false::close:data:true:true:true:close:0:false::Symbol(Symbol.asyncDispose):data:false:true:true:[Symbol.asyncDispose]:0:false::number::true::true' || matrixHandleClosedRows !== '-1:true' || matrixSyncTempRows !== 'false::path,remove::Symbol(Symbol.dispose)::path:data:true:true:true:string|remove:data:true:true:true:remove:0:false|Symbol(Symbol.dispose):data:true:true:true:[Symbol.dispose]:0:false::undefined::false' || matrixAsyncTempRows !== 'true::path,remove::Symbol(Symbol.asyncDispose)::path:data:true:true:true:string|remove:data:true:true:true:remove:0:false|Symbol(Symbol.asyncDispose):data:true:true:true:[Symbol.asyncDispose]:0:false::undefined::false::false::function::Promise') throw new Error('fs FileHandle/disposable metadata failed');; const ocFsStreamMethodPrototypeRow = (prototype, names) => names.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(prototype, name); const prototypeDescriptor = Object.getOwnPropertyDescriptor(descriptor.value, 'prototype'); return [name, Object.hasOwn(descriptor.value, 'prototype'), prototypeDescriptor?.enumerable, prototypeDescriptor?.configurable, prototypeDescriptor?.writable, Object.getOwnPropertyNames(prototypeDescriptor?.value ?? {}).join(','), prototypeDescriptor?.value?.constructor === descriptor.value].join(':'); }).join('|'); const ocFsStreamMethodPrototypeRows = [ocFsStreamMethodPrototypeRow(fs.ReadStream.prototype, ['_construct','_read','_destroy','close']), ocFsStreamMethodPrototypeRow(fs.WriteStream.prototype, ['_construct','_write','_writev','_destroy','close','destroySoon'])].join(';'); if (ocFsStreamMethodPrototypeRows !== '_construct:true:false:false:true:constructor:true|_read:true:false:false:true:constructor:true|_destroy:true:false:false:true:constructor:true|close:true:false:false:true:constructor:true;_construct:true:false:false:true:constructor:true|_write:true:false:false:true:constructor:true|_writev:true:false:false:true:constructor:true|_destroy:true:false:false:true:constructor:true|close:true:false:false:true:constructor:true|destroySoon:true:false:false:true:constructor:true') throw new Error('fs stream helper prototype metadata failed'); const ocOpenAsBlobValidationRows = [['missing', () => fs.openAsBlob()], ['number-path', () => fs.openAsBlob(1)], ['bad-options', () => fs.openAsBlob('blob.txt', 1)], ['options-null', () => fs.openAsBlob('blob.txt', null)], ['options-array', () => fs.openAsBlob('blob.txt', [])], ['bad-type-symbol', () => fs.openAsBlob('blob.txt', { type: Symbol('x') })], ['bad-type-number', () => fs.openAsBlob('blob.txt', { type: 1 })]].map(([label, action]) => { try { action(); return label + ':ok'; } catch (error) { return [label, error.name, error.code, error.message].join(':'); } }).join('|'); if (ocOpenAsBlobValidationRows !== 'missing:TypeError:ERR_INVALID_ARG_TYPE:The \"path\" argument must be of type string or an instance of Buffer or URL. Received undefined|number-path:TypeError:ERR_INVALID_ARG_TYPE:The \"path\" argument must be of type string or an instance of Buffer or URL. Received type number (1)|bad-options:TypeError:ERR_INVALID_ARG_TYPE:The \"options\" argument must be of type object. Received type number (1)|options-null:TypeError:ERR_INVALID_ARG_TYPE:The \"options\" argument must be of type object. Received null|options-array:TypeError:ERR_INVALID_ARG_TYPE:The \"options\" argument must be of type object. Received an instance of Array|bad-type-symbol:TypeError:ERR_INVALID_ARG_TYPE:The \"options.type\" argument must be of type string. Received type symbol (Symbol(x))|bad-type-number:TypeError:ERR_INVALID_ARG_TYPE:The \"options.type\" argument must be of type string. Received type number (1)') throw new Error('fs openAsBlob validation failed');" }, { "specifier": "node:fs/promises", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/fs-compat.test.mjs, tests/fs-streams-watch.test.mjs", "limitation": "Promise APIs target the virtual filesystem, including native-shaped CommonJS export order, Node-shaped FileHandle descriptor/prototype metadata, helper arities and opendir own-prototype metadata, encoding-aware file content, Stats instant/nanosecond timestamp fields, recursive readdir traversal, recursive watch async iterator filenames, async cp filters and existing-destination options, mkdtemp prefix validation and encoded path results, native-shaped fs.promises accessor identity, stream, line, web stream, glob iteration, and common AbortSignal behavior, and do not expose host OS files.", "probe": "const fsp = require('node:fs/promises'); const keys = 'access,copyFile,cp,glob,open,opendir,rename,truncate,rm,rmdir,mkdir,readdir,readlink,symlink,lstat,stat,statfs,link,unlink,chmod,lchmod,lchown,chown,utimes,lutimes,realpath,mkdtemp,mkdtempDisposable,writeFile,appendFile,readFile,watch,constants'; const opendirPrototypeDescriptor = Object.getOwnPropertyDescriptor(fsp.opendir, 'prototype'); if (Object.keys(fsp).join(',') !== keys || Object.hasOwn(fsp, 'exists') || Object.hasOwn(fsp, 'fchmod') || Object.hasOwn(fsp, 'fchown') || Object.hasOwn(fsp, 'ftruncate') || fsp.opendir.name !== 'opendir' || fsp.opendir.length !== 3 || !Object.hasOwn(fsp.opendir, 'prototype') || opendirPrototypeDescriptor.enumerable || opendirPrototypeDescriptor.configurable || !opendirPrototypeDescriptor.writable || Object.getOwnPropertyNames(opendirPrototypeDescriptor.value).join(',') !== 'constructor') throw new Error('fs/promises export shape failed')" }, { "specifier": "node:constants", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Resolvable and exposes common filesystem constants, top-level errno/dlopen/priority/signal constants without non-native SIGPOLL/SIGPWR exports, common libuv filesystem aliases, Linux-style nonblocking/sync flags, selected host-compatible signal/file flag aliases, stable TLS protocol version constants, stable crypto engine/RSA/DH/point-conversion constants, native-shaped OpenSSL option/version/defaultCoreCipherList constants, crypto-first and TLS/HTTPS-first defaultCipherList load-order parity, and native-order filesystem and crypto-tail constant metadata and native read-only top-level descriptors used by fs/crypto/TLS package probes.", "probe": "const fs = require('node:fs'); const constants = require('node:constants'); const spawnSync = require('node:child_process').spawnSync; const cryptoFirstConstants = spawnSync('node', ['-e', \"const crypto = require('node:crypto'); const originalDescriptor = Object.getOwnPropertyDescriptor(crypto.constants, 'defaultCipherList'); crypto.constants.defaultCipherList = 'override'; const constants = require('node:constants'); const descriptor = Object.getOwnPropertyDescriptor(constants, 'defaultCipherList'); console.log([Object.hasOwn(constants, 'defaultCipherList'), constants.defaultCipherList, descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value, Object.keys(constants).slice(-1)[0]].join(':')); Object.defineProperty(crypto.constants, 'defaultCipherList', originalDescriptor)\"], { encoding: 'utf8' }); const tlsFirstConstants = spawnSync('node', ['-e', \"require('node:tls'); const constants = require('node:constants'); const descriptor = Object.getOwnPropertyDescriptor(constants, 'defaultCipherList'); console.log([Object.hasOwn(constants, 'defaultCipherList'), constants.defaultCipherList === constants.defaultCoreCipherList, descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value, Object.keys(constants).slice(-1)[0]].join(':'))\"], { encoding: 'utf8' }); const httpsFirstConstants = spawnSync('node', ['-e', \"require('node:https'); const constants = require('node:constants'); const descriptor = Object.getOwnPropertyDescriptor(constants, 'defaultCipherList'); console.log([Object.hasOwn(constants, 'defaultCipherList'), constants.defaultCipherList === constants.defaultCoreCipherList, descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value, Object.keys(constants).slice(-1)[0]].join(':'))\"], { encoding: 'utf8' }); const cryptoFirstOutput = cryptoFirstConstants.stdout.trim(); const tlsFirstOutput = tlsFirstConstants.stdout.trim(); const httpsFirstOutput = httpsFirstConstants.stdout.trim(); const required = ['SIGINT','SIGCHLD','SIGWINCH','SIGINFO','F_OK','R_OK','W_OK','X_OK','COPYFILE_EXCL','COPYFILE_FICLONE','COPYFILE_FICLONE_FORCE','UV_FS_COPYFILE_EXCL','UV_FS_COPYFILE_FICLONE','UV_FS_COPYFILE_FICLONE_FORCE','UV_FS_SYMLINK_DIR','UV_FS_SYMLINK_JUNCTION','UV_FS_O_FILEMAP','UV_DIRENT_UNKNOWN','UV_DIRENT_FILE','UV_DIRENT_DIR','UV_DIRENT_LINK','UV_DIRENT_SOCKET','O_RDONLY','O_WRONLY','O_RDWR','O_CREAT','O_DSYNC','O_NONBLOCK','O_SYNC','O_SYMLINK','TLS1_VERSION','TLS1_1_VERSION','TLS1_2_VERSION','TLS1_3_VERSION','RSA_PKCS1_PADDING','RSA_X931_PADDING','RSA_PSS_SALTLEN_AUTO','DH_CHECK_P_NOT_PRIME','DH_NOT_SUITABLE_GENERATOR','ENGINE_METHOD_RSA','ENGINE_METHOD_EC','ENGINE_METHOD_ALL','POINT_CONVERSION_HYBRID','S_IFREG','S_IRUSR','ENOENT','EACCES','EADDRINUSE','RTLD_NOW','RTLD_GLOBAL','PRIORITY_HIGH','OPENSSL_VERSION_NUMBER','SSL_OP_ALL','SSL_OP_NO_TLSv1','SSL_OP_NO_TLSv1_3','SSL_OP_NO_SSLv3','SSL_OP_NO_COMPRESSION','SSL_OP_PRIORITIZE_CHACHA']; const descriptorRows = ['F_OK','ENOENT','RTLD_NOW','SIGWINCH','SIGINFO','UV_DIRENT_DIR','O_SYNC','O_SYMLINK','TLS1_3_VERSION','RSA_X931_PADDING','DH_CHECK_P_NOT_PRIME','OPENSSL_VERSION_NUMBER','SSL_OP_ALL','SSL_OP_NO_TLSv1_3','defaultCoreCipherList'].map((key) => { const descriptor = Object.getOwnPropertyDescriptor(constants, key); return [key, descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value].join(':') }).join('|'); const constantKeys = Object.keys(constants); const expectedErrnoKeys = 'E2BIG,EACCES,EADDRINUSE,EADDRNOTAVAIL,EAFNOSUPPORT,EAGAIN,EALREADY,EBADF,EBADMSG,EBUSY,ECANCELED,ECHILD,ECONNABORTED,ECONNREFUSED,ECONNRESET,EDEADLK,EDESTADDRREQ,EDOM,EDQUOT,EEXIST,EFAULT,EFBIG,EHOSTUNREACH,EIDRM,EILSEQ,EINPROGRESS,EINTR,EINVAL,EIO,EISCONN,EISDIR,ELOOP,EMFILE,EMLINK,EMSGSIZE,EMULTIHOP,ENAMETOOLONG,ENETDOWN,ENETRESET,ENETUNREACH,ENFILE,ENOBUFS,ENODATA,ENODEV,ENOENT,ENOEXEC,ENOLCK,ENOLINK,ENOMEM,ENOMSG,ENOPROTOOPT,ENOSPC,ENOSR,ENOSTR,ENOSYS,ENOTCONN,ENOTDIR,ENOTEMPTY,ENOTSOCK,ENOTSUP,ENOTTY,ENXIO,EOPNOTSUPP,EOVERFLOW,EPERM,EPIPE,EPROTO,EPROTONOSUPPORT,EPROTOTYPE,ERANGE,EROFS,ESPIPE,ESRCH,ESTALE,ETIME,ETIMEDOUT,ETXTBSY,EWOULDBLOCK,EXDEV'; const errnoWindow = constantKeys.slice(constantKeys.indexOf('E2BIG'), constantKeys.indexOf('PRIORITY_LOW')).join(','); const fsConstantWindow = constantKeys.slice(constantKeys.indexOf('UV_FS_SYMLINK_DIR'), constantKeys.indexOf('COPYFILE_FICLONE_FORCE') + 1).join(','); const cryptoTailWindow = constantKeys.slice(constantKeys.indexOf('UV_FS_COPYFILE_FICLONE_FORCE'), constantKeys.indexOf('POINT_CONVERSION_HYBRID') + 1).join(','); const mainCrypto = require('node:crypto'); const constantsAfterCryptoRows = [Object.hasOwn(constants, 'defaultCipherList'), typeof constants.defaultCipherList, constants === require('node:constants'), Object.hasOwn(mainCrypto.constants, 'defaultCipherList')].join(':'); if (Object.hasOwn(constants, 'default') || Object.hasOwn(constants, 'SIGPOLL') || Object.hasOwn(constants, 'SIGPWR') || required.some((key) => typeof constants[key] !== 'number') || cryptoFirstConstants.status !== 0 || cryptoFirstOutput !== 'true:override:true:false:false:string:defaultCipherList' || tlsFirstConstants.status !== 0 || tlsFirstOutput !== 'true:true:true:false:false:string:defaultCipherList' || httpsFirstConstants.status !== 0 || httpsFirstOutput !== 'true:true:true:false:false:string:defaultCipherList' || errnoWindow !== expectedErrnoKeys || constants.F_OK !== 0 || constants.COPYFILE_EXCL !== 1 || constants.UV_FS_COPYFILE_EXCL !== 1 || constants.UV_FS_COPYFILE_FICLONE !== 2 || constants.UV_FS_COPYFILE_FICLONE_FORCE !== 4 || constants.UV_FS_SYMLINK_DIR !== 1 || constants.UV_FS_SYMLINK_JUNCTION !== 2 || constants.UV_FS_O_FILEMAP !== 0 || constants.UV_DIRENT_UNKNOWN !== 0 || constants.UV_DIRENT_DIR !== 2 || constants.UV_DIRENT_SOCKET !== 5 || constants.O_DSYNC !== 4096 || constants.O_NONBLOCK !== 2048 || constants.O_SYNC !== 1052672 || fs.constants.O_SYNC !== constants.O_SYNC || constants.TLS1_VERSION !== 769 || constants.TLS1_1_VERSION !== 770 || constants.TLS1_2_VERSION !== 771 || constants.TLS1_3_VERSION !== 772 || constants.RSA_PKCS1_PADDING !== 1 || constants.RSA_X931_PADDING !== 5 || constants.RSA_PSS_SALTLEN_AUTO !== -2 || constants.DH_CHECK_P_NOT_PRIME !== 1 || constants.DH_CHECK_P_NOT_SAFE_PRIME !== 2 || constants.DH_UNABLE_TO_CHECK_GENERATOR !== 4 || constants.DH_NOT_SUITABLE_GENERATOR !== 8 || constants.ENGINE_METHOD_RSA !== 1 || constants.ENGINE_METHOD_EC !== 2048 || constants.ENGINE_METHOD_ALL !== 65535 || constants.POINT_CONVERSION_HYBRID !== 6 || constants.SIGINT !== 2 || constants.SIGCHLD !== 17 || constants.SIGWINCH !== 28 || constants.SIGINFO !== 29 || constants.ENOENT !== 2 || constants.EACCES !== 13 || constants.EADDRINUSE !== 98 || constants.RTLD_NOW !== 2 || constants.RTLD_GLOBAL !== 8 || constants.PRIORITY_HIGH !== -14 || constants.OPENSSL_VERSION_NUMBER !== 810549344 || constants.SSL_OP_ALL !== 2147485776 || constants.SSL_OP_NO_TLSv1 !== 67108864 || constants.SSL_OP_NO_TLSv1_3 !== 536870912 || constants.SSL_OP_NO_SSLv3 !== 33554432 || constants.SSL_OP_NO_COMPRESSION !== 131072 || constants.SSL_OP_PRIORITIZE_CHACHA !== 2097152 || constants.O_SYMLINK !== 2097152 || fs.constants.O_SYMLINK !== constants.O_SYMLINK || typeof constants.defaultCoreCipherList !== 'string' || !constants.defaultCoreCipherList.includes('TLS_AES_256_GCM_SHA384') || Object.hasOwn(constants, 'defaultCipherList') || constants.defaultCipherList !== undefined || constantsAfterCryptoRows !== 'false:undefined:true:true' || constants.O_CREAT <= 0 || constants.S_IFREG <= 0 || constants.S_IRUSR <= 0 || !Object.isFrozen(constants) || Object.getPrototypeOf(constants) !== Object.prototype || fsConstantWindow !== 'UV_FS_SYMLINK_DIR,UV_FS_SYMLINK_JUNCTION,O_RDONLY,O_WRONLY,O_RDWR,UV_DIRENT_UNKNOWN,UV_DIRENT_FILE,UV_DIRENT_DIR,UV_DIRENT_LINK,UV_DIRENT_FIFO,UV_DIRENT_SOCKET,UV_DIRENT_CHAR,UV_DIRENT_BLOCK,S_IFMT,S_IFREG,S_IFDIR,S_IFCHR,S_IFBLK,S_IFIFO,S_IFLNK,S_IFSOCK,O_CREAT,O_EXCL,UV_FS_O_FILEMAP,O_NOCTTY,O_TRUNC,O_APPEND,O_DIRECTORY,O_NOFOLLOW,O_SYNC,O_DSYNC,O_SYMLINK,O_NONBLOCK,S_IRWXU,S_IRUSR,S_IWUSR,S_IXUSR,S_IRWXG,S_IRGRP,S_IWGRP,S_IXGRP,S_IRWXO,S_IROTH,S_IWOTH,S_IXOTH,F_OK,R_OK,W_OK,X_OK,UV_FS_COPYFILE_EXCL,COPYFILE_EXCL,UV_FS_COPYFILE_FICLONE,COPYFILE_FICLONE,UV_FS_COPYFILE_FICLONE_FORCE,COPYFILE_FICLONE_FORCE' || cryptoTailWindow !== 'UV_FS_COPYFILE_FICLONE_FORCE,COPYFILE_FICLONE_FORCE,OPENSSL_VERSION_NUMBER,SSL_OP_ALL,SSL_OP_ALLOW_NO_DHE_KEX,SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION,SSL_OP_CIPHER_SERVER_PREFERENCE,SSL_OP_CISCO_ANYCONNECT,SSL_OP_COOKIE_EXCHANGE,SSL_OP_CRYPTOPRO_TLSEXT_BUG,SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS,SSL_OP_LEGACY_SERVER_CONNECT,SSL_OP_NO_COMPRESSION,SSL_OP_NO_ENCRYPT_THEN_MAC,SSL_OP_NO_QUERY_MTU,SSL_OP_NO_RENEGOTIATION,SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION,SSL_OP_NO_SSLv2,SSL_OP_NO_SSLv3,SSL_OP_NO_TICKET,SSL_OP_NO_TLSv1,SSL_OP_NO_TLSv1_1,SSL_OP_NO_TLSv1_2,SSL_OP_NO_TLSv1_3,SSL_OP_PRIORITIZE_CHACHA,SSL_OP_TLS_ROLLBACK_BUG,ENGINE_METHOD_RSA,ENGINE_METHOD_DSA,ENGINE_METHOD_DH,ENGINE_METHOD_RAND,ENGINE_METHOD_EC,ENGINE_METHOD_CIPHERS,ENGINE_METHOD_DIGESTS,ENGINE_METHOD_PKEY_METHS,ENGINE_METHOD_PKEY_ASN1_METHS,ENGINE_METHOD_ALL,ENGINE_METHOD_NONE,DH_CHECK_P_NOT_SAFE_PRIME,DH_CHECK_P_NOT_PRIME,DH_UNABLE_TO_CHECK_GENERATOR,DH_NOT_SUITABLE_GENERATOR,RSA_PKCS1_PADDING,RSA_NO_PADDING,RSA_PKCS1_OAEP_PADDING,RSA_X931_PADDING,RSA_PKCS1_PSS_PADDING,RSA_PSS_SALTLEN_DIGEST,RSA_PSS_SALTLEN_MAX_SIGN,RSA_PSS_SALTLEN_AUTO,defaultCoreCipherList,TLS1_VERSION,TLS1_1_VERSION,TLS1_2_VERSION,TLS1_3_VERSION,POINT_CONVERSION_COMPRESSED,POINT_CONVERSION_UNCOMPRESSED,POINT_CONVERSION_HYBRID' || descriptorRows !== 'F_OK:true:false:false:number|ENOENT:true:false:false:number|RTLD_NOW:true:false:false:number|SIGWINCH:true:false:false:number|SIGINFO:true:false:false:number|UV_DIRENT_DIR:true:false:false:number|O_SYNC:true:false:false:number|O_SYMLINK:true:false:false:number|TLS1_3_VERSION:true:false:false:number|RSA_X931_PADDING:true:false:false:number|DH_CHECK_P_NOT_PRIME:true:false:false:number|OPENSSL_VERSION_NUMBER:true:false:false:number|SSL_OP_ALL:true:false:false:number|SSL_OP_NO_TLSv1_3:true:false:false:number|defaultCoreCipherList:true:false:false:string') throw new Error('constants failed')" }, { "specifier": "node:_http_agent", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Deprecated private Node HTTP agent module is exposed for package probes and aliases the canonical node:http Agent/globalAgent objects, including native-shaped globalAgent and custom Agent instance option metadata.", "probe": "const http = require('node:http'); const agent = require('node:_http_agent'); const agentShape = (agent) => [Object.keys(agent).join(','), Object.keys(agent.options).join(','), agent.keepAliveMsecs, agent.keepAlive, String(agent.maxSockets), agent.maxFreeSockets, agent.scheduling, String(agent.maxTotalSockets), agent.totalSocketCount, agent.agentKeepAliveTimeoutBuffer].join(':'); const customAgent = new agent.Agent({ keepAliveMsecs: 12, maxSockets: 3, maxFreeSockets: 4, scheduling: 'fifo', maxTotalSockets: 5, agentKeepAliveTimeoutBuffer: 7 }); if (agent.Agent !== http.Agent || agent.globalAgent !== http.globalAgent || agentShape(agent.globalAgent) !== '_events,_eventsCount,_maxListeners,options,defaultPort,protocol,requests,sockets,freeSockets,keepAliveMsecs,keepAlive,maxSockets,maxFreeSockets,scheduling,maxTotalSockets,totalSocketCount,agentKeepAliveTimeoutBuffer:keepAlive,scheduling,timeout,proxyEnv,noDelay,path:1000:true:Infinity:256:lifo:Infinity:0:1000' || agentShape(customAgent) !== '_events,_eventsCount,_maxListeners,options,defaultPort,protocol,requests,sockets,freeSockets,keepAliveMsecs,keepAlive,maxSockets,maxFreeSockets,scheduling,maxTotalSockets,totalSocketCount,agentKeepAliveTimeoutBuffer:keepAliveMsecs,maxSockets,maxFreeSockets,scheduling,maxTotalSockets,agentKeepAliveTimeoutBuffer,noDelay,path:12:false:3:4:fifo:5:0:7') throw new Error('_http_agent alias failed')" }, { "specifier": "node:_http_client", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Deprecated private Node HTTP client module is exposed for package probes and aliases node:http ClientRequest.", "probe": "const http = require('node:http'); if (require('node:_http_client').ClientRequest !== http.ClientRequest) throw new Error('_http_client alias failed')" }, { "specifier": "node:_http_common", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Deprecated private HTTP parser/common module exposes native-shaped CommonJS export order, token/header checks, parser constants, parser placeholders including native-shaped parser pool name metadata, HTTPParser prototype own-property order/method arities, helper own-prototype metadata, and method metadata for package probes; it is not a native llhttp binding.", "probe": "const common = require('node:_http_common'); const row = (namespace, names) => names.map((name) => { const fn = namespace[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, fn.name, fn.length, Object.hasOwn(fn, 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(','), descriptor?.value?.constructor === fn].join(':'); }).join('|'); const keys = '_checkInvalidHeaderChar,_checkIsHttpToken,chunkExpression,continueExpression,CRLF,freeParser,methods,parsers,kIncomingMessage,HTTPParser,isLenient,calculateLenientFlags,prepareError,kSkipPendingData'; const proto = 'close,free,remove,execute,finish,initialize,pause,resume,consume,unconsume,getCurrentBuffer'; const protoNames = proto + ',constructor'; const parserPrototypeDescriptors = ['constructor','execute','initialize','close','free','getCurrentBuffer'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(common.HTTPParser.prototype, name); return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype')].join(':'); }).join('|'); const helpers = 'freeParser:freeParser:3:true:false:false:true:constructor:true|isLenient:isLenient:0:true:false:false:true:constructor:true|calculateLenientFlags:calculateLenientFlags:2:true:false:false:true:constructor:true|prepareError:prepareError:3:true:false:false:true:constructor:true'; const parsersDescriptor = Object.getOwnPropertyDescriptor(common, 'parsers'); const parserPoolMeta = ['parsers', parsersDescriptor.enumerable, parsersDescriptor.configurable, parsersDescriptor.writable, typeof parsersDescriptor.value, parsersDescriptor.value.name, parsersDescriptor.value.length ?? '', Object.hasOwn(parsersDescriptor.value, 'prototype')].join(':'); if (Object.keys(common).join(',') !== keys || common.HTTPParser.name !== 'HTTPParser' || common.HTTPParser.length !== 0 || Object.keys(common.HTTPParser.prototype).join(',') !== proto || Object.getOwnPropertyNames(common.HTTPParser.prototype).join(',') !== protoNames || parserPrototypeDescriptors !== 'constructor:false:true:true:HTTPParser:0:true|execute:true:true:true:execute:0:false|initialize:true:true:true:initialize:0:false|close:true:true:true:close:0:false|free:true:true:true:free:0:false|getCurrentBuffer:true:true:true:getCurrentBuffer:0:false' || row(common, ['freeParser', 'isLenient', 'calculateLenientFlags', 'prepareError']) !== helpers || parserPoolMeta !== 'parsers:true:true:true:object:parsers::false' || common.freeParser.length !== 3 || common.calculateLenientFlags.length !== 2 || common.prepareError.length !== 3 || String(common.kIncomingMessage) !== 'Symbol(IncomingMessage)' || String(common.kSkipPendingData) !== 'Symbol(SkipPendingData)' || !common._checkIsHttpToken('content-type') || common._checkIsHttpToken('bad header') || !common._checkInvalidHeaderChar('bad\\nheader') || common.HTTPParser.REQUEST !== 1) throw new Error('_http_common failed')" }, { "specifier": "node:_http_incoming", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Deprecated private incoming-message module is exposed for package probes and aliases node:http IncomingMessage with pause/resume read helpers, native-shaped IncomingMessage accessor/method descriptors, parser header helpers, helper own-prototype metadata, and setTimeout metadata.", "probe": "const http = require('node:http'); const incoming = require('node:_http_incoming'); const row = (namespace, names) => names.map((name) => { const fn = namespace[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, fn.name, fn.length, Object.hasOwn(fn, 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(','), descriptor?.value?.constructor === fn].join(':'); }).join('|'); const proto = incoming.IncomingMessage.prototype; const protoNames = 'constructor,connection,headers,headersDistinct,trailers,trailersDistinct,signal,setTimeout,_read,_destroy,_addHeaderLines,_addHeaderLine,_addHeaderLineDistinct,_dumpAndCloseReadable,_dump'; const protoKeys = 'setTimeout,_read,_destroy,_addHeaderLines,_addHeaderLine,_addHeaderLineDistinct,_dumpAndCloseReadable,_dump'; const descriptorRows = ['connection','headers','headersDistinct','trailers','trailersDistinct','signal','setTimeout','_read','_destroy','_addHeaderLines','_addHeaderLine','_addHeaderLineDistinct','_dumpAndCloseReadable','_dump'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(proto, name); if ('value' in descriptor) return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype')].join(':'); return [name, descriptor.enumerable, descriptor.configurable, typeof descriptor.get, descriptor.get.name, descriptor.get.length, typeof descriptor.set, descriptor.set?.name ?? '', descriptor.set?.length ?? '', Object.hasOwn(descriptor.get, 'prototype'), descriptor.set ? Object.hasOwn(descriptor.set, 'prototype') : ''].join(':'); }).join('|'); const expectedDescriptorRows = 'connection:false:false:function:get:0:function:set:1:true:true|headers:false:false:function:get:0:function:set:1:true:true|headersDistinct:false:false:function:get:0:function:set:1:true:true|trailers:false:false:function:get:0:function:set:1:true:true|trailersDistinct:false:false:function:get:0:function:set:1:true:true|signal:false:true:function:get:0:undefined:::true:|setTimeout:true:true:true:setTimeout:2:true|_read:true:true:true:_read:1:true|_destroy:true:true:true:_destroy:2:true|_addHeaderLines:true:true:true:_addHeaderLines:2:true|_addHeaderLine:true:true:true:_addHeaderLine:3:true|_addHeaderLineDistinct:true:true:true:_addHeaderLineDistinct:3:true|_dumpAndCloseReadable:true:true:true:_dumpAndCloseReadable:0:true|_dump:true:true:true:_dump:0:true'; const helpers = 'readStart:readStart:1:true:false:false:true:constructor:true|readStop:readStop:1:true:false:false:true:constructor:true'; const message = new incoming.IncomingMessage({ headers: [['A', '1'], ['A', '2'], ['Cookie', 'a'], ['Cookie', 'b'], ['Set-Cookie', 'x'], ['Set-Cookie', 'y']], trailers: [['T', '1'], ['T', '2']], port: 8080 }); const parsed = new incoming.IncomingMessage({ headers: [], port: 8080 }); parsed._addHeaderLines(['A', '1', 'A', '2', 'C', '3'], 4); const headerState = JSON.stringify([message.headers, message.headersDistinct, message.trailers, message.trailersDistinct, parsed.rawHeaders, parsed.headers, parsed.headersDistinct]); const expectedHeaderState = '[{\"a\":\"1, 2\",\"cookie\":\"a; b\",\"set-cookie\":[\"x\",\"y\"]},{\"a\":[\"1\",\"2\"],\"cookie\":[\"a\",\"b\"],\"set-cookie\":[\"x\",\"y\"]},{\"t\":\"2\"},{\"t\":[\"1\",\"2\"]},[\"A\",\"1\",\"A\",\"2\",\"C\",\"3\"],{\"a\":\"1, 2\"},{\"a\":[\"1\",\"2\"]}]'; if (incoming.IncomingMessage !== http.IncomingMessage || row(incoming, ['readStart', 'readStop']) !== helpers || Object.getOwnPropertyNames(proto).join(',') !== protoNames || Object.keys(proto).join(',') !== protoKeys || descriptorRows !== expectedDescriptorRows || headerState !== expectedHeaderState) throw new Error('_http_incoming failed')" }, { "specifier": "node:_http_outgoing", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Deprecated private outgoing-message module is exposed with native-shaped CommonJS export order for package probes and aliases node:http OutgoingMessage plus header validators, unique-header parsing, and helper own-prototype metadata.", "probe": "const http = require('node:http'); const outgoing = require('node:_http_outgoing'); const row = (namespace, names) => names.map((name) => { const fn = namespace[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, fn.name, fn.length, Object.hasOwn(fn, 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(','), descriptor?.value?.constructor === fn].join(':'); }).join('|'); const keys = 'kHighWaterMark,kUniqueHeaders,parseUniqueHeadersOption,validateHeaderName,validateHeaderValue,OutgoingMessage'; const unique = outgoing.parseUniqueHeadersOption(['Host', 'HOST']); const helpers = 'parseUniqueHeadersOption:parseUniqueHeadersOption:1:true:false:false:true:constructor:true'; if (Object.keys(outgoing).join(',') !== keys || outgoing.OutgoingMessage !== http.OutgoingMessage || row(outgoing, ['parseUniqueHeadersOption']) !== helpers || !(unique instanceof Set) || unique.size !== 1) throw new Error('_http_outgoing failed')" }, { "specifier": "node:_http_server", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Deprecated private HTTP server module is exposed with native-shaped CommonJS export order for package probes and aliases node:http Server, ServerResponse, STATUS_CODES, lightweight connection tracking hooks, and helper own-prototype metadata.", "probe": "const http = require('node:http'); const server = require('node:_http_server'); const row = (namespace, names) => names.map((name) => { const fn = namespace[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, fn.name, fn.length, Object.hasOwn(fn, 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(','), descriptor?.value?.constructor === fn].join(':'); }).join('|'); const keys = 'STATUS_CODES,Server,ServerResponse,setupConnectionsTracking,storeHTTPOptions,_connectionListener,kServerResponse,httpServerPreClose,kConnectionsCheckingInterval'; const helpers = 'setupConnectionsTracking:setupConnectionsTracking:0:true:false:false:true:constructor:true|storeHTTPOptions:storeHTTPOptions:1:true:false:false:true:constructor:true|httpServerPreClose:httpServerPreClose:1:true:false:false:true:constructor:true'; if (Object.keys(server).join(',') !== keys || row(server, ['setupConnectionsTracking', 'storeHTTPOptions', 'httpServerPreClose']) !== helpers || server.storeHTTPOptions.length !== 1 || String(server.kServerResponse) !== 'Symbol(ServerResponse)' || String(server.kConnectionsCheckingInterval) !== 'Symbol(http.server.connectionsCheckingInterval)' || server.Server !== http.Server || server.ServerResponse !== http.ServerResponse || server.STATUS_CODES !== http.STATUS_CODES || typeof server.setupConnectionsTracking !== 'function') throw new Error('_http_server failed')" }, { "specifier": "node:http", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/http-client.test.mjs", "limitation": "Virtual loopback and preview HTTP are supported, including common IncomingMessage, ClientRequest, ServerResponse, Server, OutgoingMessage, native-shaped CommonJS export order and accessor descriptors without getter/setter own prototypes, Agent/globalAgent protocol and native-shaped instance option metadata, Agent destroy socket-pool lifecycle, native-shaped Agent and Server prototype probes including Server Symbol.asyncDispose descriptor/not-running/close behavior and helper own-prototype metadata, upgrade, validation, header, non-string header-name validation, Symbol header-value rejection, Basic auth, method/protocol/unescaped-path validation, URL-object enumerable request option parity, URL-plus-options path override/default-port normalization, IncomingMessage/ClientRequest/Server timeout helpers with helper own-prototype metadata, request-side ClientRequest/IncomingMessage prototype parity, ClientRequest socket event/createConnection probes, virtual localhost request-body chunk streaming before client end, trailer helpers including client-visible response trailers/rawTrailers, empty request/response stream end and 204 no-body semantics, full STATUS_CODES, selected HTTP message helper own-prototype metadata, and Node-shaped public helper names/arities including non-constructable setMaxIdleHTTPParsers metadata; external networking follows browser policy.", "probe": "const http = require('node:http'); const { EventEmitter } = require('node:events'); const keys = '_connectionListener,METHODS,STATUS_CODES,Agent,ClientRequest,IncomingMessage,OutgoingMessage,Server,ServerResponse,createServer,validateHeaderName,validateHeaderValue,get,request,setMaxIdleHTTPParsers,setGlobalProxyFromEnv,maxHeaderSize,globalAgent,WebSocket,CloseEvent,MessageEvent'; const server = http.createServer(); const helpers = ['close', 'closeAllConnections', 'closeIdleConnections', 'setTimeout']; const incomingTimeoutDescriptor = Object.getOwnPropertyDescriptor(http.IncomingMessage.prototype, 'setTimeout'); const incoming = new http.IncomingMessage({ method: 'GET', url: '/', headers: [], port: 8080 }); const incomingSocketTimeouts = []; incoming.socket.setTimeout = (...args) => { incomingSocketTimeouts.push(args.join(':')); return incoming.socket; }; let incomingTimeouts = 0; const incomingTimeoutOk = incoming.setTimeout(25, () => incomingTimeouts++) === incoming && incomingSocketTimeouts.join('|') === '25' && incoming.emit('timeout') === true && incomingTimeouts === 1; const accessorMeta = ['maxHeaderSize','globalAgent','WebSocket','CloseEvent','MessageEvent'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(http, name); return [name, descriptor.get?.name, descriptor.get?.length, typeof descriptor.set, descriptor.set?.name ?? '', descriptor.set?.length ?? '', descriptor.enumerable, descriptor.configurable, Object.hasOwn(descriptor.get ?? {}, 'prototype'), Object.hasOwn(descriptor.set ?? {}, 'prototype')].join(':'); }).join('|'); const maxParserPrototypeOk = !Object.hasOwn(http.setMaxIdleHTTPParsers, 'prototype') && Object.getOwnPropertyDescriptor(http.setMaxIdleHTTPParsers, 'prototype') === undefined; const req = http.request('http://localhost:3000/'); req.on('error', () => {}); const requestAgentOk = req.agent === http.globalAgent && req.agent.defaultPort === 80 && req.agent.protocol === 'http:'; req.destroy(); const requestSocketRows = []; const socketServer = http.createServer((request, response) => response.end('ok')); await new Promise((resolve) => socketServer.listen(0, '127.0.0.1', resolve)); const socketReq = http.request({ host: '127.0.0.1', port: socketServer.address().port, path: '/probe' }); requestSocketRows.push('initial:' + [socketReq.socket === null, socketReq.connection === null].join(':')); const socketSeen = new Promise((resolve) => socketReq.on('socket', (socket) => { requestSocketRows.push('socket:' + [socketReq.socket === socket, socketReq.connection === socket, socket._httpMessage === socketReq, typeof socket.setTimeout, typeof socket.destroy, socket.writable, socket.destroyed, socket.connecting, socket.localAddress].join(':')); resolve(); })); const responseSeen = new Promise((resolve) => socketReq.on('response', (response) => { requestSocketRows.push('response:' + [socketReq.socket !== null, socketReq.connection === socketReq.socket, response.statusCode].join(':')); response.resume(); response.on('end', resolve); })); socketReq.end(); await socketSeen; await responseSeen; socketServer.close(); const customSocket = new EventEmitter(); customSocket.writable = true; customSocket.destroyed = false; customSocket.connecting = false; customSocket.setTimeout = () => customSocket; customSocket.destroy = function destroy() { this.destroyed = true; this.emit('close'); return this; }; const customSocketRows = []; const customSocketReq = http.request({ host: 'example.com', port: 80, path: '/probe', createConnection(options, callback) { customSocketRows.push('createConnection:' + [options.host, options.port, options.path, typeof callback].join(':')); return customSocket; } }); customSocketRows.push('initial:' + [customSocketReq.socket === null, customSocketReq.connection === null].join(':')); await new Promise((resolve) => customSocketReq.on('socket', (socket) => { customSocketRows.push('socket:' + [socket === customSocket, customSocketReq.socket === socket, customSocketReq.connection === socket, socket._httpMessage === customSocketReq, typeof socket.setTimeout, typeof socket.destroy, socket.writable, socket.destroyed].join(':')); resolve(); })); customSocketReq.destroy(); const requestSocketOk = requestSocketRows.join('|') === 'initial:true:true|socket:true:true:true:function:function:true:false:false:127.0.0.1|response:true:true:200' && customSocketRows.join('|') === 'initial:true:true|createConnection:example.com:80:/probe:function|socket:true:true:true:true:function:function:true:false'; const urlOwnedOptions = new URL('http://user:pass@localhost/original?x=1'); urlOwnedOptions.method = 'post'; urlOwnedOptions.headers = { 'X-Url': 'yes' }; urlOwnedOptions.path = '/url-owned?z=1'; urlOwnedOptions.auth = 'override:secret'; const urlOwnedReq = http.request(urlOwnedOptions); urlOwnedReq.on('error', () => {}); const urlOwnedOptionsOk = urlOwnedReq.method === 'POST' && urlOwnedReq.path === '/url-owned?z=1' && urlOwnedReq.getHeader('x-url') === 'yes' && urlOwnedReq.getHeader('authorization') === 'Basic b3ZlcnJpZGU6c2VjcmV0' && urlOwnedReq.getHeader('host') === 'localhost'; urlOwnedReq.destroy(); const urlSecondOptions = new URL('http://localhost:3000/from-url'); urlSecondOptions.method = 'post'; urlSecondOptions.headers = { 'X-Url': 'yes' }; const urlSecondReq = http.request(urlSecondOptions, { method: 'put', headers: { 'X-Options': 'ok' }, path: '/from-options' }); urlSecondReq.on('error', () => {}); const urlSecondOptionsOk = urlSecondReq.method === 'PUT' && urlSecondReq.path === '/from-options' && urlSecondReq.getHeader('x-url') === undefined && urlSecondReq.getHeader('x-options') === 'ok' && urlSecondReq.getHeader('host') === 'localhost:3000'; urlSecondReq.destroy(); const originalGlobalAgent = http.globalAgent; const replacementGlobalAgent = { defaultPort: 80, protocol: 'http:' }; http.globalAgent = replacementGlobalAgent; const replacementReq = http.request('http://localhost:3000/'); replacementReq.on('error', () => {}); const globalAgentSetterOk = http.globalAgent === replacementGlobalAgent && replacementReq.agent === replacementGlobalAgent; replacementReq.destroy(); http.globalAgent = originalGlobalAgent; const freshAgent = new http.Agent(); const agentShape = (agent) => [Object.keys(agent).join(','), Object.keys(agent.options).join(','), agent.keepAliveMsecs, agent.keepAlive, String(agent.maxSockets), agent.maxFreeSockets, agent.scheduling, String(agent.maxTotalSockets), agent.totalSocketCount, agent.agentKeepAliveTimeoutBuffer].join(':'); const customAgent = new http.Agent({ keepAlive: false, keepAliveMsecs: 12, maxSockets: 3, maxFreeSockets: 4, scheduling: 'fifo', maxTotalSockets: 5, timeout: 6, agentKeepAliveTimeoutBuffer: 7 }); const agentInstanceOk = agentShape(freshAgent) === '_events,_eventsCount,_maxListeners,options,defaultPort,protocol,requests,sockets,freeSockets,keepAliveMsecs,keepAlive,maxSockets,maxFreeSockets,scheduling,maxTotalSockets,totalSocketCount,agentKeepAliveTimeoutBuffer:noDelay,path:1000:false:Infinity:256:lifo:Infinity:0:1000' && agentShape(http.globalAgent) === '_events,_eventsCount,_maxListeners,options,defaultPort,protocol,requests,sockets,freeSockets,keepAliveMsecs,keepAlive,maxSockets,maxFreeSockets,scheduling,maxTotalSockets,totalSocketCount,agentKeepAliveTimeoutBuffer:keepAlive,scheduling,timeout,proxyEnv,noDelay,path:1000:true:Infinity:256:lifo:Infinity:0:1000' && agentShape(customAgent) === '_events,_eventsCount,_maxListeners,options,defaultPort,protocol,requests,sockets,freeSockets,keepAliveMsecs,keepAlive,maxSockets,maxFreeSockets,scheduling,maxTotalSockets,totalSocketCount,agentKeepAliveTimeoutBuffer:keepAlive,keepAliveMsecs,maxSockets,maxFreeSockets,scheduling,maxTotalSockets,timeout,agentKeepAliveTimeoutBuffer,noDelay,path:12:false:3:4:fifo:5:0:7'; const agentMethods = ['createConnection','getName','addRequest','createSocket','removeSocket','keepSocketAlive','reuseSocket','destroy']; const agentDescriptorOk = agentMethods.every((name) => { const descriptor = Object.getOwnPropertyDescriptor(http.Agent.prototype, name); return descriptor?.value?.name === name && descriptor.enumerable === true && descriptor.configurable === true && descriptor.writable === true; }); const agentLengthOk = [['createConnection',0],['getName',0],['addRequest',4],['createSocket',3],['removeSocket',2],['keepSocketAlive',1],['reuseSocket',2],['destroy',0]].every(([name, length]) => http.Agent.prototype[name].length === length); const socketEvents = []; const fakeSocket = { setKeepAlive: (...args) => socketEvents.push(['setKeepAlive', ...args].join(':')), setTimeout: (...args) => socketEvents.push(['setTimeout', ...args].join(':')), removeListener: (name, fn) => socketEvents.push(['removeListener', name, typeof fn].join(':')), unref: () => socketEvents.push('unref'), ref: () => socketEvents.push('ref') }; const fakeReq = {}; let emptyConnectionCode = null; try { freshAgent.createConnection(); } catch (error) { emptyConnectionCode = error.code; } const createOptions = { host: 'socket-host', port: 80 }; let createdError; let createdSocket; const createReq = {}; freshAgent.createSocket(createReq, createOptions, (error, socket) => { createdError = error; createdSocket = socket; }); const createSocketProbeOk = createdError === null && createdSocket?._httpMessage === createReq && freshAgent.totalSocketCount === 1 && createOptions.encoding === null && createOptions._agentKey === 'socket-host:80:' && freshAgent.sockets[createOptions._agentKey]?.includes(createdSocket) && createdSocket.listenerCount('free') === 1 && typeof createdSocket.setKeepAlive === 'function'; const keepResult = freshAgent.keepSocketAlive(fakeSocket); const reuseResult = freshAgent.reuseSocket(fakeSocket, fakeReq); const destroyAgent = new http.Agent(); const destroyEvents = []; const destroyFreeSocket = { destroyed: false, destroy() { this.destroyed = true; destroyEvents.push('free:destroy'); } }; const destroyBusySocket = { destroyed: false, destroy() { this.destroyed = true; destroyEvents.push('busy:destroy'); } }; destroyAgent.on('free', () => destroyEvents.push('agent-free')); destroyAgent.freeSockets['example.com:80:'] = [destroyFreeSocket]; destroyAgent.sockets['example.com:80:'] = [destroyBusySocket]; const destroyResult = destroyAgent.destroy(); const agentDestroyOk = destroyResult === undefined && destroyEvents.join('|') === 'free:destroy|busy:destroy' && destroyFreeSocket.destroyed && destroyBusySocket.destroyed && Object.keys(destroyAgent.freeSockets).join(',') === 'example.com:80:' && Object.keys(destroyAgent.sockets).join(',') === 'example.com:80:'; const agentProbeOk = agentInstanceOk && agentDescriptorOk && agentLengthOk && freshAgent.getName({ host: 'example.com', port: 8080, localAddress: '127.0.0.1', family: 4, socketPath: '/tmp/sock' }) === 'example.com:8080:127.0.0.1:4:/tmp/sock' && freshAgent.getName({}) === 'localhost::' && emptyConnectionCode === 'ERR_MISSING_ARGS' && createSocketProbeOk && agentDestroyOk && keepResult === true && reuseResult === undefined && fakeReq.reusedSocket === true && socketEvents.join('|') === 'setKeepAlive:true:1000|unref|setTimeout:0|removeListener:error:function|ref'; if (Object.keys(http).join(',') !== keys || incomingTimeoutDescriptor?.value?.name !== 'setTimeout' || incomingTimeoutDescriptor.value.length !== 2 || !incomingTimeoutDescriptor.enumerable || !incomingTimeoutDescriptor.configurable || !incomingTimeoutDescriptor.writable || !incomingTimeoutOk || accessorMeta !== 'maxHeaderSize:get:0:undefined:::true:true:false:false|globalAgent:get:0:function:set:1:true:true:false:false|WebSocket:get:0:undefined:::true:true:false:false|CloseEvent:get:0:undefined:::true:true:false:false|MessageEvent:get:0:undefined:::true:true:false:false' || !globalAgentSetterOk || !(server instanceof http.Server) || typeof http.OutgoingMessage !== 'function' || typeof http.validateHeaderName !== 'function' || typeof http.validateHeaderValue !== 'function' || typeof http.setMaxIdleHTTPParsers !== 'function' || !maxParserPrototypeOk || typeof http.setGlobalProxyFromEnv() !== 'function' || http.maxHeaderSize !== 16384 || Object.keys(http.STATUS_CODES).length < 60 || http.STATUS_CODES[103] !== 'Early Hints' || http.createServer.length !== 2 || http.request.length !== 3 || http.get.length !== 3 || http.globalAgent.defaultPort !== 80 || http.globalAgent.protocol !== 'http:' || !(http.globalAgent instanceof http.Agent) || freshAgent.defaultPort !== 80 || freshAgent.protocol !== 'http:' || !requestAgentOk || !requestSocketOk || !urlOwnedOptionsOk || !urlSecondOptionsOk || !agentProbeOk || helpers.some((name) => typeof server[name] !== 'function' || !Object.getOwnPropertyDescriptor(http.Server.prototype, name)?.enumerable)) throw new Error('http shape failed'); http.validateHeaderName('x-opencontainers'); http.validateHeaderValue('x-opencontainers', ['ok']); const authReq = http.request('http://user:pass@localhost:3000/path'); authReq.on('error', () => {}); const authHeader = authReq.getHeader('authorization'); authReq.destroy(); const headerValidationRows = [['bad-name', () => http.validateHeaderName('bad header')], ['array-name', () => http.validateHeaderName(['x-opencontainers'])], ['number-name', () => http.validateHeaderName(1)], ['bad-value', () => http.validateHeaderValue('x-opencontainers', 'bad\\n')], ['undefined-value', () => http.validateHeaderValue('x-opencontainers', undefined)], ['symbol-value', () => http.validateHeaderValue('x-opencontainers', Symbol('bad'))]].map(([label, action]) => { try { action(); return label + ':ok' } catch (error) { return label + ':' + error.name + ':' + (error.code ?? 'no-code') } }).join('|'); if (headerValidationRows !== 'bad-name:TypeError:ERR_INVALID_HTTP_TOKEN|array-name:TypeError:ERR_INVALID_HTTP_TOKEN|number-name:TypeError:ERR_INVALID_HTTP_TOKEN|bad-value:TypeError:ERR_INVALID_CHAR|undefined-value:TypeError:ERR_HTTP_INVALID_HEADER_VALUE|symbol-value:TypeError:no-code') throw new Error('http header validation failed'); if (authHeader !== 'Basic dXNlcjpwYXNz') throw new Error('http auth failed'); const emptyHttpServer = http.createServer((req, res) => { const events = []; const timeout = setTimeout(() => { if (!events.some((event) => event.startsWith(\"end:\"))) { res.statusCode = 599; res.end(req.url + \":timeout:\" + events.join(\"|\")); } }, 10); req.on(\"data\", (chunk) => { events.push(\"data:\" + chunk.length); }); req.on(\"end\", () => { clearTimeout(timeout); events.push(\"end:\" + req.readableEnded); if (req.url === \"/empty-200\") { res.statusCode = 200; res.end(); return; } if (req.url === \"/status-204\") { res.statusCode = 204; res.end(\"ignored\"); return; } res.end(req.url + \":\" + events.join(\"|\")); }); }); await new Promise((resolve) => emptyHttpServer.listen(0, \"127.0.0.1\", resolve)); const emptyHttpPort = emptyHttpServer.address().port; const emptyHttpRequest = (path, options = {}, body) => new Promise((resolve, reject) => { const req = http.request({ host: \"127.0.0.1\", port: emptyHttpPort, path, ...options }, (res) => { const events = []; let text = \"\"; res.on(\"data\", (chunk) => { events.push(\"data:\" + chunk.length); text += String(chunk); }); res.on(\"end\", () => { events.push(\"end:\" + res.readableEnded); resolve(JSON.stringify([path, res.statusCode, events, text])); }); }); req.on(\"error\", reject); if (body === undefined) req.end(); else req.end(body); }); const emptyHttpRows = [await emptyHttpRequest(\"/no-body\"), await emptyHttpRequest(\"/length-zero\", { method: \"POST\", headers: { \"content-length\": \"0\" } }), await emptyHttpRequest(\"/explicit-empty\", { method: \"POST\" }, new Uint8Array(0)), await emptyHttpRequest(\"/empty-200\"), await emptyHttpRequest(\"/status-204\")]; emptyHttpServer.close(); const emptyHttpExpected = [JSON.stringify([\"/no-body\", 200, [\"data:17\", \"end:true\"], \"/no-body:end:true\"]), JSON.stringify([\"/length-zero\", 200, [\"data:21\", \"end:true\"], \"/length-zero:end:true\"]), JSON.stringify([\"/explicit-empty\", 200, [\"data:24\", \"end:true\"], \"/explicit-empty:end:true\"]), JSON.stringify([\"/empty-200\", 200, [\"end:true\"], \"\"]), JSON.stringify([\"/status-204\", 204, [\"end:true\"], \"\"])] ; if (emptyHttpRows.join(\"|\") !== emptyHttpExpected.join(\"|\")) throw new Error(\"http empty body stream lifecycle failed\"); const trailerServer = http.createServer((req, res) => { res.setHeader(\"Trailer\", \"X-Trailer, X-Multi\"); res.addTrailers({ \"X-Trailer\": \"done\", \"X-Multi\": [\"a\", \"b\"] }); res.end(\"body\"); }); await new Promise((resolve) => trailerServer.listen(0, \"127.0.0.1\", resolve)); const trailerRow = await new Promise((resolve, reject) => { const req = http.get({ host: \"127.0.0.1\", port: trailerServer.address().port, path: \"/trailers\" }, (res) => { let data = \"\"; res.on(\"data\", (chunk) => { data += String(chunk); }); res.on(\"end\", () => resolve([data, res.trailers[\"x-trailer\"], res.trailers[\"x-multi\"], res.rawTrailers.join(\"|\")].join(\":\"))); }); req.on(\"error\", reject); }); trailerServer.close(); if (trailerRow !== \"body:done:a, b:X-Trailer|done|X-Multi|a|X-Multi|b\") throw new Error(\"http trailer propagation failed\"); const httpServerAsyncDisposeDescriptor = Object.getOwnPropertyDescriptor(http.Server.prototype, Symbol.asyncDispose); let httpNotRunningResult; try { await http.createServer()[Symbol.asyncDispose](); httpNotRunningResult = 'ok'; } catch (error) { httpNotRunningResult = error.constructor.name + ':' + error.code + ':' + error.message; } const httpDisposeServer = http.createServer((req, res) => res.end('ok')); await new Promise((resolve) => httpDisposeServer.listen(0, '127.0.0.1', resolve)); const httpDisposePromise = httpDisposeServer[Symbol.asyncDispose](); const httpDisposeResult = await httpDisposePromise; if (!httpServerAsyncDisposeDescriptor || typeof httpServerAsyncDisposeDescriptor.value !== 'function' || httpServerAsyncDisposeDescriptor.value.name !== '[Symbol.asyncDispose]' || httpServerAsyncDisposeDescriptor.value.length !== 0 || httpServerAsyncDisposeDescriptor.enumerable !== true || httpServerAsyncDisposeDescriptor.configurable !== true || httpServerAsyncDisposeDescriptor.writable !== true || Object.hasOwn(httpServerAsyncDisposeDescriptor.value, 'prototype') || Object.getOwnPropertySymbols(http.Server.prototype).map(String).join(',') !== 'Symbol(Symbol.asyncDispose)' || httpNotRunningResult !== 'Error:ERR_SERVER_NOT_RUNNING:Server is not running.' || httpDisposePromise.constructor.name !== 'Promise' || httpDisposeResult !== undefined || httpDisposeServer.listening !== false) throw new Error('http Server Symbol.asyncDispose failed');; const ocHttpFunctionPrototypeRow = (fn) => { const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); if (!descriptor) return 'no-prototype'; return [descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.getOwnPropertyNames(descriptor.value).join(',')].join('/') }; const ocHttpDescriptorRow = (prototype, name) => { const descriptor = Object.getOwnPropertyDescriptor(prototype, name); if (!descriptor) return [name, 'missing', typeof prototype[name]].join(':'); if ('value' in descriptor) return [name, 'data', descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value, descriptor.value?.name, descriptor.value?.length, Object.hasOwn(descriptor.value, 'prototype'), ocHttpFunctionPrototypeRow(descriptor.value)].join(':'); return [name, 'accessor', descriptor.enumerable, descriptor.configurable, descriptor.get?.name, descriptor.get?.length, typeof descriptor.set, descriptor.set?.name ?? '', descriptor.set?.length ?? '', Object.hasOwn(descriptor.get ?? {}, 'prototype'), Object.hasOwn(descriptor.set ?? {}, 'prototype')].join(':') }; const ocHttpClientProbeNames = ['path', 'clearTimeout', 'setNoDelay', 'setSocketKeepAlive', '_implicitHeader', '_finish', '_deferToConnect', 'onSocket', 'setTimeout', 'abort', 'destroy']; const ocHttpIncomingProbeNames = ['headersDistinct', 'trailersDistinct', 'signal', 'setTimeout', '_read', '_destroy', '_dumpAndCloseReadable', '_dump']; const ocHttpClientRows = ocHttpClientProbeNames.map((name) => ocHttpDescriptorRow(http.ClientRequest.prototype, name)).join('|'); const ocHttpIncomingRows = ocHttpIncomingProbeNames.map((name) => ocHttpDescriptorRow(http.IncomingMessage.prototype, name)).join('|'); const ocHttpReq = http.request('http://localhost:3000/path?x=1'); ocHttpReq.on('error', () => {}); const ocHttpSocketRows = []; const ocHttpSocket = { connecting: false, setNoDelay: (value) => ocHttpSocketRows.push('setNoDelay:' + value), setKeepAlive: (...args) => ocHttpSocketRows.push('setKeepAlive:' + args.join(':')), setTimeout: (...args) => ocHttpSocketRows.push('setTimeout:' + args.join(':')) }; const ocHttpRequestSurface = [Object.getPrototypeOf(http.ClientRequest.prototype).constructor.name, Object.hasOwn(ocHttpReq, 'path'), ocHttpReq.path, ocHttpReq instanceof http.OutgoingMessage, ocHttpReq.onSocket(ocHttpSocket) === undefined, ocHttpReq.socket === ocHttpSocket, ocHttpSocket._httpMessage === ocHttpReq, ocHttpReq.clearTimeout() === undefined, ocHttpReq.setNoDelay(false) === undefined, ocHttpReq.setSocketKeepAlive(true, 12) === undefined, ocHttpReq._implicitHeader() === undefined, ocHttpReq._finish() === undefined, ocHttpReq._deferToConnect(() => ocHttpSocketRows.push('deferred'), []) === undefined, ocHttpSocketRows.join('|')].join('::'); ocHttpReq.destroy(); const ocHttpIncoming = new http.IncomingMessage({ method: 'GET', url: '/', headers: [['a', '1'], ['b', '2'], ['b', '3']], trailers: { t: ['x', 'y'] }, port: 80 }); const ocHttpIncomingSurface = [JSON.stringify(ocHttpIncoming.headersDistinct), Object.getPrototypeOf(ocHttpIncoming.headersDistinct) === null, JSON.stringify(ocHttpIncoming.trailersDistinct), Object.getPrototypeOf(ocHttpIncoming.trailersDistinct) === null, ocHttpIncoming.signal.constructor.name, ocHttpIncoming.signal.aborted, ocHttpIncoming._dump(), ocHttpIncoming._dumped].join('::'); if (ocHttpClientRows !== 'path:accessor:true:true:get:0:function:set:1:false:false|clearTimeout:data:true:true:true:function:clearTimeout:1:true:false/false/true/constructor|setNoDelay:data:true:true:true:function:setNoDelay:1:true:false/false/true/constructor|setSocketKeepAlive:data:true:true:true:function:setSocketKeepAlive:2:true:false/false/true/constructor|_implicitHeader:data:true:true:true:function:_implicitHeader:0:true:false/false/true/constructor|_finish:data:true:true:true:function:_finish:0:true:false/false/true/constructor|_deferToConnect:data:true:true:true:function:_deferToConnect:2:true:false/false/true/constructor|onSocket:data:true:true:true:function:onSocket:2:true:false/false/true/constructor|setTimeout:data:true:true:true:function:setTimeout:2:true:false/false/true/constructor|abort:data:true:true:true:function:abort:0:true:false/false/true/constructor|destroy:data:true:true:true:function:destroy:1:true:false/false/true/constructor' || ocHttpIncomingRows !== 'headersDistinct:accessor:false:false:get:0:function:set:1:true:true|trailersDistinct:accessor:false:false:get:0:function:set:1:true:true|signal:accessor:false:true:get:0:undefined:::true:false|setTimeout:data:true:true:true:function:setTimeout:2:true:false/false/true/constructor|_read:data:true:true:true:function:_read:1:true:false/false/true/constructor|_destroy:data:true:true:true:function:_destroy:2:true:false/false/true/constructor|_dumpAndCloseReadable:data:true:true:true:function:_dumpAndCloseReadable:0:true:false/false/true/constructor|_dump:data:true:true:true:function:_dump:0:true:false/false/true/constructor' || ocHttpRequestSurface !== 'OutgoingMessage::false::/path?x=1::true::true::true::true::true::true::true::true::true::true::setTimeout:0|setNoDelay:false|setKeepAlive:true:12|deferred' || ocHttpIncomingSurface !== '{\"a\":[\"1\"],\"b\":[\"2\",\"3\"]}::true::{\"t\":[\"x\",\"y\"]}::true::AbortSignal::false::::true') throw new Error('http request-side prototype metadata failed'); const streamingRows = []; let streamingEnded = false; const streamingServer = http.createServer((req, res) => { req.on('data', (chunk) => streamingRows.push('data:' + String(chunk) + ':' + streamingEnded)); req.on('end', () => { streamingRows.push('end:' + streamingEnded); res.end(streamingRows.join('|')); }); }); await new Promise((resolve) => streamingServer.listen(3456, '127.0.0.1', resolve)); const streamingResult = await new Promise((resolve, reject) => { const req = http.request({ host: '127.0.0.1', port: 3456, method: 'POST', path: '/stream' }, (res) => { let text = ''; res.on('data', (chunk) => { text += chunk; }); res.on('end', () => resolve(text)); }); req.on('error', reject); req.write('first'); setTimeout(() => { streamingEnded = true; req.end('second'); }, 0); }); streamingServer.close(); if (streamingResult !== 'data:first:false|data:second:true|end:true') throw new Error('http request streaming failed');" }, { "specifier": "node:https", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/http-client.test.mjs", "limitation": "HTTPS client behavior is browser-backed and shares the Node-shaped CommonJS export order, request/get/createServer helper surface, Basic auth header synthesis, protocol and unescaped-path validation, protocol-specific Agent/globalAgent metadata, native-shaped Agent instance option metadata, HTTPS Agent prototype/session-cache probes, and native-ordered Server prototype helper metadata plus Symbol.asyncDispose descriptor/not-running/close behavior with helper own-prototype metadata without extra HTTP constants; createServer exposes the Node shape on the virtual HTTP transport, while native TLS socket controls are unavailable.", "probe": "const http = require('node:http'); const https = require('node:https'); const keys = 'Agent,globalAgent,Server,createServer,get,request'; const server = https.createServer({}, () => {}); const helpers = ['close', 'closeAllConnections', 'closeIdleConnections', 'setTimeout']; const agent = new https.Agent(); const agentShape = (agent) => [Object.keys(agent).join(','), Object.keys(agent.options).join(','), agent.keepAliveMsecs, agent.keepAlive, String(agent.maxSockets), agent.maxFreeSockets, agent.scheduling, String(agent.maxTotalSockets), agent.totalSocketCount, agent.agentKeepAliveTimeoutBuffer, agent.maxCachedSessions ?? '', agent._sessionCache ? Object.keys(agent._sessionCache).join(',') : ''].join(':'); const customAgent = new https.Agent({ maxCachedSessions: 2, keepAliveMsecs: 12 }); const agentInstanceOk = agentShape(agent) === '_events,_eventsCount,_maxListeners,options,defaultPort,protocol,requests,sockets,freeSockets,keepAliveMsecs,keepAlive,maxSockets,maxFreeSockets,scheduling,maxTotalSockets,totalSocketCount,agentKeepAliveTimeoutBuffer,maxCachedSessions,_sessionCache:defaultPort,protocol,noDelay,path:1000:false:Infinity:256:lifo:Infinity:0:1000:100:map,list' && agentShape(https.globalAgent) === '_events,_eventsCount,_maxListeners,options,defaultPort,protocol,requests,sockets,freeSockets,keepAliveMsecs,keepAlive,maxSockets,maxFreeSockets,scheduling,maxTotalSockets,totalSocketCount,agentKeepAliveTimeoutBuffer,maxCachedSessions,_sessionCache:keepAlive,scheduling,timeout,proxyEnv,defaultPort,protocol,noDelay,path:1000:true:Infinity:256:lifo:Infinity:0:1000:100:map,list' && agentShape(customAgent) === '_events,_eventsCount,_maxListeners,options,defaultPort,protocol,requests,sockets,freeSockets,keepAliveMsecs,keepAlive,maxSockets,maxFreeSockets,scheduling,maxTotalSockets,totalSocketCount,agentKeepAliveTimeoutBuffer,maxCachedSessions,_sessionCache:maxCachedSessions,keepAliveMsecs,defaultPort,protocol,noDelay,path:12:false:Infinity:256:lifo:Infinity:0:1000:2:map,list'; const httpsAgentMethods = ['createConnection','getName','_getSession','_cacheSession','_evictSession']; const httpsAgentDescriptorOk = httpsAgentMethods.every((name) => { const descriptor = Object.getOwnPropertyDescriptor(https.Agent.prototype, name); return descriptor?.value?.name === name && descriptor.enumerable === true && descriptor.configurable === true && descriptor.writable === true; }); const httpsAgentLengthOk = [['createConnection',0],['getName',0],['_getSession',1],['_cacheSession',2],['_evictSession',1]].every(([name, length]) => https.Agent.prototype[name].length === length); let httpsEmptyConnectionCode = null; try { agent.createConnection(); } catch (error) { httpsEmptyConnectionCode = error.code; } const httpsNameProbeOk = agent.getName({}) === 'localhost::::::::::::::::::::::' && agent.getName({ host: 'example.com', port: 443, localAddress: '127.0.0.1', family: 4 }) === 'example.com:443:127.0.0.1:4::::::::::::::::::::'; const limitedAgent = new https.Agent({ maxCachedSessions: 2 }); limitedAgent._cacheSession('a', Buffer.from('one')); limitedAgent._cacheSession('b', Buffer.from('two')); limitedAgent._cacheSession('c', Buffer.from('three')); limitedAgent._cacheSession('b', Buffer.from('two-updated')); const sessionProbeOk = httpsAgentDescriptorOk && httpsAgentLengthOk && httpsEmptyConnectionCode === 'ERR_MISSING_ARGS' && httpsNameProbeOk && limitedAgent._getSession('a') === undefined && limitedAgent._getSession('b').toString() === 'two-updated' && limitedAgent._getSession('c').toString() === 'three' && limitedAgent._sessionCache.list.join(',') === 'b,c'; limitedAgent._evictSession('b'); const sessionEvictOk = limitedAgent._sessionCache.list.join(',') === 'c' && Object.keys(limitedAgent._sessionCache.map).join(',') === 'c'; const disabledAgent = new https.Agent({ maxCachedSessions: 0 }); disabledAgent._cacheSession('x', Buffer.from('x')); const sessionDisabledOk = JSON.stringify(disabledAgent._sessionCache) === '{\"map\":{},\"list\":[]}' && disabledAgent._getSession('x') === undefined; const req = https.request('https://localhost/'); req.on('error', () => {}); const requestAgentOk = req.agent === https.globalAgent && req.agent !== http.globalAgent && req.agent.defaultPort === 443 && req.agent.protocol === 'https:'; req.destroy(); const authReq = https.request('https://user:pass@localhost/path'); authReq.on('error', () => {}); const authHeader = authReq.getHeader('authorization'); authReq.destroy(); if (Object.keys(https).join(',') !== keys || !(server instanceof https.Server) || typeof https.request !== 'function' || typeof https.get !== 'function' || https.createServer.length !== 2 || https.request.length !== 0 || https.get.length !== 3 || https.Agent === http.Agent || https.globalAgent === http.globalAgent || !(https.globalAgent instanceof https.Agent) || !(https.globalAgent instanceof http.Agent) || https.globalAgent.defaultPort !== 443 || https.globalAgent.protocol !== 'https:' || agent.defaultPort !== 443 || agent.protocol !== 'https:' || !agentInstanceOk || !sessionProbeOk || !sessionEvictOk || !sessionDisabledOk || agent.maxCachedSessions !== 100 || JSON.stringify(agent._sessionCache) !== '{\"map\":{},\"list\":[]}' || !requestAgentOk || authHeader !== 'Basic dXNlcjpwYXNz' || Object.hasOwn(https, 'METHODS') || Object.hasOwn(https, 'STATUS_CODES') || helpers.some((name) => typeof server[name] !== 'function' || !Object.getOwnPropertyDescriptor(https.Server.prototype, name)?.enumerable)) throw new Error('https shape failed'); const httpsServerAsyncDisposeDescriptor = Object.getOwnPropertyDescriptor(https.Server.prototype, Symbol.asyncDispose); let httpsNotRunningResult; try { await https.createServer()[Symbol.asyncDispose](); httpsNotRunningResult = 'ok'; } catch (error) { httpsNotRunningResult = error.constructor.name + ':' + error.code + ':' + error.message; } const httpsDisposeServer = https.createServer({}, (req, res) => res.end('ok')); await new Promise((resolve) => httpsDisposeServer.listen(0, '127.0.0.1', resolve)); const httpsDisposePromise = httpsDisposeServer[Symbol.asyncDispose](); const httpsDisposeResult = await httpsDisposePromise; if (!httpsServerAsyncDisposeDescriptor || typeof httpsServerAsyncDisposeDescriptor.value !== 'function' || httpsServerAsyncDisposeDescriptor.value.name !== '' || httpsServerAsyncDisposeDescriptor.value.length !== 0 || httpsServerAsyncDisposeDescriptor.enumerable !== true || httpsServerAsyncDisposeDescriptor.configurable !== true || httpsServerAsyncDisposeDescriptor.writable !== true || Object.hasOwn(httpsServerAsyncDisposeDescriptor.value, 'prototype') || Object.getOwnPropertySymbols(https.Server.prototype).map(String).join(',') !== 'Symbol(Symbol.asyncDispose)' || httpsNotRunningResult !== 'Error:ERR_SERVER_NOT_RUNNING:Server is not running.' || httpsDisposePromise.constructor.name !== 'Promise' || httpsDisposeResult !== undefined || httpsDisposeServer.listening !== false) throw new Error('https Server Symbol.asyncDispose failed');" }, { "specifier": "node:os", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Virtual Linux metadata is deterministic, including package-facing homedir/tmpdir/devNull/EOL helpers, one virtual CPU, load averages, positive memory values, loopback network interfaces, encoded userInfo variants, native-shaped helper names/arities/prototype ownership, constants/descriptors, native-order errno constants, and priority validation.", "probe": "const os = require('node:os'); const constants = require('node:constants'); const lo = os.networkInterfaces().lo; const user = os.userInfo({ encoding: 'buffer' }); const upperUser = os.userInfo({ encoding: 'BUFFER' }); const hexUser = os.userInfo({ encoding: 'hex' }); const base64User = os.userInfo({ encoding: 'base64' }); const constantsDescriptor = Object.getOwnPropertyDescriptor(os, 'constants'); const eolDescriptor = Object.getOwnPropertyDescriptor(os, 'EOL'); const devNullDescriptor = Object.getOwnPropertyDescriptor(os, 'devNull'); const errnoDescriptor = Object.getOwnPropertyDescriptor(os.constants.errno, 'ENOENT'); const errnoKeys = Object.keys(os.constants.errno); const constantKeys = Object.keys(constants); const expectedErrnoKeys = constantKeys.slice(constantKeys.indexOf('E2BIG'), constantKeys.indexOf('PRIORITY_LOW')).join(','); const signalWriteResult = (() => { 'use strict'; try { os.constants.signals.__probe = 1; return 'ok'; } catch (error) { return error.name + ':' + /extensible/.test(error.message); } })(); const metadata = ['arch','availableParallelism','freemem','getPriority','homedir','hostname','release','setPriority','totalmem','type','userInfo','uptime','version','machine'].map((name) => name + ':' + os[name].name + ':' + os[name].length + ':' + Object.hasOwn(os[name], 'prototype')).join('|'); const cpu = os.cpus()[0]; if (Object.keys(os).join(',') !== 'arch,availableParallelism,cpus,endianness,freemem,getPriority,homedir,hostname,loadavg,networkInterfaces,platform,release,setPriority,tmpdir,totalmem,type,userInfo,uptime,version,machine,constants,EOL,devNull' || Object.keys(os.constants).join(',') !== 'UV_UDP_REUSEADDR,dlopen,errno,signals,priority' || metadata !== 'arch:arch:0:true|availableParallelism::0:false|freemem::0:false|getPriority:getPriority:1:true|homedir:wrappedFn:0:true|hostname:wrappedFn:0:true|release:getOSRelease:0:false|setPriority:setPriority:2:true|totalmem::0:false|type:getOSType:0:false|userInfo:userInfo:1:true|uptime:wrappedFn:0:true|version:getOSVersion:0:false|machine:getMachine:0:false' || constantsDescriptor.writable || constantsDescriptor.configurable || eolDescriptor.writable || !eolDescriptor.configurable || devNullDescriptor.writable || !devNullDescriptor.configurable || Object.getPrototypeOf(os.constants) !== null || Object.getPrototypeOf(os.constants.priority) !== null || Object.getPrototypeOf(os.constants.dlopen) !== null || errnoKeys.join(',') !== expectedErrnoKeys || errnoDescriptor.writable || errnoDescriptor.configurable || Object.isExtensible(os.constants.signals) || !Object.isSealed(os.constants.signals) || !Object.isFrozen(os.constants.signals) || signalWriteResult !== 'TypeError:true' || Object.hasOwn(os.constants.signals, '__probe')) throw new Error('os metadata failed'); if (os.platform() !== 'linux' || os.arch() !== 'x64' || os.machine() !== 'x86_64' || os.type() !== 'Linux' || os.homedir() !== '/home/opencontainers' || os.tmpdir() !== '/tmp' || os.endianness() !== 'LE' || os.EOL !== String.fromCharCode(10) || os.devNull !== '/dev/null' || os.availableParallelism() !== 1 || os.loadavg().join(',') !== '0,0,0' || !cpu || cpu.model !== 'OpenContainers Virtual CPU' || cpu.speed !== 0 || !Array.isArray(lo) || lo[0].address !== '127.0.0.1' || lo[1].scopeid !== 0 || !Buffer.isBuffer(user.username) || !Buffer.isBuffer(upperUser.username) || user.username.toString() !== 'opencontainers' || hexUser.username !== '6f70656e636f6e7461696e657273' || base64User.username !== 'b3BlbmNvbnRhaW5lcnM=' || base64User.homedir !== 'L2hvbWUvb3BlbmNvbnRhaW5lcnM=' || base64User.shell !== 'L2Jpbi9zaA==' || os.getPriority.length !== 1 || os.setPriority.length !== 2 || os.userInfo.length !== 1) throw new Error('os failed'); for (const action of [() => os.getPriority('x'), () => os.setPriority('x', 1), () => os.setPriority(0, 'x'), () => os.setPriority(0, -21)]) { try { action(); throw new Error('os validation failed') } catch (error) { if (error.message === 'os validation failed' || !['ERR_INVALID_ARG_TYPE', 'ERR_OUT_OF_RANGE'].includes(error.code)) throw error } }" }, { "specifier": "node:path", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Path helpers, validation, native-shaped helper names/arities and no-own-prototype function metadata, bound format constructor validation, _makeLong identity, namespaced path passthrough, and matchesGlob recursive/star/brace/negated-class probes are covered.", "probe": "const path = require('node:path'); const keys = 'resolve,normalize,isAbsolute,join,relative,toNamespacedPath,dirname,basename,extname,format,parse,matchesGlob,sep,delimiter,win32,posix,_makeLong'; const code = (fn) => { try { fn(); return 'ok' } catch (error) { return error.name + ':' + error.code } }; const helperNames = ['resolve','normalize','isAbsolute','join','relative','toNamespacedPath','dirname','basename','extname','format','parse','matchesGlob','_makeLong']; const constructTag = (fn) => { try { new fn(); return 'ok' } catch (error) { return error.code || (String(error.message).includes('not a constructor') ? 'notConstructor' : error.name) } }; const helperShape = (mod) => helperNames.map((name) => { const fn = mod[name]; return [name, fn.name, fn.length, Object.hasOwn(fn, 'prototype'), constructTag(fn)].join(':') }).join('|'); const expectedHelperShape = 'resolve:resolve:0:false:notConstructor|normalize:normalize:1:false:notConstructor|isAbsolute:isAbsolute:1:false:notConstructor|join:join:0:false:notConstructor|relative:relative:2:false:notConstructor|toNamespacedPath:toNamespacedPath:1:false:notConstructor|dirname:dirname:1:false:notConstructor|basename:basename:2:false:notConstructor|extname:extname:1:false:notConstructor|format:bound _format:1:false:ERR_INVALID_ARG_TYPE|parse:parse:1:false:notConstructor|matchesGlob:matchesGlob:2:false:notConstructor|_makeLong:toNamespacedPath:1:false:notConstructor'; const probe = {}; const validationChecks = [(p) => p.resolve('a', null), (p) => p.normalize(null), (p) => p.isAbsolute(null), (p) => p.join('a', null), (p) => p.relative(null, 'b'), (p) => p.relative('a', null), (p) => p.dirname(null), (p) => p.basename(null), (p) => p.extname(null), (p) => p.parse(null), (p) => p.basename('file.txt', null), (p) => p.format(null), (p) => p.format(undefined), (p) => p.format([]), (p) => p.format(function pathObject() {}), (p) => p.format(Symbol('pathObject')), (p) => p.matchesGlob(null, '*.js'), (p) => p.matchesGlob('file.js', null)]; const validation = validationChecks.every((check) => code(() => check(path)) === 'TypeError:ERR_INVALID_ARG_TYPE'); const globRows = [path.matchesGlob('src/index.test.js', 'src/*.test.js'), path.posix.matchesGlob('src/lib/index.js', 'src/**/*.js'), path.matchesGlob('src/index.js', 'src/**/*.js'), path.matchesGlob('src/.hidden.js', 'src/*.js'), path.matchesGlob('src/file.js', 'src/*.{js,ts}'), path.matchesGlob('src/c.js', 'src/[!ab].js'), path.matchesGlob('src/lib/.hidden.js', 'src/**/*.js'), path.win32.matchesGlob('src\\\\index.js', 'src\\\\**\\\\*.js'), path.win32.matchesGlob('src\\\\.hidden.js', 'src\\\\*.js'), path.win32.matchesGlob('src\\\\file.ts', 'src\\\\*.{js,ts}'), path.win32.matchesGlob('src\\\\c.js', 'src\\\\[!ab].js'), path.win32.matchesGlob('src/index.css', '*.js')].join(','); const namespaced = [null, 1, undefined].every((value) => path.toNamespacedPath(value) === value); if (Object.keys(path).join(',') !== keys || Object.keys(path.posix).join(',') !== keys || Object.keys(path.win32).join(',') !== keys || helperShape(path) !== expectedHelperShape || helperShape(path.posix) !== expectedHelperShape || helperShape(path.win32) !== expectedHelperShape || path.resolve !== path.posix.resolve || path.format !== path.posix.format || path._makeLong !== path.toNamespacedPath || path.posix._makeLong !== path.posix.toNamespacedPath || path.win32._makeLong !== path.win32.toNamespacedPath || path.posix.posix !== path.posix || path.win32.win32 !== path.win32 || path.join('/workspace', 'a') !== '/workspace/a' || path.normalize('a//b//') !== 'a/b/' || path.format({ dir: '/tmp', name: 'file', ext: 'txt' }) !== '/tmp/file.txt' || path.basename('/workspace/index.test.js', '.js') !== 'index.test' || path.basename('foo/..') !== '..' || path.basename('/workspace/index.test.js', 'index.test.js') !== 'index.test.js' || path.basename('index.test.js', 'index.test.js') !== '' || path.win32.basename('foo\\\\..') !== '..' || path.win32.basename('C:/temp/index.test.js', 'index.test.js') !== 'index.test.js' || path.win32.basename('index.test.js', 'index.test.js') !== '' || path.win32.basename('C:/') !== '' || path._makeLong('/workspace/a') !== '/workspace/a' || path.toNamespacedPath(probe) !== probe || globRows !== 'true,true,true,false,true,true,false,true,false,true,true,false' || !namespaced || !validation) throw new Error('path failed')" }, { "specifier": "node:path/posix", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "POSIX path helpers mirror node:path helper metadata, validation, _makeLong identity, namespaced passthrough, formatting, basename, and cross-namespace identity probes.", "probe": "const posix = require('node:path/posix'); const path = require('node:path'); const code = (fn) => { try { fn(); return 'ok' } catch (error) { return error.name + ':' + error.code } }; const helperNames = ['resolve','normalize','isAbsolute','join','relative','toNamespacedPath','dirname','basename','extname','format','parse','matchesGlob','_makeLong']; const constructTag = (fn) => { try { new fn(); return 'ok' } catch (error) { return error.code || (String(error.message).includes('not a constructor') ? 'notConstructor' : error.name) } }; const helperShape = (mod) => helperNames.map((name) => { const fn = mod[name]; return [name, fn.name, fn.length, Object.hasOwn(fn, 'prototype'), constructTag(fn)].join(':') }).join('|'); const expectedHelperShape = 'resolve:resolve:0:false:notConstructor|normalize:normalize:1:false:notConstructor|isAbsolute:isAbsolute:1:false:notConstructor|join:join:0:false:notConstructor|relative:relative:2:false:notConstructor|toNamespacedPath:toNamespacedPath:1:false:notConstructor|dirname:dirname:1:false:notConstructor|basename:basename:2:false:notConstructor|extname:extname:1:false:notConstructor|format:bound _format:1:false:ERR_INVALID_ARG_TYPE|parse:parse:1:false:notConstructor|matchesGlob:matchesGlob:2:false:notConstructor|_makeLong:toNamespacedPath:1:false:notConstructor'; const validationChecks = [(p) => p.resolve('a', null), (p) => p.normalize(null), (p) => p.isAbsolute(null), (p) => p.join('a', null), (p) => p.relative(null, 'b'), (p) => p.relative('a', null), (p) => p.dirname(null), (p) => p.basename(null), (p) => p.extname(null), (p) => p.parse(null), (p) => p.basename('file.txt', null), (p) => p.format(null), (p) => p.format(undefined), (p) => p.format([]), (p) => p.format(function pathObject() {}), (p) => p.format(Symbol('pathObject')), (p) => p.matchesGlob(null, '*.js'), (p) => p.matchesGlob('file.js', null)]; const namespaced = [null, 1, undefined].every((value) => posix.toNamespacedPath(value) === value); const validation = validationChecks.every((check) => code(() => check(posix)) === 'TypeError:ERR_INVALID_ARG_TYPE'); if (helperShape(posix) !== expectedHelperShape || posix.resolve !== path.resolve || posix.format !== path.format || posix._makeLong !== posix.toNamespacedPath || posix.normalize('a//b//') !== 'a/b/' || posix.format({ dir: '/tmp', name: 'file', ext: 'txt' }) !== '/tmp/file.txt' || posix.basename('/a/b.txt', '.txt') !== 'b' || posix.basename('foo/..') !== '..' || posix.basename('/a/b.txt', 'b.txt') !== 'b.txt' || posix.basename('b.txt', 'b.txt') !== '' || posix.basename('/') !== '' || posix.posix !== posix || posix.win32 !== require('node:path/win32') || !namespaced || !validation) throw new Error('path posix failed')" }, { "specifier": "node:path/win32", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Win32 path helpers mirror native helper metadata, validation, _makeLong identity, namespaced conversion, formatting, basename, drive/UNC, and cross-namespace probes.", "probe": "const win32 = require('node:path/win32'); const code = (fn) => { try { fn(); return 'ok' } catch (error) { return error.name + ':' + error.code } }; const helperNames = ['resolve','normalize','isAbsolute','join','relative','toNamespacedPath','dirname','basename','extname','format','parse','matchesGlob','_makeLong']; const constructTag = (fn) => { try { new fn(); return 'ok' } catch (error) { return error.code || (String(error.message).includes('not a constructor') ? 'notConstructor' : error.name) } }; const helperShape = (mod) => helperNames.map((name) => { const fn = mod[name]; return [name, fn.name, fn.length, Object.hasOwn(fn, 'prototype'), constructTag(fn)].join(':') }).join('|'); const expectedHelperShape = 'resolve:resolve:0:false:notConstructor|normalize:normalize:1:false:notConstructor|isAbsolute:isAbsolute:1:false:notConstructor|join:join:0:false:notConstructor|relative:relative:2:false:notConstructor|toNamespacedPath:toNamespacedPath:1:false:notConstructor|dirname:dirname:1:false:notConstructor|basename:basename:2:false:notConstructor|extname:extname:1:false:notConstructor|format:bound _format:1:false:ERR_INVALID_ARG_TYPE|parse:parse:1:false:notConstructor|matchesGlob:matchesGlob:2:false:notConstructor|_makeLong:toNamespacedPath:1:false:notConstructor'; const probe = {}; const validationChecks = [(p) => p.resolve('a', null), (p) => p.normalize(null), (p) => p.isAbsolute(null), (p) => p.join('a', null), (p) => p.relative(null, 'b'), (p) => p.relative('a', null), (p) => p.dirname(null), (p) => p.basename(null), (p) => p.extname(null), (p) => p.parse(null), (p) => p.basename('file.txt', null), (p) => p.format(null), (p) => p.format(undefined), (p) => p.format([]), (p) => p.format(function pathObject() {}), (p) => p.format(Symbol('pathObject')), (p) => p.matchesGlob(null, '*.js'), (p) => p.matchesGlob('file.js', null)]; const namespaced = [null, 1, undefined].every((value) => win32.toNamespacedPath(value) === value); const validation = validationChecks.every((check) => code(() => check(win32)) === 'TypeError:ERR_INVALID_ARG_TYPE'); if (helperShape(win32) !== expectedHelperShape || win32._makeLong !== win32.toNamespacedPath || win32.normalize('C:/temp//foo/../bar') !== 'C:\\\\temp\\\\bar' || win32.normalize('a\\\\\\\\b\\\\\\\\') !== 'a\\\\b\\\\' || win32.format({ dir: 'C:\\\\tmp', name: 'file', ext: 'txt' }) !== 'C:\\\\tmp\\\\file.txt' || win32.basename('C:/temp/index.test.js', '.js') !== 'index.test' || win32.basename('foo\\\\..') !== '..' || win32.basename('C:/temp/index.test.js', 'index.test.js') !== 'index.test.js' || win32.basename('index.test.js', 'index.test.js') !== '' || win32.basename('C:/') !== '' || win32.basename('C:') !== '' || win32.basename('C:/tmp/') !== 'tmp' || win32.win32 !== win32 || win32.posix !== require('node:path/posix') || win32._makeLong('C:/temp/bar') !== '\\\\\\\\?\\\\C:\\\\temp\\\\bar' || win32.toNamespacedPath(probe) !== probe || !namespaced || !validation) throw new Error('path win32 failed')" }, { "specifier": "node:punycode", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Native-shaped CommonJS export metadata including constructable helper prototype ownership, encode/decode helpers, ucs2 helpers, Unicode domain separator normalization, and native null/non-string coercion errors are covered.", "probe": "const punycode = require('node:punycode'); const describe = (action) => { try { return 'ok:' + JSON.stringify(action()); } catch (error) { return error.name + ':' + error.message; } }; const validationRows = [['toASCII-null', () => punycode.toASCII(null)], ['toASCII-undefined', () => punycode.toASCII(undefined)], ['toUnicode-null', () => punycode.toUnicode(null)], ['encode-null', () => punycode.encode(null)], ['decode-null', () => punycode.decode(null)], ['ucs2-decode-null', () => punycode.ucs2.decode(null)], ['ucs2-encode-null', () => punycode.ucs2.encode(null)]].map(([label, action]) => label + ':' + describe(action)).join('|'); const coercionRows = [['encode-number', () => punycode.encode(123)], ['ucs2-decode-number', () => punycode.ucs2.decode(123)], ['decode-boolean', () => punycode.decode(true)], ['toASCII-number', () => punycode.toASCII(123)], ['ucs2-encode-string', () => punycode.ucs2.encode('AB')]].map(([label, action]) => label + ':' + describe(action)).join('|'); if (punycode.toASCII('mañana.com') !== 'xn--maana-pta.com' || punycode.toASCII('mañana。com') !== 'xn--maana-pta.com' || punycode.toASCII('mañana.com') !== 'xn--maana-pta.com' || punycode.toASCII('mañana。com') !== 'xn--maana-pta.com' || punycode.toUnicode('xn--maana-pta。com') !== 'mañana.com' || Object.keys(punycode).join(',') !== 'version,ucs2,decode,encode,toASCII,toUnicode' || Object.hasOwn(punycode, 'default') || punycode.version !== '2.1.0' || ['decode','encode','toASCII','toUnicode'].map((name) => `${name}:${punycode[name].name}:${punycode[name].length}:${Object.hasOwn(punycode[name], 'prototype')}`).join('|') !== 'decode:decode:1:true|encode:encode:1:true|toASCII:toASCII:1:true|toUnicode:toUnicode:1:true' || ['decode','encode'].map((name) => `${name}:${punycode.ucs2[name].name}:${punycode.ucs2[name].length}:${Object.hasOwn(punycode.ucs2[name], 'prototype')}`).join('|') !== 'decode:ucs2decode:1:true|encode:ucs2encode:1:true' || validationRows !== \"toASCII-null:TypeError:Cannot read properties of null (reading 'split')|toASCII-undefined:TypeError:Cannot read properties of undefined (reading 'split')|toUnicode-null:TypeError:Cannot read properties of null (reading 'split')|encode-null:TypeError:Cannot read properties of null (reading 'length')|decode-null:TypeError:Cannot read properties of null (reading 'lastIndexOf')|ucs2-decode-null:TypeError:Cannot read properties of null (reading 'length')|ucs2-encode-null:TypeError:codePoints is not iterable (cannot read property null)\" || coercionRows !== \"encode-number:ok:\\\"\\\"|ucs2-decode-number:ok:[]|decode-boolean:TypeError:input.lastIndexOf is not a function|toASCII-number:TypeError:domain.split is not a function|ucs2-encode-string:RangeError:Invalid code point NaN\") throw new Error('punycode failed')" }, { "specifier": "node:querystring", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Native-shaped export order, parse/stringify defaults including null separators, maxKeys, custom codec hooks, prototype-safe parse objects, and invalid escape handling are covered.", "probe": "const qs = require('node:querystring'); const decoded = qs.unescapeBuffer('a+b%20c', true); const parsed = qs.parse('__proto__=x&a=1&a=2'); const limited = qs.parse('a=1&b=2&c=3', undefined, undefined, { maxKeys: 2 }); const customDecoded = qs.parse('a=x+y', undefined, undefined, { decodeURIComponent: value => 'D(' + value + ')' }); if (Object.keys(qs).join(',') !== 'unescapeBuffer,unescape,escape,stringify,encode,parse,decode' || qs.stringify({ a: 'b c' }) !== 'a=b%20c' || qs.stringify({ a: 'b', c: 'd' }, null, null) !== 'a=b&c=d' || JSON.stringify(qs.parse('a=b&c=d', null, null)) !== '{\"a\":\"b\",\"c\":\"d\"}' || qs.stringify('ab') !== '' || qs.stringify(123) !== '' || qs.stringify(true) !== '' || qs.stringify(['a','b']) !== '0=a&1=b' || qs.stringify({ 0: 'a', 1: 'b' }) !== '0=a&1=b' || qs.stringify({ a: {}, c: [1, {}], d: null, e: undefined }) !== 'a=&c=1&c=&d=&e=' || qs.stringify({ a: 'x y' }, undefined, undefined, { encodeURIComponent: value => 'E(' + value + ')' }) !== 'E(a)=E(x y)' || !Buffer.isBuffer(decoded) || decoded.toString() !== 'a b c' || qs.parse.length !== 4 || qs.stringify.length !== 4 || qs.unescape.length !== 2 || qs.unescapeBuffer.length !== 2 || qs.escape.name !== 'qsEscape' || Object.getPrototypeOf(parsed) !== null || parsed.__proto__ !== 'x' || !Array.isArray(parsed.a) || Object.keys(limited).join(',') !== 'a,b' || Object.keys(qs.parse(Array.from({ length: 1002 }, (_, index) => 'k' + index + '=v').join('&'))).length !== 1000 || customDecoded['D(a)'] !== 'D(x%20y)' || qs.parse('a=%FF+b').a !== '� b') throw new Error('querystring failed')" }, { "specifier": "node:readline", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/tty-readline.test.mjs", "limitation": "TTY-backed readline works in virtual PTY flows, including Node-shaped CommonJS export order and metadata, legacy positional createInterface streams, native-shaped createInterface validation, callback questions, async iteration, keypress events, terminal history recording/navigation with Node-shaped history accessors, prompt-aware getCursorPos cursor wrapping, native-shaped legacy _getCursorPos alias metadata, native-shaped callback Interface parent prototype metadata including public symbol descriptors and legacy private accessor/method probes, and common ANSI cursor and clear helpers, top-level ANSI helper callback validation, output.isTTY terminal defaulting, fallback cursorTo no-op/NaN validation; deeper terminal edge cases are still expanding.", "probe": "const readline = require(\"node:readline\"); const { EventEmitter } = require(\"node:events\"); const input = new EventEmitter(); let output = \"\"; const sink = { write(value) { output += String(value); return true; } }; const completer = (line) => [[line], line]; const rl = readline.createInterface(input, sink, completer, true); const callbackParent = Object.getPrototypeOf(readline.Interface.prototype); const callbackGrandparent = Object.getPrototypeOf(callbackParent); const descriptor = Object.getOwnPropertyDescriptor(callbackParent, \"getCursorPos\"); const legacyDescriptor = Object.getOwnPropertyDescriptor(readline.Interface.prototype, \"_getCursorPos\"); const legacyAccessorNames = [\"_decoder\",\"_line_buffer\",\"_oldPrompt\",\"_previousKey\",\"_prompt\",\"_questionCallback\",\"_sawKeyPress\",\"_sawReturnAt\"]; const legacyMethodNames = [\"question\",\"_setRawMode\",\"_onLine\",\"_writeToOutput\",\"_addHistory\",\"_refreshLine\",\"_normalWrite\",\"_insertString\",\"_tabComplete\",\"_wordLeft\",\"_wordRight\",\"_deleteLeft\",\"_deleteRight\",\"_deleteWordLeft\",\"_deleteWordRight\",\"_deleteLineLeft\",\"_deleteLineRight\",\"_line\",\"_historyNext\",\"_historyPrev\",\"_getDisplayPos\",\"_getCursorPos\",\"_moveCursor\",\"_ttyWrite\"]; const legacyOwnNames = Object.getOwnPropertyNames(readline.Interface.prototype).join(\",\"); const legacyKeys = Object.keys(readline.Interface.prototype).join(\",\"); const callbackParentNames = Object.getOwnPropertyNames(callbackParent).join(\",\"); const callbackParentKeys = Object.keys(callbackParent).join(\",\"); const callbackGrandparentNames = Object.getOwnPropertyNames(callbackGrandparent).join(\",\"); const callbackGrandparentCtor = callbackGrandparent.constructor.name + \":\" + Object.getPrototypeOf(callbackGrandparent).constructor.name; const callbackParentSymbolMeta = [Symbol.asyncIterator, Symbol.dispose].map((symbol) => { const descriptor = Object.getOwnPropertyDescriptor(callbackParent, symbol); if (!descriptor) return String(symbol) + ':missing'; return [String(symbol), typeof descriptor.value, descriptor.value.name, descriptor.value.length, descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.hasOwn(descriptor.value, 'prototype')].join(':') }).join('|'); const callbackParentMeta = [\"constructor\", \"columns\", \"setPrompt\", \"getPrompt\", \"setupHistoryManager\", \"prompt\", \"close\", \"pause\", \"resume\", \"write\", \"clearLine\", \"getCursorPos\"].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(callbackParent, name); if (!descriptor) return name + \":missing\"; const detail = \"value\" in descriptor ? descriptor.value.name + \"/\" + descriptor.value.length + \"/\" + descriptor.writable + \"/\" + Object.hasOwn(descriptor.value, \"prototype\") : descriptor.get.name + \"/\" + descriptor.get.length + \"/\" + typeof descriptor.set + \"/\" + Object.hasOwn(descriptor.get, \"prototype\"); return [name, descriptor.enumerable, descriptor.configurable, detail].join(\":\") }).join(\"|\"); const legacyAccessorMeta = legacyAccessorNames.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(readline.Interface.prototype, name); return [name, descriptor.get.name, descriptor.set.name, descriptor.enumerable, descriptor.configurable, Object.hasOwn(descriptor.get, \"prototype\"), Object.hasOwn(descriptor.set, \"prototype\")].join(\":\") }).join(\"|\"); const legacyMethodMeta = legacyMethodNames.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(readline.Interface.prototype, name); return [name, descriptor.value.name, descriptor.value.length, descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.hasOwn(descriptor.value, \"prototype\")].join(\":\") }).join(\"|\"); const legacyRl = readline.createInterface({ input: new EventEmitter(), output: { write() { return true; } } }); legacyRl._line_buffer = \"alpha beta\"; legacyRl.cursor = legacyRl.line.length; legacyRl._wordLeft(); const legacyLeft = legacyRl.cursor; legacyRl._deleteWordRight(); const legacyEdit = [legacyLeft, JSON.stringify(legacyRl.line), legacyRl.cursor, JSON.stringify(legacyRl._getDisplayPos(\"abcdef\"))].join(\":\"); legacyRl.close(); const invalidRows = [[\"missing\", () => readline.createInterface()], [\"null\", () => readline.createInterface(null)], [\"string\", () => readline.createInterface(\"x\")], [\"empty-object\", () => readline.createInterface({})], [\"output-only\", () => readline.createInterface({ output: { write() { return true; } } })]].map(([label, action]) => { try { action(); return label + \":return\" } catch (error) { return label + \":\" + error.constructor.name + \":\" + (error.code ?? \"\") + \":\" + error.message } }).join(\"|\"); const cursorOutput = { columns: 5, write() { return true; } }; const cursorRl = readline.createInterface({ input: new EventEmitter(), output: cursorOutput, prompt: \"p> \", terminal: true }); cursorRl.write(\"abcdef\"); const historyInput = new EventEmitter(); const historyRl = readline.createInterface({ input: historyInput, output: cursorOutput, terminal: true, historySize: 10, removeHistoryDuplicates: false }); const historyDescriptor = Object.getOwnPropertyDescriptor(historyRl, \"history\"); const historyIndexDescriptor = Object.getOwnPropertyDescriptor(historyRl, \"historyIndex\"); historyInput.emit(\"data\", \"one\\n\"); historyInput.emit(\"data\", \"two\\n\"); const historyRows = [JSON.stringify(historyRl.history), historyRl.historyIndex, historyDescriptor.enumerable, historyDescriptor.configurable, typeof historyDescriptor.get, typeof historyDescriptor.set, historyIndexDescriptor.enumerable, typeof historyIndexDescriptor.get].join(\":\"); historyRl._historyPrev(); const historyPrev = [JSON.stringify(historyRl.line), historyRl.cursor, historyRl.historyIndex].join(\":\"); historyRl._historyPrev(); historyRl._historyPrev(); const historyOldest = [JSON.stringify(historyRl.line), historyRl.cursor, historyRl.historyIndex].join(\":\"); historyRl._historyNext(); historyRl._historyNext(); historyRl._historyNext(); const historyNext = [JSON.stringify(historyRl.line), historyRl.cursor, historyRl.historyIndex].join(\":\"); historyRl.close(); const duplicateRl = readline.createInterface({ input: new EventEmitter(), output: cursorOutput, terminal: true, historySize: 2 }); for (const value of [\"one\", \"two\", \"two\", \"three\"]) { duplicateRl.line = value; duplicateRl.cursor = value.length; duplicateRl._addHistory(); } const duplicateHistory = JSON.stringify(duplicateRl.history); duplicateRl.close(); const legacyLineRl = readline.createInterface({ input: new EventEmitter(), output: cursorOutput, terminal: false }); legacyLineRl.line = \"manual\"; legacyLineRl.cursor = legacyLineRl.line.length; legacyLineRl._line(); const legacyLineHistory = [JSON.stringify(legacyLineRl.history), JSON.stringify(legacyLineRl.line), legacyLineRl.cursor, legacyLineRl.historyIndex].join(\":\"); legacyLineRl.close(); const draftRl = readline.createInterface({ input: new EventEmitter(), output: cursorOutput, terminal: true }); for (const value of [\"one\", \"two\", \"three\"]) { draftRl.line = value; draftRl.cursor = value.length; draftRl._addHistory(); } draftRl.line = \"draft\"; draftRl.cursor = draftRl.line.length; draftRl._historyPrev(); const draftPrev = [JSON.stringify(draftRl.line), draftRl.cursor, draftRl.historyIndex].join(\":\"); draftRl._historyNext(); const draftNext = [JSON.stringify(draftRl.line), draftRl.cursor, draftRl.historyIndex].join(\":\"); draftRl.close(); let answer; rl.question(\"Q? \", (value) => { answer = value; }); input.emit(\"data\", \"Alice\\n\"); if (Object.keys(readline).join(\",\") !== \"Interface,clearLine,clearScreenDown,createInterface,cursorTo,emitKeypressEvents,moveCursor,promises\" || Object.hasOwn(readline, \"default\") || readline.Interface.length !== 4 || readline.createInterface.name !== \"createInterface\" || readline.createInterface.length !== 4 || readline.clearLine.length !== 3 || readline.cursorTo.length !== 4 || readline.moveCursor.length !== 4 || legacyOwnNames !== \"constructor,question,_decoder,_line_buffer,_oldPrompt,_previousKey,_prompt,_questionCallback,_sawKeyPress,_sawReturnAt,_setRawMode,_onLine,_writeToOutput,_addHistory,_refreshLine,_normalWrite,_insertString,_tabComplete,_wordLeft,_wordRight,_deleteLeft,_deleteRight,_deleteWordLeft,_deleteWordRight,_deleteLineLeft,_deleteLineRight,_line,_historyNext,_historyPrev,_getDisplayPos,_getCursorPos,_moveCursor,_ttyWrite\" || legacyKeys !== \"question,_setRawMode,_onLine,_writeToOutput,_addHistory,_refreshLine,_normalWrite,_insertString,_tabComplete,_wordLeft,_wordRight,_deleteLeft,_deleteRight,_deleteWordLeft,_deleteWordRight,_deleteLineLeft,_deleteLineRight,_line,_historyNext,_historyPrev,_getDisplayPos,_getCursorPos,_moveCursor,_ttyWrite\" || callbackParentNames !== \"constructor,columns,setPrompt,getPrompt,setupHistoryManager,prompt,close,pause,resume,write,clearLine,getCursorPos\" || callbackParentKeys !== \"\" || callbackParentSymbolMeta !== \"Symbol(Symbol.asyncIterator):function:[Symbol.asyncIterator]:0:false:true:true:false|Symbol(Symbol.dispose):function:[Symbol.dispose]:0:true:true:true:true\" || callbackGrandparentNames !== \"constructor\" || callbackGrandparentCtor !== \"InterfaceConstructor:EventEmitter\" || callbackParentMeta !== \"constructor:false:true:Interface/0/true/true|columns:false:true:get columns/0/undefined/false|setPrompt:false:true:setPrompt/1/true/false|getPrompt:false:true:getPrompt/0/true/false|setupHistoryManager:false:true:setupHistoryManager/1/true/false|prompt:false:true:prompt/1/true/false|close:false:true:close/0/true/false|pause:false:true:pause/0/true/false|resume:false:true:resume/0/true/false|write:false:true:write/2/true/false|clearLine:false:true:clearLine/0/true/false|getCursorPos:false:true:getCursorPos/0/true/false\" || legacyAccessorMeta !== \"_decoder:get:set:false:false:false:false|_line_buffer:get:set:false:false:false:false|_oldPrompt:get:set:false:false:false:false|_previousKey:get:set:false:false:false:false|_prompt:get:set:false:false:false:false|_questionCallback:get:set:false:false:false:false|_sawKeyPress:get:set:false:false:false:false|_sawReturnAt:get:set:false:false:false:false\" || legacyMethodMeta !== \"question:question:3:true:true:true:true|_setRawMode:[_setRawMode]:1:true:true:true:false|_onLine:[_onLine]:1:true:true:true:false|_writeToOutput:[_writeToOutput]:1:true:true:true:false|_addHistory:[_addHistory]:0:true:true:true:false|_refreshLine:[_refreshLine]:0:true:true:true:false|_normalWrite:[_normalWrite]:1:true:true:true:false|_insertString:[_insertString]:1:true:true:true:false|_tabComplete::1:true:true:true:true|_wordLeft:[_wordLeft]:0:true:true:true:false|_wordRight:[_wordRight]:0:true:true:true:false|_deleteLeft:[_deleteLeft]:0:true:true:true:false|_deleteRight:[_deleteRight]:0:true:true:true:false|_deleteWordLeft:[_deleteWordLeft]:0:true:true:true:false|_deleteWordRight:[_deleteWordRight]:0:true:true:true:false|_deleteLineLeft:[_deleteLineLeft]:0:true:true:true:false|_deleteLineRight:[_deleteLineRight]:0:true:true:true:false|_line:[_line]:0:true:true:true:false|_historyNext:[_historyNext]:0:true:true:true:false|_historyPrev:[_historyPrev]:0:true:true:true:false|_getDisplayPos:[_getDisplayPos]:1:true:true:true:false|_getCursorPos:getCursorPos:0:true:true:true:false|_moveCursor:[_moveCursor]:1:true:true:true:false|_ttyWrite:[_ttyWrite]:2:true:true:true:false\" || legacyEdit !== '6:\"alpha \":6:{\"cols\":6,\"rows\":0}' || !descriptor || descriptor.enumerable || !descriptor.configurable || !descriptor.writable || descriptor.value.name !== \"getCursorPos\" || descriptor.value.length !== 0 || !legacyDescriptor || !legacyDescriptor.enumerable || !legacyDescriptor.configurable || !legacyDescriptor.writable || legacyDescriptor.value.name !== \"getCursorPos\" || legacyDescriptor.value.length !== 0 || invalidRows !== \"missing:TypeError::Cannot read properties of undefined (reading 'history')|null:TypeError::Cannot read properties of null (reading 'history')|string:TypeError::input.on is not a function|empty-object:TypeError::input.on is not a function|output-only:TypeError::input.on is not a function\" || duplicateHistory !== \"[\\\"three\\\",\\\"two\\\"]\" || legacyLineHistory !== \"[\\\"manual\\\"]:\\\"\\\":0:-1\" || draftPrev !== \"\\\"three\\\":5:0\" || draftNext !== \"\\\"\\\":0:-1\" || historyRows !== '[\"two\",\"one\"]:-1:true:true:function:function:true:function' || historyPrev !== '\"two\":3:0' || historyOldest !== '\"\":0:2' || historyNext !== '\"\":0:-1' || JSON.stringify(cursorRl._getCursorPos()) !== '{\"cols\":4,\"rows\":1}' || cursorRl.line !== \"abcdef\" || cursorRl.cursor !== 6 || rl.input !== input || rl.output !== sink || rl.completer !== completer || rl.terminal !== true || output !== \"Q? \" || answer !== \"Alice\") throw new Error(\"readline failed\"); cursorRl.close(); rl.close();; const invalidReadlineCallbackSink = { write() { return true; } }; const invalidReadlineCallbackRows = [['clearLine', () => readline.clearLine(invalidReadlineCallbackSink, 0, 'x')], ['clearScreenDown', () => readline.clearScreenDown(invalidReadlineCallbackSink, 'x')], ['cursorToY', () => readline.cursorTo(invalidReadlineCallbackSink, 1, 2, 'x')], ['moveCursor', () => readline.moveCursor(invalidReadlineCallbackSink, 1, 1, 'x')], ['moveCursorNoop', () => readline.moveCursor(invalidReadlineCallbackSink, 0, 0, 'x')]].map(([label, action]) => { try { action(); return label + ':ok'; } catch (error) { return [label, error.name, error.code, String(error)].join(':'); } }).join('|'); if (invalidReadlineCallbackRows !== 'clearLine:TypeError:ERR_INVALID_ARG_TYPE:TypeError [ERR_INVALID_ARG_TYPE]: The \"callback\" argument must be of type function. Received type string (\\'x\\')|clearScreenDown:TypeError:ERR_INVALID_ARG_TYPE:TypeError [ERR_INVALID_ARG_TYPE]: The \"callback\" argument must be of type function. Received type string (\\'x\\')|cursorToY:TypeError:ERR_INVALID_ARG_TYPE:TypeError [ERR_INVALID_ARG_TYPE]: The \"callback\" argument must be of type function. Received type string (\\'x\\')|moveCursor:TypeError:ERR_INVALID_ARG_TYPE:TypeError [ERR_INVALID_ARG_TYPE]: The \"callback\" argument must be of type function. Received type string (\\'x\\')|moveCursorNoop:TypeError:ERR_INVALID_ARG_TYPE:TypeError [ERR_INVALID_ARG_TYPE]: The \"callback\" argument must be of type function. Received type string (\\'x\\')') throw new Error('readline callback validation failed'); const { PassThrough: ocReadlinePassThrough, Writable: ocReadlineWritable } = require('node:stream'); const makeOcReadlineOutput = (isTTY) => { const output = new ocReadlineWritable({ write(_chunk, _encoding, callback) { callback(); } }); output.isTTY = isTTY; return output; }; const terminalDefaultRows = [['tty-default', { output: makeOcReadlineOutput(true) }], ['notty-default', { output: makeOcReadlineOutput(false) }], ['tty-false', { output: makeOcReadlineOutput(true), terminal: false }], ['tty-true', { output: makeOcReadlineOutput(false), terminal: true }], ['tty-null', { output: makeOcReadlineOutput(true), terminal: null }]].map(([label, options]) => { const instance = readline.createInterface({ input: new ocReadlinePassThrough(), ...options }); const row = label + ':' + instance.terminal; instance.close(); return row; }).join('|'); const cursorFallbackSink = () => { const chunks = []; return { chunks, write(value, callback) { chunks.push(String(value)); callback?.(); return true; } }; }; const cursorFallbackRows = [['missing', (output) => readline.cursorTo(output)], ['string', (output) => readline.cursorTo(output, '2')], ['nan', (output) => readline.cursorTo(output, NaN)], ['number', (output) => readline.cursorTo(output, 2)], ['numberY', (output) => readline.cursorTo(output, 2, 3)]].map(([label, action]) => { const output = cursorFallbackSink(); try { return [label, 'ok', action(output), JSON.stringify(output.chunks.join(''))].join(':'); } catch (error) { return [label, error.name, error.code, error.message, JSON.stringify(output.chunks.join(''))].join(':'); } }).join('|'); if (terminalDefaultRows !== 'tty-default:true|notty-default:false|tty-false:false|tty-true:true|tty-null:false' || cursorFallbackRows !== 'missing:ok:true:\"\"|string:ok:true:\"\"|nan:TypeError:ERR_INVALID_ARG_VALUE:The argument \\'x\\' is invalid. Received NaN:\"\"|number:ok:true:\"\\\\u001b[3G\"|numberY:ok:true:\"\\\\u001b[4;3H\"') throw new Error('readline terminal/cursor fallback failed')" }, { "specifier": "node:readline/promises", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/tty-readline.test.mjs", "limitation": "Promise question support is present for virtual stdin/stdout with Node-shaped promise module exports, legacy positional createInterface streams, output.isTTY terminal defaulting, createInterface metadata, inherited prompt-aware getCursorPos cursor wrapping, native-shaped Readline prototype order/arities, native-shaped promise Interface parent prototype metadata including public symbol descriptors, native-shaped createInterface validation for missing/malformed input, Node-shaped Readline constructor, options.autoCommit, and cursor argument validation including bracketed String(error) codes, and native-order moveCursor escape output.", "probe": "const readline = require(\"node:readline/promises\"); const { EventEmitter } = require(\"node:events\"); const { Writable } = require(\"node:stream\"); const input = new EventEmitter(); let output = \"\"; const sink = { write(value) { output += String(value); return true; } }; const completer = (line) => [[line], line]; const rl = readline.createInterface(input, sink, completer, true); const answerPromise = rl.question(\"P? \"); input.emit(\"data\", \"Bob\\n\"); const answer = await answerPromise; rl.write(\"abcd\"); const parent = Object.getPrototypeOf(readline.Interface.prototype); const parentSymbolMeta = [Symbol.asyncIterator, Symbol.dispose].map((symbol) => { const descriptor = Object.getOwnPropertyDescriptor(parent, symbol); if (!descriptor) return String(symbol) + ':missing'; return [String(symbol), typeof descriptor.value, descriptor.value.name, descriptor.value.length, descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.hasOwn(descriptor.value, 'prototype')].join(':') }).join('|'); const parentDescriptors = [\"constructor\",\"columns\",\"setPrompt\",\"getPrompt\",\"setupHistoryManager\",\"prompt\",\"close\",\"pause\",\"resume\",\"write\",\"clearLine\",\"getCursorPos\"].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(parent, name); if (!descriptor) return name + \":missing\"; const detail = \"value\" in descriptor ? descriptor.value.name + \"/\" + descriptor.value.length + \"/\" + descriptor.writable : descriptor.get.name + \"/\" + descriptor.get.length + \"/\" + typeof descriptor.set; return [name, descriptor.enumerable, descriptor.configurable, detail].join(\":\") }).join(\"|\"); const invalidRows = [[\"missing\", () => readline.createInterface()], [\"null\", () => readline.createInterface(null)], [\"string\", () => readline.createInterface(\"x\")], [\"empty-object\", () => readline.createInterface({})]].map(([label, action]) => { try { action(); return label + \":return\" } catch (error) { return label + \":\" + error.constructor.name + \":\" + (error.code ?? \"\") + \":\" + error.message } }).join(\"|\"); const validationStream = new Writable({ write(_chunk, _encoding, callback) { callback() } }); const validationReadline = new readline.Readline(validationStream); const validationRows = [[\"ctor-missing\", () => new readline.Readline()], [\"ctor-object\", () => new readline.Readline({})], [\"ctor-autoCommit-string\", () => new readline.Readline(validationStream, { autoCommit: \"x\" })], [\"cursorTo-string\", () => validationReadline.cursorTo(\"2\")], [\"clearLine-float\", () => validationReadline.clearLine(1.5)]].map(([label, action]) => { try { action(); return label + \":return\" } catch (error) { return label + \":\" + error.name + \":\" + error.code + \":\" + error.message + \":\" + String(error) } }).join(\"|\"); if (Object.keys(readline).join(\",\") !== \"Interface,Readline,createInterface\" || Object.hasOwn(readline, \"default\") || readline.Interface.name !== \"Interface\" || readline.Interface.length !== 0 || readline.Readline.name !== \"Readline\" || readline.Readline.length !== 1 || readline.createInterface.name !== \"createInterface\" || readline.createInterface.length !== 4 || Object.getOwnPropertyNames(readline.Readline.prototype).join(\",\") !== \"constructor,cursorTo,moveCursor,clearLine,clearScreenDown,commit,rollback\" || Object.keys(readline.Readline.prototype).join(\",\") !== \"\" || Object.getOwnPropertyNames(parent).join(\",\") !== \"constructor,columns,setPrompt,getPrompt,setupHistoryManager,prompt,close,pause,resume,write,clearLine,getCursorPos\" || Object.keys(parent).join(\",\") !== \"\" || parentSymbolMeta !== \"Symbol(Symbol.asyncIterator):function:[Symbol.asyncIterator]:0:false:true:true:false|Symbol(Symbol.dispose):function:[Symbol.dispose]:0:true:true:true:true\" || parentDescriptors !== \"constructor:false:true:Interface/0/true|columns:false:true:get columns/0/undefined|setPrompt:false:true:setPrompt/1/true|getPrompt:false:true:getPrompt/0/true|setupHistoryManager:false:true:setupHistoryManager/1/true|prompt:false:true:prompt/1/true|close:false:true:close/0/true|pause:false:true:pause/0/true|resume:false:true:resume/0/true|write:false:true:write/2/true|clearLine:false:true:clearLine/0/true|getCursorPos:false:true:getCursorPos/0/true\" || invalidRows !== \"missing:TypeError::Cannot read properties of undefined (reading 'history')|null:TypeError::Cannot read properties of null (reading 'history')|string:TypeError::input.on is not a function|empty-object:TypeError::input.on is not a function\" || validationRows !== \"ctor-missing:TypeError:ERR_INVALID_ARG_TYPE:The \\\"stream\\\" argument must be an instance of Writable. Received undefined:TypeError [ERR_INVALID_ARG_TYPE]: The \\\"stream\\\" argument must be an instance of Writable. Received undefined|ctor-object:TypeError:ERR_INVALID_ARG_TYPE:The \\\"stream\\\" argument must be an instance of Writable. Received an instance of Object:TypeError [ERR_INVALID_ARG_TYPE]: The \\\"stream\\\" argument must be an instance of Writable. Received an instance of Object|ctor-autoCommit-string:TypeError:ERR_INVALID_ARG_TYPE:The \\\"options.autoCommit\\\" property must be of type boolean. Received type string ('x'):TypeError [ERR_INVALID_ARG_TYPE]: The \\\"options.autoCommit\\\" property must be of type boolean. Received type string ('x')|cursorTo-string:TypeError:ERR_INVALID_ARG_TYPE:The \\\"x\\\" argument must be of type number. Received type string ('2'):TypeError [ERR_INVALID_ARG_TYPE]: The \\\"x\\\" argument must be of type number. Received type string ('2')|clearLine-float:RangeError:ERR_OUT_OF_RANGE:The value of \\\"dir\\\" is out of range. It must be an integer. Received 1.5:RangeError [ERR_OUT_OF_RANGE]: The value of \\\"dir\\\" is out of range. It must be an integer. Received 1.5\" || readline.Readline.prototype.clearLine.length !== 1 || readline.Readline.prototype.cursorTo.length !== 1 || readline.Readline.prototype.moveCursor.length !== 2 || typeof rl.getCursorPos !== \"function\" || JSON.stringify(rl.getCursorPos()) !== '{\"cols\":6,\"rows\":0}' || rl.line !== \"abcd\" || rl.cursor !== 4 || rl.input !== input || rl.output !== sink || rl.completer !== completer || rl.terminal !== true || output !== \"P? \" || answer !== \"Bob\") throw new Error(\"readline/promises failed\"); rl.close();; const makeOcPromiseOutput = (isTTY) => { const output = new Writable({ write(_chunk, _encoding, callback) { callback(); } }); output.isTTY = isTTY; return output; }; const promiseTerminalRows = [['tty-default', { output: makeOcPromiseOutput(true) }], ['notty-default', { output: makeOcPromiseOutput(false) }], ['tty-false', { output: makeOcPromiseOutput(true), terminal: false }], ['tty-true', { output: makeOcPromiseOutput(false), terminal: true }], ['tty-null', { output: makeOcPromiseOutput(true), terminal: null }]].map(([label, options]) => { const instance = readline.createInterface({ input: new EventEmitter(), ...options }); const row = label + ':' + instance.terminal; instance.close(); return row; }).join('|'); if (promiseTerminalRows !== 'tty-default:true|notty-default:false|tty-false:false|tty-true:true|tty-null:false') throw new Error('readline/promises terminal default failed')" }, { "specifier": "node:stream", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Core stream classes, OpenContainers package-facing CommonJS export order, Node-shaped constructor and duplexPair arities, native-shaped root Stream prototype descriptor and PassThrough _transform metadata, native-shaped promises accessor identity, stream-to-stream, iterable-source, and function-stage pipeline, compose, Web conversion helpers including Readable.fromWeb destroy/iterator cancellation and Writable.fromWeb close/abort propagation, Node-shaped Readable/Writable/Duplex legacy helper metadata including native-shaped Writable/Duplex prototype order, enumerable keys, helper own-prototype metadata, Writable capture-rejection metadata, inherited async-disposal ownership, and own Readable listener-removal aliases, _undestroy reset helpers, default _destroy callbacks, Writable _writev = null, Writable default pipe/_write probes, Duplex writable defaults, Transform default hook probes, and Readable pause/unshift/pipe/prototype wrap/static wrap probes, Readable.pipe backpressure pause/resume and end:false option, pull-driven custom Readable sources, Readable.from string/Buffer single-chunk and typed-array iterable validation/default-state parity, setEncoding split-byte decoding, native-shaped Readable iterator/compose helper metadata, Transform/PassThrough readable-side async iteration, constructor transform options, native-like static/prototype ancestry, Writable instanceof recognition, and basic state metadata, native-shaped Readable static internals, static helper, fresh Web ReadableStream/WritableStream/TransformStream state-helper probes, and Web bridge metadata, synchronous invalid Web bridge input validation, and inherited isDisturbed helper metadata, Readable iterator helpers including early-termination lifecycle, Writable backpressure/cork buffering probes, addAbortSignal abort behavior and native-shaped argument validation, Node-shaped disturbed/destroyed/state probes for stream and non-stream values, async disposal, default high-water-mark helpers, public helper names and _isArrayBufferView nonconstructable metadata, native-shaped Readable/Writable/Duplex state accessors without own instance state fields, corked writableBuffer visibility, and common lifecycle state exist; deeper stream fixture coverage is still expanding.", "probe": "const stream = require('node:stream'); const streamPromises = require('node:stream/promises'); const keys = 'isDestroyed,isDisturbed,isErrored,isReadable,isWritable,Readable,Writable,Duplex,Transform,PassThrough,duplexPair,pipeline,addAbortSignal,finished,destroy,compose,setDefaultHighWaterMark,getDefaultHighWaterMark,promises,Stream,_isArrayBufferView,_isUint8Array,_uint8ArrayToBuffer'; const promisesDescriptor = Object.getOwnPropertyDescriptor(stream, 'promises'); const prototypeDescriptor = Object.getOwnPropertyDescriptor(stream, 'prototype'); const constructorDescriptor = Object.getOwnPropertyDescriptor(stream.prototype, 'constructor'); const descriptorRow = (prototype, names) => names.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(prototype, name); return [name, descriptor ? 'accessor' : 'missing', descriptor?.get ? 'get' : '', descriptor?.set ? 'set' : '', descriptor?.enumerable, descriptor?.configurable, descriptor?.get?.name ?? '', descriptor?.set?.name ?? ''].join(':'); }).join('|'); const readableStateDescriptors = descriptorRow(stream.Readable.prototype, ['readable','readableDidRead','readableAborted','readableHighWaterMark','readableBuffer','readableFlowing','readableLength','readableObjectMode','readableEncoding','errored','closed','destroyed','readableEnded']); const writableStateDescriptors = descriptorRow(stream.Writable.prototype, ['closed','destroyed','writable','writableFinished','writableObjectMode','writableBuffer','writableEnded','writableNeedDrain','writableHighWaterMark','writableCorked','writableLength','errored','writableAborted']); const duplexWritableDescriptors = descriptorRow(stream.Duplex.prototype, ['writable','writableHighWaterMark','writableObjectMode','writableBuffer','writableLength','writableFinished','writableCorked','writableEnded','writableNeedDrain','destroyed']); const stateOwnRows = (() => { const readable = new stream.Readable({ read() {} }); const writable = new stream.Writable({ write() {} }); const duplex = new stream.Duplex({ read() {}, write() {} }); return ['readable','readableLength','destroyed','closed','writable','writableLength'].map((name) => [name, Object.hasOwn(readable, name), Object.hasOwn(writable, name), Object.hasOwn(duplex, name)].join(':')).join('|'); })(); const writableBufferRow = (() => { const writable = new stream.Writable({ write() {} }); writable.cork(); writable.write('x'); return [Array.isArray(writable.writableBuffer), writable.writableBuffer.length, writable.writableLength, writable.writableBuffer[0]?.chunk].join(':'); })(); const writableStaticNames = Object.getOwnPropertyNames(stream.Writable).join(','); const duplexStaticNames = Object.getOwnPropertyNames(stream.Duplex).join(','); const writableStateDescriptor = Object.getOwnPropertyDescriptor(stream.Writable, 'WritableState'); const writableStateStaticRow = [writableStateDescriptor.value.name, writableStateDescriptor.value.length, writableStateDescriptor.enumerable, writableStateDescriptor.configurable, writableStateDescriptor.writable, Object.hasOwn(writableStateDescriptor.value, 'prototype')].join(':'); const writableStatePrototypeNames = Object.getOwnPropertyNames(stream.Writable.WritableState.prototype).join(','); const writableStatePrototypeKeys = Object.keys(stream.Writable.WritableState.prototype).join(','); const writableState = new stream.Writable.WritableState({ objectMode: true, highWaterMark: 4, decodeStrings: false, defaultEncoding: 'latin1' }, null, false); const writableStateInstanceRow = [Object.keys(writableState).join(','), writableState.objectMode, writableState.highWaterMark, writableState.decodeStrings, writableState.defaultEncoding, writableState.getBuffer().length, writableState.bufferedRequestCount].join(':'); if (readableStateDescriptors !== 'readable:accessor:get:set:false:false:get:set|readableDidRead:accessor:get::false:false:get:|readableAborted:accessor:get::false:false:get:|readableHighWaterMark:accessor:get::false:false:get:|readableBuffer:accessor:get::false:false:get:|readableFlowing:accessor:get:set:false:false:get:set|readableLength:accessor:get::false:false:get:|readableObjectMode:accessor:get::false:false:get:|readableEncoding:accessor:get::false:false:get:|errored:accessor:get::false:false:get:|closed:accessor:get::false:false:get:|destroyed:accessor:get:set:false:false:get:set|readableEnded:accessor:get::false:false:get:' || writableStateDescriptors !== 'closed:accessor:get::false:false:get:|destroyed:accessor:get:set:false:false:get:set|writable:accessor:get:set:false:false:get:set|writableFinished:accessor:get::false:false:get:|writableObjectMode:accessor:get::false:false:get:|writableBuffer:accessor:get::false:false:get:|writableEnded:accessor:get::false:false:get:|writableNeedDrain:accessor:get::false:false:get:|writableHighWaterMark:accessor:get::false:false:get:|writableCorked:accessor:get::false:false:get:|writableLength:accessor:get::false:false:get:|errored:accessor:get::false:false:get:|writableAborted:accessor:get::false:false:get:' || duplexWritableDescriptors !== 'writable:accessor:get:set:false:false:get:set|writableHighWaterMark:accessor:get::false:false:get:|writableObjectMode:accessor:get::false:false:get:|writableBuffer:accessor:get::false:false:get:|writableLength:accessor:get::false:false:get:|writableFinished:accessor:get::false:false:get:|writableCorked:accessor:get::false:false:get:|writableEnded:accessor:get::false:false:get:|writableNeedDrain:accessor:get::false:false:get:|destroyed:accessor:get:set:false:false:get:set' || stateOwnRows !== 'readable:false:false:false|readableLength:false:false:false|destroyed:false:false:false|closed:false:false:false|writable:false:false:false|writableLength:false:false:false' || writableBufferRow !== 'true:1:1:x' || writableStaticNames !== 'length,name,prototype,WritableState,fromWeb,toWeb' || duplexStaticNames !== 'length,name,prototype,fromWeb,toWeb,from' || writableStateStaticRow !== 'WritableState:3:true:true:true:true' || writableStatePrototypeNames !== 'constructor,objectMode,finalCalled,needDrain,ending,ended,finished,destroyed,decodeStrings,writing,sync,bufferProcessing,constructed,prefinished,errorEmitted,emitClose,autoDestroy,closed,closeEmitted,allBuffers,allNoop,errored,writable,defaultEncoding,writecb,afterWriteTickInfo,buffered,bufferedRequestCount,getBuffer' || writableStatePrototypeKeys !== 'getBuffer' || writableStateInstanceRow !== 'highWaterMark,length,corked,onwrite,writelen,bufferedIndex,pendingcb:true:4:false:latin1:0:0' || Object.hasOwn(stream, 'default') || Object.keys(stream).join(',') !== keys || [stream, stream.Readable, stream.Writable, stream.Duplex, stream.Transform, stream.PassThrough].map((constructor) => constructor.length).join(',') !== '1,1,1,1,1,1' || stream.duplexPair.length !== 1 || stream.pipeline.length !== 0 || stream.compose.length !== 0 || stream.finished.name !== 'eos' || stream.destroy.name !== 'destroyer' || stream._isArrayBufferView.name !== 'isView' || stream._isArrayBufferView.length !== 1 || Object.hasOwn(stream._isArrayBufferView, 'prototype') || !Object.hasOwn(stream._isUint8Array, 'prototype') || !promisesDescriptor?.get || promisesDescriptor.set !== undefined || !promisesDescriptor.enumerable || !promisesDescriptor.configurable || stream.promises.pipeline !== streamPromises.pipeline || stream.promises.finished !== streamPromises.finished || prototypeDescriptor.enumerable || prototypeDescriptor.configurable || !prototypeDescriptor.writable || constructorDescriptor.enumerable || !constructorDescriptor.configurable || !constructorDescriptor.writable || stream.prototype.constructor !== stream) throw new Error('stream metadata failed'); const readableHelperNames = ['iterator','compose','map','filter','flatMap','drop','take','reduce','toArray','some','find','forEach','every']; const readableHelperMeta = readableHelperNames.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(stream.Readable.prototype, name); return [name, descriptor?.value?.name, descriptor?.value?.length, descriptor?.enumerable].join(':'); }).join('|'); if (readableHelperMeta !== 'iterator::1:true|compose:compose:2:true|map:map:2:false|filter:filter:2:false|flatMap:flatMap:2:false|drop:drop:1:false|take:take:1:false|reduce:reduce:3:false|toArray:toArray:1:false|some:some:1:false|find:find:2:false|forEach:forEach:2:false|every:every:1:false') throw new Error('stream readable helper metadata failed'); const readableLegacyNames = ['_read','_undestroy','_destroy','push','unshift','isPaused','setEncoding','read','pipe','unpipe','on','addListener','removeListener','off','removeAllListeners','pause','resume','wrap','destroy']; const readableLegacyMeta = readableLegacyNames.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(stream.Readable.prototype, name); return [name, descriptor?.value?.name, descriptor?.value?.length, descriptor?.enumerable, descriptor?.configurable, descriptor?.writable].join(':'); }).join('|'); if (readableLegacyMeta !== '_read::1:true:true:true|_undestroy:undestroy:0:true:true:true|_destroy::2:true:true:true|push::2:true:true:true|unshift::2:true:true:true|isPaused::0:true:true:true|setEncoding::1:true:true:true|read::1:true:true:true|pipe::2:true:true:true|unpipe::1:true:true:true|on:on:2:true:true:true|addListener:addListener:2:true:true:true|removeListener::2:true:true:true|off::2:true:true:true|removeAllListeners::1:true:true:true|pause::0:true:true:true|resume::0:true:true:true|wrap::1:true:true:true|destroy:destroy:2:true:true:true') throw new Error('stream readable legacy metadata failed'); const writableLegacyNames = ['pipe','write','end','destroy','_write','_undestroy','_destroy','cork','uncork','setDefaultEncoding']; const writableLegacyMeta = writableLegacyNames.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(stream.Writable.prototype, name); return [name, descriptor?.value?.name, descriptor?.value?.length, descriptor?.enumerable, descriptor?.configurable, descriptor?.writable].join(':'); }).join('|'); const functionPrototypeRow = (fn) => { const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); if (!descriptor) return 'no-prototype'; return [descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.getOwnPropertyNames(descriptor.value).join(',')].join('/'); }; const streamDescriptorRow = (prototype, name) => { const label = typeof name === 'symbol' ? String(name) : name; const descriptor = Object.getOwnPropertyDescriptor(prototype, name); if (!descriptor) { const inherited = prototype[name]; if (typeof inherited !== 'function') return [label, 'missing', typeof inherited].join(':'); return [label, 'missing', 'function', inherited.name, inherited.length, Object.hasOwn(inherited, 'prototype'), functionPrototypeRow(inherited)].join(':'); } const value = descriptor.value; if (typeof value !== 'function') return [label, 'data', descriptor.enumerable, descriptor.configurable, descriptor.writable, value === null ? 'null' : typeof value].join(':'); return [label, 'data', descriptor.enumerable, descriptor.configurable, descriptor.writable, 'function', value.name, value.length, Object.hasOwn(value, 'prototype'), functionPrototypeRow(value)].join(':'); }; const writablePrototypeOrderRows = [Object.getOwnPropertyNames(stream.Writable.prototype).join(','), Object.keys(stream.Writable.prototype).join(','), Object.getOwnPropertySymbols(stream.Writable.prototype).map(String).join(',')].join(' '); const writableDescriptorShape = ['pipe','write','cork','uncork','setDefaultEncoding','_write','_writev','end','destroy','_destroy','_undestroy'].map((name) => streamDescriptorRow(stream.Writable.prototype, name)).join('|'); const rejectionDescriptor = Object.getOwnPropertyDescriptor(stream.Writable.prototype, Symbol.for('nodejs.rejection')); const writableAsyncDescriptor = Object.getOwnPropertyDescriptor(stream.Writable.prototype, Symbol.asyncDispose); const writableSymbolDescriptors = [['rejection', rejectionDescriptor.enumerable, rejectionDescriptor.configurable, rejectionDescriptor.writable, rejectionDescriptor.value.name, rejectionDescriptor.value.length, Object.hasOwn(rejectionDescriptor.value, 'prototype'), functionPrototypeRow(rejectionDescriptor.value)].join(':'), ['async', writableAsyncDescriptor.enumerable, writableAsyncDescriptor.configurable, writableAsyncDescriptor.writable, writableAsyncDescriptor.value.name, writableAsyncDescriptor.value.length, Object.hasOwn(writableAsyncDescriptor.value, 'prototype'), functionPrototypeRow(writableAsyncDescriptor.value)].join(':')].join(' '); const writevDescriptor = Object.getOwnPropertyDescriptor(stream.Writable.prototype, '_writev'); const writableDefaultError = (() => { try { stream.Writable.prototype._write.call({ _writev: null }, 'x', 'buffer', () => {}); return 'ok'; } catch (error) { return [error.name,error.code,error.message].join(':'); } })(); const delegatedWritableRows = []; stream.Writable.prototype._write.call({ _writev(entries, callback) { delegatedWritableRows.push(entries[0].chunk + ':' + entries[0].encoding); callback(); } }, 'x', 'utf8', () => delegatedWritableRows.push('callback')); const pipeWritable = new stream.Writable({ write(_chunk, _encoding, callback) { callback(); } }); const pipeRows = []; pipeWritable.on('error', (error) => pipeRows.push([error.name,error.code,error.message].join(':'))); const pipeResult = pipeWritable.pipe(new stream.Writable({ write(_chunk, _encoding, callback) { callback(); } })); await new Promise((resolve) => setTimeout(resolve, 0)); const writableDefaultRows = [writableDefaultError, delegatedWritableRows.join('|'), String(pipeResult), pipeRows.join('|'), pipeWritable.destroyed, pipeWritable.errored?.code].join(':'); const duplexLegacyNames = ['write','end','destroy','cork','uncork','setDefaultEncoding','_write']; const duplexLegacyMeta = duplexLegacyNames.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(stream.Duplex.prototype, name); return [name, descriptor?.value?.name, descriptor?.value?.length, descriptor?.enumerable, descriptor?.configurable, descriptor?.writable].join(':'); }).join('|'); const duplexPrototypeOrderRows = [Object.getOwnPropertyNames(stream.Duplex.prototype).join(','), Object.keys(stream.Duplex.prototype).join(','), Object.getOwnPropertySymbols(stream.Duplex.prototype).map(String).join(',') || ''].join(' '); const duplexDescriptorShape = ['write','pipe','cork','uncork','setDefaultEncoding','_write','_writev','end','destroy','_destroy','_undestroy',Symbol.asyncDispose].map((name) => streamDescriptorRow(stream.Duplex.prototype, name)).join('|'); const duplexAsyncOwnership = [Object.hasOwn(stream.Duplex.prototype, Symbol.asyncDispose), stream.Duplex.prototype[Symbol.asyncDispose] === stream.Readable.prototype[Symbol.asyncDispose], stream.Duplex.prototype[Symbol.asyncDispose] === stream.Writable.prototype[Symbol.asyncDispose]].join(':'); const duplexWritevDescriptor = Object.getOwnPropertyDescriptor(stream.Duplex.prototype, '_writev'); const descriptorDuplex = new stream.Duplex({ read() {}, write(_chunk, _encoding, callback) { callback(); } }); const duplexDefaultRows = [String(duplexWritevDescriptor?.value), duplexWritevDescriptor?.enumerable, duplexWritevDescriptor?.configurable, duplexWritevDescriptor?.writable, descriptorDuplex.setDefaultEncoding('utf8') === descriptorDuplex].join(':'); const transformHookNames = ['_final','_transform','_write','_read']; const transformHookMeta = transformHookNames.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(stream.Transform.prototype, name); return [name, descriptor?.value?.name, descriptor?.value?.length, descriptor?.enumerable, descriptor?.configurable, descriptor?.writable].join(':'); }).join('|'); const transformDefaultError = (() => { try { stream.Transform.prototype._transform.call(new stream.Transform(), 'x', 'buffer', () => {}); return 'ok'; } catch (error) { return [error.name,error.code,error.message].join(':'); } })(); const flushedTransform = new stream.Transform({ flush(callback) { callback(null, 'flushed'); } }); const finalRows = []; stream.Transform.prototype._final.call(flushedTransform, (error) => { finalRows.push(error ? error.code : 'ok'); finalRows.push(String(flushedTransform.read())); }); const transformHookRows = [Object.keys(stream.Transform.prototype).slice(0, 4).join(','), transformDefaultError, finalRows.join('|')].join(':'); const destroyPrototypeMeta = [Object.hasOwn(stream.Readable.prototype._destroy, 'prototype'), Object.getOwnPropertyNames(stream.Readable.prototype._destroy.prototype).join(','), Object.hasOwn(stream.Readable.prototype._undestroy, 'prototype'), Object.getOwnPropertyNames(stream.Readable.prototype._undestroy.prototype).join(','), Object.hasOwn(stream.Writable.prototype._destroy, 'prototype'), Object.getOwnPropertyNames(stream.Writable.prototype._destroy.prototype).join(','), Object.hasOwn(stream.Writable.prototype._undestroy, 'prototype'), Object.getOwnPropertyNames(stream.Writable.prototype._undestroy.prototype).join(',')].join('|'); const destroyCallbacks = []; const destroyReadable = new stream.Readable({ read() {} }); destroyReadable.on('error', () => {}); const destroyWritable = new stream.Writable({ write(_chunk, _encoding, callback) { callback(); } }); destroyWritable.on('error', () => {}); stream.Readable.prototype._destroy.call(destroyReadable, new Error('readable-destroy'), (error) => destroyCallbacks.push('readable:' + error.message)); stream.Writable.prototype._destroy.call(destroyWritable, new Error('writable-destroy'), (error) => destroyCallbacks.push('writable:' + error.message)); destroyReadable.destroy(new Error('readable-boom')); destroyWritable.destroy(new Error('writable-boom')); stream.Readable.prototype._undestroy.call(destroyReadable); stream.Writable.prototype._undestroy.call(destroyWritable); const undestroyState = [destroyReadable.destroyed, destroyReadable.closed, destroyReadable.errored, destroyReadable.readableAborted, destroyReadable.readable, destroyWritable.destroyed, destroyWritable.closed, destroyWritable.errored, destroyWritable.writableAborted, destroyWritable.writable].map(String).join(':'); const listenerReadable = new stream.Readable({ read() {} }); const listenerRows = []; function first() { listenerRows.push('first') } function second() { listenerRows.push('second') } function third() { listenerRows.push('third') } listenerReadable.on('data', first); listenerReadable.removeListener('data', first); listenerReadable.emit('data', 'a'); listenerReadable.on('data', second); listenerReadable.off('data', second); listenerReadable.emit('data', 'b'); listenerReadable.on('data', third); listenerReadable.removeAllListeners('data'); listenerReadable.emit('data', 'c'); const listenerRemoval = JSON.stringify(listenerRows) + ':' + listenerReadable.listenerCount('data'); if (writableLegacyMeta !== 'pipe::0:true:true:true|write::3:true:true:true|end::3:true:true:true|destroy::2:true:true:true|_write::3:true:true:true|_undestroy:undestroy:0:true:true:true|_destroy::2:true:true:true|cork::0:true:true:true|uncork::0:true:true:true|setDefaultEncoding:setDefaultEncoding:1:true:true:true' || writablePrototypeOrderRows !== 'constructor,pipe,write,cork,uncork,setDefaultEncoding,_write,_writev,end,closed,destroyed,writable,writableFinished,writableObjectMode,writableBuffer,writableEnded,writableNeedDrain,writableHighWaterMark,writableCorked,writableLength,errored,writableAborted,destroy,_undestroy,_destroy pipe,write,cork,uncork,setDefaultEncoding,_write,_writev,end,destroy,_undestroy,_destroy Symbol(nodejs.rejection),Symbol(Symbol.asyncDispose)' || writableDescriptorShape !== 'pipe:data:true:true:true:function::0:true:false/false/true/constructor|write:data:true:true:true:function::3:true:false/false/true/constructor|cork:data:true:true:true:function::0:true:false/false/true/constructor|uncork:data:true:true:true:function::0:true:false/false/true/constructor|setDefaultEncoding:data:true:true:true:function:setDefaultEncoding:1:true:false/false/true/constructor|_write:data:true:true:true:function::3:true:false/false/true/constructor|_writev:data:true:true:true:null|end:data:true:true:true:function::3:true:false/false/true/constructor|destroy:data:true:true:true:function::2:true:false/false/true/constructor|_destroy:data:true:true:true:function::2:true:false/false/true/constructor|_undestroy:data:true:true:true:function:undestroy:0:true:false/false/true/constructor' || writableSymbolDescriptors !== 'rejection:true:true:true::3:true:false/false/true/constructor async:true:true:true::0:false:no-prototype' || writevDescriptor?.value !== null || !writevDescriptor.enumerable || !writevDescriptor.configurable || !writevDescriptor.writable || writableDefaultRows !== 'Error:ERR_METHOD_NOT_IMPLEMENTED:The _write() method is not implemented:x:utf8|callback:undefined:Error:ERR_STREAM_CANNOT_PIPE:Cannot pipe, not readable:true:ERR_STREAM_CANNOT_PIPE' || duplexLegacyMeta !== 'write::3:true:true:true|end::3:true:true:true|destroy::2:true:true:true|cork::0:true:true:true|uncork::0:true:true:true|setDefaultEncoding:setDefaultEncoding:1:true:true:true|_write::3:true:true:true' || duplexPrototypeOrderRows !== 'constructor,write,cork,uncork,setDefaultEncoding,_write,_writev,end,destroy,writable,writableHighWaterMark,writableObjectMode,writableBuffer,writableLength,writableFinished,writableCorked,writableEnded,writableNeedDrain,destroyed write,cork,uncork,setDefaultEncoding,_write,_writev,end,destroy ' || duplexDescriptorShape !== 'write:data:true:true:true:function::3:true:false/false/true/constructor|pipe:missing:function::2:true:false/false/true/constructor|cork:data:true:true:true:function::0:true:false/false/true/constructor|uncork:data:true:true:true:function::0:true:false/false/true/constructor|setDefaultEncoding:data:true:true:true:function:setDefaultEncoding:1:true:false/false/true/constructor|_write:data:true:true:true:function::3:true:false/false/true/constructor|_writev:data:true:true:true:null|end:data:true:true:true:function::3:true:false/false/true/constructor|destroy:data:true:true:true:function::2:true:false/false/true/constructor|_destroy:missing:function::2:true:false/false/true/constructor|_undestroy:missing:function:undestroy:0:true:false/false/true/constructor|Symbol(Symbol.asyncDispose):missing:function::0:false:no-prototype' || duplexAsyncOwnership !== 'false:true:false' || duplexDefaultRows !== 'null:true:true:true:true' || transformHookMeta !== '_final:final:1:true:true:true|_transform::3:true:true:true|_write::3:true:true:true|_read::0:true:true:true' || transformHookRows !== '_final,_transform,_write,_read:Error:ERR_METHOD_NOT_IMPLEMENTED:The _transform() method is not implemented:ok|flushed' || destroyPrototypeMeta !== 'true|constructor|true|constructor|true|constructor|true|constructor' || destroyCallbacks.join('|') !== 'readable:readable-destroy|writable:writable-destroy' || undestroyState !== 'false:false:null:false:true:false:false:null:false:true' || listenerRemoval !== '[]:0') throw new Error('stream writable legacy metadata failed'); const legacyReadable = new stream.Readable(); legacyReadable.pause(); const legacyPaused = legacyReadable.isPaused(); legacyReadable.resume(); legacyReadable.unshift('b'); legacyReadable.unshift('a'); if (!legacyPaused || legacyReadable.isPaused() || String(legacyReadable.read()) !== 'a' || String(legacyReadable.read()) !== 'b') throw new Error('stream readable legacy helpers failed'); const pullEvents = []; const pullReadable = new stream.Readable({ highWaterMark: 7, read(size) { pullEvents.push('read:' + size); this.push('x'); this.push(null); } }); const pullChunks = []; pullReadable.on('data', (chunk) => pullChunks.push(String(chunk))); await new Promise((resolve) => pullReadable.on('end', resolve)); if (pullEvents.join('|') !== 'read:7' || pullChunks.join('') !== 'x') throw new Error('stream readable pull failed'); const encodedReadable = new stream.Readable({ read() {} }); encodedReadable.push(Buffer.from([0xe2])); encodedReadable.push(Buffer.from([0x82, 0xac])); encodedReadable.push(null); encodedReadable.setEncoding('utf8'); const liveBase64Readable = new stream.Readable({ read() {} }); liveBase64Readable.setEncoding('base64'); liveBase64Readable.push(Buffer.from([1])); liveBase64Readable.push(Buffer.from([2])); liveBase64Readable.push(Buffer.from([3, 4])); liveBase64Readable.push(null); const lateBase64Readable = new stream.Readable({ read() {} }); lateBase64Readable.push(Buffer.from([1])); lateBase64Readable.push(Buffer.from([2, 3, 4])); lateBase64Readable.push(null); lateBase64Readable.setEncoding('base64'); const nullEncodingReadable = new stream.Readable({ read() {} }); if (encodedReadable.read() !== '€' || encodedReadable.read() !== null || liveBase64Readable.read() !== 'AQID' || liveBase64Readable.read() !== 'BA==' || lateBase64Readable.read() !== 'AQID' || lateBase64Readable.read() !== null || nullEncodingReadable.setEncoding(null).readableEncoding !== 'utf8') throw new Error('stream setEncoding failed'); const legacySource = new stream.Readable(); let legacyOutput = ''; const legacySink = new stream.Writable({ write(chunk) { legacyOutput += String(chunk); } }); if (legacySource.pipe(legacySink) !== legacySink || legacySource.unpipe(legacySink) !== legacySource) throw new Error('stream readable pipe metadata failed'); const legacyDone = new Promise((resolve) => legacySink.on('finish', resolve)); legacySource.pipe(legacySink); legacySource.push('take'); legacySource.push(null); await legacyDone; if (legacyOutput !== 'take') throw new Error('stream readable pipe failed'); const backpressureSource = new stream.Readable({ read() {} }); const backpressureWrites = []; const backpressureSink = new stream.Writable({ highWaterMark: 2, write(chunk, _encoding, callback) { backpressureWrites.push(String(chunk)); setTimeout(callback, 0); } }); backpressureSource.pipe(backpressureSink); backpressureSource.push('aa'); const backpressurePaused = backpressureSource.isPaused() && backpressureWrites.join(',') === 'aa'; backpressureSource.push('bb'); backpressureSource.push('cc'); const backpressureQueued = backpressureWrites.join(',') === 'aa'; backpressureSource.push(null); await new Promise((resolve) => backpressureSink.on('finish', resolve)); if (!backpressurePaused || !backpressureQueued || backpressureWrites.join(',') !== 'aa,bb,cc') throw new Error('stream readable pipe backpressure failed'); const endFalseSource = new stream.Readable({ read() {} }); let endFalseFinished = false; const endFalseSink = new stream.Writable({ write(chunk, _encoding, callback) { callback(); } }); endFalseSink.on('finish', () => { endFalseFinished = true; }); endFalseSource.pipe(endFalseSink, { end: false }); endFalseSource.push('end-false'); endFalseSource.push(null); await new Promise((resolve) => setTimeout(resolve, 0)); if (endFalseSink.writableEnded || endFalseSink.writableFinished || endFalseFinished) throw new Error('stream readable pipe end option failed'); endFalseSink.end(); const legacyEvents = new (require('node:events').EventEmitter)(); const wrappedReadable = new stream.Readable().wrap(legacyEvents); const wrappedChunks = []; wrappedReadable.on('data', (chunk) => wrappedChunks.push(String(chunk))); const wrappedDone = new Promise((resolve) => wrappedReadable.on('end', resolve)); legacyEvents.emit('data', 'wrap'); legacyEvents.emit('end'); await wrappedDone; if (wrappedChunks.join('') !== 'wrap' || !wrappedReadable.readableEnded) throw new Error('stream readable wrap failed'); const staticLegacyEvents = new (require('node:events').EventEmitter)(); const staticWrappedReadable = stream.Readable.wrap(staticLegacyEvents, { objectMode: true, highWaterMark: 3 }); const staticWrappedChunks = []; staticWrappedReadable.on('data', (chunk) => staticWrappedChunks.push(String(chunk))); const staticWrappedDone = new Promise((resolve) => staticWrappedReadable.on('end', resolve)); staticLegacyEvents.emit('data', 'static-a'); staticLegacyEvents.emit('data', 'static-b'); staticLegacyEvents.emit('end'); await staticWrappedDone; if (!(staticWrappedReadable instanceof stream.Readable) || !staticWrappedReadable.readableObjectMode || staticWrappedReadable.readableHighWaterMark !== 3 || staticWrappedChunks.join('|') !== 'static-a|static-b' || !staticWrappedReadable.readableEnded || !staticWrappedReadable.destroyed) throw new Error('stream static Readable.wrap failed'); const readableStaticKeys = Object.keys(stream.Readable).join(','); const readableStaticInternals = ['ReadableState','_fromList'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(stream.Readable, name); return [name, descriptor?.value?.name, descriptor?.value?.length, descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.hasOwn(descriptor?.value, 'prototype')].join(':'); }).join('|'); const readableStatePrototype = Object.getOwnPropertyNames(stream.Readable.ReadableState.prototype).join(','); const stateReadable = new stream.Readable({ objectMode: true, highWaterMark: 3, read() {} }); const readableStateInitial = [stateReadable._readableState instanceof stream.Readable.ReadableState, Object.keys(stateReadable._readableState).join(','), stateReadable._readableState.objectMode, stateReadable._readableState.highWaterMark, Array.isArray(stateReadable._readableState.buffer), stateReadable._readableState.length].join(':'); stateReadable.push('state-a'); stateReadable.push('state-b'); const readableStateBuffered = [stateReadable._readableState.length, stateReadable._readableState.buffer.join('|'), stateReadable._readableState.flowing, stateReadable._readableState.paused].join(':'); stateReadable.pause(); const readableStatePaused = [stateReadable._readableState.paused, stateReadable._readableState.flowing].join(':'); stateReadable.resume(); const readableStateResumed = [stateReadable._readableState.paused, stateReadable._readableState.flowing].join(':'); stateReadable.on('error', () => {}); stateReadable.destroy(new Error('state-boom')); const readableStateDestroyed = [stateReadable._readableState.destroyed, stateReadable._readableState.closed, stateReadable._readableState.errored.message].join(':'); const listState = new stream.Readable.ReadableState({ highWaterMark: 3 }, null, false); listState.buffer.push(Buffer.from('abc')); listState.length = 3; const listFirst = stream.Readable._fromList(1, listState); const listRest = stream.Readable._fromList(2, listState); const objectState = new stream.Readable.ReadableState({ objectMode: true }, null, false); objectState.buffer.push('one', 'two'); objectState.length = 2; const fromListRow = [listFirst.toString(), listRest.toString(), listState.buffer.length, stream.Readable._fromList(1, objectState), objectState.buffer.join('|')].join(':'); if (readableStaticKeys !== 'ReadableState,_fromList,from,fromWeb,toWeb,wrap' || readableStaticInternals !== 'ReadableState:ReadableState:3:true:true:true:true|_fromList:fromList:2:true:true:true:true' || readableStatePrototype !== 'constructor,objectMode,ended,endEmitted,reading,constructed,sync,needReadable,emittedReadable,readableListening,resumeScheduled,errorEmitted,emitClose,autoDestroy,destroyed,closed,closeEmitted,multiAwaitDrain,readingMore,dataEmitted,errored,defaultEncoding,decoder,encoding,flowing,pipesCount,paused' || readableStateInitial !== 'true:highWaterMark,buffer,bufferIndex,length,pipes,awaitDrainWriters:true:3:true:0' || readableStateBuffered !== '2:state-a|state-b::false' || readableStatePaused !== 'true:false' || readableStateResumed !== 'false:true' || readableStateDestroyed !== 'true:true:state-boom' || fromListRow !== 'a:bc:0:one:two') throw new Error('stream Readable static internals failed'); const staticHelperMeta = [['Readable','from'],['Readable','fromWeb'],['Readable','toWeb'],['Readable','wrap'],['Writable','fromWeb'],['Writable','toWeb'],['Duplex','from'],['Duplex','fromWeb'],['Duplex','toWeb']].map(([constructorName, name]) => { const descriptor = Object.getOwnPropertyDescriptor(stream[constructorName], name); return [constructorName + '.' + name, descriptor?.value?.name, descriptor?.value?.length, descriptor?.enumerable, descriptor?.configurable, descriptor?.writable].join(':'); }).join('|'); if (staticHelperMeta !== 'Readable.from::2:true:true:true|Readable.fromWeb::2:true:true:true|Readable.toWeb::2:true:true:true|Readable.wrap::2:true:true:true|Writable.fromWeb::2:true:true:true|Writable.toWeb::1:true:true:true|Duplex.from::1:true:true:true|Duplex.fromWeb::2:true:true:true|Duplex.toWeb::2:true:true:true') throw new Error('stream static helper metadata failed'); const invalidWebBridgeRows = [[\"readable-null\", () => stream.Readable.fromWeb(null)], [\"readable-object\", () => stream.Readable.fromWeb({})], [\"writable-null\", () => stream.Writable.fromWeb(null)], [\"writable-object\", () => stream.Writable.fromWeb({})], [\"duplex-null\", () => stream.Duplex.fromWeb(null)], [\"duplex-missing\", () => stream.Duplex.fromWeb()], [\"duplex-empty\", () => stream.Duplex.fromWeb({})], [\"duplex-bad-writable\", () => stream.Duplex.fromWeb({ readable: new ReadableStream(), writable: null })]].map(([label, action]) => { try { action(); return label + \":ok\"; } catch (error) { return [label, error.name, error.code, error.message].join(\":\"); } }).join(\"|\"); if (invalidWebBridgeRows !== \"readable-null:TypeError:ERR_INVALID_ARG_TYPE:The \\\"readableStream\\\" argument must be an instance of ReadableStream. Received null|readable-object:TypeError:ERR_INVALID_ARG_TYPE:The \\\"readableStream\\\" argument must be an instance of ReadableStream. Received an instance of Object|writable-null:TypeError:ERR_INVALID_ARG_TYPE:The \\\"writableStream\\\" argument must be an instance of WritableStream. Received null|writable-object:TypeError:ERR_INVALID_ARG_TYPE:The \\\"writableStream\\\" argument must be an instance of WritableStream. Received an instance of Object|duplex-null:TypeError:ERR_INVALID_ARG_TYPE:The \\\"pair\\\" argument must be of type object. Received null|duplex-missing:TypeError:ERR_INVALID_ARG_TYPE:The \\\"pair.readable\\\" property must be an instance of ReadableStream. Received undefined|duplex-empty:TypeError:ERR_INVALID_ARG_TYPE:The \\\"pair.readable\\\" property must be an instance of ReadableStream. Received undefined|duplex-bad-writable:TypeError:ERR_INVALID_ARG_TYPE:The \\\"pair.writable\\\" property must be an instance of WritableStream. Received null\") throw new Error(\"stream Web bridge validation failed\"); const iteratorSource = stream.Readable.from(['i', 'j']); const iterator = iteratorSource.iterator({ destroyOnReturn: false }); const iteratorFirst = await iterator.next(); await iterator.return(); const iteratorDestroyedAfterReturn = iteratorSource.destroyed; const iteratorRemaining = await iteratorSource.toArray(); const readableComposed = await stream.Readable.from(['a']).compose(async function* upper(source) { for await (const chunk of source) yield String(chunk).toUpperCase(); }).toArray(); if (iteratorFirst.value !== 'i' || iteratorDestroyedAfterReturn || iteratorRemaining.join('') !== 'j' || readableComposed.join('') !== 'A') throw new Error('stream readable iterator/compose failed'); const previousBinary = stream.getDefaultHighWaterMark(false); const previousObject = stream.getDefaultHighWaterMark(true); stream.setDefaultHighWaterMark(false, 12345); stream.setDefaultHighWaterMark(true, 12); const binary = new stream.Readable(); const object = new stream.Readable({ objectMode: true }); const bytes = new Uint8Array([1, 2, 3]); const view = new DataView(new ArrayBuffer(1)); const buffer = stream._uint8ArrayToBuffer(bytes); if (previousBinary !== 65536 || previousObject !== 16 || binary.readableHighWaterMark !== 12345 || object.readableHighWaterMark !== 12 || !stream._isUint8Array(bytes) || stream._isUint8Array(view) || !stream._isArrayBufferView(view) || !Buffer.isBuffer(buffer) || buffer.toString('hex') !== '010203') throw new Error('stream defaults failed'); stream.setDefaultHighWaterMark(false, previousBinary); stream.setDefaultHighWaterMark(true, previousObject); const input = stream.Readable.from(['a', 'b']); let output = ''; const writable = new stream.Writable({ write(chunk) { output += String(chunk); } }); await streamPromises.pipeline(input, writable); if (output !== 'ab') throw new Error('stream pipeline failed'); let transformed = ''; const transformedWritable = new stream.Writable({ write(chunk) { transformed += String(chunk); } }); await streamPromises.pipeline(['x', 'y'], async function* upper(source) { for await (const chunk of source) yield String(chunk).toUpperCase(); }, transformedWritable); if (transformed !== 'XY') throw new Error('stream iterable pipeline failed'); let pipelineError; const failedWritable = new stream.Writable({ write(_chunk, _encoding, callback) { callback(); } }); try { await streamPromises.pipeline(['z'], async function* explode(source) { for await (const chunk of source) { yield chunk; throw new Error('pipeline boom'); } }, failedWritable); } catch (error) { pipelineError = error; } if (pipelineError?.message !== 'pipeline boom' || !failedWritable.destroyed) throw new Error('stream pipeline error failed'); const finishedReadable = stream.Readable.from(['done']); const finishedPromise = streamPromises.finished(finishedReadable); finishedReadable.resume(); await finishedPromise; const mapped = await stream.Readable.from([1, 2, 3, 4]).map((value) => value * 2).filter((value) => value > 4).toArray(); const flattened = await stream.Readable.from([1, 2]).flatMap((value) => [value, value + 10]).toArray(); const windowed = await stream.Readable.from([1, 2, 3, 4]).drop(1).take(2).toArray(); const reduced = await stream.Readable.from([1, 2, 3]).reduce((total, value) => total + value, 0); if (JSON.stringify(mapped) !== '[6,8]' || JSON.stringify(flattened) !== '[1,11,2,12]' || JSON.stringify(windowed) !== '[2,3]' || reduced !== 6) throw new Error('stream iterator helpers failed'); const controller = new AbortController(); const aborted = new stream.Readable(); stream.addAbortSignal(controller.signal, aborted); aborted.on('error', () => {}); controller.abort('stop'); await new Promise((resolve) => setTimeout(resolve, 0)); const addAbortValidation = [['missing-signal', () => stream.addAbortSignal(undefined, new stream.PassThrough())], ['fake-signal', () => stream.addAbortSignal({}, new stream.PassThrough())], ['missing-stream', () => stream.addAbortSignal(new AbortController().signal)], ['fake-stream', () => stream.addAbortSignal(new AbortController().signal, {})]].map(([label, action]) => { try { action(); return label + ':return'; } catch (error) { return [label, error.name, error.code, error.message].join(':'); } }).join('|'); if (!aborted.destroyed || aborted.errored?.name !== 'AbortError' || aborted.errored?.code !== 'ABORT_ERR' || aborted.errored?.cause !== 'stop' || addAbortValidation !== 'missing-signal:TypeError:ERR_INVALID_ARG_TYPE:The \"signal\" argument must be an instance of AbortSignal. Received undefined|fake-signal:TypeError:ERR_INVALID_ARG_TYPE:The \"signal\" argument must be an instance of AbortSignal. Received an instance of Object|missing-stream:TypeError:ERR_INVALID_ARG_TYPE:The \"stream\" argument must be an instance of ReadableStream, WritableStream, or Stream. Received undefined|fake-stream:TypeError:ERR_INVALID_ARG_TYPE:The \"stream\" argument must be an instance of ReadableStream, WritableStream, or Stream. Received an instance of Object') throw new Error('stream abort failed'); const [left, right] = stream.duplexPair(); const leftChunks = []; const rightChunks = []; left.on('data', (chunk) => leftChunks.push(String(chunk))); right.on('data', (chunk) => rightChunks.push(String(chunk))); left.write('to-right'); right.write('to-left'); left.end('left-end'); right.end('right-end'); await new Promise((resolve) => setTimeout(resolve, 0)); if (leftChunks.join('|') !== 'to-left|right-end' || rightChunks.join('|') !== 'to-right|left-end') throw new Error('stream duplexPair failed'); const upper = new stream.Transform(); upper._transform = (chunk, _encoding, callback) => callback(null, String(chunk).toUpperCase()); const suffix = new stream.Transform(); suffix._transform = (chunk, _encoding, callback) => callback(null, String(chunk) + '!'); const duplex = stream.compose(upper, suffix); const composedChunks = []; const done = (async () => { for await (const chunk of duplex) composedChunks.push(String(chunk)); })(); duplex.write('a'); duplex.end('b'); await done; if (composedChunks.join('') !== 'A!B!') throw new Error('stream compose failed'); const bufferedPass = new stream.PassThrough({ objectMode: true }); const passShape = [typeof bufferedPass[Symbol.asyncIterator], typeof bufferedPass.iterator, typeof bufferedPass.read, typeof bufferedPass.pause, bufferedPass._readableState?.objectMode, bufferedPass._writableState?.objectMode].join(':'); bufferedPass.write('a'); bufferedPass.end('b'); const passChunks = []; for await (const chunk of bufferedPass) passChunks.push(String(chunk)); if (passShape !== 'function:function:function:function:true:true' || passChunks.join('') !== 'ab') throw new Error('stream transform async iteration failed'); const optionTransform = new stream.Transform({ transform(chunk, _encoding, callback) { callback(null, String(chunk).toUpperCase()) } }); const transformParents = [Object.getPrototypeOf(stream.Transform).name, Object.getPrototypeOf(stream.PassThrough).name, Object.getPrototypeOf(stream.Transform.prototype).constructor.name].join(':'); const transformInstanceof = [optionTransform instanceof stream.Transform, optionTransform instanceof stream.Duplex, optionTransform instanceof stream.Readable, optionTransform instanceof stream.Writable].join(':'); optionTransform.write('a'); optionTransform.end('b'); const transformChunks = []; for await (const chunk of optionTransform) transformChunks.push(String(chunk)); if (transformParents !== 'Duplex:Transform:Duplex' || transformInstanceof !== 'true:true:true:true' || transformChunks.join('') !== 'AB' || optionTransform.readableLength !== 0 || optionTransform._readableState.ended !== true || optionTransform._writableState.finished !== true) throw new Error('stream transform ancestry/options failed'); const disposed = new stream.PassThrough(); await disposed[Symbol.asyncDispose](); const asyncDisposeOwnerRow = (label, prototype) => { const descriptor = Object.getOwnPropertyDescriptor(prototype, Symbol.asyncDispose); const value = prototype[Symbol.asyncDispose]; if (descriptor) return [label, 'own', descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype')].join(':'); return [label, 'missing', typeof value, value?.name ?? '', value?.length ?? '', typeof value === 'function' ? Object.hasOwn(value, 'prototype') : ''].join(':'); }; const asyncDisposeOwners = [asyncDisposeOwnerRow('Stream', stream.prototype), asyncDisposeOwnerRow('Readable', stream.Readable.prototype), asyncDisposeOwnerRow('Writable', stream.Writable.prototype), asyncDisposeOwnerRow('Duplex', stream.Duplex.prototype), asyncDisposeOwnerRow('Transform', stream.Transform.prototype)].join('|'); if (!disposed.destroyed || !disposed.closed || stream.isReadable(disposed) || stream.isWritable(disposed) || !stream.isDestroyed(disposed) || asyncDisposeOwners !== 'Stream:missing:undefined:::|Readable:own:true:true:true::0:false|Writable:own:true:true:true::0:false|Duplex:missing:function::0:false|Transform:missing:function::0:false') throw new Error('stream disposal/state failed'); const webStateRows = [stream.isReadable(new ReadableStream()), stream.isWritable(new ReadableStream()), stream.isErrored(new ReadableStream()), stream.isDisturbed(new ReadableStream()), stream.isReadable(new WritableStream()), stream.isWritable(new WritableStream()), stream.isErrored(new WritableStream()), stream.isDisturbed(new WritableStream()), stream.isReadable(new TransformStream()), stream.isWritable(new TransformStream()), stream.isErrored(new TransformStream()), stream.isDisturbed(new TransformStream())].map(String).join(':'); if (webStateRows !== 'true:null:false:false:null:true:false:false:null:null:false:false') throw new Error('stream Web state helpers failed'); const pair = { readable: new ReadableStream({ start(controller) { controller.enqueue('web'); controller.close(); } }), writable: new WritableStream({ write(chunk) { globalThis.__streamProbeWrite = String(chunk); } }) }; const webDuplex = stream.Duplex.fromWeb(pair); const webChunks = []; webDuplex.on('data', (chunk) => webChunks.push(String(chunk))); webDuplex.write('sink'); webDuplex.end(); await new Promise((resolve) => setTimeout(resolve, 0)); const webPair = stream.Duplex.toWeb(webDuplex); const webCloseEvents = []; const closeWritable = stream.Writable.fromWeb(new WritableStream({ write(chunk) { webCloseEvents.push('write:' + String(chunk)); }, close() { webCloseEvents.push('close'); } })); closeWritable.write('close-me'); closeWritable.end(); await new Promise((resolve) => closeWritable.on('close', resolve)); const webAbortEvents = []; const abortWritable = stream.Writable.fromWeb(new WritableStream({ abort(reason) { webAbortEvents.push('abort:' + reason.message); } })); abortWritable.on('error', () => {}); abortWritable.destroy(new Error('abort-me')); await new Promise((resolve) => setTimeout(resolve, 0)); const webCancelEvents = []; const cancelReason = new Error('cancel-me'); const cancelReadable = stream.Readable.fromWeb(new ReadableStream({ start(controller) { controller.enqueue('cancelled'); }, cancel(reason) { webCancelEvents.push('cancel:' + reason.message); } })); cancelReadable.on('error', () => {}); cancelReadable.destroy(cancelReason); await new Promise((resolve) => setTimeout(resolve, 0)); const webBreakEvents = []; const breakReadable = stream.Readable.fromWeb(new ReadableStream({ start(controller) { controller.enqueue('first'); }, cancel(reason) { webBreakEvents.push('cancel:' + reason.name + ':' + reason.code); } })); let breakChunk = ''; for await (const chunk of breakReadable) { breakChunk = String(chunk); break; } await new Promise((resolve) => setTimeout(resolve, 0)); if (webChunks.join('') !== 'web' || globalThis.__streamProbeWrite !== 'sink' || typeof webPair.readable.getReader !== 'function' || typeof webPair.writable.getWriter !== 'function' || webCloseEvents.join('|') !== 'write:close-me|close' || !closeWritable.writableFinished || !closeWritable.closed || webAbortEvents.join('|') !== 'abort:abort-me' || !abortWritable.destroyed || !abortWritable.closed || webCancelEvents.join('|') !== 'cancel:cancel-me' || !cancelReadable.destroyed || !cancelReadable.closed || cancelReadable.errored !== cancelReason || breakChunk !== 'first' || webBreakEvents.join('|') !== 'cancel:AbortError:ABORT_ERR' || !breakReadable.destroyed || !breakReadable.closed || breakReadable.errored?.name !== 'AbortError' || breakReadable.errored?.code !== 'ABORT_ERR') throw new Error('stream web conversion failed'); const streamRootDescriptorRow = (prototype, name) => { const descriptor = Object.getOwnPropertyDescriptor(prototype, name); if (!descriptor) return [name, 'missing', typeof prototype[name]].join(':'); return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype')].join(':') }; const streamRootRows = [Object.getOwnPropertyNames(stream.Stream.prototype).join(','), Object.keys(stream.Stream.prototype).join(','), ['constructor','pipe','unpipe','eventNames'].map((name) => streamRootDescriptorRow(stream.Stream.prototype, name)).join('|')].join('::'); const passTransformDescriptor = Object.getOwnPropertyDescriptor(stream.PassThrough.prototype, '_transform'); const passTransformRow = ['_transform', passTransformDescriptor.enumerable, passTransformDescriptor.configurable, passTransformDescriptor.writable, typeof passTransformDescriptor.value, passTransformDescriptor.value.name, passTransformDescriptor.value.length, Object.hasOwn(passTransformDescriptor.value, 'prototype')].join(':'); if (streamRootRows !== 'constructor,pipe,eventNames::pipe,eventNames::constructor:false:true:true:function:Stream:1:true|pipe:true:true:true:function::2:true|unpipe:missing:undefined|eventNames:true:true:true:function:eventNames:0:true' || passTransformRow !== '_transform:true:true:true:function::3:true') throw new Error('stream root/PassThrough metadata failed'); const ocReadableFromDescribe = (chunk) => { if (Buffer.isBuffer(chunk)) return 'Buffer:' + chunk.toString('hex'); if (ArrayBuffer.isView(chunk)) return chunk.constructor.name + ':' + Array.from(new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength)).join(','); return typeof chunk + ':' + String(chunk); }; const ocReadableFromRow = async (label, input) => { try { const readableFrom = stream.Readable.from(input); const rows = []; for await (const chunk of readableFrom) rows.push(ocReadableFromDescribe(chunk)); return label + ':' + readableFrom.readableObjectMode + ':' + readableFrom.readableHighWaterMark + ':' + rows.join('|'); } catch (error) { return [label, error.name, error.code, error.message].join(':'); } }; const ocReadableFromRows = (await Promise.all([ocReadableFromRow('string', 'abc'), ocReadableFromRow('buffer', Buffer.from('abc')), ocReadableFromRow('uint8', new Uint8Array([1, 2])), ocReadableFromRow('int16', new Int16Array([256, 257])), ocReadableFromRow('dataview', new DataView(Uint8Array.from([3, 4]).buffer)), ocReadableFromRow('arraybuffer', Uint8Array.from([5, 6]).buffer), ocReadableFromRow('null', null), ocReadableFromRow('undefined', undefined), ocReadableFromRow('number', 1)])).join(';'); if (ocReadableFromRows !== 'string:true:16:string:abc;buffer:true:16:Buffer:616263;uint8:true:1:number:1|number:2;int16:true:1:number:256|number:257;dataview:TypeError:ERR_INVALID_ARG_TYPE:The \"iterable\" argument must be an instance of Iterable. Received an instance of DataView;arraybuffer:TypeError:ERR_INVALID_ARG_TYPE:The \"iterable\" argument must be an instance of Iterable. Received an instance of ArrayBuffer;null:TypeError:ERR_INVALID_ARG_TYPE:The \"iterable\" argument must be an instance of Iterable. Received null;undefined:TypeError:ERR_INVALID_ARG_TYPE:The \"iterable\" argument must be an instance of Iterable. Received undefined;number:TypeError:ERR_INVALID_ARG_TYPE:The \"iterable\" argument must be an instance of Iterable. Received type number (1)') throw new Error('Readable.from input parity failed');" }, { "specifier": "node:stream/consumers", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "CommonJS export shape, helper names/arities, native-shaped invalid input rejections, and text/json/bytes/buffer/blob/arrayBuffer consumers are implemented for strings, blobs, iterables, promises, Web streams, and Node streams.", "probe": "const consumers = require('node:stream/consumers'); const keys = 'arrayBuffer,blob,buffer,bytes,text,json'; const meta = keys.split(',').map((key) => key + ':' + consumers[key].name + ':' + consumers[key].length).join('|'); const invalidConsumerCodes = await Promise.all([['text-null', () => consumers.text(null)], ['buffer-null', () => consumers.buffer(null)], ['bytes-null', () => consumers.bytes(null)], ['arrayBuffer-null', () => consumers.arrayBuffer(null)], ['text-number', () => consumers.text(123)], ['buffer-object', () => consumers.buffer({ plain: true })]].map(async ([label, action]) => { try { await action(); return label + ':ok'; } catch (error) { return [label, error.name, String(error.code), error.message].join(':'); } })); const bytes = await consumers.bytes(['o', 'k']); if (Object.hasOwn(consumers, 'default') || Object.keys(consumers).join(',') !== keys || meta !== 'arrayBuffer:arrayBuffer:1|blob:blob:1|buffer:buffer:1|bytes:bytes:1|text:text:1|json:json:1' || invalidConsumerCodes.join('|') !== \"text-null:TypeError:undefined:Cannot read properties of null (reading 'Symbol(Symbol.asyncIterator)')|buffer-null:TypeError:undefined:Cannot read properties of null (reading 'Symbol(Symbol.asyncIterator)')|bytes-null:TypeError:undefined:Cannot read properties of null (reading 'Symbol(Symbol.asyncIterator)')|arrayBuffer-null:TypeError:undefined:Cannot read properties of null (reading 'Symbol(Symbol.asyncIterator)')|text-number:TypeError:undefined:stream is not async iterable|buffer-object:TypeError:undefined:stream is not async iterable\" || await consumers.text('ok') !== 'ok' || !(bytes instanceof Uint8Array) || Buffer.isBuffer(bytes) || new TextDecoder().decode(bytes) !== 'ok' || (await consumers.buffer('ok')).toString('utf8') !== 'ok' || (await consumers.blob('ok')).size !== 2 || new Uint8Array(await consumers.arrayBuffer(['o', 'k'])).join(',') !== '111,107' || (await consumers.json('{\"ok\":true}')).ok !== true) throw new Error('stream/consumers failed')" }, { "specifier": "node:stream/promises", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Native-shaped CommonJS export order is present, and finished() matches Node cleanup option listener retention/removal and validation semantics.", "probe": "const streamModule = require('node:stream'); const { PassThrough } = streamModule; const promises = require('node:stream/promises'); const { pipeline, finished } = promises; const promisesDescriptor = Object.getOwnPropertyDescriptor(streamModule, 'promises'); if (Object.keys(promises).join(',') !== 'finished,pipeline' || pipeline.name !== 'pipeline' || pipeline.length !== 0 || finished.name !== 'finished' || finished.length !== 2 || typeof promisesDescriptor.get !== 'function' || promisesDescriptor.set !== undefined || streamModule.promises.pipeline !== pipeline || streamModule.promises.finished !== finished) throw new Error('stream/promises metadata failed'); const stream = new PassThrough(); const done = finished(stream); stream.resume(); stream.end('ok'); await done; const listenerRow = async (options) => { const target = new PassThrough(); const promise = finished(target, options); target.resume(); target.end('ok'); await promise; return ['end','finish','error','close'].map((event) => target.listenerCount(event)).join(',') + ':' + [target.readableEnded,target.writableFinished,target.closed].join(':'); }; const cleanupDefault = await listenerRow(); const cleanupFalse = await listenerRow({ cleanup: false }); const cleanupTrue = await listenerRow({ cleanup: true }); let cleanupInvalid; try { finished(new PassThrough(), { cleanup: 'yes' }); cleanupInvalid = 'ok'; } catch (error) { cleanupInvalid = [error.name,error.code,error.message].join(':'); } const optionsInvalid = await finished(new PassThrough(), 'yes').then(() => 'ok', (error) => [error.name,error.code,error.message].join(':')); if (cleanupDefault !== '1,1,1,1:true:true:true' || cleanupFalse !== '1,1,1,1:true:true:true' || cleanupTrue !== '0,0,0,0:true:true:true' || cleanupInvalid !== `TypeError:ERR_INVALID_ARG_TYPE:The \"cleanup\" argument must be of type boolean. Received type string ('yes')` || optionsInvalid !== `TypeError:ERR_INVALID_ARG_TYPE:The \"options\" argument must be of type object. Received type string ('yes')`) throw new Error('stream/promises finished cleanup failed')" }, { "specifier": "node:stream/web", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs, tests/globals-isolation.test.mjs", "limitation": "Host Web Streams are preferred; OpenContainers fallback covers Node-shaped CommonJS and static ESM namespace export shape, default stream construction, readers, writers, transforms, text streams, queueing strategies, desiredSize/highWaterMark accounting, and queued byte/BYOB reads. Advanced byte/BYOB semantics remain partial.", "probe": "const web = require('node:stream/web'); const keys = 'ReadableStream,ReadableStreamDefaultReader,ReadableStreamBYOBReader,ReadableStreamBYOBRequest,ReadableByteStreamController,ReadableStreamDefaultController,TransformStream,TransformStreamDefaultController,WritableStream,WritableStreamDefaultWriter,WritableStreamDefaultController,ByteLengthQueuingStrategy,CountQueuingStrategy,TextEncoderStream,TextDecoderStream,CompressionStream,DecompressionStream'; const metadata = ['ReadableStream','ReadableStreamDefaultReader','ReadableStreamBYOBReader','TransformStream','WritableStream','WritableStreamDefaultWriter','ByteLengthQueuingStrategy','CountQueuingStrategy','CompressionStream','DecompressionStream'].map((name) => name + ':' + web[name].name + ':' + web[name].length).join('|'); const stream = new web.ReadableStream({ start(controller) { controller.enqueue('ok'); controller.close() } }); const reader = stream.getReader(); const chunk = await reader.read(); const desiredRows = []; let desiredController; const desiredStream = new web.ReadableStream({ start(controller) { desiredController = controller; desiredRows.push(controller.desiredSize); controller.enqueue('aa'); desiredRows.push(controller.desiredSize); controller.enqueue('b'); desiredRows.push(controller.desiredSize); } }, { highWaterMark: 4, size(chunk) { return chunk.length; } }); const desiredReader = desiredStream.getReader(); await desiredReader.read(); desiredRows.push(desiredController.desiredSize); await desiredReader.read(); desiredRows.push(desiredController.desiredSize); desiredController.close(); desiredReader.releaseLock(); if (Object.keys(web).join(',') !== keys || Object.hasOwn(web, 'default') || metadata !== 'ReadableStream:ReadableStream:0|ReadableStreamDefaultReader:ReadableStreamDefaultReader:1|ReadableStreamBYOBReader:ReadableStreamBYOBReader:1|TransformStream:TransformStream:0|WritableStream:WritableStream:0|WritableStreamDefaultWriter:WritableStreamDefaultWriter:1|ByteLengthQueuingStrategy:ByteLengthQueuingStrategy:1|CountQueuingStrategy:CountQueuingStrategy:1|CompressionStream:CompressionStream:1|DecompressionStream:DecompressionStream:1' || chunk.value !== 'ok' || desiredRows.join(',') !== '4,2,1,3,4') throw new Error('stream/web failed')" }, { "specifier": "node:string_decoder", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Chunked UTF-8/base64/base64url/ascii decoding, accepted string/DataView inputs, native-shaped constructor/prototype descriptors, enumerable helper metadata with own prototypes, symbol-backed decoder state accessors, text(offset) helper behavior, and invalid buffer validation are covered; deeper undocumented decoder internals are not exposed.", "probe": "const { StringDecoder } = require('node:string_decoder'); const methodRow = (name) => { const descriptor = Object.getOwnPropertyDescriptor(StringDecoder.prototype, name); const prototype = Object.getOwnPropertyDescriptor(descriptor.value, 'prototype'); return [name, descriptor.value.name, descriptor.value.length, descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.hasOwn(descriptor.value, 'prototype'), prototype?.writable, prototype?.enumerable, prototype?.configurable, Object.getOwnPropertyNames(prototype?.value ?? {}).join(','), prototype?.value?.constructor === descriptor.value].join(':') }; const accessorRow = (name) => { const descriptor = Object.getOwnPropertyDescriptor(StringDecoder.prototype, name); return [name, descriptor.get.name, descriptor.get.length, typeof descriptor.set, descriptor.enumerable, descriptor.configurable, Object.hasOwn(descriptor.get, 'prototype')].join(':') }; const prototypeDescriptor = Object.getOwnPropertyDescriptor(StringDecoder, 'prototype'); const shape = new StringDecoder('utf8'); const symbol = Object.getOwnPropertySymbols(shape)[0]; const symbolDescriptor = Object.getOwnPropertyDescriptor(shape, symbol); const shapeRow = [Object.keys(shape).join(','), Object.getOwnPropertyNames(shape).join(','), Reflect.ownKeys(shape).map(String).join(','), symbolDescriptor.enumerable, symbolDescriptor.configurable, symbolDescriptor.writable, shape[symbol].toString('hex'), JSON.stringify(shape.lastChar), shape.lastNeed, shape.lastTotal].join('|'); const utf8State = new StringDecoder('utf8'); const utf8Symbol = Object.getOwnPropertySymbols(utf8State)[0]; const utf8StateRow = JSON.stringify([utf8State.write(Buffer.from([0xe2])), utf8State[utf8Symbol].toString('hex'), utf8State.lastNeed, utf8State.lastTotal, utf8State.write(Buffer.from([0x82])), utf8State[utf8Symbol].toString('hex'), utf8State.end(Buffer.from([0xac])), utf8State[utf8Symbol].toString('hex')]); const incompleteUtf8 = new StringDecoder('utf8'); const incompleteUtf8Symbol = Object.getOwnPropertySymbols(incompleteUtf8)[0]; const incompleteUtf8Row = JSON.stringify([incompleteUtf8.write(Buffer.from([0xe2])), incompleteUtf8.end(), incompleteUtf8[incompleteUtf8Symbol].toString('hex'), incompleteUtf8.lastNeed, incompleteUtf8.lastTotal]); const base64State = new StringDecoder('base64'); const base64Symbol = Object.getOwnPropertySymbols(base64State)[0]; const base64StateRow = JSON.stringify([base64State.write(Buffer.from([0x61])), base64State[base64Symbol].toString('hex'), base64State.lastNeed, base64State.lastTotal, base64State.write(Buffer.from([0x62])), base64State[base64Symbol].toString('hex'), base64State.end(Buffer.from([0x63])), base64State[base64Symbol].toString('hex')]); const textOffsets = JSON.stringify([new StringDecoder('utf8').text(Buffer.from('abc'), 0), new StringDecoder('utf8').text(Buffer.from('abc'), 1), new StringDecoder('utf8').text(Buffer.from('abc'), 3), new StringDecoder('utf8').text(Buffer.from('abc'), -1)]); const utf8 = new StringDecoder('utf8'); const euro = Buffer.from('€'); const base64 = new StringDecoder('base64'); const invalid = (() => { try { new StringDecoder('nope'); return false } catch (error) { return error.code === 'ERR_UNKNOWN_ENCODING' } })(); const viewBuffer = Buffer.from('view'); const invalidBuffers = [() => new StringDecoder('utf8').write(), () => new StringDecoder('utf8').write(null), () => new StringDecoder('utf8').write([97]), () => new StringDecoder('utf8').write(new ArrayBuffer(1)), () => new StringDecoder('utf8').end(null), () => new StringDecoder('utf8').end({ 0: 97, length: 1 })].map((action) => { try { action(); return 'ok' } catch (error) { return error.name + ':' + error.code } }).join('|'); if (StringDecoder.name !== 'StringDecoder' || StringDecoder.length !== 1 || Object.getOwnPropertyNames(StringDecoder).join(',') !== 'length,name,prototype' || [prototypeDescriptor.writable, prototypeDescriptor.enumerable, prototypeDescriptor.configurable].join(':') !== 'true:false:false' || Object.getOwnPropertyNames(StringDecoder.prototype).join(',') !== 'constructor,write,end,text,lastChar,lastNeed,lastTotal' || Object.keys(StringDecoder.prototype).join(',') !== 'write,end,text,lastChar,lastNeed,lastTotal' || ['write', 'end', 'text'].map(methodRow).join('|') !== 'write:write:1:true:true:true:true:true:false:false:constructor:true|end:end:1:true:true:true:true:true:false:false:constructor:true|text:text:2:true:true:true:true:true:false:false:constructor:true' || ['lastChar', 'lastNeed', 'lastTotal'].map(accessorRow).join('|') !== 'lastChar:get:0:undefined:true:true:false|lastNeed:get:0:undefined:true:true:false|lastTotal:get:0:undefined:true:true:false' || shapeRow !== 'encoding|encoding|encoding,Symbol(kNativeDecoder)|true|true|true|00000000000001|{\"type\":\"Buffer\",\"data\":[0,0,0,0]}|0|0' || utf8StateRow !== '[\"\",\"e2000000020301\",2,3,\"\",\"e2820000010301\",\"€\",\"e282ac00000001\"]' || incompleteUtf8Row !== '[\"\",\"�\",\"e2000000000001\",0,0]' || base64StateRow !== '[\"\",\"61000000020302\",2,3,\"\",\"61620000010302\",\"YWJj\",\"61626300000002\"]' || textOffsets !== '[\"abc\",\"bc\",\"\",\"c\"]' || utf8.write(euro.subarray(0, 1)) !== '' || utf8.end(euro.subarray(1)) !== '€' || base64.write(Buffer.from([0x61])) !== '' || base64.end(Buffer.from([0x62, 0x63])) !== 'YWJj' || new StringDecoder('base64url').end(Buffer.from([0xff, 0xee, 0xdd])) !== '_-7d' || new StringDecoder('utf8').write('plain') !== 'plain' || new StringDecoder('utf8').end(new DataView(viewBuffer.buffer, viewBuffer.byteOffset, viewBuffer.byteLength)) !== 'view' || new StringDecoder('utf8').end() !== '' || invalidBuffers !== 'TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE' || !invalid) throw new Error('string_decoder failed')" }, { "specifier": "node:timers", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Native-shaped CommonJS export order, public helper names/arities and own-prototype metadata, non-constructible promises accessor descriptor, callback validation, handle refs, primitive ids, and Symbol.dispose cancellation are present.", "probe": "const timers = require('node:timers'); const timerMeta = ['setTimeout','clearTimeout','setImmediate','clearImmediate','setInterval','clearInterval'].map((name) => name + ':' + timers[name].name + ':' + timers[name].length).join('|'); const timerPrototypeMeta = ['setTimeout','setImmediate','setInterval'].map((name) => { const fn = timers[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, Object.hasOwn(fn, 'prototype'), descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.getOwnPropertyNames(descriptor.value).join(',')].join(':'); }).join('|'); const promisesDescriptor = Object.getOwnPropertyDescriptor(timers, 'promises'); const promisesMeta = ['promises', promisesDescriptor.get.name, promisesDescriptor.get.length, Object.hasOwn(promisesDescriptor.get, 'prototype'), typeof promisesDescriptor.set, promisesDescriptor.enumerable, promisesDescriptor.configurable].join(':'); if (Object.keys(timers).join(',') !== 'setTimeout,clearTimeout,setImmediate,clearImmediate,setInterval,clearInterval,promises' || timerMeta !== 'setTimeout:setTimeout:2|clearTimeout:clearTimeout:1|setImmediate:setImmediate:1|clearImmediate:clearImmediate:1|setInterval:setInterval:2|clearInterval:clearInterval:1' || timerPrototypeMeta !== 'setTimeout:true:false:false:true:constructor|setImmediate:true:false:false:true:constructor|setInterval:true:false:false:true:constructor' || promisesMeta !== 'promises:get:0:false:undefined:true:true' || timers.promises !== require('node:timers/promises')) throw new Error('timers metadata failed'); for (const [label, action] of [['timeout', () => timers.setTimeout(undefined, 1)], ['interval', () => timers.setInterval(null, 1)], ['immediate', () => timers.setImmediate(123)]]) { try { action(); throw new Error(label + ' callback validation failed') } catch (error) { if (error.message === label + ' callback validation failed' || error.code !== 'ERR_INVALID_ARG_TYPE') throw error } } const timeout = timers.setTimeout(() => {}, 1000); const interval = timers.setInterval(() => {}, 1000); const immediate = timers.setImmediate(() => {}); if (typeof timeout[Symbol.dispose] !== 'function' || typeof interval[Symbol.dispose] !== 'function' || typeof immediate[Symbol.dispose] !== 'function' || typeof timeout[Symbol.toPrimitive]() !== 'number') throw new Error('timers handle shape failed'); timeout[Symbol.dispose](); interval[Symbol.dispose](); immediate[Symbol.dispose]();" }, { "specifier": "node:timers/promises", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Native-shaped CommonJS export order, public helper names/arities/descriptors, scheduler prototype metadata, scheduler marker symbol, basic wait/yield behavior, AbortSignal cancellation, and native-shaped promise option validation are present.", "probe": "const timers = require('node:timers/promises'); const promiseMeta = ['setTimeout','setImmediate','setInterval'].map((name) => name + ':' + timers[name].name + ':' + timers[name].length).join('|'); const promiseDescriptorRows = ['setTimeout','setImmediate','setInterval','scheduler'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(timers, name); return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value?.name, descriptor.value?.length, Object.hasOwn(descriptor.value ?? {}, 'prototype')].join(':'); }).join('|'); const scheduler = timers.scheduler; const schedulerPrototype = Object.getPrototypeOf(scheduler); const schedulerSymbols = Object.getOwnPropertySymbols(scheduler); const schedulerSymbolRows = schedulerSymbols.map((symbol) => { const descriptor = Object.getOwnPropertyDescriptor(scheduler, symbol); return [String(symbol), descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value].join(':'); }).join('|'); const schedulerPrototypeRows = ['constructor','yield','wait'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(schedulerPrototype, name); return [name, descriptor.value.name, descriptor.value.length, descriptor.enumerable, descriptor.configurable, descriptor.writable].join(':'); }).join('|'); const timeout = await timers.setTimeout(1, 'ok'); const immediate = await timers.setImmediate('now'); const schedulerWait = await scheduler.wait(0); const schedulerYield = await scheduler.yield(); const invalidTimerOptions = await Promise.all([['timeout-signal-object', () => timers.setTimeout(0, 'x', { signal: {} })], ['timeout-signal-null', () => timers.setTimeout(0, 'x', { signal: null })], ['immediate-signal-object', () => timers.setImmediate('x', { signal: {} })], ['scheduler-signal-object', () => scheduler.wait(0, { signal: {} })], ['timeout-ref-string', () => timers.setTimeout(0, 'x', { ref: 'no' })], ['interval-signal-object', async () => { const iterator = timers.setInterval(0, 'x', { signal: {} }); await iterator.next(); }]].map(async ([label, action]) => { try { await action(); return label + ':resolved'; } catch (error) { return [label, error.name, error.code, error.message].join(':'); } })); if (Object.keys(timers).join(',') !== 'setTimeout,setImmediate,setInterval,scheduler' || promiseMeta !== 'setTimeout:setTimeout:2|setImmediate:setImmediate:1|setInterval:setInterval:2' || promiseDescriptorRows !== 'setTimeout:true:true:true:setTimeout:2:true|setImmediate:true:true:true:setImmediate:1:true|setInterval:true:true:true:setInterval:2:true|scheduler:true:true:true:::false' || Object.keys(scheduler).join(',') !== '' || Object.getOwnPropertyNames(scheduler).join(',') !== '' || schedulerSymbols.map(String).join(',') !== 'Symbol(kScheduler)' || schedulerPrototype.constructor.name !== 'Scheduler' || Object.getOwnPropertyNames(schedulerPrototype).join(',') !== 'constructor,yield,wait' || Object.keys(schedulerPrototype).join(',') !== '' || schedulerPrototypeRows !== 'constructor:Scheduler:0:false:true:true|yield:yield:0:false:true:true|wait:wait:2:false:true:true' || schedulerSymbolRows !== 'Symbol(kScheduler):true:true:true:boolean' || timeout !== 'ok' || immediate !== 'now' || schedulerWait !== undefined || schedulerYield !== undefined || invalidTimerOptions.join('|') !== `timeout-signal-object:TypeError:ERR_INVALID_ARG_TYPE:The \"options.signal\" property must be an instance of AbortSignal. Received an instance of Object|timeout-signal-null:TypeError:ERR_INVALID_ARG_TYPE:The \"options.signal\" property must be an instance of AbortSignal. Received null|immediate-signal-object:TypeError:ERR_INVALID_ARG_TYPE:The \"options.signal\" property must be an instance of AbortSignal. Received an instance of Object|scheduler-signal-object:TypeError:ERR_INVALID_ARG_TYPE:The \"options.signal\" property must be an instance of AbortSignal. Received an instance of Object|timeout-ref-string:TypeError:ERR_INVALID_ARG_TYPE:The \"options.ref\" property must be of type boolean. Received type string ('no')|interval-signal-object:TypeError:ERR_INVALID_ARG_TYPE:The \"options.signal\" property must be an instance of AbortSignal. Received an instance of Object`) throw new Error('timers/promises failed')" }, { "specifier": "node:tty", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/tty-readline.test.mjs", "limitation": "Virtual TTY metadata, Node-shaped constructor/prototype descriptors and ordering, helper names/arities, helper own-prototype metadata, descriptor validation, native-aligned TERM_PROGRAM, FORCE_COLOR, and TMUX color probes, explicit hasColors(count, env) validation, window-size helpers, resize hooks, native-order moveCursor output, invalid ANSI helper callback validation, native-aligned WriteStream cursorTo no-op/NaN/negative-coordinate behavior, and common ANSI cursor/clear helpers are implemented for OpenContainers PTYs.", "probe": "const tty = require('node:tty'); const stream = new tty.WriteStream(1); const writeKeys = 'isTTY,getColorDepth,hasColors,_refreshSize,cursorTo,moveCursor,clearLine,clearScreenDown,getWindowSize'; const names = [tty.ReadStream.prototype.setRawMode, tty.WriteStream.prototype.clearLine, tty.WriteStream.prototype.clearScreenDown, tty.WriteStream.prototype.cursorTo, tty.WriteStream.prototype.moveCursor, tty.WriteStream.prototype.getWindowSize, tty.WriteStream.prototype._refreshSize, tty.WriteStream.prototype.getColorDepth, tty.WriteStream.prototype.hasColors].map((fn) => fn.name + ':' + fn.length).join('|'); const prototypeRows = [['ReadStream', tty.ReadStream.prototype, ['setRawMode']], ['WriteStream', tty.WriteStream.prototype, ['clearLine','clearScreenDown','cursorTo','moveCursor','getWindowSize','_refreshSize','getColorDepth','hasColors']]].flatMap(([owner, prototype, keys]) => keys.map((key) => { const descriptor = Object.getOwnPropertyDescriptor(prototype, key); const prototypeDescriptor = Object.getOwnPropertyDescriptor(descriptor.value, 'prototype'); return [owner + '.' + key, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype'), prototypeDescriptor?.enumerable, prototypeDescriptor?.configurable, prototypeDescriptor?.writable, Object.getOwnPropertyNames(prototypeDescriptor?.value ?? {}).join(','), prototypeDescriptor?.value?.constructor === descriptor.value].join(':') })).join('|'); const invalidHasColorsRows = [[undefined, {}], [undefined, { TERM: 'xterm-256color' }]].map((args) => { try { stream.hasColors(...args); return 'ok' } catch (error) { return error.name + ':' + error.code } }).join('|'); const cursorProbe = new tty.WriteStream(1); const cursorProbeChunks = []; cursorProbe.on('data', (chunk) => cursorProbeChunks.push(String(chunk))); const cursorNoop = [cursorProbe.cursorTo(), cursorProbe.cursorTo('2'), cursorProbeChunks.join('')].join(':'); cursorProbe.cursorTo(-1); cursorProbe.cursorTo(1, -1); const cursorNegative = cursorProbeChunks.join(''); const cursorErrors = [[NaN], [1, NaN]].map((args) => { try { cursorProbe.cursorTo(...args); return 'ok' } catch (error) { return error.name + ':' + error.code + ':' + error.message } }).join('|'); if (Object.hasOwn(tty, 'default') || Object.keys(tty).join(',') !== 'isatty,ReadStream,WriteStream' || tty.ReadStream.length !== 2 || tty.WriteStream.length !== 1 || tty.isatty.name !== 'isatty' || tty.isatty.length !== 1 || Object.keys(tty.ReadStream.prototype).join(',') !== 'setRawMode' || Object.getOwnPropertyNames(tty.WriteStream.prototype).join(',') !== 'constructor,' + writeKeys || Object.keys(tty.WriteStream.prototype).join(',') !== writeKeys || !Object.getOwnPropertyDescriptor(tty.WriteStream.prototype, 'isTTY').enumerable || !Object.getOwnPropertyDescriptor(tty.WriteStream.prototype, 'clearLine').enumerable || names !== ':1|:2|:1|:3|:3|:0|:0|getColorDepth:0|hasColors:2' || prototypeRows !== 'ReadStream.setRawMode:true:true:true::1:true:false:false:true:constructor:true|WriteStream.clearLine:true:true:true::2:true:false:false:true:constructor:true|WriteStream.clearScreenDown:true:true:true::1:true:false:false:true:constructor:true|WriteStream.cursorTo:true:true:true::3:true:false:false:true:constructor:true|WriteStream.moveCursor:true:true:true::3:true:false:false:true:constructor:true|WriteStream.getWindowSize:true:true:true::0:true:false:false:true:constructor:true|WriteStream._refreshSize:true:true:true::0:true:false:false:true:constructor:true|WriteStream.getColorDepth:true:true:true:getColorDepth:0:true:false:false:true:constructor:true|WriteStream.hasColors:true:true:true:hasColors:2:true:false:false:true:constructor:true' || invalidHasColorsRows !== 'TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE' || cursorNoop !== 'true:true:' || cursorNegative !== '\\x1b[0G\\x1b[0;2H' || cursorErrors !== \"TypeError:ERR_INVALID_ARG_VALUE:The argument 'x' is invalid. Received NaN|TypeError:ERR_INVALID_ARG_VALUE:The argument 'y' is invalid. Received NaN\" || !tty.isatty(0) || !tty.isatty(1) || !tty.isatty(2) || tty.isatty(3) || tty.isatty('1') || tty.isatty(null) || stream.isTTY !== true || JSON.stringify(stream.getWindowSize()) !== '[80,24]' || stream.getColorDepth() !== 24 || !stream.hasColors() || stream.getColorDepth({ FORCE_COLOR: '0' }) !== 1 || stream.getColorDepth({ FORCE_COLOR: 'false' }) !== 1 || stream.getColorDepth({ FORCE_COLOR: '2' }) !== 8 || stream.getColorDepth({ COLORTERM: 'truecolor' }) !== 24 || stream.getColorDepth({ TERM_PROGRAM: 'Apple_Terminal' }) !== 8 || stream.getColorDepth({ TERM_PROGRAM: 'iTerm.app' }) !== 8 || stream.getColorDepth({ TERM_PROGRAM: 'MacTerm' }) !== 24 || stream.getColorDepth({ TERM_PROGRAM: 'Hyper' }) !== 1 || stream.getColorDepth({ TMUX: '1' }) !== 24 || stream.getColorDepth({ TMUX: '1', TERM_PROGRAM: 'Apple_Terminal' }) !== 24 || stream.getColorDepth({ TMUX: '1', TERM: 'dumb' }) !== 1 || stream.getColorDepth({ TERM_PROGRAM: 'Apple_Terminal', COLORTERM: 'truecolor' }) !== 8 || stream.getColorDepth({ TERM_PROGRAM: 'Apple_Terminal', FORCE_COLOR: '3' }) !== 24 || stream.getColorDepth({ TERM_PROGRAM: 'Hyper', COLORTERM: 'truecolor' }) !== 24 || stream.hasColors(1 << 24, { TERM_PROGRAM: 'Apple_Terminal', COLORTERM: 'truecolor' }) || stream.hasColors(16, { TERM_PROGRAM: 'Hyper' }) || !stream.hasColors(1 << 24, { TMUX: '1' }) || stream.hasColors(16, { FORCE_COLOR: 'false' }) || !stream.hasColors(256, { FORCE_COLOR: '2' }) || stream.hasColors(16, { TERM: 'dumb' })) throw new Error('tty metadata failed'); const chunks = []; let callbacks = 0; stream.on('data', (chunk) => chunks.push(String(chunk))); stream.clearLine(0, () => callbacks++); stream.cursorTo(2); stream.cursorTo(2, 3); stream.moveCursor(-1, 2); stream.clearScreenDown(() => callbacks++); if (chunks.join('') !== '\\u001b[2K\\u001b[3G\\u001b[4;3H\\u001b[1D\\u001b[2B\\u001b[0J' || callbacks !== 2) throw new Error('tty control failed'); const invalidTtyCallbackRows = [['clearLine', () => stream.clearLine(0, 'x')], ['clearScreenDown', () => stream.clearScreenDown('x')], ['cursorToY', () => stream.cursorTo(1, 2, 'x')], ['moveCursor', () => stream.moveCursor(1, 1, 'x')], ['moveCursorNoop', () => stream.moveCursor(0, 0, 'x')]].map(([label, action]) => { try { action(); return label + ':ok'; } catch (error) { return [label, error.name, error.code, error.message].join(':'); } }).join('|'); if (invalidTtyCallbackRows !== 'clearLine:TypeError:ERR_INVALID_ARG_TYPE:The \"callback\" argument must be of type function. Received type string (\\'x\\')|clearScreenDown:TypeError:ERR_INVALID_ARG_TYPE:The \"callback\" argument must be of type function. Received type string (\\'x\\')|cursorToY:TypeError:ERR_INVALID_ARG_TYPE:The \"callback\" argument must be of type function. Received type string (\\'x\\')|moveCursor:TypeError:ERR_INVALID_ARG_TYPE:The \"callback\" argument must be of type function. Received type string (\\'x\\')|moveCursorNoop:TypeError:ERR_INVALID_ARG_TYPE:The \"callback\" argument must be of type function. Received type string (\\'x\\')') throw new Error('tty callback validation failed')" }, { "specifier": "node:url", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs, tests/process-builtin.test.mjs", "limitation": "WHATWG URL, legacy Url helpers, IDNA helpers, URL-object format options including unicode hosts, URL-to-HTTP option translation with null-prototype output, enumerable string/symbol URL property copying, IPv6 hostname normalization, native object validation, file URL buffer decoding, pathToFileURL/fileURLToPath { windows } option handling, string-or-URL file path input validation, encoded separator validation, native-shaped helper metadata, and native-shaped legacy Url constructor/prototype metadata are covered.", "probe": "const url = require('node:url'); const keys = 'Url,parse,resolve,resolveObject,format,URL,URLPattern,URLSearchParams,domainToASCII,domainToUnicode,pathToFileURL,fileURLToPath,fileURLToPathBuffer,urlToHttpOptions'; const options = url.urlToHttpOptions(new URL('https://user:pass@example.com:8443/path?q=1#h')); const unicodeUrl = new URL('https://xn--bcher-kva.example/a?x=1#h'); const httpOptionSymbol = Symbol('s'); unicodeUrl.extra = 'value'; unicodeUrl.portHint = 123; unicodeUrl[httpOptionSymbol] = 'sym-value'; Object.defineProperty(unicodeUrl, 'hidden', { value: 'secret', enumerable: false }); const unicodeHttpOptions = url.urlToHttpOptions(unicodeUrl); const ipv6HttpOptions = url.urlToHttpOptions(new URL('http://[::1]:1234/a?q=1')); const plainHttpOptions = url.urlToHttpOptions({ href: 'https://example.com/' }); const invalidHttpOptionRows = ['https://example.com', null, undefined, 42].map((value) => { try { url.urlToHttpOptions(value); return 'ok' } catch (error) { return error.name + ':' + error.code + ':' + error.message } }).join('|'); const idna = [url.domainToASCII('b\\u00fccher.example'), Buffer.from(url.domainToUnicode('xn--bcher-kva.example')).toString('hex'), Buffer.from(url.domainToUnicode('xn--n3h.com')).toString('hex'), url.domainToUnicode('xn--')].join(':'); const urlPrototype = url.Url.prototype; const urlPrototypeMeta = ['parse','format','resolve','resolveObject','parseHost'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(urlPrototype, name); return [name, descriptor?.value?.name, descriptor?.value?.length, descriptor?.enumerable, descriptor?.configurable, descriptor?.writable].join(':'); }).join('|'); const urlPrototypeDescriptor = Object.getOwnPropertyDescriptor(url.Url, 'prototype'); const urlMethodPrototypeMeta = ['parse','format','resolve','resolveObject','parseHost'].map((name) => { const fn = urlPrototype[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name,Object.hasOwn(fn,'prototype'),descriptor?.enumerable,descriptor?.configurable,descriptor?.writable,typeof descriptor?.value].join(':'); }).join('|'); const parseHostRows = ['example.com:8080','example.com:','example.com:abc','[::1]:443',':123'].map((host) => { const parsedHost = new url.Url(); parsedHost.host = host; const returned = parsedHost.parseHost(); return [host, returned === undefined, parsedHost.hostname ?? '', parsedHost.port ?? ''].join('=>'); }).join('|'); if (Object.keys(url).join(',') !== keys || Object.getOwnPropertyNames(urlPrototype).join(',') !== 'constructor,parse,format,resolve,resolveObject,parseHost' || Object.keys(urlPrototype).join(',') !== 'parse,format,resolve,resolveObject,parseHost' || urlPrototypeMeta !== 'parse:parse:3:true:true:true|format:format:0:true:true:true|resolve:resolve:1:true:true:true|resolveObject:resolveObject:1:true:true:true|parseHost:parseHost:0:true:true:true' || urlPrototypeDescriptor.enumerable || urlPrototypeDescriptor.configurable || !urlPrototypeDescriptor.writable || typeof urlPrototypeDescriptor.value !== 'object' || urlMethodPrototypeMeta !== 'parse:true:false:false:true:object|format:true:false:false:true:object|resolve:true:false:false:true:object|resolveObject:true:false:false:true:object|parseHost:true:false:false:true:object' || parseHostRows !== 'example.com:8080=>true=>example.com=>8080|example.com:=>true=>example.com=>|example.com:abc=>true=>example.com:abc=>|[::1]:443=>true=>[::1]=>443|:123=>true=>=>123' || url.pathToFileURL('/workspace/a b').href !== 'file:///workspace/a%20b' || url.pathToFileURL('a b').href !== 'file:///workspace/a%20b' || !(url.parse('/a?b=1') instanceof url.Url)) throw new Error('url failed'); try { url.parse(null); throw new Error('url parse validation failed') } catch (error) { if (error.message === 'url parse validation failed' || error.code !== 'ERR_INVALID_ARG_TYPE') throw error } if (url.resolveObject('/one/two', '../three').href !== '/three') throw new Error('resolveObject failed'); const validFileUrl = new URL('file:///tmp/a%20b'); const invalidFileUrlInputs = [() => url.fileURLToPath({ href: 'file:///tmp/a%20b' }), () => url.fileURLToPathBuffer({ href: 'file:///tmp/a%20b' })].map((action) => { try { action(); return 'ok' } catch (error) { return error.name + ':' + error.code } }).join('|'); if (url.fileURLToPathBuffer('file:///tmp/a%FFb').toString('hex') !== '2f746d702f61ff62' || url.fileURLToPath(validFileUrl) !== '/tmp/a b' || url.fileURLToPathBuffer(validFileUrl).toString() !== '/tmp/a b' || invalidFileUrlInputs !== 'TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE') throw new Error('fileURLToPathBuffer failed'); if (url.pathToFileURL('C:\\\\temp\\\\a b.txt', { windows: true }).href !== 'file:///C:/temp/a%20b.txt' || url.fileURLToPath('file:///C:/temp/a%20b.txt', { windows: true }) !== 'C:\\\\temp\\\\a b.txt' || url.fileURLToPathBuffer('file:///C:/temp/a%20b.txt', { windows: true }).toString('hex') !== '433a5c74656d705c6120622e747874' || url.fileURLToPathBuffer('file:///tmp/a%2Fb').toString() !== '/tmp/a/b') throw new Error('file URL windows options failed'); try { url.fileURLToPath('file:///tmp/a%2Fb'); throw new Error('encoded slash validation failed') } catch (error) { if (error.message === 'encoded slash validation failed' || error.code !== 'ERR_INVALID_FILE_URL_PATH') throw error } if (idna !== 'xn--bcher-kva.example:62c3bc636865722e6578616d706c65:e298832e636f6d:') throw new Error('domainToUnicode failed'); if (Object.hasOwn(options, 'host') || options.port !== 8443 || typeof options.port !== 'number' || options.auth !== 'user:pass' || url.format(unicodeUrl, { unicode: true }) !== 'https://bücher.example/a?x=1#h' || url.format(unicodeUrl, { unicode: true, fragment: false, search: false }) !== 'https://bücher.example/a' || Object.keys(unicodeHttpOptions).join(',') !== 'extra,portHint,protocol,hostname,hash,search,pathname,path,href' || unicodeHttpOptions.extra !== 'value' || unicodeHttpOptions.portHint !== 123 || Object.hasOwn(unicodeHttpOptions, 'hidden') || unicodeHttpOptions.hostname !== 'xn--bcher-kva.example' || Object.getPrototypeOf(unicodeHttpOptions) !== null || Object.getOwnPropertySymbols(unicodeHttpOptions).map((symbol) => String(symbol) + ':' + unicodeHttpOptions[symbol]).join(',') !== 'Symbol(s):sym-value' || ipv6HttpOptions.hostname !== '::1' || Object.keys(plainHttpOptions).join(',') !== 'href,protocol,hostname,hash,search,pathname,path,port' || !Object.hasOwn(plainHttpOptions, 'port') || !Number.isNaN(plainHttpOptions.port) || invalidHttpOptionRows !== \"TypeError:ERR_INVALID_ARG_TYPE:The \\\"url\\\" argument must be of type object. Received type string ('https://example.com')|TypeError:ERR_INVALID_ARG_TYPE:The \\\"url\\\" argument must be of type object. Received null|TypeError:ERR_INVALID_ARG_TYPE:The \\\"url\\\" argument must be of type object. Received undefined|TypeError:ERR_INVALID_ARG_TYPE:The \\\"url\\\" argument must be of type object. Received type number (42)\") throw new Error('urlToHttpOptions failed'); if (url.fileURLToPath.name !== 'fileURLToPath' || url.format.name !== 'urlFormat' || url.format.length !== 2 || url.parse.name !== 'urlParse' || url.parse.length !== 3 || url.pathToFileURL.length !== 2 || url.resolve.name !== 'urlResolve' || url.resolveObject.name !== 'urlResolveObject') throw new Error('url metadata failed')" }, { "specifier": "node:zlib", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Callback/sync helpers, util.promisify-compatible async compression, crc32 with Node-shaped typed-array validation, Node-shaped CommonJS export order without zlib.promises, public helper names/arities, native-shaped codes map, readonly codes/constants/factory descriptors, constants including native-shaped Brotli/Zstd insertion order, native-shaped non-enumerable top-level constant insertion order, non-enumerable top-level aliases, host-backed zstd when available, buffered transform streams, native-shaped callable classic/Brotli transform constructors, Zstd class-constructor no-new behavior, transform constructor prototype descriptors, transform prototype hierarchy metadata, native-shaped transform instance state, and stream probe methods are implemented, including common options, synchronous classic-option, params, flush-kind validation, and gzip flush output before end; browser zstd and deeper native stream parity remain limited.", "probe": "const zlib = require('node:zlib'); const keys = 'crc32,Deflate,Inflate,Gzip,Gunzip,DeflateRaw,InflateRaw,Unzip,BrotliCompress,BrotliDecompress,ZstdCompress,ZstdDecompress,deflate,deflateSync,gzip,gzipSync,deflateRaw,deflateRawSync,unzip,unzipSync,inflate,inflateSync,gunzip,gunzipSync,inflateRaw,inflateRawSync,brotliCompress,brotliCompressSync,brotliDecompress,brotliDecompressSync,zstdCompress,zstdCompressSync,zstdDecompress,zstdDecompressSync,createDeflate,createInflate,createDeflateRaw,createInflateRaw,createGzip,createGunzip,createUnzip,createBrotliCompress,createBrotliDecompress,createZstdCompress,createZstdDecompress,constants,codes'; const constantKeys = Object.keys(zlib.constants); const constantsWindow = constantKeys.slice(constantKeys.indexOf('DEFLATERAW'), constantKeys.indexOf('Z_DEFAULT_WINDOWBITS') + 1).join(','); const topLevelNames = Object.getOwnPropertyNames(zlib); const topLevelConstantsPrefix = topLevelNames.slice(topLevelNames.indexOf('codes') + 1, topLevelNames.indexOf('UNZIP') + 1).join(','); const topLevelZstdWindow = topLevelNames.slice(topLevelNames.indexOf('ZSTD_DECOMPRESS'), topLevelNames.indexOf('ZSTD_CLEVEL_DEFAULT') + 1).join(','); const methodRows = (prototype, names) => names.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(prototype, name); if (!descriptor) return name + ':missing'; if ('value' in descriptor) return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype')].join(':'); return [name, descriptor.enumerable, descriptor.configurable, descriptor.get.name, descriptor.get.length, typeof descriptor.set, Object.hasOwn(descriptor.get, 'prototype')].join(':') }).join('|'); const constructorNames = ['Deflate','Inflate','Gzip','Gunzip','DeflateRaw','InflateRaw','Unzip','BrotliCompress','BrotliDecompress','ZstdCompress','ZstdDecompress']; const constructorPrototypeRows = constructorNames.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(zlib[name], 'prototype'); return [name, typeof zlib[name], zlib[name].name, zlib[name].length, descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.getOwnPropertyNames(descriptor.value).join(','), Object.getPrototypeOf(descriptor.value).constructor.name].join(':'); }).join('|'); const constructorCallRows = constructorNames.map((name) => { try { const value = zlib[name](); const row = [name, 'call-ok', value.constructor.name, value instanceof zlib[name]].join(':'); value.destroy?.(); return row; } catch (error) { return [name, error.constructor.name, error.name, error.code, error.message].join(':'); } }).join('|'); const zlibParent = Object.getPrototypeOf(zlib.Gzip.prototype); const brotliParent = Object.getPrototypeOf(zlib.BrotliCompress.prototype); const zstdParent = Object.getPrototypeOf(zlib.ZstdCompress.prototype); const zlibBase = Object.getPrototypeOf(zlibParent); const zlibChain = [zlibParent.constructor.name, brotliParent.constructor.name, Object.getPrototypeOf(brotliParent).constructor.name, zstdParent.constructor.name, Object.getPrototypeOf(zstdParent).constructor.name].join(':'); const zlibParentNames = Object.getOwnPropertyNames(zlibParent).join(',') + '/' + Object.keys(zlibParent).join(','); const zlibBaseNames = Object.getOwnPropertyNames(zlibBase).join(',') + '/' + Object.keys(zlibBase).join(','); const zlibParentRows = methodRows(zlibParent, ['constructor', 'params']); const zlibWrapperRows = methodRows(brotliParent, ['constructor']) + '/' + methodRows(zstdParent, ['constructor']); const zlibBaseRows = methodRows(zlibBase, ['constructor', '_closed', 'reset', '_flush', '_final', 'flush', 'close', '_destroy', '_transform', '_processChunk']); const zlibParamsTypes = [typeof zlib.createGzip().params, typeof zlib.createBrotliCompress().params, typeof zlib.createZstdCompress().params].join(':'); if (Object.keys(zlib).join(',') !== keys || Object.keys(zlib.codes).length !== 18 || zlib.codes.Z_OK !== 0 || zlib.codes['-6'] !== 'Z_VERSION_ERROR' || Object.getOwnPropertyDescriptor(zlib, 'codes').writable || Object.getOwnPropertyDescriptor(zlib, 'constants').writable || Object.getOwnPropertyDescriptor(zlib, 'createGzip').writable || constantsWindow !== 'DEFLATERAW,INFLATERAW,UNZIP,BROTLI_DECODE,BROTLI_ENCODE,ZSTD_DECOMPRESS,ZSTD_COMPRESS,Z_MIN_WINDOWBITS,Z_MAX_WINDOWBITS,Z_DEFAULT_WINDOWBITS' || topLevelConstantsPrefix !== 'Z_NO_FLUSH,Z_PARTIAL_FLUSH,Z_SYNC_FLUSH,Z_FULL_FLUSH,Z_FINISH,Z_BLOCK,Z_OK,Z_STREAM_END,Z_NEED_DICT,Z_ERRNO,Z_STREAM_ERROR,Z_DATA_ERROR,Z_MEM_ERROR,Z_BUF_ERROR,Z_VERSION_ERROR,Z_NO_COMPRESSION,Z_BEST_SPEED,Z_BEST_COMPRESSION,Z_DEFAULT_COMPRESSION,Z_FILTERED,Z_HUFFMAN_ONLY,Z_RLE,Z_FIXED,Z_DEFAULT_STRATEGY,ZLIB_VERNUM,DEFLATE,INFLATE,GZIP,GUNZIP,DEFLATERAW,INFLATERAW,UNZIP' || topLevelZstdWindow !== 'ZSTD_DECOMPRESS,ZSTD_COMPRESS,Z_MIN_WINDOWBITS,Z_MAX_WINDOWBITS,Z_DEFAULT_WINDOWBITS,Z_MIN_CHUNK,Z_MAX_CHUNK,Z_DEFAULT_CHUNK,Z_MIN_MEMLEVEL,Z_MAX_MEMLEVEL,Z_DEFAULT_MEMLEVEL,Z_MIN_LEVEL,Z_MAX_LEVEL,Z_DEFAULT_LEVEL,ZSTD_e_continue,ZSTD_e_flush,ZSTD_e_end,ZSTD_fast,ZSTD_dfast,ZSTD_greedy,ZSTD_lazy,ZSTD_lazy2,ZSTD_btlazy2,ZSTD_btopt,ZSTD_btultra,ZSTD_btultra2,ZSTD_c_compressionLevel,ZSTD_c_windowLog,ZSTD_c_hashLog,ZSTD_c_chainLog,ZSTD_c_searchLog,ZSTD_c_minMatch,ZSTD_c_targetLength,ZSTD_c_strategy,ZSTD_c_enableLongDistanceMatching,ZSTD_c_ldmHashLog,ZSTD_c_ldmMinMatch,ZSTD_c_ldmBucketSizeLog,ZSTD_c_ldmHashRateLog,ZSTD_c_contentSizeFlag,ZSTD_c_checksumFlag,ZSTD_c_dictIDFlag,ZSTD_c_nbWorkers,ZSTD_c_jobSize,ZSTD_c_overlapLog,ZSTD_d_windowLogMax,ZSTD_CLEVEL_DEFAULT' || zlib.constants.BROTLI_DECODE !== 8 || zlib.constants.BROTLI_ENCODE !== 9 || zlib.constants.ZSTD_DECOMPRESS !== 11 || zlib.constants.ZSTD_COMPRESS !== 10 || Object.getPrototypeOf(zlib.constants) !== null || Object.hasOwn(zlib.constants, 'Z_TREES') || zlibChain !== 'Zlib:Brotli:Zlib:Zstd:ZlibBase' || zlibParentNames !== 'constructor,params/params' || zlibBaseNames !== 'constructor,_closed,reset,_flush,_final,flush,close,_destroy,_transform,_processChunk/_closed,reset,_flush,_final,flush,close,_destroy,_transform,_processChunk' || zlibParentRows !== 'constructor:false:true:true:Zlib:2:true|params:true:true:true:params:3:true' || zlibWrapperRows !== 'constructor:false:true:true:Brotli:2:true/constructor:false:true:true:Zstd:4:true' || zlibBaseRows !== 'constructor:false:true:true:ZlibBase:4:true|_closed:true:true:get:0:undefined:true|reset:true:true:true:reset:0:true|_flush:true:true:true::1:true|_final:true:true:true::1:true|flush:true:true:true::2:true|close:true:true:true::1:true|_destroy:true:true:true::2:true|_transform:true:true:true::3:true|_processChunk:true:true:true::3:true' || constructorPrototypeRows !== 'Deflate:function:Deflate:1:false:false:true:constructor:Zlib|Inflate:function:Inflate:1:false:false:true:constructor:Zlib|Gzip:function:Gzip:1:false:false:true:constructor:Zlib|Gunzip:function:Gunzip:1:false:false:true:constructor:Zlib|DeflateRaw:function:DeflateRaw:1:false:false:true:constructor:Zlib|InflateRaw:function:InflateRaw:1:false:false:true:constructor:Zlib|Unzip:function:Unzip:1:false:false:true:constructor:Zlib|BrotliCompress:function:BrotliCompress:1:false:false:true:constructor:Brotli|BrotliDecompress:function:BrotliDecompress:1:false:false:true:constructor:Brotli|ZstdCompress:function:ZstdCompress:1:false:false:false:constructor:Zstd|ZstdDecompress:function:ZstdDecompress:1:false:false:false:constructor:Zstd' || constructorCallRows !== \"Deflate:call-ok:Deflate:true|Inflate:call-ok:Inflate:true|Gzip:call-ok:Gzip:true|Gunzip:call-ok:Gunzip:true|DeflateRaw:call-ok:DeflateRaw:true|InflateRaw:call-ok:InflateRaw:true|Unzip:call-ok:Unzip:true|BrotliCompress:call-ok:BrotliCompress:true|BrotliDecompress:call-ok:BrotliDecompress:true|ZstdCompress:TypeError:TypeError::Class constructor ZstdCompress cannot be invoked without 'new'|ZstdDecompress:TypeError:TypeError::Class constructor ZstdDecompress cannot be invoked without 'new'\" || zlibParamsTypes !== 'function:function:undefined') throw new Error('zlib metadata failed'); try { zlib.createGzip({ level: 99 }); throw new Error('zlib range validation failed') } catch (error) { if (error.message === 'zlib range validation failed' || error.code !== 'ERR_OUT_OF_RANGE') throw error } try { zlib.gzip(Buffer.from('x'), {}); throw new Error('zlib callback validation failed') } catch (error) { if (error.message === 'zlib callback validation failed' || error.code !== 'ERR_INVALID_ARG_TYPE') throw error } const paramsProbe = zlib.createDeflate(); for (const [label, action, code] of [['levelType', () => paramsProbe.params('1', zlib.constants.Z_DEFAULT_STRATEGY, () => {}), 'ERR_INVALID_ARG_TYPE'], ['levelHigh', () => paramsProbe.params(99, zlib.constants.Z_DEFAULT_STRATEGY, () => {}), 'ERR_OUT_OF_RANGE'], ['strategyType', () => paramsProbe.params(zlib.constants.Z_DEFAULT_COMPRESSION, '0', () => {}), 'ERR_INVALID_ARG_TYPE'], ['strategyHigh', () => paramsProbe.params(zlib.constants.Z_DEFAULT_COMPRESSION, 99, () => {}), 'ERR_OUT_OF_RANGE']]) { try { action(); throw new Error('zlib params ' + label + ' validation failed') } catch (error) { if (error.message === 'zlib params ' + label + ' validation failed' || error.code !== code) throw error } } if (paramsProbe.params(zlib.constants.Z_BEST_SPEED, zlib.constants.Z_DEFAULT_STRATEGY) !== undefined) throw new Error('zlib params callback optional failed'); const flushOutputProbe = zlib.createGzip(); const flushChunks = []; flushOutputProbe.on('data', (chunk) => flushChunks.push(Buffer.from(chunk))); flushOutputProbe.write('abc'); const flushSummary = await new Promise((resolve, reject) => flushOutputProbe.flush(zlib.constants.Z_SYNC_FLUSH, (error) => error ? reject(error) : resolve([flushChunks.length > 0, Buffer.concat(flushChunks).length > 0].join(':')))); flushOutputProbe.end('def'); await new Promise((resolve, reject) => { flushOutputProbe.on('error', reject); flushOutputProbe.on('end', resolve); }); const flushedOutput = Buffer.concat(flushChunks); if (flushSummary !== 'true:true' || zlib.gunzipSync(flushedOutput).toString() !== 'abcdef' || flushChunks.length < 2) throw new Error('zlib flush output failed'); const ocZlibStateValue = (value) => { if (value === null) return 'null'; if (value === undefined) return 'undefined'; if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'string') return String(value); if (Buffer.isBuffer(value)) return 'Buffer:' + value.length; if (ArrayBuffer.isView(value)) return value.constructor.name + ':' + value.byteLength; return value.constructor?.name ?? typeof value; }; const ocZlibStateRows = (instance, names) => names.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(instance, name); const value = instance[name]; if (!descriptor) return [name, 'missing', typeof value, ocZlibStateValue(value)].join(':'); if ('value' in descriptor) return [name, 'data', descriptor.enumerable, descriptor.configurable, descriptor.writable, ocZlibStateValue(value)].join(':'); return [name, 'accessor', descriptor.enumerable, descriptor.configurable, descriptor.get?.name, descriptor.get?.length, typeof descriptor.set, ocZlibStateValue(value)].join(':'); }).join('|'); const ocZlibInstanceStateFields = ['bytesWritten', '_handle', '_outBuffer', '_outOffset', '_chunkSize', '_defaultFlushFlag', '_finishFlushFlag', '_defaultFullFlushFlag', '_info', '_maxOutputLength', '_rejectGarbageAfterEnd', '_level', '_strategy', '_mode', '_dictionary', '_closed']; const ocZlibStateGzip = zlib.createGzip(); const ocZlibStateGzipOptions = zlib.createGzip({ chunkSize: 4096, level: 3, strategy: zlib.constants.Z_FILTERED, flush: zlib.constants.Z_FULL_FLUSH, finishFlush: zlib.constants.Z_SYNC_FLUSH, info: true, maxOutputLength: 12345 }); const ocZlibStateBrotli = zlib.createBrotliCompress({ chunkSize: 4096, flush: zlib.constants.BROTLI_OPERATION_FLUSH, finishFlush: zlib.constants.BROTLI_OPERATION_FINISH }); const ocZlibStateZstd = zlib.createZstdCompress({ chunkSize: 4096, flush: zlib.constants.ZSTD_e_flush, finishFlush: zlib.constants.ZSTD_e_end }); const ocZlibInstanceState = ocZlibStateRows(ocZlibStateGzip, ocZlibInstanceStateFields); const ocZlibOptionState = ocZlibStateRows(ocZlibStateGzipOptions, ['_outBuffer', '_chunkSize', '_defaultFlushFlag', '_finishFlushFlag', '_defaultFullFlushFlag', '_info', '_maxOutputLength', '_level', '_strategy', '_mode']); const ocZlibModernState = ocZlibStateRows(ocZlibStateBrotli, ['_handle', '_chunkSize', '_defaultFlushFlag', '_finishFlushFlag', '_defaultFullFlushFlag', '_level', '_strategy', '_mode']) + ' ' + ocZlibStateRows(ocZlibStateZstd, ['_handle', '_chunkSize', '_defaultFlushFlag', '_finishFlushFlag', '_defaultFullFlushFlag', '_level', '_strategy', '_mode']); await new Promise((resolve, reject) => ocZlibStateGzip.params(zlib.constants.Z_BEST_SPEED, zlib.constants.Z_HUFFMAN_ONLY, (error) => error ? reject(error) : resolve())); const ocZlibParamsState = [ocZlibStateGzip._level, ocZlibStateGzip._strategy].join(' '); ocZlibStateGzip.destroy(); await new Promise((resolve) => ocZlibStateGzipOptions.close(resolve)); const ocZlibClosedState = ocZlibStateRows(ocZlibStateGzip, ['_handle', '_closed']) + ' ' + ocZlibStateRows(ocZlibStateGzipOptions, ['_handle', '_closed']); if (ocZlibInstanceState !== 'bytesWritten:data:true:true:true:0|_handle:data:true:true:true:Zlib|_outBuffer:data:true:true:true:Buffer:16384|_outOffset:data:true:true:true:0|_chunkSize:data:true:true:true:16384|_defaultFlushFlag:data:true:true:true:0|_finishFlushFlag:data:true:true:true:4|_defaultFullFlushFlag:data:true:true:true:3|_info:data:true:true:true:undefined|_maxOutputLength:data:true:true:true:9007199254740991|_rejectGarbageAfterEnd:data:true:true:true:false|_level:data:true:true:true:-1|_strategy:data:true:true:true:0|_mode:data:true:true:true:3|_dictionary:missing:undefined:undefined|_closed:missing:boolean:false' || ocZlibOptionState !== '_outBuffer:data:true:true:true:Buffer:4096|_chunkSize:data:true:true:true:4096|_defaultFlushFlag:data:true:true:true:3|_finishFlushFlag:data:true:true:true:2|_defaultFullFlushFlag:data:true:true:true:3|_info:data:true:true:true:true|_maxOutputLength:data:true:true:true:12345|_level:data:true:true:true:3|_strategy:data:true:true:true:1|_mode:data:true:true:true:3' || ocZlibModernState !== '_handle:data:true:true:true:BrotliEncoder|_chunkSize:data:true:true:true:4096|_defaultFlushFlag:data:true:true:true:1|_finishFlushFlag:data:true:true:true:2|_defaultFullFlushFlag:data:true:true:true:1|_level:missing:undefined:undefined|_strategy:missing:undefined:undefined|_mode:missing:undefined:undefined _handle:data:true:true:true:ZstdCompress|_chunkSize:data:true:true:true:4096|_defaultFlushFlag:data:true:true:true:1|_finishFlushFlag:data:true:true:true:2|_defaultFullFlushFlag:data:true:true:true:1|_level:missing:undefined:undefined|_strategy:missing:undefined:undefined|_mode:missing:undefined:undefined' || ocZlibParamsState !== '1 2' || ocZlibClosedState !== '_handle:data:true:true:true:null|_closed:missing:boolean:true _handle:data:true:true:true:null|_closed:missing:boolean:true') throw new Error('zlib instance state metadata failed')" }, { "specifier": "node:net", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/net-builtin.test.mjs", "limitation": "Virtual loopback TCP supports constructor sockets, Node-shaped public export order and BlockList/SocketAddress accessor descriptors, Socket/Server/createServer/private helper names/arities, Server Symbol.asyncDispose descriptor/idle close behavior, and exported helper own-prototype metadata, Stream aliasing, native-shaped Socket prototype control/accessor rows, fresh-socket state, accepted server sockets as net.Socket instances, legacy argument normalization probes, missing connect target validation, Node-shaped bad port validation, common socket state fields, paused reads, allowHalfOpen readOnly/writeOnly lifecycle with delayed peer writes, timeouts, chainable socket controls, Node-shaped BlockList/SocketAddress static guards, accessors, native-aligned SocketAddress parse/port/address/family/flowlabel validation, JSON probes, and auto-select-family defaults; external raw TCP and native libuv server handles are blocked.", "probe": "const net = require('node:net'); const keys = '_createServerHandle,_normalizeArgs,BlockList,SocketAddress,connect,createConnection,createServer,isIP,isIPv4,isIPv6,Server,Socket,Stream,getDefaultAutoSelectFamily,setDefaultAutoSelectFamily,getDefaultAutoSelectFamilyAttemptTimeout,setDefaultAutoSelectFamilyAttemptTimeout'; const blockListDescriptor = Object.getOwnPropertyDescriptor(net, 'BlockList'); const socketAddressDescriptor = Object.getOwnPropertyDescriptor(net, 'SocketAddress'); const helperPrototypeRows = ['connect','createConnection','createServer','isIPv4','isIPv6','getDefaultAutoSelectFamily','setDefaultAutoSelectFamily','getDefaultAutoSelectFamilyAttemptTimeout','setDefaultAutoSelectFamilyAttemptTimeout'].map((name) => { const fn = net[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, Object.hasOwn(fn, 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(','), descriptor?.value?.constructor === fn].join(':') }).join('|'); if (Object.hasOwn(net, 'default') || Object.keys(net).join(',') !== keys || blockListDescriptor?.get?.name !== 'get BlockList' || blockListDescriptor.set !== undefined || !blockListDescriptor.enumerable || !blockListDescriptor.configurable || socketAddressDescriptor?.get?.name !== 'get SocketAddress' || socketAddressDescriptor.set !== undefined || !socketAddressDescriptor.enumerable || !socketAddressDescriptor.configurable || net.Socket.length !== 1 || net.Server.length !== 2 || net.createServer.length !== 2 || net._normalizeArgs.length !== 1 || net._createServerHandle.length !== 5 || net._normalizeArgs.name !== 'normalizeArgs' || net._createServerHandle.name !== 'createServerHandle' || helperPrototypeRows !== 'connect:true:false:false:true:constructor:true|createConnection:true:false:false:true:constructor:true|createServer:true:false:false:true:constructor:true|isIPv4:true:false:false:true:constructor:true|isIPv6:true:false:false:true:constructor:true|getDefaultAutoSelectFamily:true:false:false:true:constructor:true|setDefaultAutoSelectFamily:true:false:false:true:constructor:true|getDefaultAutoSelectFamilyAttemptTimeout:true:false:false:true:constructor:true|setDefaultAutoSelectFamilyAttemptTimeout:true:false:false:true:constructor:true' || net.Stream !== net.Socket || !(new net.Stream() instanceof net.Socket)) throw new Error('net metadata failed'); const normalized = net._normalizeArgs([4321, 'localhost', () => {}]); const normalizedPath = net._normalizeArgs(['/tmp/opencontainers.sock']); if (normalized[0].port !== 4321 || normalized[0].host !== 'localhost' || typeof normalized[1] !== 'function' || normalizedPath[0].path !== '/tmp/opencontainers.sock' || normalizedPath[1] !== undefined) throw new Error('net normalize failed'); if (net.getDefaultAutoSelectFamily() !== true || net.getDefaultAutoSelectFamilyAttemptTimeout() !== 500 || net.setDefaultAutoSelectFamily(false) !== undefined || net.setDefaultAutoSelectFamilyAttemptTimeout(123) !== undefined || net.getDefaultAutoSelectFamily() !== false || net.getDefaultAutoSelectFamilyAttemptTimeout() !== 123) throw new Error('net auto family failed'); const parsed4 = net.SocketAddress.parse('127.0.0.1'); const parsed4WithPort = net.SocketAddress.parse('127.0.0.1:4321'); const parsed6 = net.SocketAddress.parse('[::1]:4321'); const parsed6NoPort = net.SocketAddress.parse('[::1]'); const address = new net.SocketAddress({ address: '127.0.0.1', port: 80, family: 'ipv4' }); const address4Flow = new net.SocketAddress({ address: '127.0.0.1', flowlabel: 1048576 }); const address6 = new net.SocketAddress({ address: '::1', port: 443, family: 'ipv6', flowlabel: 7 }); if (JSON.stringify(parsed4.toJSON()) !== '{\"address\":\"127.0.0.1\",\"port\":0,\"family\":\"ipv4\",\"flowlabel\":0}' || JSON.stringify(parsed4WithPort.toJSON()) !== '{\"address\":\"127.0.0.1\",\"port\":4321,\"family\":\"ipv4\",\"flowlabel\":0}' || JSON.stringify(parsed6.toJSON()) !== '{\"address\":\"::1\",\"port\":4321,\"family\":\"ipv6\",\"flowlabel\":0}' || JSON.stringify(parsed6NoPort.toJSON()) !== '{\"address\":\"::1\",\"port\":0,\"family\":\"ipv6\",\"flowlabel\":0}' || net.SocketAddress.parse('not-an-address') !== undefined || JSON.stringify(address.toJSON()) !== '{\"address\":\"127.0.0.1\",\"port\":80,\"family\":\"ipv4\",\"flowlabel\":0}' || JSON.stringify(address4Flow.toJSON()) !== '{\"address\":\"127.0.0.1\",\"port\":0,\"family\":\"ipv4\",\"flowlabel\":0}' || JSON.stringify(address6.toJSON()) !== '{\"address\":\"::1\",\"port\":443,\"family\":\"ipv6\",\"flowlabel\":7}' || !net.SocketAddress.isSocketAddress(address) || net.SocketAddress.isSocketAddress({}) || Object.getOwnPropertyDescriptor(net.SocketAddress.prototype, 'address').enumerable) throw new Error('net SocketAddress failed'); const socketAddressValidationRows = [['parseMissing', () => net.SocketAddress.parse(), 'ERR_INVALID_ARG_TYPE'], ['parseNull', () => net.SocketAddress.parse(null), 'ERR_INVALID_ARG_TYPE'], ['parseObject', () => net.SocketAddress.parse({}), 'ERR_INVALID_ARG_TYPE'], ['addressNull', () => new net.SocketAddress({ address: null }), 'ERR_INVALID_ARG_TYPE'], ['addressNumber', () => new net.SocketAddress({ address: 1 }), 'ERR_INVALID_ARG_TYPE'], ['portNull', () => new net.SocketAddress({ port: null }), 'ERR_SOCKET_BAD_PORT'], ['portBoolean', () => new net.SocketAddress({ port: true }), 'ERR_SOCKET_BAD_PORT'], ['portEmpty', () => new net.SocketAddress({ port: '' }), 'ERR_SOCKET_BAD_PORT'], ['portBlank', () => new net.SocketAddress({ port: ' ' }), 'ERR_SOCKET_BAD_PORT'], ['portArray', () => new net.SocketAddress({ port: [] }), 'ERR_SOCKET_BAD_PORT'], ['portArrayValue', () => new net.SocketAddress({ port: [80] }), 'ERR_SOCKET_BAD_PORT'], ['portBigInt', () => new net.SocketAddress({ port: 1n }), 'ERR_SOCKET_BAD_PORT'], ['portSymbol', () => new net.SocketAddress({ port: Symbol('p') }), 'ERR_SOCKET_BAD_PORT'], ['familyNull', () => new net.SocketAddress({ address: '127.0.0.1', family: null }), 'ERR_INVALID_ARG_VALUE'], ['flowlabelNull', () => new net.SocketAddress({ address: '127.0.0.1', flowlabel: null }), 'ERR_INVALID_ARG_TYPE'], ['flowlabelString', () => new net.SocketAddress({ address: '127.0.0.1', flowlabel: '1' }), 'ERR_INVALID_ARG_TYPE']].map(([label, action, code]) => { try { action(); return label + ':ok' } catch (error) { return [label, error.code].join(':') } }).join('|'); if (socketAddressValidationRows !== 'parseMissing:ERR_INVALID_ARG_TYPE|parseNull:ERR_INVALID_ARG_TYPE|parseObject:ERR_INVALID_ARG_TYPE|addressNull:ERR_INVALID_ARG_TYPE|addressNumber:ERR_INVALID_ARG_TYPE|portNull:ERR_SOCKET_BAD_PORT|portBoolean:ERR_SOCKET_BAD_PORT|portEmpty:ERR_SOCKET_BAD_PORT|portBlank:ERR_SOCKET_BAD_PORT|portArray:ERR_SOCKET_BAD_PORT|portArrayValue:ERR_SOCKET_BAD_PORT|portBigInt:ERR_SOCKET_BAD_PORT|portSymbol:ERR_SOCKET_BAD_PORT|familyNull:ERR_INVALID_ARG_VALUE|flowlabelNull:ERR_INVALID_ARG_TYPE|flowlabelString:ERR_INVALID_ARG_TYPE') throw new Error('net SocketAddress validation failed'); const blockList = new net.BlockList(); blockList.addAddress('127.0.0.1'); blockList.addAddress('::1', 'ipv6'); blockList.addRange('10.0.0.1', '10.0.0.3'); blockList.addSubnet('192.168.0.0', 24); const blockListCopy = new net.BlockList(); if (net.BlockList.isBlockList({}) || !net.BlockList.isBlockList(blockList) || blockList.rules.join('|') !== 'Subnet: IPv4 192.168.0.0/24|Range: IPv4 10.0.0.1-10.0.0.3|Address: IPv6 ::1|Address: IPv4 127.0.0.1' || Object.getOwnPropertyDescriptor(net.BlockList.prototype, 'rules').enumerable || JSON.stringify(blockList.toJSON()) !== '[\"Subnet: IPv4 192.168.0.0/24\",\"Range: IPv4 10.0.0.1-10.0.0.3\",\"Address: IPv6 ::1\",\"Address: IPv4 127.0.0.1\"]' || blockListCopy.fromJSON(blockList.toJSON()) !== undefined || blockListCopy.rules.join('|') !== 'Address: IPv4 127.0.0.1|Address: IPv6 ::1|Range: IPv4 10.0.0.1-10.0.0.3|Subnet: IPv4 192.168.0.0/24' || !blockList.check('127.0.0.1') || !blockList.check('::1', 'ipv6') || !blockList.check('10.0.0.2') || blockList.check('10.0.0.4') || !blockList.check('192.168.0.42') || blockList.check('192.168.1.1') || net.isIP('127.0.0.1') !== 4 || net.isIP('::1') !== 6 || net.isIP('01.2.3.4') !== 0) throw new Error('net BlockList failed'); for (const [label, action, code] of [['familyString', () => new net.SocketAddress({ address: '127.0.0.1', family: '4' }), 'ERR_INVALID_ARG_VALUE'], ['familyNumber', () => new net.SocketAddress({ address: '127.0.0.1', family: 4 }), 'ERR_INVALID_ARG_VALUE'], ['flowlabel', () => new net.SocketAddress({ address: '127.0.0.1', flowlabel: -1 }), 'ERR_OUT_OF_RANGE'], ['blockFamilyString', () => blockList.addAddress('127.0.0.1', '4'), 'ERR_INVALID_ARG_VALUE'], ['blockFamilyNumber', () => blockList.addAddress('127.0.0.1', 4), 'ERR_INVALID_ARG_TYPE'], ['blockAddressType', () => blockList.addAddress(123), 'ERR_INVALID_ARG_TYPE']]) { try { action(); throw new Error(label + ' validation failed') } catch (error) { if (error.message === label + ' validation failed' || error.code !== code) throw error } } const halfOpenRows = []; const halfOpenServer = net.createServer({ allowHalfOpen: true }, (socket) => { socket.on('data', (chunk) => halfOpenRows.push('server-data:' + chunk + ':' + socket.readyState + ':' + socket.destroyed)); socket.on('end', () => { halfOpenRows.push('server-end:' + socket.readyState + ':' + socket.destroyed); setTimeout(() => { halfOpenRows.push('server-late:' + socket.readyState + ':' + socket.destroyed); socket.end('late'); }, 0); }); }); await new Promise((resolve) => halfOpenServer.listen(0, '127.0.0.1', resolve)); await new Promise((resolve, reject) => { const client = net.createConnection({ port: halfOpenServer.address().port, host: '127.0.0.1', allowHalfOpen: true }); client.setEncoding('utf8'); client.on('connect', () => { halfOpenRows.push('client-connect:' + client.readyState + ':' + client.destroyed); client.end('ping'); halfOpenRows.push('client-ended:' + client.readyState + ':' + client.destroyed); }); client.on('data', (chunk) => halfOpenRows.push('client-data:' + chunk + ':' + client.readyState + ':' + client.destroyed)); client.on('end', () => halfOpenRows.push('client-end:' + client.readyState + ':' + client.destroyed)); client.on('error', reject); client.on('close', () => { halfOpenRows.push('client-close:' + client.readyState + ':' + client.destroyed); resolve(); }); }); halfOpenServer.close(); await new Promise((resolve) => halfOpenServer.on('close', resolve)); if (halfOpenRows.join('|') !== 'client-connect:open:false|client-ended:readOnly:false|server-data:ping:open:false|server-end:writeOnly:false|server-late:writeOnly:false|client-data:late:readOnly:false|client-end:closed:false|client-close:closed:true') throw new Error('net half-open lifecycle failed'); net.setDefaultAutoSelectFamily(true); net.setDefaultAutoSelectFamilyAttemptTimeout(500); const netServerAsyncDisposeDescriptor = Object.getOwnPropertyDescriptor(net.Server.prototype, Symbol.asyncDispose); const netIdleServer = net.createServer(); const netIdleDispose = netIdleServer[Symbol.asyncDispose](); const netIdleDisposeResult = await netIdleDispose; if (!netServerAsyncDisposeDescriptor || typeof netServerAsyncDisposeDescriptor.value !== 'function' || netServerAsyncDisposeDescriptor.value.name !== '' || netServerAsyncDisposeDescriptor.value.length !== 0 || netServerAsyncDisposeDescriptor.enumerable !== true || netServerAsyncDisposeDescriptor.configurable !== true || netServerAsyncDisposeDescriptor.writable !== true || Object.hasOwn(netServerAsyncDisposeDescriptor.value, 'prototype') || Object.getOwnPropertySymbols(net.Server.prototype).map(String).join(',') !== 'Symbol(Symbol.asyncDispose)' || netIdleDispose.constructor.name !== 'Promise' || netIdleDisposeResult !== undefined || netIdleServer.listening !== false) throw new Error('net Server Symbol.asyncDispose failed');; const socketPrototypeRows = ['connect','setTimeout','setNoDelay','setKeepAlive','address','ref','unref','end','pause','resume','destroySoon','resetAndDestroy','pending','readyState','bufferSize','remoteAddress','remoteFamily','remotePort','localAddress','localPort','localFamily','bytesRead','bytesWritten'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(net.Socket.prototype, name); if (!descriptor) return name + ':missing'; if ('value' in descriptor) return [name,'data',descriptor.enumerable,descriptor.configurable,descriptor.writable,descriptor.value.name,descriptor.value.length,Object.hasOwn(descriptor.value,'prototype')].join(':'); return [name,'accessor',descriptor.enumerable,descriptor.configurable,descriptor.get.name,descriptor.get.length,Object.hasOwn(descriptor.get,'prototype'),typeof descriptor.set].join(':'); }).join('|'); const expectedSocketPrototypeRows = 'connect:data:true:true:true::0:true|setTimeout:data:true:true:true:setStreamTimeout:2:true|setNoDelay:data:true:true:true::1:true|setKeepAlive:data:true:true:true::2:true|address:data:true:true:true::0:true|ref:data:true:true:true::0:true|unref:data:true:true:true::0:true|end:data:true:true:true::3:true|pause:data:true:true:true::0:true|resume:data:true:true:true::0:true|destroySoon:data:true:true:true::0:true|resetAndDestroy:data:true:true:true::0:true|pending:accessor:false:true:get:0:false:undefined|readyState:accessor:false:false:get:0:true:undefined|bufferSize:accessor:false:false:get:0:true:undefined|remoteAddress:accessor:true:false:remoteAddress:0:true:undefined|remoteFamily:accessor:true:false:remoteFamily:0:true:undefined|remotePort:accessor:true:false:remotePort:0:true:undefined|localAddress:accessor:true:false:localAddress:0:true:undefined|localPort:accessor:true:false:localPort:0:true:undefined|localFamily:accessor:true:false:localFamily:0:true:undefined|bytesRead:accessor:true:false:bytesRead:0:true:undefined|bytesWritten:accessor:true:false:bytesWritten:0:true:undefined'; const socketPrototypeNames = Object.getOwnPropertyNames(net.Socket.prototype).join(','); const socketPrototypeKeys = Object.keys(net.Socket.prototype).join(','); const freshSocket = new net.Socket(); const freshSocketOk = freshSocket.pending === true && freshSocket.readyState === 'open' && freshSocket.connecting === false && freshSocket.destroyed === false && freshSocket.closed === false && freshSocket.localAddress === undefined && freshSocket.remoteAddress === undefined && freshSocket.bufferSize === undefined && JSON.stringify(freshSocket.address()) === '{}' && freshSocket.setTimeout(0) === freshSocket && freshSocket.setNoDelay() === freshSocket && freshSocket.setKeepAlive(true, 10) === freshSocket && freshSocket.ref() === freshSocket && freshSocket.unref() === freshSocket; const socketServer = net.createServer((socket) => { if (!(socket instanceof net.Socket)) throw new Error('accepted socket is not net.Socket'); socket.end(); }); await new Promise((resolve) => socketServer.listen(0, '127.0.0.1', resolve)); const socketClient = net.connect(socketServer.address().port, '127.0.0.1'); await new Promise((resolve, reject) => { socketClient.on('error', reject); socketClient.on('close', resolve); }); socketServer.close(); await new Promise((resolve) => socketServer.on('close', resolve)); if (socketPrototypeRows !== expectedSocketPrototypeRows || socketPrototypeNames !== 'constructor,setTimeout,setNoDelay,setKeepAlive,address,pending,readyState,bufferSize,end,resetAndDestroy,pause,resume,destroySoon,bytesRead,remoteAddress,remoteFamily,remotePort,localAddress,localPort,localFamily,bytesWritten,connect,ref,unref' || socketPrototypeKeys !== 'setTimeout,setNoDelay,setKeepAlive,address,end,resetAndDestroy,pause,resume,destroySoon,bytesRead,remoteAddress,remoteFamily,remotePort,localAddress,localPort,localFamily,bytesWritten,connect,ref,unref' || !freshSocketOk) throw new Error('net Socket prototype shape failed');; const netBadPortRows = [['connect-string', () => net.connect({ port: 'abc' })], ['connect-negative', () => net.connect(-1)], ['connect-high', () => net.connect(65536)], ['connect-null', () => net.connect({ port: null })], ['connect-function', () => net.connect(() => {})], ['createConnection-string', () => net.createConnection({ port: 'abc' })], ['socket-connect-high', () => new net.Socket().connect(65536)], ['listen-negative', () => net.createServer().listen(-1)], ['listen-high', () => net.createServer().listen(65536)], ['listen-object-string', () => net.createServer().listen({ port: 'abc' })]].map(([label, action]) => { try { const value = action(); value.destroy?.(); value.close?.(); return label + ':ok'; } catch (error) { return [label, error.constructor.name, error.code, error.message].join(':'); } }).join('|'); if (netBadPortRows !== 'connect-string:RangeError:ERR_SOCKET_BAD_PORT:Port should be >= 0 and < 65536. Received type string (\\'abc\\').|connect-negative:RangeError:ERR_SOCKET_BAD_PORT:Port should be >= 0 and < 65536. Received type number (-1).|connect-high:RangeError:ERR_SOCKET_BAD_PORT:Port should be >= 0 and < 65536. Received type number (65536).|connect-null:TypeError:ERR_INVALID_ARG_TYPE:The \"options.port\" property must be one of type number or string. Received null|connect-function:TypeError:ERR_INVALID_ARG_TYPE:The \"options.port\" property must be one of type number or string. Received function |createConnection-string:RangeError:ERR_SOCKET_BAD_PORT:Port should be >= 0 and < 65536. Received type string (\\'abc\\').|socket-connect-high:RangeError:ERR_SOCKET_BAD_PORT:Port should be >= 0 and < 65536. Received type number (65536).|listen-negative:RangeError:ERR_SOCKET_BAD_PORT:options.port should be >= 0 and < 65536. Received type number (-1).|listen-high:RangeError:ERR_SOCKET_BAD_PORT:options.port should be >= 0 and < 65536. Received type number (65536).|listen-object-string:RangeError:ERR_SOCKET_BAD_PORT:options.port should be >= 0 and < 65536. Received type string (\\'abc\\').') throw new Error('net bad port validation failed')", "unsupported": { "probe": "require('node:net')._createServerHandle('127.0.0.1', 4321, 4)", "code": "ERR_OPENCONTAINERS_NET_UNSUPPORTED" } }, { "specifier": "node:async_hooks", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "AsyncLocalStorage supports default values, names, bound callbacks, native-shaped accessor export/prototype metadata, withScope disposable scope probes, AsyncResource lifecycle hooks, scoped execution IDs/resources, native-shaped helper metadata, null-prototype provider constants, Node-shaped CommonJS export shape, and AsyncResource prototype order, native-shaped AsyncHook createHook instances/validation, AsyncResource type/trigger/bind validation, and RunScope metadata; native hook timing fidelity is incomplete.", "probe": "const asyncHooks = require('node:async_hooks'); const { AsyncLocalStorage, AsyncResource, createHook, executionAsyncId, executionAsyncResource, triggerAsyncId, asyncWrapProviders } = asyncHooks; const descriptor = Object.getOwnPropertyDescriptor(asyncHooks, 'AsyncLocalStorage'); const nameDescriptor = Object.getOwnPropertyDescriptor(AsyncLocalStorage.prototype, 'name'); const withScopeDescriptor = Object.getOwnPropertyDescriptor(AsyncLocalStorage.prototype, 'withScope'); const helperMeta = ['executionAsyncId','triggerAsyncId','executionAsyncResource'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(asyncHooks, name); return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype')].join(':') }).join('|'); const providerMeta = [Object.getPrototypeOf(asyncWrapProviders) === null, Object.keys(asyncWrapProviders).slice(0, 4).join(','), Object.keys(asyncWrapProviders).length].join(':'); const asyncResourcePrototypeNames = Object.getOwnPropertyNames(AsyncResource.prototype).join(','); const asyncResourcePrototypeKeys = Object.keys(AsyncResource.prototype).join(','); const asyncResourcePrototypeMeta = Object.getOwnPropertyNames(AsyncResource.prototype).map((name) => { const descriptor = Object.getOwnPropertyDescriptor(AsyncResource.prototype, name); return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value?.name, descriptor.value?.length].join(':') }).join('|'); const metadataHook = createHook({}); const metadataHookPrototype = Object.getPrototypeOf(metadataHook); const hookShape = JSON.stringify([metadataHook.constructor.name, Object.keys(metadataHook).join(','), Object.getOwnPropertyNames(metadataHook).join(','), metadataHookPrototype.constructor.name, Object.getOwnPropertyNames(metadataHookPrototype).join(','), Object.keys(metadataHookPrototype).join(',')]); const hookPrototypeMeta = Object.getOwnPropertyNames(metadataHookPrototype).map((name) => { const descriptor = Object.getOwnPropertyDescriptor(metadataHookPrototype, name); return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value?.name, descriptor.value?.length, Object.hasOwn(descriptor.value ?? {}, 'prototype')].join(':') }).join('|'); const hookValidationRows = [['missing', () => createHook()], ['null', () => createHook(null)], ['init', () => createHook({ init: 1 })], ['number', () => createHook(1)]].map(([label, action]) => { try { const value = action(); return [label, value.constructor.name, Object.keys(value).join(','), Object.getOwnPropertyNames(value).join(',')].join(':') } catch (error) { return [label, error.name, error.code, error.message].join(':') } }).join('|'); const resourceValidationRows = [['missing-type', () => new AsyncResource()], ['null-type', () => new AsyncResource(null)], ['number-type', () => new AsyncResource(1)], ['symbol-type', () => new AsyncResource(Symbol('x'))], ['string-trigger', () => new AsyncResource('x', { triggerAsyncId: '7' })], ['float-trigger', () => new AsyncResource('x', { triggerAsyncId: 1.5 })], ['null-trigger', () => new AsyncResource('x', { triggerAsyncId: null })], ['nan-trigger', () => new AsyncResource('x', NaN)], ['too-high-trigger', () => new AsyncResource('x', { triggerAsyncId: 2 ** 53 })], ['valid-number-trigger', () => new AsyncResource('x', 7).triggerAsyncId()], ['valid-object-trigger', () => new AsyncResource('x', { triggerAsyncId: 7 }).triggerAsyncId()], ['static-bind-number', () => AsyncResource.bind(123)], ['instance-bind-number', () => new AsyncResource('x').bind(123)], ['storage-bind-number', () => AsyncLocalStorage.bind(123)], ['static-bind-name', () => AsyncResource.bind(function named() {}).name], ['instance-bind-name', () => new AsyncResource('x').bind(function named() {}).name], ['storage-bind-name', () => AsyncLocalStorage.bind(function named() {}).name]].map(([label, action]) => { try { return label + ':ok:' + action() } catch (error) { return [label, error.name, error.code, error.message].join(':') } }).join('|'); if (Object.hasOwn(asyncHooks, 'default') || Object.keys(asyncHooks).join(',') !== 'AsyncLocalStorage,createHook,executionAsyncId,triggerAsyncId,executionAsyncResource,asyncWrapProviders,AsyncResource' || !descriptor?.enumerable || !descriptor.configurable || typeof descriptor.get !== 'function' || descriptor.set !== undefined || Object.keys(AsyncLocalStorage.prototype).length !== 0 || Object.getOwnPropertyNames(AsyncLocalStorage.prototype).join(',') !== 'constructor,name,disable,enterWith,run,exit,getStore,withScope' || !nameDescriptor?.get || nameDescriptor.enumerable || !withScopeDescriptor?.writable || withScopeDescriptor.value.name !== 'withScope' || withScopeDescriptor.value.length !== 1 || AsyncResource.length !== 1 || createHook.length !== 1 || helperMeta !== \"executionAsyncId:true:true:true:executionAsyncId:0:true|triggerAsyncId:true:true:true:triggerAsyncId:0:true|executionAsyncResource:true:true:true:executionAsyncResource:0:true\" || providerMeta !== \"true:NONE,DIRHANDLE,DNSCHANNEL,ELDHISTOGRAM:68\" || asyncResourcePrototypeNames !== 'constructor,runInAsyncScope,emitDestroy,asyncId,triggerAsyncId,bind' || asyncResourcePrototypeKeys !== '' || asyncResourcePrototypeMeta !== 'constructor:false:true:true:AsyncResource:1|runInAsyncScope:false:true:true:runInAsyncScope:2|emitDestroy:false:true:true:emitDestroy:0|asyncId:false:true:true:asyncId:0|triggerAsyncId:false:true:true:triggerAsyncId:0|bind:false:true:true:bind:2' || hookShape !== '[\"AsyncHook\",\"\",\"\",\"AsyncHook\",\"constructor,enable,disable\",\"\"]' || hookPrototypeMeta !== 'constructor:false:true:true:AsyncHook:1:true|enable:false:true:true:enable:0:false|disable:false:true:true:disable:0:false' || hookValidationRows !== \"missing:TypeError::Cannot destructure property 'init' of 'undefined' as it is undefined.|null:TypeError::Cannot destructure property 'init' of 'object null' as it is null.|init:TypeError:ERR_ASYNC_CALLBACK:hook.init must be a function|number:AsyncHook::\" || resourceValidationRows !== 'missing-type:TypeError:ERR_INVALID_ARG_TYPE:The \"type\" argument must be of type string. Received undefined|null-type:TypeError:ERR_INVALID_ARG_TYPE:The \"type\" argument must be of type string. Received null|number-type:TypeError:ERR_INVALID_ARG_TYPE:The \"type\" argument must be of type string. Received type number (1)|symbol-type:TypeError:ERR_INVALID_ARG_TYPE:The \"type\" argument must be of type string. Received type symbol (Symbol(x))|string-trigger:RangeError:ERR_INVALID_ASYNC_ID:Invalid triggerAsyncId value: 7|float-trigger:RangeError:ERR_INVALID_ASYNC_ID:Invalid triggerAsyncId value: 1.5|null-trigger:RangeError:ERR_INVALID_ASYNC_ID:Invalid triggerAsyncId value: null|nan-trigger:RangeError:ERR_INVALID_ASYNC_ID:Invalid triggerAsyncId value: NaN|too-high-trigger:RangeError:ERR_INVALID_ASYNC_ID:Invalid triggerAsyncId value: 9007199254740992|valid-number-trigger:ok:7|valid-object-trigger:ok:7|static-bind-number:TypeError:ERR_INVALID_ARG_TYPE:The \"fn\" argument must be of type function. Received type number (123)|instance-bind-number:TypeError:ERR_INVALID_ARG_TYPE:The \"fn\" argument must be of type function. Received type number (123)|storage-bind-number:TypeError:ERR_INVALID_ARG_TYPE:The \"fn\" argument must be of type function. Received type number (123)|static-bind-name:ok:bound|instance-bind-name:ok:bound|storage-bind-name:ok:bound' || AsyncLocalStorage.prototype.run.length !== 2 || AsyncResource.prototype.runInAsyncScope.length !== 2) throw new Error('async_hooks metadata failed'); const storage = new AsyncLocalStorage({ name: 'request', defaultValue: { requestId: 'default' } }); if (storage.name !== 'request' || JSON.stringify(storage.getStore()) !== '{\"requestId\":\"default\"}') throw new Error('async_hooks storage defaults failed'); await storage.run({ requestId: 'run' }, async () => { await Promise.resolve(); if (JSON.stringify(storage.getStore()) !== '{\"requestId\":\"run\"}') throw new Error('async_hooks async context failed') }); const scope = storage.withScope({ requestId: 'scope' }); if (JSON.stringify(storage.getStore()) !== '{\"requestId\":\"scope\"}' || scope.constructor.name !== 'RunScope' || scope.constructor.length !== 2 || typeof scope[Symbol.dispose] !== 'function') throw new Error('async_hooks scope failed'); scope[Symbol.dispose](); if (JSON.stringify(storage.getStore()) !== '{\"requestId\":\"default\"}') throw new Error('async_hooks scope dispose failed'); const events = []; const hook = createHook({ init(asyncId, type, triggerId) { events.push(`init:${type}:${triggerId}:${Number.isInteger(asyncId)}`); }, before(asyncId) { events.push(`before:${asyncId}`); }, after(asyncId) { events.push(`after:${asyncId}`); }, destroy(asyncId) { events.push(`destroy:${asyncId}`); } }); if (hook.enable() !== hook || hook.disable() !== hook) throw new Error('async_hooks hook chain failed'); hook.enable(); const resource = new AsyncResource('probe', { triggerAsyncId: 7 }); const scoped = resource.runInAsyncScope(function (value) { return [this.label, value, executionAsyncId() === resource.asyncId(), triggerAsyncId(), executionAsyncResource() === resource].join(':'); }, { label: 'ctx' }, 'ok'); const bound = resource.bind(function (value) { return [this.label, value, executionAsyncResource() === resource].join(':'); }, { label: 'bound' }); const staticBound = AsyncResource.bind(() => executionAsyncId() > 0, 'static-probe'); if (scoped !== 'ctx:ok:true:7:true' || bound('ok') !== 'bound:ok:true' || bound.asyncResource !== resource || staticBound() !== true || staticBound.asyncResource.type !== 'static-probe' || asyncWrapProviders.PROMISE !== 27 || asyncHooks.asyncWrapProviders.TCPWRAP !== 40 || resource.emitDestroy() !== resource) throw new Error('async_hooks resource failed'); hook.disable(); new AsyncResource('disabled-probe').emitDestroy(); if (!events.includes('init:probe:7:true') || events.filter((event) => event === 'before:' + resource.asyncId()).length !== 2 || events.filter((event) => event === 'after:' + resource.asyncId()).length !== 2 || !events.includes('init:static-probe:0:true') || !events.includes('destroy:' + resource.asyncId()) || events.some((event) => event.includes('disabled-probe'))) throw new Error('async_hooks events failed')" }, { "specifier": "node:child_process", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/child-process-sync.test.mjs, tests/shell-features.test.mjs", "limitation": "Virtual child process execution is supported for OpenContainers commands, including Node-shaped CommonJS export order/helper arities/helper own prototypes, spawn/exec/execFile sync and async helpers, spawn event plus spawnfile/spawnargs/stdio metadata, shell mode, sync stdin input, sync and async encoding buffer results, sync maxBuffer validation/ENOBUFS results, sync timeout validation/ETIMEDOUT results, sync missing executable ENOENT result/error shape, async missing executable ENOENT event/callback shape, shell command-not-found status 127 behavior, async per-stream maxBuffer validation/ERR_CHILD_PROCESS_STDIO_MAXBUFFER results, async timeout kill semantics, AbortSignal cancellation with Node-shaped AbortError events, fork JSON IPC, and ChildProcess package-probe constructors, writable ChildProcess constructor prototype descriptor, prototype metadata, and Symbol.dispose descriptor/kill-call parity. Host OS processes, direct ChildProcess.spawn, child_process._forkChild, and IPC handle/fd passing are unsupported.", "probe": "const cp = require('node:child_process'); const keys = '_forkChild,ChildProcess,exec,execFile,execFileSync,execSync,fork,spawn,spawnSync'; const metadata = ['ChildProcess','_forkChild','spawn','spawnSync','exec','execFile','execFileSync','execSync','fork'].map((name) => name + ':' + cp[name].name + ':' + cp[name].length).join('|'); const helperPrototypeMeta = ['spawn','spawnSync','exec','execFile','execFileSync','execSync','fork','_forkChild'].map((name) => { const fn = cp[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, fn.name, fn.length, Object.hasOwn(fn, 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(','), descriptor?.value?.constructor === fn].join(':') }).join('|'); const childProcessPrototypeDescriptor = Object.getOwnPropertyDescriptor(cp.ChildProcess, 'prototype'); const childProcessPrototypeDescriptorRow = [childProcessPrototypeDescriptor.enumerable, childProcessPrototypeDescriptor.configurable, childProcessPrototypeDescriptor.writable, Object.getOwnPropertyNames(childProcessPrototypeDescriptor.value).join(','), childProcessPrototypeDescriptor.value.constructor === cp.ChildProcess].join(':'); const direct = new cp.ChildProcess(); const prototypeMethods = ['spawn','kill','ref','unref']; const prototypeMeta = [Object.getOwnPropertyNames(cp.ChildProcess.prototype).join(','), Object.keys(cp.ChildProcess.prototype).join(','), prototypeMethods.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(cp.ChildProcess.prototype, name); return [name, descriptor.value.name, descriptor.value.length, descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.hasOwn(descriptor.value, 'prototype')].join(':'); }).join('|')].join(';'); const directRefRows = [direct.ref(), direct.unref(), direct.kill(), direct.killed].map(String).join(':'); const metadataChild = cp.spawn('node', ['-e', '']); const spawnMetaResult = await new Promise((resolve) => { const rows = []; metadataChild.on('spawn', () => rows.push(['spawn', metadataChild.spawnfile, JSON.stringify(metadataChild.spawnargs), metadataChild.pid > 0, metadataChild.killed, typeof metadataChild.kill, Array.isArray(metadataChild.stdio), metadataChild.stdio.length, metadataChild.stdin === metadataChild.stdio[0], metadataChild.stdout === metadataChild.stdio[1], metadataChild.stderr === metadataChild.stdio[2]].join(':'))); metadataChild.on('close', (code, signal) => { rows.push(['close', code, signal, metadataChild.exitCode, metadataChild.signalCode, metadataChild.killed].join(':')); resolve(rows.join('|')); }); }); const sync = cp.spawnSync('node', ['-e', \"console.log('sync child')\"]); const bufferEncoding = Buffer.isBuffer(cp.spawnSync('node', ['-e', \"process.stdout.write('a')\"], { encoding: 'buffer' }).stdout) && Buffer.isBuffer(cp.execFileSync('node', ['-e', \"process.stdout.write('b')\"], { encoding: 'buffer' })) && Buffer.isBuffer(cp.execSync('printf c', { encoding: 'buffer' })); const limited = cp.spawnSync('node', ['-e', \"process.stdout.write('abc'); process.stderr.write('d')\"], { maxBuffer: 3, encoding: 'utf8', killSignal: 'SIGKILL' }); const timedOut = cp.spawnSync('node', ['-e', \"Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 20)\"], { timeout: 5, encoding: 'utf8', killSignal: 'SIGKILL' }); const formatMissingError = (error) => [error.name, error.code, error.errno, error.syscall, error.path, JSON.stringify(error.spawnargs), Object.keys(error).join(','), error.message].map(String).join(':'); const missingCommand = 'definitely-missing-opencontainers-command'; const missingSync = cp.spawnSync(missingCommand, ['--flag'], { encoding: 'utf8' }); const missingSyncRow = [Object.keys(missingSync).join(','), missingSync.status, missingSync.signal, missingSync.pid, missingSync.output, missingSync.stdout, missingSync.stderr, formatMissingError(missingSync.error)].map(String).join(':'); let missingExecFileRow = ''; try { cp.execFileSync(missingCommand, ['--flag'], { encoding: 'utf8' }) } catch (error) { missingExecFileRow = [error.status, error.signal, error.pid, error.output, error.stdout, error.stderr, formatMissingError(error)].map(String).join(':') } let timeoutType; try { cp.spawnSync('node', ['-e', ''], { timeout: '5' }) } catch (error) { timeoutType = error.code } let timeoutRange; try { cp.spawnSync('node', ['-e', ''], { timeout: -1 }) } catch (error) { timeoutRange = error.code } let maxBufferType; try { cp.spawnSync('node', ['-e', ''], { maxBuffer: '3' }) } catch (error) { maxBufferType = error.code } let maxBufferRange; try { cp.spawnSync('node', ['-e', ''], { maxBuffer: -1 }) } catch (error) { maxBufferRange = error.code } const abortController = new AbortController(); const abortChild = cp.spawn('node', ['-e', 'setTimeout(() => {}, 1000)'], { signal: abortController.signal, killSignal: 'SIGKILL' }); const abortRows = []; abortChild.on('error', (error) => abortRows.push(['error', error.name, error.code, error.message, error.cause].join(':'))); const abortResult = await new Promise((resolve) => { abortChild.on('close', (code, signal) => { abortRows.push(['close', code, signal, abortChild.killed, abortChild.exitCode, abortChild.signalCode].join(':')); resolve(abortRows.join('|')); }); abortController.abort('probe'); }); let invalidSignal; try { cp.spawn('node', ['-e', ''], { signal: 123 }) } catch (error) { invalidSignal = error.code } const asyncSpawnMissingRow = await new Promise((resolve) => { const child = cp.spawn(missingCommand, ['--flag']); const rows = []; let stdout = ''; let stderr = ''; child.stdout?.on('data', (chunk) => { stdout += chunk }); child.stderr?.on('data', (chunk) => { stderr += chunk }); child.on('spawn', () => rows.push('spawn')); child.on('error', (error) => rows.push(['error', error.name, error.code, error.errno, error.syscall, error.path, JSON.stringify(error.spawnargs), error.message].join(':'))); child.on('exit', (code, signal) => rows.push(['exit', code, signal].join(':'))); child.on('close', (code, signal) => { rows.push(['close', code, signal].join(':')); resolve(JSON.stringify({ rows, stdout, stderr })) }); }); const asyncShellMissingRow = await new Promise((resolve) => { const child = cp.spawn(missingCommand + ' --flag', { shell: true }); const rows = []; let stdout = ''; let stderr = ''; child.stdout?.on('data', (chunk) => { stdout += chunk }); child.stderr?.on('data', (chunk) => { stderr += chunk }); child.on('spawn', () => rows.push('spawn')); child.on('error', (error) => rows.push(['error', error.code].join(':'))); child.on('exit', (code, signal) => rows.push(['exit', code, signal].join(':'))); child.on('close', (code, signal) => { rows.push(['close', code, signal].join(':')); resolve(JSON.stringify({ rows, stdout, stderr })) }); }); const asyncExecFileMissingRow = await new Promise((resolve) => { const rows = []; const child = cp.execFile(missingCommand, ['--flag'], (error, stdout, stderr) => { rows.push(['callback', stdout, stderr, error?.name, error?.code, error?.errno, error?.syscall, error?.path, JSON.stringify(error?.spawnargs), error?.cmd, error?.message].join(':')) }); child.on('spawn', () => rows.push('spawn')); child.on('error', (error) => rows.push(['error', error.name, error.code, error.errno, error.syscall, error.path, JSON.stringify(error.spawnargs), error.cmd, error.message].join(':'))); child.on('exit', (code, signal) => rows.push(['exit', code, signal].join(':'))); child.on('close', (code, signal) => { rows.push(['close', code, signal].join(':')); setImmediate(() => resolve(JSON.stringify(rows))) }); }); const asyncExecShellMissingRow = await new Promise((resolve) => cp.exec(missingCommand + ' --flag', (error, stdout, stderr) => resolve(JSON.stringify({ name: error.name, code: error.code, killed: error.killed, signal: error.signal, cmd: error.cmd, message: error.message, stdout, stderr })))); const expectedMissingArgs = JSON.stringify(['--flag']); const expectedShellStderr = '/bin/sh: definitely-missing-opencontainers-command: command not found\\n'; const expectedAsyncSpawnMissingRow = JSON.stringify({ rows: ['error:Error:ENOENT:-2:spawn definitely-missing-opencontainers-command:definitely-missing-opencontainers-command:' + expectedMissingArgs + ':spawn definitely-missing-opencontainers-command ENOENT', 'close:-2:'], stdout: '', stderr: '' }); const expectedAsyncShellMissingRow = JSON.stringify({ rows: ['spawn', 'exit:127:', 'close:127:'], stdout: '', stderr: expectedShellStderr }); const expectedAsyncExecFileMissingRow = JSON.stringify(['callback:::Error:ENOENT:-2:spawn definitely-missing-opencontainers-command:definitely-missing-opencontainers-command:' + expectedMissingArgs + ':definitely-missing-opencontainers-command --flag:spawn definitely-missing-opencontainers-command ENOENT', 'error:Error:ENOENT:-2:spawn definitely-missing-opencontainers-command:definitely-missing-opencontainers-command:' + expectedMissingArgs + ':definitely-missing-opencontainers-command --flag:spawn definitely-missing-opencontainers-command ENOENT', 'close:-2:']); const expectedAsyncExecShellMissingRow = JSON.stringify({ name: 'Error', code: 127, killed: false, signal: null, cmd: 'definitely-missing-opencontainers-command --flag', message: 'Command failed: definitely-missing-opencontainers-command --flag\\n' + expectedShellStderr, stdout: '', stderr: expectedShellStderr }); if (Object.hasOwn(cp, 'default') || Object.keys(cp).join(',') !== keys || metadata !== 'ChildProcess:ChildProcess:0|_forkChild:_forkChild:2|spawn:spawn:3|spawnSync:spawnSync:3|exec:exec:3|execFile:execFile:4|execFileSync:execFileSync:3|execSync:execSync:2|fork:fork:1' || helperPrototypeMeta !== 'spawn:spawn:3:true:false:false:true:constructor:true|spawnSync:spawnSync:3:true:false:false:true:constructor:true|exec:exec:3:true:false:false:true:constructor:true|execFile:execFile:4:true:false:false:true:constructor:true|execFileSync:execFileSync:3:true:false:false:true:constructor:true|execSync:execSync:2:true:false:false:true:constructor:true|fork:fork:1:true:false:false:true:constructor:true|_forkChild:_forkChild:2:true:false:false:true:constructor:true' || childProcessPrototypeDescriptorRow !== 'false:false:true:constructor,spawn,kill,ref,unref:true' || prototypeMeta !== 'constructor,spawn,kill,ref,unref;spawn,kill,ref,unref;spawn:spawn:1:true:true:true:true|kill:kill:1:true:true:true:true|ref:ref:0:true:true:true:true|unref:unref:0:true:true:true:true' || directRefRows !== 'undefined:undefined:false:false' || !(direct instanceof cp.ChildProcess) || direct.connected !== false || direct.killed !== false || direct.exitCode !== null || direct.spawnfile !== null || typeof direct.kill !== 'function' || typeof direct.ref !== 'function' || typeof direct.unref !== 'function' || spawnMetaResult !== 'spawn:node:[\\\"node\\\",\\\"-e\\\",\\\"\\\"]:true:false:function:true:3:true:true:true|close:0::0::false' || sync.status !== 0 || sync.stdout.toString().trim() !== 'sync child' || cp.execSync('echo sync shell').toString().trim() !== 'sync shell' || !bufferEncoding || limited.status !== null || limited.signal !== 'SIGKILL' || limited.error?.code !== 'ENOBUFS' || limited.error?.errno !== -55 || limited.error?.syscall !== 'spawnSync node' || limited.stdout !== 'abc' || limited.stderr !== 'd' || limited.output[1] !== limited.stdout || limited.output[2] !== limited.stderr || timedOut.status !== null || timedOut.signal !== 'SIGKILL' || timedOut.error?.code !== 'ETIMEDOUT' || timedOut.error?.errno !== -60 || timedOut.error?.syscall !== 'spawnSync node' || timedOut.stdout !== '' || timedOut.stderr !== '' || missingSyncRow !== 'error,status,signal,output,pid,stdout,stderr:null:null:0:null:undefined:undefined:Error:ENOENT:-2:spawnSync definitely-missing-opencontainers-command:definitely-missing-opencontainers-command:[\"--flag\"]:errno,code,syscall,path,spawnargs:spawnSync definitely-missing-opencontainers-command ENOENT' || missingExecFileRow !== 'null:null:0:null:undefined:undefined:Error:ENOENT:-2:spawnSync definitely-missing-opencontainers-command:definitely-missing-opencontainers-command:[\"--flag\"]:errno,code,syscall,path,spawnargs,error,status,signal,output,pid,stdout,stderr:spawnSync definitely-missing-opencontainers-command ENOENT' || timeoutType !== 'ERR_INVALID_ARG_TYPE' || timeoutRange !== 'ERR_OUT_OF_RANGE' || maxBufferType !== 'ERR_INVALID_ARG_TYPE' || maxBufferRange !== 'ERR_OUT_OF_RANGE' || asyncSpawnMissingRow !== expectedAsyncSpawnMissingRow || asyncShellMissingRow !== expectedAsyncShellMissingRow || asyncExecFileMissingRow !== expectedAsyncExecFileMissingRow || asyncExecShellMissingRow !== expectedAsyncExecShellMissingRow || abortResult !== 'error:AbortError:ABORT_ERR:The operation was aborted:probe|close::SIGKILL:true::SIGKILL' || invalidSignal !== 'ERR_INVALID_ARG_TYPE') throw new Error('child_process probe failed'); const asyncBufferResult = await new Promise((resolve) => cp.execFile('node', ['-e', \"process.stdout.write('ab'); process.stderr.write('cd')\"], { encoding: 'buffer' }, (error, stdout, stderr) => resolve({ error, stdout, stderr }))); if (asyncBufferResult.error || !Buffer.isBuffer(asyncBufferResult.stdout) || asyncBufferResult.stdout.toString() !== 'ab' || !Buffer.isBuffer(asyncBufferResult.stderr) || asyncBufferResult.stderr.toString() !== 'cd') throw new Error('child_process async buffer encoding failed'); const asyncLimited = await new Promise((resolve) => cp.execFile('node', ['-e', \"process.stdout.write('abcd'); process.stderr.write('e')\"], { maxBuffer: 3, encoding: 'utf8' }, (error, stdout, stderr) => resolve({ error, stdout, stderr }))); if (asyncLimited.error?.name !== 'RangeError' || asyncLimited.error?.code !== 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER' || asyncLimited.error?.message !== 'stdout maxBuffer length exceeded' || asyncLimited.stdout !== 'abc' || asyncLimited.stderr !== '') throw new Error('child_process async maxBuffer failed'); const asyncExecLimited = await new Promise((resolve) => cp.exec('printf abcd', { maxBuffer: 3, encoding: 'utf8' }, (error, stdout, stderr) => resolve({ error, stdout, stderr }))); if (asyncExecLimited.error?.code !== 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER' || asyncExecLimited.stdout !== 'abc' || asyncExecLimited.stderr !== '') throw new Error('child_process exec async maxBuffer failed'); const asyncTimeout = await new Promise((resolve) => cp.execFile('node', ['-e', \"setTimeout(() => {}, 1000)\"], { timeout: 5, killSignal: 'SIGKILL', encoding: 'utf8' }, (error, stdout, stderr) => resolve({ error, stdout, stderr }))); if (asyncTimeout.error?.killed !== true || asyncTimeout.error?.signal !== 'SIGKILL' || asyncTimeout.error?.code !== null || asyncTimeout.stdout !== '' || asyncTimeout.stderr !== '') throw new Error('child_process async timeout failed'); const asyncExecTimeout = await new Promise((resolve) => cp.exec(\"node -e 'setTimeout(() => {}, 1000)'\", { timeout: 5, encoding: 'utf8' }, (error, stdout, stderr) => resolve({ error, stdout, stderr }))); if (asyncExecTimeout.error?.killed !== true || asyncExecTimeout.error?.signal !== 'SIGTERM' || asyncExecTimeout.error?.code !== null || asyncExecTimeout.stdout !== '' || asyncExecTimeout.stderr !== '') throw new Error('child_process exec async timeout failed'); const asyncPerStreamOk = await new Promise((resolve) => cp.execFile('node', ['-e', \"process.stdout.write('ab'); process.stderr.write('cd')\"], { maxBuffer: 3, encoding: 'utf8' }, (error, stdout, stderr) => resolve({ error, stdout, stderr }))); if (asyncPerStreamOk.error || asyncPerStreamOk.stdout !== 'ab' || asyncPerStreamOk.stderr !== 'cd') throw new Error('child_process async maxBuffer per-stream failed'); const asyncBoundaryOk = await new Promise((resolve) => cp.execFile('node', ['-e', \"process.stdout.write('abc'); process.stderr.write('xyz')\"], { maxBuffer: 3, encoding: 'utf8' }, (error, stdout, stderr) => resolve({ error, stdout, stderr }))); if (asyncBoundaryOk.error || asyncBoundaryOk.stdout !== 'abc' || asyncBoundaryOk.stderr !== 'xyz') throw new Error('child_process async maxBuffer boundary failed'); const asyncBufferLimited = await new Promise((resolve) => cp.execFile('node', ['-e', \"process.stdout.write('abcd')\"], { maxBuffer: 3, encoding: 'buffer' }, (error, stdout, stderr) => resolve({ error, stdout, stderr }))); if (asyncBufferLimited.error?.name !== 'RangeError' || asyncBufferLimited.error?.code !== 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER' || Object.keys(asyncBufferLimited.error).join(',') !== 'code,cmd' || 'killed' in asyncBufferLimited.error || 'signal' in asyncBufferLimited.error || 'stdout' in asyncBufferLimited.error || 'stderr' in asyncBufferLimited.error || !Buffer.isBuffer(asyncBufferLimited.stdout) || asyncBufferLimited.stdout.toString() !== 'abc' || !Buffer.isBuffer(asyncBufferLimited.stderr) || asyncBufferLimited.stderr.length !== 0) throw new Error('child_process async buffer maxBuffer failed'); const asyncExecBufferResult = await new Promise((resolve) => cp.exec('printf bufexec', { encoding: 'buffer' }, (error, stdout, stderr) => resolve({ error, stdout, stderr }))); if (asyncExecBufferResult.error || !Buffer.isBuffer(asyncExecBufferResult.stdout) || asyncExecBufferResult.stdout.toString() !== 'bufexec' || !Buffer.isBuffer(asyncExecBufferResult.stderr) || asyncExecBufferResult.stderr.length !== 0) throw new Error('child_process exec async buffer encoding failed'); const childDisposeDescriptor = Object.getOwnPropertyDescriptor(cp.ChildProcess.prototype, Symbol.dispose); const childDisposable = new cp.ChildProcess(); let childDisposeKills = 0; childDisposable.kill = () => { childDisposeKills += 1; return true; }; const childDisposeReturn = childDisposable[Symbol.dispose](); if (!childDisposeDescriptor || typeof childDisposeDescriptor.value !== 'function' || childDisposeDescriptor.value.name !== '' || childDisposeDescriptor.value.length !== 0 || childDisposeDescriptor.enumerable !== true || childDisposeDescriptor.configurable !== true || childDisposeDescriptor.writable !== true || !Object.hasOwn(childDisposeDescriptor.value, 'prototype') || Object.getOwnPropertySymbols(cp.ChildProcess.prototype).map(String).join(',') !== 'Symbol(Symbol.dispose)' || childDisposeReturn !== undefined || childDisposeKills !== 1) throw new Error('child_process Symbol.dispose failed');", "unsupported": { "probe": "require('node:child_process')._forkChild()", "code": "ERR_OPENCONTAINERS_CHILD_PROCESS_UNSUPPORTED" } }, { "specifier": "node:cluster", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Virtual cluster workers can fork the current OpenContainers entrypoint and emit lifecycle events with Node-shaped CommonJS export order, module EventEmitter metadata without leaking the internal OpenContainers event storage symbol, and Worker callable constructor/prototype plus method prototype metadata, and native-shaped setup/fork/disconnect helper function metadata; IPC, handle passing, shared server handles, and real multi-process OS semantics remain unsupported.", "probe": "const cluster = require('node:cluster'); const { EventEmitter } = require('node:events'); const clusterKeys = Reflect.ownKeys(cluster).map(String); const clusterShape = [cluster instanceof EventEmitter, ['_events','_eventsCount','_maxListeners','Symbol(shapeMode)','Symbol(kCapture)'].every((key) => clusterKeys.includes(key)), !clusterKeys.includes('Symbol(opencontainers.events)'), Object.getPrototypeOf(cluster._events) === null, cluster._eventsCount, cluster._maxListeners === undefined].join(':'); const keys = '_events,_eventsCount,_maxListeners,isWorker,isMaster,isPrimary,Worker,workers,settings,SCHED_NONE,SCHED_RR,schedulingPolicy,setupPrimary,setupMaster,fork,disconnect'; const helperMeta = ['setupPrimary','setupMaster','fork','disconnect'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(cluster, name); const fn = cluster[name]; return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, JSON.stringify(fn.name), fn.length, Object.hasOwn(fn, 'prototype'), Object.getOwnPropertyNames(fn.prototype ?? {}).join(','), Object.keys(fn.prototype ?? {}).join(',')].join(':'); }).join('|'); const workerPrototypeDescriptor = Object.getOwnPropertyDescriptor(cluster.Worker, 'prototype'); const workerPrototypeMeta = [workerPrototypeDescriptor.enumerable, workerPrototypeDescriptor.configurable, workerPrototypeDescriptor.writable, Object.getOwnPropertyNames(workerPrototypeDescriptor.value).join(',')].join(':'); const calledWorker = cluster.Worker(); const calledWorkerMeta = [calledWorker instanceof cluster.Worker, calledWorker.id, calledWorker.state].join(':'); const workerMethodPrototypeMeta = ['kill','send','isDead','isConnected','disconnect','destroy'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(cluster.Worker.prototype, name); const fn = descriptor.value; const prototypeDescriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); const constructorDescriptor = Object.getOwnPropertyDescriptor(prototypeDescriptor?.value ?? {}, 'constructor'); let constructable = 'no'; try { Reflect.construct(Object, [], fn); constructable = 'yes'; } catch {} return [name, Object.hasOwn(fn, 'prototype'), prototypeDescriptor?.enumerable ?? '', prototypeDescriptor?.configurable ?? '', prototypeDescriptor?.writable ?? '', Object.getOwnPropertyNames(prototypeDescriptor?.value ?? {}).join(','), constructorDescriptor?.value === fn, constructable].join(':'); }).join('|'); if (Object.keys(cluster).join(',') !== keys || clusterShape !== 'true:true:true:true:0:true' || !cluster.isPrimary || typeof cluster.setupPrimary !== 'function' || typeof cluster.fork !== 'function' || cluster.setupPrimary !== cluster.setupMaster || helperMeta !== 'setupPrimary:true:true:true:\"\":1:true:constructor:|setupMaster:true:true:true:\"\":1:true:constructor:|fork:true:true:true:\"\":1:true:constructor:|disconnect:true:true:true:\"\":1:true:constructor:' || typeof cluster.Worker !== 'function' || cluster.Worker.name !== 'Worker' || cluster.Worker.length !== 1 || workerPrototypeMeta !== 'false:false:true:constructor,kill,send,isDead,isConnected,disconnect,destroy' || calledWorkerMeta !== 'true:0:none' || workerMethodPrototypeMeta !== 'kill:true:false:false:true:constructor:true:yes|send:true:false:false:true:constructor:true:yes|isDead:true:false:false:true:constructor:true:yes|isConnected:true:false:false:true:constructor:true:yes|disconnect:true:false:false:true:constructor:true:yes|destroy:true:false:false:true:constructor:true:yes') throw new Error('cluster failed')", "unsupported": { "probe": "new (require('node:cluster').Worker)().send({})", "code": "ERR_OPENCONTAINERS_CLUSTER_IPC_UNSUPPORTED" } }, { "specifier": "node:crypto", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Common hash algorithms including MD5/SHA with buffer digest output, native-ordered getHashes/getCurves discovery-list probes, random UUID v4/v7 helpers, Node-shaped randomBytes/randomInt/randomFill validation, native-shaped CommonJS export order, native-shaped descriptor, browser-safe prime check/generation probes, OpenSSL/FIPS helper validation, random/helper own-prototype metadata, and function/prototype metadata for constants/WebCrypto/legacy random aliases/timingSafeEqual/common helpers, stable OpenSSL option/version/cipher-list constants including native-shaped defaultCipherList accessor-to-data assignment metadata plus TLS protocol aliases and RSA/DH/engine/point-conversion constants, getRandomValues, HMAC, AES-CBC/CTR/GCM, PBKDF2/HKDF/scrypt KDFs, WebCrypto, OpenSSL engine/FIPS probes, Node-shaped Hash/Hmac deprecated public constructor names, callable Hash/Hmac direct constructors, and Cipheriv/Decipheriv constructors, callable Certificate constructor with native-shaped static/prototype descriptor metadata and malformed-SPKAC fallbacks, X509Certificate metadata, public/private key probes, and constructable/writable asymmetric package probes are present; native OpenSSL coverage, Argon2, and KEM encapsulation/decapsulation remain unsupported with stable errors and Node-shaped arities.", "unsupported": { "probe": "const crypto = require('node:crypto'); const params = { message: Buffer.from('password'), nonce: Buffer.alloc(16), parallelism: 1, tagLength: 32, memory: 1024, passes: 1 }; crypto.argon2Sync('argon2id', params)", "code": "ERR_OPENCONTAINERS_CRYPTO_UNSUPPORTED" }, "probe": "const crypto = require('node:crypto'); const expectedCryptoKeys = 'argon2,argon2Sync,checkPrime,checkPrimeSync,createCipheriv,createDecipheriv,createDiffieHellman,createDiffieHellmanGroup,createECDH,createHash,createHmac,createPrivateKey,createPublicKey,createSecretKey,createSign,createVerify,diffieHellman,generatePrime,generatePrimeSync,getCiphers,getCipherInfo,getCurves,getDiffieHellman,getHashes,hkdf,hkdfSync,pbkdf2,pbkdf2Sync,generateKeyPair,generateKeyPairSync,generateKey,generateKeySync,privateDecrypt,privateEncrypt,publicDecrypt,publicEncrypt,randomBytes,randomFill,randomFillSync,randomInt,randomUUID,randomUUIDv7,scrypt,scryptSync,sign,setEngine,timingSafeEqual,getFips,setFips,verify,hash,encapsulate,decapsulate,Certificate,Cipheriv,Decipheriv,DiffieHellman,DiffieHellmanGroup,ECDH,Hash,Hmac,KeyObject,Sign,Verify,X509Certificate,secureHeapUsed,constants,webcrypto,subtle,getRandomValues'; const constantsDescriptor = Object.getOwnPropertyDescriptor(crypto, 'constants'); const webcryptoDescriptor = Object.getOwnPropertyDescriptor(crypto, 'webcrypto'); const getRandomValuesDescriptor = Object.getOwnPropertyDescriptor(crypto, 'getRandomValues'); const fipsDescriptor = Object.getOwnPropertyDescriptor(crypto, 'fips'); const aliasDescriptor = Object.getOwnPropertyDescriptor(crypto, 'pseudoRandomBytes'); const paddingDescriptor = Object.getOwnPropertyDescriptor(crypto.constants, 'RSA_PKCS1_PADDING'); const tlsDescriptor = Object.getOwnPropertyDescriptor(crypto.constants, 'TLS1_3_VERSION'); const coreCipherDescriptor = Object.getOwnPropertyDescriptor(crypto.constants, 'defaultCoreCipherList'); const cipherDescriptor = Object.getOwnPropertyDescriptor(crypto.constants, 'defaultCipherList'); crypto.constants.defaultCipherList = 'override'; const assignedCipherDescriptor = Object.getOwnPropertyDescriptor(crypto.constants, 'defaultCipherList'); if (Object.keys(crypto).join(',') !== expectedCryptoKeys || !constantsDescriptor.enumerable || constantsDescriptor.configurable || constantsDescriptor.writable || Object.getPrototypeOf(crypto.constants) !== null || !paddingDescriptor.enumerable || paddingDescriptor.configurable || paddingDescriptor.writable || crypto.constants.RSA_X931_PADDING !== 5 || crypto.constants.DH_CHECK_P_NOT_PRIME !== 1 || crypto.constants.DH_NOT_SUITABLE_GENERATOR !== 8 || crypto.constants.POINT_CONVERSION_HYBRID !== 6 || crypto.constants.TLS1_VERSION !== 769 || crypto.constants.TLS1_1_VERSION !== 770 || crypto.constants.TLS1_2_VERSION !== 771 || crypto.constants.TLS1_3_VERSION !== 772 || !tlsDescriptor.enumerable || tlsDescriptor.configurable || tlsDescriptor.writable || crypto.constants.OPENSSL_VERSION_NUMBER !== 810549344 || crypto.constants.SSL_OP_ALL !== 2147485776 || crypto.constants.SSL_OP_NO_TLSv1 !== 67108864 || crypto.constants.SSL_OP_NO_TLSv1_3 !== 536870912 || crypto.constants.SSL_OP_NO_SSLv3 !== 33554432 || crypto.constants.SSL_OP_NO_COMPRESSION !== 131072 || crypto.constants.SSL_OP_PRIORITIZE_CHACHA !== 2097152 || typeof crypto.constants.defaultCoreCipherList !== 'string' || !crypto.constants.defaultCoreCipherList.includes('TLS_AES_256_GCM_SHA384') || !coreCipherDescriptor.enumerable || coreCipherDescriptor.configurable || coreCipherDescriptor.writable || typeof coreCipherDescriptor.value !== 'string' || !cipherDescriptor.enumerable || !cipherDescriptor.configurable || typeof cipherDescriptor.get !== 'function' || typeof cipherDescriptor.set !== 'function' || crypto.constants.defaultCipherList !== 'override' || !assignedCipherDescriptor.enumerable || !assignedCipherDescriptor.configurable || !assignedCipherDescriptor.writable || typeof assignedCipherDescriptor.value !== 'string' || typeof assignedCipherDescriptor.get !== 'undefined' || typeof assignedCipherDescriptor.set !== 'undefined' || !webcryptoDescriptor.enumerable || webcryptoDescriptor.configurable || typeof webcryptoDescriptor.get !== 'function' || !getRandomValuesDescriptor.enumerable || getRandomValuesDescriptor.configurable || typeof getRandomValuesDescriptor.get !== 'function' || crypto.getRandomValues.name !== 'getRandomValues' || crypto.getRandomValues.length !== 1 || fipsDescriptor.enumerable || fipsDescriptor.configurable || typeof fipsDescriptor.get !== 'function' || fipsDescriptor.get.name !== 'deprecated' || fipsDescriptor.get.length !== 0 || !Object.hasOwn(fipsDescriptor.get, 'prototype') || typeof fipsDescriptor.set !== 'function' || fipsDescriptor.set.name !== 'deprecated' || fipsDescriptor.set.length !== 1 || !Object.hasOwn(fipsDescriptor.set, 'prototype') || aliasDescriptor.enumerable || !aliasDescriptor.configurable || typeof aliasDescriptor.get !== 'function' || typeof aliasDescriptor.set !== 'function' || Object.keys(crypto).includes('pseudoRandomBytes') || crypto.pseudoRandomBytes !== crypto.randomBytes) throw new Error('crypto descriptor metadata failed'); const cryptoMetadata = ['checkPrime','checkPrimeSync','createDiffieHellman','createHash','createHmac','createSecretKey','createSign','createVerify','diffieHellman','generatePrime','generatePrimeSync','generateKeyPair','generateKeyPairSync','generateKey','generateKeySync','privateDecrypt','privateEncrypt','publicDecrypt','publicEncrypt','randomFill','randomFillSync','randomInt','randomUUID','randomUUIDv7','scrypt','pbkdf2Sync','setEngine','getFips','setFips','timingSafeEqual','sign','verify','getCiphers','getCurves','getHashes','getDiffieHellman','Cipheriv','Decipheriv','Hash','Hmac','Sign','Verify','secureHeapUsed'].map((name) => name + ':' + crypto[name].name + '/' + crypto[name].length).join('|'); const deprecatedConstructorRows = [crypto.Hash.name, crypto.Hmac.name, crypto.Hash('sha256').constructor.name, crypto.Hmac('sha256', 'key').constructor.name].join(':'); const cryptoPrototypeMetadata = ['setEngine','getFips','setFips','secureHeapUsed'].map((name) => { const prototypeDescriptor = Object.getOwnPropertyDescriptor(crypto[name], 'prototype'); return [name, crypto[name].name, crypto[name].length, Object.hasOwn(crypto[name], 'prototype'), prototypeDescriptor.enumerable, prototypeDescriptor.configurable, prototypeDescriptor.writable, Object.getOwnPropertyNames(prototypeDescriptor.value).join(',')].join(':'); }).join('|'); const randomPrototypeMetadata = ['randomBytes','randomFill','randomFillSync','randomInt','randomUUID','randomUUIDv7'].map((name) => { const prototypeDescriptor = Object.getOwnPropertyDescriptor(crypto[name], 'prototype'); return [name, crypto[name].name, crypto[name].length, Object.hasOwn(crypto[name], 'prototype'), prototypeDescriptor.enumerable, prototypeDescriptor.configurable, prototypeDescriptor.writable, Object.getOwnPropertyNames(prototypeDescriptor.value).join(',')].join(':'); }).join('|'); const helperPrototypeMetadata = ['createCipheriv','createDecipheriv','createDiffieHellman','createDiffieHellmanGroup','createECDH','createHash','createHmac','createPrivateKey','createPublicKey','createSecretKey','createSign','createVerify','diffieHellman','generateKeyPair','generateKeyPairSync','generateKey','generateKeySync','getDiffieHellman','hkdf','pbkdf2','scrypt','sign','verify'].map((name) => { const prototypeDescriptor = Object.getOwnPropertyDescriptor(crypto[name], 'prototype'); return [name, crypto[name].name, crypto[name].length, Object.hasOwn(crypto[name], 'prototype'), prototypeDescriptor.enumerable, prototypeDescriptor.configurable, prototypeDescriptor.writable, Object.getOwnPropertyNames(prototypeDescriptor.value).join(',')].join(':'); }).join('|'); const certificateFunctionRow = (target, name) => { const descriptor = Object.getOwnPropertyDescriptor(target, name); const prototypeDescriptor = Object.getOwnPropertyDescriptor(descriptor.value, 'prototype'); return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype'), prototypeDescriptor?.enumerable, prototypeDescriptor?.configurable, prototypeDescriptor?.writable, Object.getOwnPropertyNames(prototypeDescriptor?.value ?? {}).join(','), prototypeDescriptor?.value?.constructor === descriptor.value].join(':'); }; const certificateRows = [crypto.Certificate() instanceof crypto.Certificate, new crypto.Certificate() instanceof crypto.Certificate, crypto.Certificate.length, Object.getOwnPropertyNames(crypto.Certificate).join(','), Object.keys(crypto.Certificate).join(','), Object.getOwnPropertyNames(crypto.Certificate.prototype).join(','), Object.keys(crypto.Certificate.prototype).join(','), JSON.stringify(crypto.Certificate.verifySpkac(Buffer.alloc(0))), crypto.Certificate.verifySpkac(Buffer.from('x')), JSON.stringify(crypto.Certificate.exportPublicKey(Buffer.alloc(0))), JSON.stringify(new crypto.Certificate().exportChallenge(Buffer.alloc(0)))].join(';'); const certificateStaticMetadata = ['exportChallenge','exportPublicKey','verifySpkac'].map((name) => certificateFunctionRow(crypto.Certificate, name)).join('|'); const certificatePrototypeMetadata = ['verifySpkac','exportPublicKey','exportChallenge'].map((name) => certificateFunctionRow(crypto.Certificate.prototype, name)).join('|'); const certificateMissingRows = ['verifySpkac','exportPublicKey','exportChallenge'].map((name) => { try { crypto.Certificate[name](); return name + ':ok'; } catch (error) { return [name, error.name, error.code].join(':'); } }).join('|'); const hashes = crypto.getHashes(); const curves = crypto.getCurves(); hashes.push('mutated'); curves.push('mutated'); const discoveryRows = [hashes.length, hashes[0], hashes.at(-2), crypto.getHashes().length, crypto.getHashes().at(-1), crypto.getHashes().includes('mutated'), crypto.getHashes().includes('RSA-SHA256'), curves.length, curves[0], curves.at(-2), crypto.getCurves().length, crypto.getCurves().at(-1), crypto.getCurves().includes('mutated'), crypto.getCurves().includes('prime256v1'), crypto.getCurves().includes('secp256k1')].join(':'); if (discoveryRows !== '53:RSA-MD5:ssl3-sha1:52:ssl3-sha1:false:true:83:Oakley-EC2N-3:wap-wsg-idm-ecid-wtls9:82:wap-wsg-idm-ecid-wtls9:false:true:true' || deprecatedConstructorRows !== 'deprecated:deprecated:Hash:Hmac' || cryptoMetadata !== 'checkPrime:checkPrime/1|checkPrimeSync:checkPrimeSync/1|createDiffieHellman:createDiffieHellman/4|createHash:createHash/2|createHmac:createHmac/3|createSecretKey:createSecretKey/2|createSign:createSign/2|createVerify:createVerify/2|diffieHellman:diffieHellman/2|generatePrime:generatePrime/3|generatePrimeSync:generatePrimeSync/1|generateKeyPair:generateKeyPair/3|generateKeyPairSync:generateKeyPairSync/2|generateKey:generateKey/3|generateKeySync:generateKeySync/2|privateDecrypt:/2|privateEncrypt:/2|publicDecrypt:/2|publicEncrypt:/2|randomFill:randomFill/4|randomFillSync:randomFillSync/1|randomInt:randomInt/3|randomUUID:randomUUID/1|randomUUIDv7:randomUUIDv7/1|scrypt:scrypt/4|pbkdf2Sync:pbkdf2Sync/5|setEngine:setEngine/2|getFips:getFips/0|setFips:setFips/1|timingSafeEqual:/0|sign:signOneShot/4|verify:verifyOneShot/5|getCiphers:/0|getCurves:/0|getHashes:/0|getDiffieHellman:createDiffieHellmanGroup/1|Cipheriv:Cipheriv/4|Decipheriv:Decipheriv/4|Hash:deprecated/2|Hmac:deprecated/3|Sign:Sign/2|Verify:Verify/2|secureHeapUsed:secureHeapUsed/0' || cryptoPrototypeMetadata !== 'setEngine:setEngine:2:true:false:false:true:constructor|getFips:getFips:0:true:false:false:true:constructor|setFips:setFips:1:true:false:false:true:constructor|secureHeapUsed:secureHeapUsed:0:true:false:false:true:constructor' || randomPrototypeMetadata !== 'randomBytes:randomBytes:2:true:false:false:true:constructor|randomFill:randomFill:4:true:false:false:true:constructor|randomFillSync:randomFillSync:1:true:false:false:true:constructor|randomInt:randomInt:3:true:false:false:true:constructor|randomUUID:randomUUID:1:true:false:false:true:constructor|randomUUIDv7:randomUUIDv7:1:true:false:false:true:constructor' || helperPrototypeMetadata !== 'createCipheriv:createCipheriv:4:true:false:false:true:constructor|createDecipheriv:createDecipheriv:4:true:false:false:true:constructor|createDiffieHellman:createDiffieHellman:4:true:false:false:true:constructor|createDiffieHellmanGroup:createDiffieHellmanGroup:1:true:false:false:true:constructor|createECDH:createECDH:1:true:false:false:true:constructor|createHash:createHash:2:true:false:false:true:constructor|createHmac:createHmac:3:true:false:false:true:constructor|createPrivateKey:createPrivateKey:1:true:false:false:true:constructor|createPublicKey:createPublicKey:1:true:false:false:true:constructor|createSecretKey:createSecretKey:2:true:false:false:true:constructor|createSign:createSign:2:true:false:false:true:constructor|createVerify:createVerify:2:true:false:false:true:constructor|diffieHellman:diffieHellman:2:true:false:false:true:constructor|generateKeyPair:generateKeyPair:3:true:false:false:true:constructor|generateKeyPairSync:generateKeyPairSync:2:true:false:false:true:constructor|generateKey:generateKey:3:true:false:false:true:constructor|generateKeySync:generateKeySync:2:true:false:false:true:constructor|getDiffieHellman:createDiffieHellmanGroup:1:true:false:false:true:constructor|hkdf:hkdf:6:true:false:false:true:constructor|pbkdf2:pbkdf2:6:true:false:false:true:constructor|scrypt:scrypt:4:true:false:false:true:constructor|sign:signOneShot:4:true:false:false:true:constructor|verify:verifyOneShot:5:true:false:false:true:constructor' || certificateRows !== 'true;true;0;length,name,prototype,exportChallenge,exportPublicKey,verifySpkac;exportChallenge,exportPublicKey,verifySpkac;constructor,verifySpkac,exportPublicKey,exportChallenge;verifySpkac,exportPublicKey,exportChallenge;\"\";false;\"\";\"\"' || certificateStaticMetadata !== 'exportChallenge:true:true:true:exportChallenge:2:true:false:false:true:constructor:true|exportPublicKey:true:true:true:exportPublicKey:2:true:false:false:true:constructor:true|verifySpkac:true:true:true:verifySpkac:2:true:false:false:true:constructor:true' || certificatePrototypeMetadata !== 'verifySpkac:true:true:true:verifySpkac:2:true:false:false:true:constructor:true|exportPublicKey:true:true:true:exportPublicKey:2:true:false:false:true:constructor:true|exportChallenge:true:true:true:exportChallenge:2:true:false:false:true:constructor:true' || certificateMissingRows !== 'verifySpkac:TypeError:ERR_INVALID_ARG_TYPE|exportPublicKey:TypeError:ERR_INVALID_ARG_TYPE|exportChallenge:TypeError:ERR_INVALID_ARG_TYPE') throw new Error('crypto function metadata failed'); const primeRows = [crypto.checkPrimeSync(Buffer.from([4])), crypto.checkPrimeSync(Buffer.from([5])), crypto.checkPrimeSync(new Uint8Array([17])), crypto.checkPrimeSync(new DataView(Uint8Array.from([17]).buffer)), crypto.checkPrimeSync(5n), crypto.checkPrimeSync(Buffer.alloc(0)), crypto.checkPrimeSync(Buffer.from([5]), { checks: 0 })].join(':'); const generatedPrime = crypto.generatePrimeSync(8); const generatedPrimeBigInt = crypto.generatePrimeSync(8, { bigint: true }); const generatedSafePrime = crypto.generatePrimeSync(8, { safe: true, bigint: true }); const generatedConstrainedPrime = crypto.generatePrimeSync(8, { add: Buffer.from([3]), rem: Buffer.from([2]), bigint: true }); const primeAsyncRows = []; await new Promise((resolve) => { let pending = 2; const done = () => { pending -= 1; if (pending === 0) resolve(); }; crypto.checkPrime(Buffer.from([5]), (error, value) => { primeAsyncRows.push('check:' + error + ':' + value); done(); }); crypto.generatePrime(8, { bigint: true }, (error, value) => { primeAsyncRows.push('generate:' + error + ':' + typeof value + ':' + crypto.checkPrimeSync(value)); done(); }); }); const primeErrorRows = [['candidate-number', () => crypto.checkPrimeSync(5)], ['options-null', () => crypto.checkPrimeSync(Buffer.from([5]), null)], ['checks-string', () => crypto.checkPrimeSync(Buffer.from([5]), { checks: '1' })], ['checks-negative', () => crypto.checkPrimeSync(Buffer.from([5]), { checks: -1 })], ['size-zero', () => crypto.generatePrimeSync(0)], ['size-one', () => crypto.generatePrimeSync(1)], ['size-string', () => crypto.generatePrimeSync('8')], ['bigint-string', () => crypto.generatePrimeSync(8, { bigint: 'yes' })], ['add-number', () => crypto.generatePrimeSync(8, { add: 3 })], ['check-callback-missing', () => crypto.checkPrime(Buffer.from([5]))], ['generate-callback-missing', () => crypto.generatePrime(8)]].map(([label, action]) => { try { action(); return label + ':ok'; } catch (error) { return [label, error.name, error.code].join(':'); } }).join('|'); if (primeRows !== 'false:true:true:true:true:false:true' || Object.prototype.toString.call(generatedPrime) !== '[object ArrayBuffer]' || generatedPrime.byteLength !== 1 || !crypto.checkPrimeSync(generatedPrime) || typeof generatedPrimeBigInt !== 'bigint' || !crypto.checkPrimeSync(generatedPrimeBigInt) || typeof generatedSafePrime !== 'bigint' || !crypto.checkPrimeSync(generatedSafePrime) || !crypto.checkPrimeSync((generatedSafePrime - 1n) / 2n) || generatedConstrainedPrime % 3n !== 2n || !crypto.checkPrimeSync(generatedConstrainedPrime) || primeAsyncRows.join('|') !== 'check:undefined:true|generate:undefined:bigint:true' || primeErrorRows !== 'candidate-number:TypeError:ERR_INVALID_ARG_TYPE|options-null:TypeError:ERR_INVALID_ARG_TYPE|checks-string:TypeError:ERR_INVALID_ARG_TYPE|checks-negative:RangeError:ERR_OUT_OF_RANGE|size-zero:RangeError:ERR_OUT_OF_RANGE|size-one:Error:ERR_OSSL_BN_BITS_TOO_SMALL|size-string:TypeError:ERR_INVALID_ARG_TYPE|bigint-string:TypeError:ERR_INVALID_ARG_TYPE|add-number:TypeError:ERR_INVALID_ARG_TYPE|check-callback-missing:TypeError:ERR_INVALID_ARG_TYPE|generate-callback-missing:TypeError:ERR_INVALID_ARG_TYPE') throw new Error('crypto prime helpers failed'); for (const [label, action, code] of [['randomBytes-undefined', () => crypto.randomBytes(undefined), 'ERR_INVALID_ARG_TYPE'], ['randomBytes-string', () => crypto.randomBytes('4'), 'ERR_INVALID_ARG_TYPE'], ['randomBytes-nan', () => crypto.randomBytes(NaN), 'ERR_OUT_OF_RANGE'], ['randomBytes-infinity', () => crypto.randomBytes(Infinity), 'ERR_OUT_OF_RANGE'], ['randomBytes-negative', () => crypto.randomBytes(-1), 'ERR_OUT_OF_RANGE'], ['randomBytes-too-large', () => crypto.randomBytes(2 ** 31), 'ERR_OUT_OF_RANGE'], ['randomBytes-callback', () => crypto.randomBytes(4, 123), 'ERR_INVALID_ARG_TYPE']]) { try { action(); throw new Error(label + ' validation failed') } catch (error) { if (error.message === label + ' validation failed' || error.code !== code) throw error } } const cryptoValidationRows = [[\"randomInt-range\", () => crypto.randomInt(0, 2 ** 48), \"ERR_OUT_OF_RANGE\"], [\"randomInt-min-type\", () => crypto.randomInt(\"1\", 3), \"ERR_INVALID_ARG_TYPE\"], [\"randomInt-callback\", () => crypto.randomInt(1, 3, \"callback\"), \"ERR_INVALID_ARG_TYPE\"], [\"randomFill-callback\", () => crypto.randomFill(Buffer.alloc(4)), \"ERR_INVALID_ARG_TYPE\"], [\"randomFill-buf\", () => crypto.randomFill(\"x\", () => {}), \"ERR_INVALID_ARG_TYPE\"], [\"randomFill-offset\", () => crypto.randomFill(Buffer.alloc(4), \"1\", () => {}), \"ERR_INVALID_ARG_TYPE\"], [\"randomFill-size\", () => crypto.randomFill(Buffer.alloc(4), 0, \"2\", () => {}), \"ERR_INVALID_ARG_TYPE\"], [\"randomFill-range\", () => crypto.randomFill(Buffer.alloc(4), 0, 5, () => {}), \"ERR_OUT_OF_RANGE\"], [\"randomFillSync-buf\", () => crypto.randomFillSync(\"x\"), \"ERR_INVALID_ARG_TYPE\"], [\"randomFillSync-null\", () => crypto.randomFillSync(null), \"ERR_INVALID_ARG_TYPE\"], [\"randomFillSync-range\", () => crypto.randomFillSync(Buffer.alloc(4), 0, 5), \"ERR_OUT_OF_RANGE\"]]; for (const [label, action, code] of cryptoValidationRows) { try { action(); throw new Error(label + \" validation failed\") } catch (error) { if (error.message === label + \" validation failed\" || error.code !== code) throw error } } for (const [label, action] of [['setEngine-id', () => crypto.setEngine()], ['setEngine-flags', () => crypto.setEngine('missing', 'bad')]]) { try { action(); throw new Error(label + ' validation failed') } catch (error) { if (error.message === label + ' validation failed' || error.code !== 'ERR_INVALID_ARG_TYPE') throw error } } const oneArgRandomInt = crypto.randomInt(2); const randomFillArrayBuffer = new ArrayBuffer(4); const randomFillDataView = new DataView(new ArrayBuffer(4)); const randomFillTypedArray = new Uint16Array(2); if (!Number.isInteger(oneArgRandomInt) || oneArgRandomInt < 0 || oneArgRandomInt >= 2 || crypto.randomFillSync(randomFillArrayBuffer) !== randomFillArrayBuffer || crypto.randomFillSync(randomFillDataView) !== randomFillDataView || crypto.randomFillSync(randomFillTypedArray) !== randomFillTypedArray) throw new Error(\"crypto random validation success paths failed\"); if (crypto.randomBytes(1.5).length !== 1) throw new Error('randomBytes fraction failed'); const key = crypto.createSecretKey(Buffer.alloc(32, 7)); const iv = Buffer.alloc(16, 1); const digestBuffer = crypto.createHash('sha256').update('abc').digest('buffer'); const hmacBuffer = crypto.createHmac('sha256', 'secret').update('hello').digest('buffer'); const oneShotHash = crypto.hash('sha256', 'abc', 'buffer'); const cipher = crypto.createCipheriv('aes-256-cbc', key, iv); const encrypted = Buffer.concat([cipher.update('secret'), cipher.final()]); const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv); const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]).toString(); const hmac = crypto.createHmac('sha256', key).update('hello').digest('hex'); const pbkdf2 = crypto.pbkdf2Sync('password', 'salt', 2, 16, 'sha1'); const scrypt = crypto.scryptSync('password', 'salt', 16, { N: 16, r: 1, p: 1 }); const keyPairError = await new Promise((resolve) => crypto.generateKeyPair('rsa', { modulusLength: 2048 }, (error) => resolve(error))); const argon2Error = await new Promise((resolve) => crypto.argon2('argon2id', {}, (error) => resolve(error))); if (!crypto.getCiphers().includes('aes-256-cbc') || !crypto.getHashes().includes('sha256') || crypto.hash.length !== 3 || !Buffer.isBuffer(digestBuffer) || digestBuffer.toString('hex').slice(0, 8) !== 'ba7816bf' || !Buffer.isBuffer(hmacBuffer) || hmacBuffer.toString('hex').slice(0, 8) !== '88aab3ed' || !Buffer.isBuffer(oneShotHash) || oneShotHash.toString('hex').slice(0, 8) !== 'ba7816bf' || decrypted !== 'secret' || hmac.length !== 64 || !Buffer.isBuffer(pbkdf2) || pbkdf2.length !== 16 || !Buffer.isBuffer(scrypt) || scrypt.length !== 16 || crypto.argon2.length !== 3 || crypto.argon2Sync.length !== 2 || keyPairError?.code !== 'ERR_OPENCONTAINERS_CRYPTO_UNSUPPORTED' || argon2Error?.code !== 'ERR_OPENCONTAINERS_CRYPTO_UNSUPPORTED') throw new Error('crypto failed')" }, { "specifier": "node:dgram", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/net-builtin.test.mjs", "limitation": "Virtual UDP loopback sockets support udp4/udp6 bind, connect, disconnect/remoteAddress lifecycle errors, message callbacks, send/sendto chunk-array delivery, connected offset/length send overloads, unconnected numeric string port sends and native-shaped ambiguous send overload validation, queue probes, buffer sizing, AbortSignal socket option close behavior, Node-shaped CommonJS export/prototype order, native-shaped public Socket own-prototype names, writable Socket prototype descriptor, callable Socket constructor no-op parity, socket option method metadata plus native-shaped own function prototype descriptors, async disposal, Node-shaped socket type/TTL/buffer-size validation errors, unbound setBroadcast/setTTL EBADF behavior, duplicate close errors, non-function close callback tolerance, and multicast argument validation before stable unsupported multicast failures; external UDP and multicast remain blocked by the browser security model.", "probe": "const dgram = require('node:dgram'); const methods = 'bind,connect,disconnect,sendto,send,close,address,remoteAddress,setBroadcast,setTTL,setMulticastTTL,setMulticastLoopback,setMulticastInterface,addMembership,dropMembership,addSourceSpecificMembership,dropSourceSpecificMembership,ref,unref,setRecvBufferSize,setSendBufferSize,getRecvBufferSize,getSendBufferSize,getSendQueueSize,getSendQueueCount'; const own = 'constructor,' + methods; const methodList = methods.split(','); const lengths = methodList.map((name) => name + ':' + dgram.Socket.prototype[name].length).join('|'); const names = methodList.map((name) => dgram.Socket.prototype[name].name).join('|'); const prototypeRows = ['createSocket', ...methodList].map((name) => { const fn = name === 'createSocket' ? dgram.createSocket : dgram.Socket.prototype[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, Boolean(descriptor), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(','), descriptor?.value?.constructor === fn].join(':') }).join('|'); if (Object.hasOwn(dgram, 'default') || Object.keys(dgram).join(',') !== 'createSocket,Socket' || dgram.createSocket.length !== 2 || dgram.Socket.length !== 2 || Object.getOwnPropertyNames(dgram.Socket.prototype).join(',') !== own || Object.keys(dgram.Socket.prototype).join(',') !== methods || Object.getOwnPropertyNames(dgram.Socket.prototype).includes('__opencontainersReceive') || lengths !== 'bind:2|connect:3|disconnect:0|sendto:6|send:6|close:1|address:0|remoteAddress:0|setBroadcast:1|setTTL:1|setMulticastTTL:1|setMulticastLoopback:1|setMulticastInterface:1|addMembership:2|dropMembership:2|addSourceSpecificMembership:3|dropSourceSpecificMembership:3|ref:0|unref:0|setRecvBufferSize:1|setSendBufferSize:1|getRecvBufferSize:0|getSendBufferSize:0|getSendQueueSize:0|getSendQueueCount:0' || names !== '||||||||||||||||||||||||' || prototypeRows !== 'createSocket:true:false:false:true:constructor:true|bind:true:false:false:true:constructor:true|connect:true:false:false:true:constructor:true|disconnect:true:false:false:true:constructor:true|sendto:true:false:false:true:constructor:true|send:true:false:false:true:constructor:true|close:true:false:false:true:constructor:true|address:true:false:false:true:constructor:true|remoteAddress:true:false:false:true:constructor:true|setBroadcast:true:false:false:true:constructor:true|setTTL:true:false:false:true:constructor:true|setMulticastTTL:true:false:false:true:constructor:true|setMulticastLoopback:true:false:false:true:constructor:true|setMulticastInterface:true:false:false:true:constructor:true|addMembership:true:false:false:true:constructor:true|dropMembership:true:false:false:true:constructor:true|addSourceSpecificMembership:true:false:false:true:constructor:true|dropSourceSpecificMembership:true:false:false:true:constructor:true|ref:true:false:false:true:constructor:true|unref:true:false:false:true:constructor:true|setRecvBufferSize:true:false:false:true:constructor:true|setSendBufferSize:true:false:false:true:constructor:true|getRecvBufferSize:true:false:false:true:constructor:true|getSendBufferSize:true:false:false:true:constructor:true|getSendQueueSize:true:false:false:true:constructor:true|getSendQueueCount:true:false:false:true:constructor:true') throw new Error('dgram metadata failed'); const captureCode = (action) => { try { action(); return 'ok' } catch (error) { return error.code } }; const socket = dgram.createSocket('udp4'); const unboundControls = [captureCode(() => socket.disconnect()), captureCode(() => socket.remoteAddress()), captureCode(() => socket.setBroadcast(true)), captureCode(() => socket.setTTL(64)), socket.setRecvBufferSize(32) === socket, socket.setSendBufferSize(64) === socket, socket.getRecvBufferSize(), socket.getSendBufferSize(), socket.getSendQueueSize(), socket.getSendQueueCount(), socket.ref() === socket, socket.unref() === socket].join(':'); if (!(socket instanceof dgram.Socket) || !Object.prototype.hasOwnProperty.call(socket, '__opencontainersReceive') || unboundControls !== 'ERR_SOCKET_DGRAM_NOT_CONNECTED:ERR_SOCKET_DGRAM_NOT_CONNECTED:EBADF:EBADF:true:true:32:64:0:0:true:true') throw new Error('dgram unbound controls failed'); const disposeDescriptor = Object.getOwnPropertyDescriptor(dgram.Socket.prototype, Symbol.asyncDispose); if (typeof socket[Symbol.asyncDispose] !== 'function' || socket[Symbol.asyncDispose].name !== '' || socket[Symbol.asyncDispose].length !== 0 || !disposeDescriptor.enumerable || Object.hasOwn(socket[Symbol.asyncDispose], 'prototype')) throw new Error('dgram async dispose failed'); await socket[Symbol.asyncDispose](); const disposedRemoteCode = captureCode(() => socket.remoteAddress()); if (disposedRemoteCode !== 'ERR_SOCKET_DGRAM_NOT_RUNNING') throw new Error('dgram disposed remoteAddress failed'); const bound = dgram.createSocket('udp4'); await new Promise((resolve) => bound.bind(0, '127.0.0.1', resolve)); const boundControlsOk = bound.setBroadcast(true) === undefined && bound.setTTL(64) === 64 && bound.setRecvBufferSize(48) === bound && bound.setSendBufferSize(96) === bound && bound.getRecvBufferSize() === 48 && bound.getSendBufferSize() === 96; const closeResultOk = bound.close(123) === bound; await new Promise((resolve) => bound.on('close', resolve)); if (!boundControlsOk || !closeResultOk || captureCode(() => bound.close()) !== 'ERR_SOCKET_DGRAM_NOT_RUNNING') throw new Error('dgram bound controls failed'); const lifecycleServer = dgram.createSocket('udp4'); const lifecycleClient = dgram.createSocket('udp4'); await new Promise((resolve) => lifecycleServer.bind(0, '127.0.0.1', resolve)); await new Promise((resolve) => lifecycleClient.connect(lifecycleServer.address().port, '127.0.0.1', resolve)); const lifecycleRemote = lifecycleClient.remoteAddress(); const lifecycleRemotePort = lifecycleServer.address().port; const lifecycleDisconnectOk = lifecycleClient.disconnect() === undefined && captureCode(() => lifecycleClient.remoteAddress()) === 'ERR_SOCKET_DGRAM_NOT_CONNECTED'; const lifecycleClientClosed = new Promise((resolve) => lifecycleClient.on('close', resolve)); const lifecycleServerClosed = new Promise((resolve) => lifecycleServer.on('close', resolve)); lifecycleClient.close(); lifecycleServer.close(); await Promise.all([lifecycleClientClosed, lifecycleServerClosed]); if (!lifecycleDisconnectOk || lifecycleRemote.address !== '127.0.0.1' || lifecycleRemote.port !== lifecycleRemotePort) throw new Error('dgram disconnect lifecycle failed'); const connectedServer = dgram.createSocket('udp4'); const connectedClient = dgram.createSocket('udp4'); let connectedRow = ''; connectedServer.on('message', (message, rinfo) => { connectedRow = 'server:' + message.toString() + ':' + rinfo.size; connectedClient.close(); connectedServer.close(); }); await new Promise((resolve) => connectedServer.bind(0, '127.0.0.1', resolve)); await new Promise((resolve) => connectedClient.connect(connectedServer.address().port, '127.0.0.1', resolve)); connectedClient.send(Buffer.from('abcdef'), 1, 3, (error, bytes) => { connectedRow += '|callback:' + (error?.code ?? 'null') + ':' + bytes; }); await new Promise((resolve) => connectedServer.on('close', resolve)); await new Promise((resolve) => setTimeout(resolve, 0)); if (connectedRow !== 'server:bcd:3|callback:null:3') throw new Error('dgram connected offset send failed'); const overloadValidationSocket = dgram.createSocket('udp4'); const overloadValidationRows = [['callback-only', () => overloadValidationSocket.send('x', () => {})], ['offset-length-no-port', () => overloadValidationSocket.send(Buffer.from('abcd'), 1, 2, () => {})], ['bad-port-zero', () => overloadValidationSocket.send('x', 0, '127.0.0.1', () => {})]].map(([label, action]) => { try { action(); return label + ':ok' } catch (error) { return [label, error.constructor.name, error.code, error.message].join(':') } }).join('|'); overloadValidationSocket.close(); if (overloadValidationRows !== 'callback-only:RangeError:ERR_SOCKET_BAD_PORT:Port should be > 0 and < 65536. Received function .|offset-length-no-port:TypeError:ERR_INVALID_ARG_TYPE:The \"address\" argument must be of type string. Received type number (2)|bad-port-zero:RangeError:ERR_SOCKET_BAD_PORT:Port should be > 0 and < 65536. Received type number (0).') throw new Error('dgram send overload validation failed'); const stringPortServer = dgram.createSocket('udp4'); const stringPortClient = dgram.createSocket('udp4'); let stringPortRow = ''; stringPortServer.on('message', (message, rinfo) => { stringPortRow = 'server:' + message.toString() + ':' + rinfo.size; stringPortClient.close(); stringPortServer.close(); }); await new Promise((resolve) => stringPortServer.bind(0, '127.0.0.1', resolve)); stringPortClient.send('x', String(stringPortServer.address().port), '127.0.0.1', (error, bytes) => { stringPortRow += '|callback:' + (error?.code ?? 'null') + ':' + bytes; }); await new Promise((resolve) => stringPortServer.on('close', resolve)); await new Promise((resolve) => setTimeout(resolve, 0)); if (stringPortRow !== 'server:x:1|callback:null:1') throw new Error('dgram numeric string port send failed'); const udp6Server = dgram.createSocket('udp6'); const udp6Client = dgram.createSocket({ type: 'udp6' }); const udp6Rows = []; udp6Server.on('message', (message, rinfo) => { udp6Rows.push(['server', message.toString(), rinfo.address, rinfo.family, rinfo.port > 0].join(':')); udp6Server.send('pong', rinfo.port, rinfo.address); }); udp6Client.on('message', (message, rinfo) => { udp6Rows.push(['client', message.toString(), rinfo.address, rinfo.family, rinfo.port > 0].join(':')); udp6Client.close(); udp6Server.close(); }); await new Promise((resolve) => udp6Server.bind(0, '::1', resolve)); udp6Rows.push(['address', udp6Server.address().address, udp6Server.address().family, udp6Server.address().port > 0].join(':')); udp6Client.send(Buffer.from('ping'), udp6Server.address().port, '::1'); await new Promise((resolve) => udp6Server.on('close', resolve)); if (udp6Rows.join('|') !== 'address:::1:IPv6:true|server:ping:::1:IPv6:true|client:pong:::1:IPv6:true') throw new Error('dgram udp6 loopback failed'); const preAbortedController = new AbortController(); preAbortedController.abort('done'); const preAborted = dgram.createSocket({ type: 'udp4', signal: preAbortedController.signal }); const preAbortedClosed = new Promise((resolve) => preAborted.on('close', resolve)); await preAbortedClosed; const signalRows = ['pre-bind:' + captureCode(() => preAborted.bind(0))]; const abortController = new AbortController(); const abortSocket = dgram.createSocket({ type: 'udp4', signal: abortController.signal }); await new Promise((resolve) => abortSocket.bind(0, '127.0.0.1', resolve)); const abortClosed = new Promise((resolve) => abortSocket.on('close', resolve)); abortController.abort(); await abortClosed; signalRows.push('abort-send:' + captureCode(() => abortSocket.send('x', 1, '127.0.0.1'))); if (signalRows.join('|') !== 'pre-bind:ERR_SOCKET_DGRAM_NOT_RUNNING|abort-send:ERR_SOCKET_DGRAM_NOT_RUNNING') throw new Error('dgram signal lifecycle failed'); for (const [label, action, code] of [['bad-type', () => dgram.createSocket(), 'ERR_SOCKET_BAD_TYPE'], ['bad-signal', () => dgram.createSocket({ type: 'udp4', signal: {} }), 'ERR_INVALID_ARG_TYPE'], ['bad-ttl', () => dgram.createSocket('udp4').setTTL(0), 'EINVAL'], ['bad-recv-buffer', () => dgram.createSocket('udp4').setRecvBufferSize(-1), 'ERR_SOCKET_BAD_BUFFER_SIZE'], ['bad-multicast-ttl-type', () => dgram.createSocket('udp4').setMulticastTTL('1'), 'ERR_INVALID_ARG_TYPE'], ['bad-multicast-ttl-range', () => dgram.createSocket('udp4').setMulticastTTL(256), 'EINVAL'], ['bad-multicast-interface-type', () => dgram.createSocket('udp4').setMulticastInterface(1), 'ERR_INVALID_ARG_TYPE'], ['bad-multicast-interface-empty', () => dgram.createSocket('udp4').setMulticastInterface(''), 'EINVAL'], ['missing-membership', () => dgram.createSocket('udp4').addMembership(), 'ERR_MISSING_ARGS'], ['bad-membership', () => dgram.createSocket('udp4').addMembership(''), 'EINVAL'], ['bad-membership-name', () => dgram.createSocket('udp4').addMembership('not-an-ip'), 'EINVAL'], ['bad-ssm-source', () => dgram.createSocket('udp4').addSourceSpecificMembership(), 'ERR_INVALID_ARG_TYPE'], ['bad-ssm-group', () => dgram.createSocket('udp4').dropSourceSpecificMembership('127.0.0.1'), 'ERR_INVALID_ARG_TYPE'], ['unsupported-multicast-ttl', () => dgram.createSocket('udp4').setMulticastTTL(1), 'ERR_OPENCONTAINERS_DGRAM_UNSUPPORTED'], ['unsupported-multicast-loopback', () => dgram.createSocket('udp4').setMulticastLoopback(true), 'ERR_OPENCONTAINERS_DGRAM_UNSUPPORTED'], ['unsupported-multicast-interface', () => dgram.createSocket('udp4').setMulticastInterface('127.0.0.1'), 'ERR_OPENCONTAINERS_DGRAM_UNSUPPORTED'], ['unsupported-membership', () => dgram.createSocket('udp4').addMembership('224.0.0.114'), 'ERR_OPENCONTAINERS_DGRAM_UNSUPPORTED'], ['unsupported-ssm', () => dgram.createSocket('udp4').addSourceSpecificMembership('127.0.0.1', '224.0.0.114'), 'ERR_OPENCONTAINERS_DGRAM_UNSUPPORTED']]) { try { action(); throw new Error(label + ' validation failed') } catch (error) { if (error.message === label + ' validation failed' || error.code !== code) throw error } }", "unsupported": { "probe": "const socket = require('node:dgram').createSocket('udp4'); socket.addMembership('224.0.0.1')", "code": "ERR_OPENCONTAINERS_DGRAM_UNSUPPORTED" } }, { "specifier": "node:domain", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Legacy domain APIs, Node-shaped CommonJS export shape, create/createDomain aliases, active stack probes, native-shaped active data property, Domain prototype metadata including own-prototype parity, Domain instance domain descriptor plus EventEmitter own state without leaking the internal OpenContainers event storage symbol, Domain add/remove return and validation parity, pre-load process.domain value descriptor plus post-load accessors with native getter/setter own-prototype metadata, bind/intercept wrapper receiver and metadata parity, and EventEmitter error routing are shimmed.", "probe": "const preDomainDescriptor = Object.getOwnPropertyDescriptor(process, 'domain'); const preDomainDescriptorRow = [preDomainDescriptor.enumerable, preDomainDescriptor.configurable, preDomainDescriptor.writable, typeof preDomainDescriptor.value, Object.hasOwn(preDomainDescriptor.get ?? {}, 'prototype'), Object.hasOwn(preDomainDescriptor.set ?? {}, 'prototype')].join(':'); const domain = require('node:domain'); const d = domain.create(); const processDomainDescriptor = Object.getOwnPropertyDescriptor(process, 'domain'); const processDomainDescriptorRow = [processDomainDescriptor.enumerable, processDomainDescriptor.configurable, typeof processDomainDescriptor.get, processDomainDescriptor.get.name, processDomainDescriptor.get.length, Object.hasOwn(processDomainDescriptor.get, 'prototype'), typeof processDomainDescriptor.set, processDomainDescriptor.set.name, processDomainDescriptor.set.length, Object.hasOwn(processDomainDescriptor.set, 'prototype')].join(':'); const activeDescriptor = Object.getOwnPropertyDescriptor(domain, 'active'); const instanceDomainDescriptor = Object.getOwnPropertyDescriptor(d, 'domain'); const domainInstanceShape = [Object.keys(d).join(','), Object.getOwnPropertyNames(d).join(','), ['Symbol(shapeMode)','Symbol(kCapture)'].every((key) => Reflect.ownKeys(d).map(String).includes(key)), !Reflect.ownKeys(d).map(String).includes('Symbol(opencontainers.events)'), Object.getPrototypeOf(d._events) === null, d._eventsCount, d._maxListeners === undefined].join('|'); const prototype = domain.Domain.prototype; const prototypeNames = Object.getOwnPropertyNames(prototype).join(','); const prototypeKeys = Object.keys(prototype).join(','); const prototypeDescriptors = ['members','_errorHandler','enter','exit','add','remove','run','intercept','bind','dispose'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(prototype, name); if (!descriptor) return name + ':missing'; const valueName = typeof descriptor.value === 'function' ? descriptor.value.name : String(descriptor.value); const valueLength = typeof descriptor.value === 'function' ? descriptor.value.length : ''; return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, valueName, valueLength, Object.hasOwn(descriptor.value ?? {}, 'prototype')].join(':'); }).join('|'); const domainValidation = domain.create(); const domainValidationObject = {}; const domainValidationRows = [['add-undefined', () => domainValidation.add()], ['remove-undefined', () => domainValidation.remove()], ['add-null', () => domainValidation.add(null)], ['remove-null', () => domainValidation.remove(null)], ['add-number', () => domainValidation.add(1)], ['remove-number', () => domainValidation.remove(1)], ['add-object', () => { const result = domainValidation.add(domainValidationObject); const descriptor = Object.getOwnPropertyDescriptor(domainValidationObject, 'domain'); return ['ok', result === undefined, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value === domainValidation].join(':'); }], ['remove-object', () => { const result = domainValidation.remove(domainValidationObject); const descriptor = Object.getOwnPropertyDescriptor(domainValidationObject, 'domain'); return ['ok', result === undefined, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value === null].join(':'); }], ['remove-fresh', () => { const target = {}; const result = domainValidation.remove(target); const descriptor = Object.getOwnPropertyDescriptor(target, 'domain'); return ['ok', result === undefined, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value === null].join(':'); }]].map(([label, action]) => { try { return label + ':' + action(); } catch (error) { return [label, error.constructor.name, error.code ?? '', error.message].join(':'); } }).join('|'); if (preDomainDescriptorRow !== 'true:true:true:object:false:false' || Object.keys(domain).join(',') !== '_stack,Domain,createDomain,create,active' || processDomainDescriptorRow !== 'true:true:function:get:0:true:function:set:1:true' || domain.create !== domain.createDomain || domain.create.name !== 'createDomain' || domain.active !== null || !activeDescriptor.enumerable || !activeDescriptor.configurable || !activeDescriptor.writable || activeDescriptor.value !== null || domainInstanceShape !== '_events,_eventsCount,_maxListeners,members|_events,_eventsCount,_maxListeners,domain,members|true|true|true|0|true' || !Object.getOwnPropertyNames(d).includes('domain') || instanceDomainDescriptor.enumerable || !instanceDomainDescriptor.configurable || !instanceDomainDescriptor.writable || instanceDomainDescriptor.value !== null || prototypeNames !== 'constructor,members,_errorHandler,enter,exit,add,remove,run,intercept,bind' || prototypeKeys !== 'members,_errorHandler,enter,exit,add,remove,run,intercept,bind' || prototypeDescriptors !== 'members:true:true:true:undefined::false|_errorHandler:true:true:true::1:true|enter:true:true:true::0:true|exit:true:true:true::0:true|add:true:true:true::1:true|remove:true:true:true::1:true|run:true:true:true::1:true|intercept:true:true:true::1:true|bind:true:true:true::1:true|dispose:missing' || domainValidationRows !== \"add-undefined:TypeError::Cannot read properties of undefined (reading 'domain')|remove-undefined:TypeError::Cannot set properties of undefined (setting 'domain')|add-null:TypeError::Cannot read properties of null (reading 'domain')|remove-null:TypeError::Cannot set properties of null (setting 'domain')|add-number:TypeError::Object.defineProperty called on non-object|remove-number:TypeError::Cannot create property 'domain' on number '1'|add-object:ok:true:false:true:true:true|remove-object:ok:true:false:true:true:true|remove-fresh:ok:true:true:true:true:true\") throw new Error('domain metadata failed'); d.run(() => { if (domain.active !== d || process.domain !== d) throw new Error('domain active failed') }); if (domain.active !== undefined || process.domain !== undefined) throw new Error('domain exit failed')" }, { "specifier": "node:http2", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/http2-builtin.test.mjs", "limitation": "Virtual cleartext h2c sessions are supported for loopback server/client streams and createServer request/response handlers with native-shaped CommonJS export order, constants, helper metadata/own-prototype descriptors, sensitiveHeaders symbol, settings packing probes, exact Http2ServerRequest/Http2ServerResponse prototype order, inherited request stream helpers, response symbol descriptors, and response helper/accessor probes; secure HTTP/2, external HTTP/2, raw wire-level protocol negotiation, push streams, and performServerHandshake raw stream handoff remain unsupported with stable errors.", "probe": "const http2 = require('node:http2'); const keys = 'connect,constants,createServer,createSecureServer,getDefaultSettings,getPackedSettings,getUnpackedSettings,performServerHandshake,sensitiveHeaders,Http2ServerRequest,Http2ServerResponse'; const metadata = [http2.connect, http2.createServer, http2.createSecureServer, http2.getDefaultSettings, http2.getPackedSettings, http2.getUnpackedSettings, http2.performServerHandshake, http2.Http2ServerRequest, http2.Http2ServerResponse].map((value) => value.name + ':' + value.length).join('|'); const helperPrototypeRows = ['connect','createServer','createSecureServer','getDefaultSettings','getPackedSettings','getUnpackedSettings','performServerHandshake'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(http2[name], 'prototype'); return [name, Object.hasOwn(http2[name], 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(','), descriptor?.value?.constructor === http2[name]].join(':'); }).join('|'); const requestPrototypeNames = Object.getOwnPropertyNames(http2.Http2ServerRequest.prototype); const responsePrototypeNames = Object.getOwnPropertyNames(http2.Http2ServerResponse.prototype); const requestMethodDescriptor = Object.getOwnPropertyDescriptor(http2.Http2ServerRequest.prototype, 'method'); const requestReadDescriptor = Object.getOwnPropertyDescriptor(http2.Http2ServerRequest.prototype, '_read'); const responseStatusDescriptor = Object.getOwnPropertyDescriptor(http2.Http2ServerResponse.prototype, 'statusCode'); const responseEarlyHintsDescriptor = Object.getOwnPropertyDescriptor(http2.Http2ServerResponse.prototype, 'writeEarlyHints'); const expectedRequestPrototypeNames = 'constructor,aborted,complete,stream,headers,rawHeaders,trailers,rawTrailers,httpVersionMajor,httpVersionMinor,httpVersion,socket,connection,_read,method,authority,scheme,url,setTimeout'; const expectedResponsePrototypeNames = 'constructor,_header,writableEnded,finished,socket,connection,stream,headersSent,sendDate,statusCode,writableCorked,writableHighWaterMark,writableObjectMode,writableFinished,writableLength,writableNeedDrain,setTrailer,addTrailers,getHeader,getHeaderNames,getHeaders,hasHeader,removeHeader,setHeader,appendHeader,statusMessage,flushHeaders,writeHead,cork,uncork,write,end,destroy,setTimeout,createPushResponse,writeInformation,writeContinue,writeEarlyHints'; const requestInheritedRows = ['setEncoding','pause','resume','destroy'].map((name) => typeof http2.Http2ServerRequest.prototype[name] + ':' + Object.hasOwn(http2.Http2ServerRequest.prototype, name)).join('|'); const responseSymbolNames = Object.getOwnPropertySymbols(http2.Http2ServerResponse.prototype).map(String).join(','); const responseSymbolDescriptorRows = Object.getOwnPropertySymbols(http2.Http2ServerResponse.prototype).map((symbol) => { const descriptor = Object.getOwnPropertyDescriptor(http2.Http2ServerResponse.prototype, symbol); return [String(symbol), descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype')].join(':'); }).join('|'); const packed = http2.getPackedSettings({ headerTableSize: 123, enablePush: false, maxHeaderSize: 42, enableConnectProtocol: true }); const unpacked = http2.getUnpackedSettings(packed); const aliasPacked = http2.getPackedSettings({ enableConnectProtocol: true, maxHeaderListSize: 99 }); const aliasUnpacked = http2.getUnpackedSettings(aliasPacked); const custom = http2.getUnpackedSettings(Buffer.from('000700000063', 'hex')); let invalidError; try { http2.getUnpackedSettings(Buffer.from('000100', 'hex')); } catch (error) { invalidError = error; } if (Object.keys(http2).join(',') !== keys || Object.hasOwn(http2, 'default') || Object.hasOwn(http2, 'ServerHttp2Stream') || Object.hasOwn(http2, 'ClientHttp2Stream') || Object.hasOwn(http2, 'ClientHttp2Session') || Object.keys(http2.constants).length !== 240 || http2.constants.HTTP2_HEADER_PATH !== ':path' || http2.constants.HTTP2_HEADER_PROTOCOL !== ':protocol' || String(http2.sensitiveHeaders) !== 'Symbol(sensitiveHeaders)' || http2.sensitiveHeaders.description !== 'sensitiveHeaders' || metadata !== 'connect:3|createServer:2|createSecureServer:2|getDefaultSettings:0|getPackedSettings:1|getUnpackedSettings:1|performServerHandshake:1|Http2ServerRequest:4|Http2ServerResponse:2' || helperPrototypeRows !== 'connect:true:false:false:true:constructor:true|createServer:true:false:false:true:constructor:true|createSecureServer:true:false:false:true:constructor:true|getDefaultSettings:true:false:false:true:constructor:true|getPackedSettings:true:false:false:true:constructor:true|getUnpackedSettings:true:false:false:true:constructor:true|performServerHandshake:true:false:false:true:constructor:true' || requestPrototypeNames.join(',') !== expectedRequestPrototypeNames || requestInheritedRows !== 'function:false|function:false|function:false|function:false' || responsePrototypeNames.join(',') !== expectedResponsePrototypeNames || responseSymbolNames !== 'Symbol(setHeader),Symbol(appendHeader),Symbol(begin-send)' || responseSymbolDescriptorRows !== 'Symbol(setHeader):false:true:true:[setHeader]:2:false|Symbol(appendHeader):false:true:true:[appendHeader]:2:false|Symbol(begin-send):false:true:true:[begin-send]:0:false' || requestMethodDescriptor?.enumerable !== false || typeof requestMethodDescriptor?.get !== 'function' || typeof requestMethodDescriptor?.set !== 'function' || requestReadDescriptor?.value?.length !== 1 || responseStatusDescriptor?.enumerable !== false || typeof responseStatusDescriptor?.get !== 'function' || typeof responseStatusDescriptor?.set !== 'function' || responseEarlyHintsDescriptor?.value?.length !== 1 || http2.getDefaultSettings().maxHeaderSize !== 65535 || http2.getDefaultSettings().enableConnectProtocol !== false || packed.toString('hex') !== '00010000007b00020000000000060000002a000800000001' || aliasPacked.toString('hex') !== '000600000063000800000001' || unpacked.maxHeaderSize !== 42 || unpacked.maxHeaderListSize !== 42 || unpacked.enableConnectProtocol !== true || aliasUnpacked.maxHeaderSize !== 99 || aliasUnpacked.maxHeaderListSize !== 99 || aliasUnpacked.enableConnectProtocol !== true || custom.customSettings?.['7'] !== 99 || invalidError?.name !== 'RangeError' || invalidError?.code !== 'ERR_HTTP2_INVALID_PACKED_SETTINGS_LENGTH' || !invalidError?.message.includes('multiple of six')) throw new Error('http2 metadata failed'); const { HTTP2_HEADER_METHOD, HTTP2_HEADER_PATH, HTTP2_HEADER_STATUS } = http2.constants; let streamSeen = false; const server = http2.createServer((req, res) => { if (!(req instanceof http2.Http2ServerRequest) || !(res instanceof http2.Http2ServerResponse) || req.method !== 'POST' || req.url !== '/probe' || req.httpVersion !== '2.0' || req.httpVersionMajor !== 2 || req.httpVersionMinor !== 0 || req.connection !== req.socket || !Array.isArray(req.rawHeaders) || !Array.isArray(req.rawTrailers) || res._header !== null || res.writableEnded || res.finished || res.writableFinished || res.writableHighWaterMark !== 16384 || res.writableObjectMode !== false || res.writableNeedDrain !== false || res.writableLength !== 0 || res.connection !== res.socket || res.stream !== req.stream) throw new Error('http2 request wrapper failed'); res.appendHeader('x-extra', 'one'); res.appendHeader('x-extra', 'two'); if (JSON.stringify(res.getHeader('x-extra')) !== '[\"one\",\"two\"]') throw new Error('http2 response appendHeader failed'); try { res.createPushResponse({}, () => {}); throw new Error('push response failed'); } catch (error) { if (error.message === 'push response failed' || error.code !== 'ERR_OPENCONTAINERS_HTTP2_UNSUPPORTED') throw error; } let body = ''; req.setEncoding('utf8'); req.on('data', (chunk) => { body += chunk; }); req.on('end', () => { if (body !== 'payload' || req.complete !== true) throw new Error('http2 request body failed'); res.statusCode = 202; res.setHeader('x-probe', 'ok'); res.end('done'); }); }); if (server.listenerCount('request') !== 1 || server.listenerCount('stream') !== 1) throw new Error('http2 listener wiring failed'); server.on('stream', () => { streamSeen = true; }); await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)); const client = http2.connect('http://localhost:' + server.address().port); await new Promise((resolve) => client.once('connect', resolve)); const request = client.request({ [HTTP2_HEADER_METHOD]: 'POST', [HTTP2_HEADER_PATH]: '/probe' }); request.setEncoding('utf8'); let status = 0; let header = ''; let response = ''; request.on('response', (headers) => { status = headers[HTTP2_HEADER_STATUS]; header = headers['x-probe']; }); request.on('data', (chunk) => { response += chunk; }); request.end('payload'); await new Promise((resolve) => request.on('end', resolve)); client.close(); server.close(); if (!streamSeen || status !== 202 || header !== 'ok' || response !== 'done') throw new Error('http2 request handler failed')", "unsupported": { "probe": "require('node:http2').createSecureServer()", "code": "ERR_OPENCONTAINERS_HTTP2_UNSUPPORTED" } }, { "specifier": "node:module", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs, tests/esm-exports-loader.test.mjs", "limitation": "CommonJS helpers, default-free CommonJS export shape, native-shaped CommonJS export and own-property order including flushCompileCache no-own-prototype metadata, native-shaped builtinModules order, require-cache parity, require.extensions handlers, public require/resolve request validation, relative paths lookup behavior, and null-receiver Module.prototype.require fallback, createRequire filename validation, parent-aware Module._load, native-shaped public helper metadata/own-prototype shape including module.register arity, Module.wrapper/wrap probes, native-shaped Module.prototype method/accessor metadata including constructor and parent accessor own-prototype shape plus manual require/load/_compile probes, native-shaped private resolver hook arities and private helper metadata, private _stat/_readPackage accessors and package probes, native-shaped SourceMap prototype/accessor metadata including Symbol(kMappings) tuple-array probes plus simple VLQ findEntry/findOrigin mapping lookups, Node-shaped builtin metadata including node:-only test/sqlite modules, native-shaped transformed ESM builtin namespace order/descriptors/assignment probes, syncBuiltinESMExports mutation/delete refresh behavior for builtin namespaces, package self-reference exports, import.meta.resolve package exports/imports including pattern targets, package exports/imports pattern arrays, mixed package exports config validation, package imports target validation, require.resolve/_resolveFilename explicit lookup paths, virtual HOME/NODE_PATH-backed Module.globalPaths and _initPaths reset behavior, static ESM package imports/re-exports, default+namespace imports, and namespace re-exports using import-condition resolution, and declaration-order conditional targets with browser fallback, package lookup with native-shaped findPackageJSON argument and resolution validation, compile-cache cacheDir validation/source-map probes, stripTypeScriptTypes strip-mode validation/sourceURL trailers, synchronous registerHooks resolve/load execution for CommonJS require and dynamic ESM import, data: URL and parentURL-backed file module.register loader hooks for dynamic ESM import, and native-shaped registerHooks handle keys/descriptors/prototype metadata are shimmed, while native .node add-ons fail with a stable OpenContainers unsupported error; broader custom loader coverage remains partial.", "probe": "const Module = require('node:module'); const fs = require('node:fs'); const expectedModuleKeys = '_cache,_pathCache,_extensions,globalPaths,isBuiltin,_findPath,_nodeModulePaths,_resolveLookupPaths,_load,_resolveFilename,createRequire,_initPaths,_preloadModules,syncBuiltinESMExports,Module,registerHooks,builtinModules,runMain,register,constants,enableCompileCache,findPackageJSON,flushCompileCache,getCompileCacheDir,stripTypeScriptTypes,findSourceMap,SourceMap,getSourceMapsSupport,setSourceMapsSupport'; const expectedModuleOwnNames = 'length,name,prototype,_stat,_cache,_pathCache,_extensions,globalPaths,wrap,wrapper,isBuiltin,_readPackage,_findPath,_nodeModulePaths,_resolveLookupPaths,_load,_resolveFilename,createRequire,_initPaths,_preloadModules,syncBuiltinESMExports,Module,registerHooks,builtinModules,runMain,register,constants,enableCompileCache,findPackageJSON,flushCompileCache,getCompileCacheDir,stripTypeScriptTypes,findSourceMap,SourceMap,getSourceMapsSupport,setSourceMapsSupport'; fs.writeFileSync('/workspace/package.json', JSON.stringify({ name: 'module-probe', exports: { '.': './self-main.js', './feature': './self-feature.js' }, imports: { '#metaLocal': './meta-local.js', '#metaExternal': 'meta-resolve-pkg/feature', '#metaPattern/*': './meta-imports/*.js', '#metaBlocked': null, '#metaEscape': '../outside-meta.js' } })); fs.writeFileSync('/workspace/self-main.js', 'module.exports = \\'self-main\\';'); fs.writeFileSync('/workspace/self-feature.js', 'module.exports = \\'self-feature\\';'); fs.writeFileSync('/workspace/meta-local.js', 'export default \\'local\\';'); fs.mkdirSync('/workspace/meta-imports', { recursive: true }); fs.writeFileSync('/workspace/meta-imports/name.js', 'export default \\'import-pattern\\';'); fs.writeFileSync('/outside-meta.js', 'export default \\'outside\\';'); fs.mkdirSync('/workspace/node_modules/meta-resolve-pkg', { recursive: true }); fs.writeFileSync('/workspace/node_modules/meta-resolve-pkg/package.json', JSON.stringify({ name: 'meta-resolve-pkg', type: 'module', exports: { '.': { import: './import.js', require: './require.cjs', default: './default.js' }, './feature': './feature.js', './pattern/*': './pattern/*.js', './blocked': null, './escape': '../escape.js' } })); fs.writeFileSync('/workspace/node_modules/meta-resolve-pkg/import.js', 'export default \\'import\\';'); fs.writeFileSync('/workspace/node_modules/meta-resolve-pkg/require.cjs', 'module.exports = \\'require\\';'); fs.writeFileSync('/workspace/node_modules/meta-resolve-pkg/default.js', 'export default \\'default\\';'); fs.writeFileSync('/workspace/node_modules/meta-resolve-pkg/feature.js', 'export default \\'feature\\';'); fs.mkdirSync('/workspace/node_modules/meta-resolve-pkg/pattern', { recursive: true }); fs.writeFileSync('/workspace/node_modules/meta-resolve-pkg/pattern/name.js', 'export default \\'export-pattern\\';'); fs.writeFileSync('/workspace/receiver-relative.js', 'module.exports = \\'relative-ok\\';'); fs.writeFileSync('/workspace/esm-namespace-base.mjs', 'export const value = \\'namespace-value\\'; export default \\'namespace-default\\';'); fs.writeFileSync('/workspace/esm-namespace-reexport.mjs', 'export * as grouped from \\'./esm-namespace-base.mjs\\';'); fs.writeFileSync('/workspace/esm-namespace-main.mjs', 'import defaultValue, * as everything from \\'./esm-namespace-base.mjs\\'; import { grouped } from \\'./esm-namespace-reexport.mjs\\'; export default [defaultValue, everything.value, grouped.value].join(\\':\\');'); const expectedBuiltinModules = '_http_agent,_http_client,_http_common,_http_incoming,_http_outgoing,_http_server,_tls_common,_tls_wrap,assert,assert/strict,async_hooks,buffer,child_process,cluster,console,constants,crypto,dgram,diagnostics_channel,dns,dns/promises,domain,events,fs,fs/promises,http,http2,https,inspector,inspector/promises,module,net,os,path,path/posix,path/win32,perf_hooks,process,punycode,querystring,readline,readline/promises,repl,stream,stream/consumers,stream/promises,stream/web,string_decoder,sys,timers,timers/promises,tls,trace_events,tty,url,util,util/types,v8,vm,wasi,worker_threads,zlib,node:sea,node:sqlite,node:test,node:test/reporters'; fs.mkdirSync('/workspace/module-imports-probe/node_modules/dep', { recursive: true }); fs.writeFileSync('/workspace/module-imports-probe/package.json', JSON.stringify({ imports: { '#escape': '../outside.js', '#nodeModules': './node_modules/hidden.js', '#external': 'dep' } })); fs.writeFileSync('/workspace/outside.js', 'module.exports = \\'outside\\';'); fs.writeFileSync('/workspace/module-imports-probe/node_modules/hidden.js', 'module.exports = \\'hidden\\';'); fs.writeFileSync('/workspace/module-imports-probe/node_modules/dep/package.json', JSON.stringify({ name: 'dep', main: 'index.js' })); fs.writeFileSync('/workspace/module-imports-probe/node_modules/dep/index.js', 'module.exports = \\'dep\\';'); fs.mkdirSync('/workspace/isolated/node_modules/pkg', { recursive: true }); fs.writeFileSync('/workspace/isolated/node_modules/pkg/index.js', 'module.exports = \\'isolated\\';'); fs.mkdirSync('/workspace/node_modules/mixed-exports', { recursive: true }); fs.writeFileSync('/workspace/node_modules/mixed-exports/package.json', JSON.stringify({ name: 'mixed-exports', exports: { '.': './index.js', default: './index.js' } })); fs.writeFileSync('/workspace/node_modules/mixed-exports/index.js', 'module.exports = 42;'); const resolverRequire = Module.createRequire('/workspace/main.js'); const selfReferenceRows = [resolverRequire('module-probe'), resolverRequire('module-probe/feature'), resolverRequire.resolve('module-probe', { paths: ['/tmp'] }), (() => { try { resolverRequire('module-probe/missing'); return 'loaded'; } catch (error) { return error.code; } })()].join('|'); const explicitResolveRows = [resolverRequire.resolve('pkg', { paths: ['/workspace/isolated'] }), resolverRequire.resolve('pkg', { paths: ['/workspace/isolated/node_modules'] }), Module._resolveFilename('pkg', { filename: '/workspace/main.js' }, false, { paths: ['/workspace/isolated'] }), resolverRequire.resolve('node:fs', { paths: [1] })]; const explicitResolveValidation = [() => resolverRequire.resolve('pkg'), () => resolverRequire.resolve('pkg', { paths: null }), () => resolverRequire.resolve('pkg', { paths: 1 }), () => resolverRequire.resolve('pkg', { paths: 'x' }), () => resolverRequire.resolve('pkg', { paths: {} }), () => resolverRequire.resolve('pkg', { paths: [1] }), () => resolverRequire.resolve('pkg', { paths: [null] }), () => resolverRequire.resolve('pkg', { paths: [] }), () => resolverRequire.resolve('pkg', { paths: undefined })].map((run) => { try { return 'ok:' + run(); } catch (error) { return error.name + ':' + error.code; } }).join('|'); const mixedExportsCode = (() => { try { resolverRequire('mixed-exports'); return 'loaded'; } catch (error) { return [error.code, error.message.includes('cannot contain some keys starting')].join(':'); } })(); const importRequire = Module.createRequire('/workspace/module-imports-probe/main.cjs'); const importTargetCodes = []; for (const id of ['#escape', '#nodeModules']) { try { importRequire(id); importTargetCodes.push('loaded'); } catch (error) { importTargetCodes.push(error.code); } } const metaResolveRow = (specifier) => { try { return import.meta.resolve(specifier); } catch (error) { return error.code; } }; const metaResolveRows = ['meta-resolve-pkg','meta-resolve-pkg/feature','meta-resolve-pkg/pattern/name','#metaLocal','#metaExternal','#metaPattern/name','#metaMissing','#metaBlocked','#metaEscape','meta-resolve-pkg/blocked','meta-resolve-pkg/escape'].map(metaResolveRow).join('|'); const requireFromUrl = Module.createRequire(new URL('file:///workspace/module-probe.mjs')); const manualValidationModule = new Module('/workspace/manual-validation.js'); manualValidationModule.filename = '/workspace/manual-validation.js'; const publicRequireValidationRows = [() => requireFromUrl(), () => requireFromUrl(1), () => requireFromUrl.resolve(), () => requireFromUrl.resolve(1), () => requireFromUrl.resolve.paths(), () => requireFromUrl.resolve.paths(1), () => manualValidationModule.require(), () => manualValidationModule.require(1)].map((action) => { try { return 'ok:' + action(); } catch (error) { return [error.name, error.code, error.message].join(':'); } }).join('|'); const expectedPublicRequireValidationRows = ['TypeError:ERR_INVALID_ARG_TYPE:The \"id\" argument must be of type string. Received undefined', 'TypeError:ERR_INVALID_ARG_TYPE:The \"id\" argument must be of type string. Received type number (1)', 'TypeError:ERR_INVALID_ARG_TYPE:The \"request\" argument must be of type string. Received undefined', 'TypeError:ERR_INVALID_ARG_TYPE:The \"request\" argument must be of type string. Received type number (1)', 'TypeError:ERR_INVALID_ARG_TYPE:The \"request\" argument must be of type string. Received undefined', 'TypeError:ERR_INVALID_ARG_TYPE:The \"request\" argument must be of type string. Received type number (1)', 'TypeError:ERR_INVALID_ARG_TYPE:The \"id\" argument must be of type string. Received undefined', 'TypeError:ERR_INVALID_ARG_TYPE:The \"id\" argument must be of type string. Received type number (1)'].join('|'); const publicRequirePathRows = [requireFromUrl.resolve.paths('node:fs') === null, requireFromUrl.resolve.paths('./x').join(','), requireFromUrl.resolve.paths('.').join(','), requireFromUrl.resolve.paths('..').join(','), Array.isArray(requireFromUrl.resolve.paths('/abs'))].join(':'); const publicRequireReceiverRows = [typeof Module.prototype.require.call(null, 'node:path').join, typeof Module.prototype.require.call(undefined, 'fs').readFile, Module.prototype.require.call(null, './receiver-relative'), Module.prototype.require.call(undefined, './receiver-relative'), Module.prototype.require.call({}, './receiver-relative')].join(':'); const namespaceSyntaxModule = await import('./esm-namespace-main.mjs'); const esmHookRows = []; const esmHook = Module.registerHooks({ resolve(specifier, context, nextResolve) { esmHookRows.push('r:' + specifier + ':' + context.conditions.join(',')); if (specifier === 'virtual:esm-hook') return { url: 'virtual:esm-hook', format: 'module', shortCircuit: true }; return nextResolve(specifier, context); }, load(url, context, nextLoad) { esmHookRows.push('l:' + url + ':' + context.conditions.join(',') + ':' + context.format + ':' + ('parentURL' in context)); if (url === 'virtual:esm-hook') return { format: 'module', source: 'export const value = 42;\\nexport default value + 1;', shortCircuit: true }; return nextLoad(url, context); } }); const esmHookModule = await import('virtual:esm-hook'); esmHook.deregister(); const registeredLoaderRows = []; globalThis.__registeredLoaderRows = registeredLoaderRows; const registeredLoaderSource = `export async function resolve(specifier, context, nextResolve) { if (specifier === \"virtual:registered-loader\") { globalThis.__registeredLoaderRows.push(\"r:\" + context.conditions.join(\",\")); return { url: \"virtual:registered-loader\", format: \"module\", shortCircuit: true }; } return nextResolve(specifier, context); } export async function load(url, context, nextLoad) { if (url === \"virtual:registered-loader\") { globalThis.__registeredLoaderRows.push(\"l:\" + context.format); return { format: \"module\", source: \"export default 46;\", shortCircuit: true }; } return nextLoad(url, context); }`; Module.register('data:text/javascript,' + encodeURIComponent(registeredLoaderSource)); const registeredLoaderModule = await import('virtual:registered-loader'); delete globalThis.__registeredLoaderRows; const hookHandle = Module.registerHooks({ resolve() {}, load() {} }); const hookDescriptorMeta = ['resolve','load'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(hookHandle, name); return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype')].join(':'); }).join('|'); const hookPrototype = Object.getPrototypeOf(hookHandle); const hookPrototypeDescriptor = Object.getOwnPropertyDescriptor(hookPrototype, 'deregister'); const hookPrototypeMeta = [Object.keys(hookHandle).join(','), Object.getOwnPropertyNames(hookHandle).join(','), hookPrototype.constructor.name, Object.getOwnPropertyNames(hookPrototype).join(','), Object.keys(hookPrototype).join(',') || '', hookPrototypeDescriptor.enumerable, hookPrototypeDescriptor.configurable, hookPrototypeDescriptor.writable, hookPrototypeDescriptor.value.name, hookPrototypeDescriptor.value.length, Object.hasOwn(hookPrototypeDescriptor.value, 'prototype')].join(':'); hookHandle.deregister(); const hookPostDeregisterMeta = [Object.hasOwn(hookHandle, 'active'), hookHandle.active, typeof hookHandle.resolve, typeof hookHandle.load].join(':'); const stripped = Module.stripTypeScriptTypes('interface User { id: number }\\nconst user: User = { id: 1 };'); const sourceMap = new Module.SourceMap({ version: 3, sources: [], names: [], mappings: '' }); const mappedSourceMap = new Module.SourceMap({ version: 3, file: 'gen.js', sources: ['orig.js'], names: ['foo'], mappings: 'AAAAA;AACA' }); const mappedEntryRows = [mappedSourceMap.findEntry(0, 0), mappedSourceMap.findEntry(1, 0), mappedSourceMap.findEntry(2, 0)].map((entry) => JSON.stringify(entry)).join('|'); const mappedOriginRows = [mappedSourceMap.findOrigin(2, 0), mappedSourceMap.findOrigin(2, 1)].map((entry) => JSON.stringify(entry)).join('|'); const sourceMapAccessors = ['payload','lineLengths'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(Module.SourceMap.prototype, name); return [name, descriptor.enumerable, descriptor.configurable, descriptor.get.name, descriptor.get.length, typeof descriptor.set].join(':') }).join('|'); const metadata = ['createRequire','isBuiltin','wrap','registerHooks','register','enableCompileCache','findPackageJSON','flushCompileCache','stripTypeScriptTypes'].map((name) => name + ':' + Module[name].name + ':' + Module[name].length + ':' + Object.hasOwn(Module[name], 'prototype')).join('|'); const findPackageJSONRows = []; for (const [label, action] of [['missing', () => Module.findPackageJSON()], ['null-spec', () => Module.findPackageJSON(null, '/workspace/module-probe.mjs')], ['number-spec', () => Module.findPackageJSON(42, '/workspace/module-probe.mjs')], ['empty-spec', () => Module.findPackageJSON('', '/workspace/module-probe.mjs')], ['symbol-spec', () => Module.findPackageJSON(Symbol('x'), '/workspace/module-probe.mjs')], ['base-null', () => Module.findPackageJSON('.', null)], ['base-number', () => Module.findPackageJSON('.', 42)], ['base-url-object', () => Module.findPackageJSON('.', new URL('file:///workspace/module-probe.mjs'))]]) { try { findPackageJSONRows.push(label + ':ok:' + action()); } catch (error) { findPackageJSONRows.push(label + ':' + error.name + ':' + error.code); } } const wrapDescriptor = Object.getOwnPropertyDescriptor(Module, 'wrap'); const resolverLengths = [Module._resolveFilename,Module._load,Module._nodeModulePaths,Module._resolveLookupPaths,Module._findPath].map((fn) => fn.length).join(','); const privateHelperMeta = ['_findPath','_nodeModulePaths','_resolveLookupPaths','_load','_resolveFilename','_initPaths','_preloadModules'].map((name) => { const fn = Module[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); let constructable = false; try { constructable = Reflect.construct(Object, [], fn) instanceof fn; } catch {} return [name, fn.name, fn.length, Object.hasOwn(fn, 'prototype'), descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.getOwnPropertyNames(descriptor.value).join(','), constructable].join(':'); }).join('|'); const privateMeta = ['_stat','_readPackage'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(Module, name); const fn = Module[name]; return [name, descriptor.enumerable, descriptor.configurable, descriptor.get.name, descriptor.get.length, descriptor.set.name, descriptor.set.length, fn.name, fn.length, Object.hasOwn(fn, 'prototype')].join(':') }).join('|'); if (Object.hasOwn(Module, 'default') || Object.keys(Module).join(',') !== expectedModuleKeys || Object.getOwnPropertyNames(Module).join(',') !== expectedModuleOwnNames || Object.hasOwn(Module, '_builtinLibs') || Module.builtinModules.join(',') !== expectedBuiltinModules || Module.builtinModules.length !== 66 || Module.Module !== Module || Module._cache !== require.cache || Module._extensions !== require.extensions || Module.isBuiltin('node:sqlite') !== true || Module.isBuiltin('sqlite') !== false || Module.isBuiltin('node:test/reporters') !== true || Module.isBuiltin('test/reporters') !== false || importTargetCodes.join(',') !== 'ERR_INVALID_PACKAGE_TARGET,ERR_INVALID_PACKAGE_TARGET' || metaResolveRows !== 'file:///workspace/node_modules/meta-resolve-pkg/import.js|file:///workspace/node_modules/meta-resolve-pkg/feature.js|file:///workspace/node_modules/meta-resolve-pkg/pattern/name.js|file:///workspace/meta-local.js|file:///workspace/node_modules/meta-resolve-pkg/feature.js|file:///workspace/meta-imports/name.js|ERR_PACKAGE_IMPORT_NOT_DEFINED|ERR_PACKAGE_IMPORT_NOT_DEFINED|ERR_INVALID_PACKAGE_TARGET|ERR_PACKAGE_PATH_NOT_EXPORTED|ERR_INVALID_PACKAGE_TARGET' || mixedExportsCode !== 'ERR_INVALID_PACKAGE_CONFIG:true' || selfReferenceRows !== 'self-main|self-feature|/workspace/self-main.js|ERR_PACKAGE_PATH_NOT_EXPORTED' || importRequire('#external') !== 'dep' || explicitResolveRows.join('|') !== '/workspace/isolated/node_modules/pkg/index.js|/workspace/isolated/node_modules/pkg/index.js|/workspace/isolated/node_modules/pkg/index.js|node:fs' || explicitResolveValidation !== 'Error:MODULE_NOT_FOUND|TypeError:ERR_INVALID_ARG_VALUE|TypeError:ERR_INVALID_ARG_VALUE|TypeError:ERR_INVALID_ARG_VALUE|TypeError:ERR_INVALID_ARG_VALUE|TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE|Error:MODULE_NOT_FOUND|Error:MODULE_NOT_FOUND' || publicRequireValidationRows !== expectedPublicRequireValidationRows || publicRequirePathRows !== 'true:/workspace:/workspace:/workspace:true' || publicRequireReceiverRows !== 'function:function:relative-ok:relative-ok:relative-ok' || namespaceSyntaxModule.default !== 'namespace-default:namespace-value:namespace-value' || requireFromUrl('node:path').basename('/tmp/file.txt') !== 'file.txt' || esmHookModule.value !== 42 || esmHookModule.default !== 43 || esmHookRows.join('|') !== 'r:virtual:esm-hook:node,import,module-sync,node-addons|l:virtual:esm-hook:node,import,module-sync,node-addons:module:false' || registeredLoaderModule.default !== 46 || registeredLoaderRows.join('|') !== 'r:node,import,module-sync,node-addons|l:module' || !Array.isArray(Module.wrapper) || Module.wrap('x') !== Module.wrapper[0] + 'x' + Module.wrapper[1] || hookDescriptorMeta !== 'resolve:true:false:false:function:resolve:0:false|load:true:false:false:function:load:0:false' || hookPrototypeMeta !== 'resolve,load:resolve,load:ModuleHooks:constructor,deregister::false:true:true:deregister:0:false' || hookPostDeregisterMeta !== 'false::function:function' || metadata !== 'createRequire:createRequire:1:true|isBuiltin:isBuiltin:1:false|wrap:wrap:1:true|registerHooks:registerHooks:1:true|register:register:1:true|enableCompileCache:enableCompileCache:1:true|findPackageJSON:findPackageJSON:1:true|flushCompileCache:flushCompileCache:0:false|stripTypeScriptTypes:stripTypeScriptTypes:1:true' || findPackageJSONRows.join('|') !== 'missing:TypeError:ERR_MISSING_ARGS|null-spec:Error:ERR_MODULE_NOT_FOUND|number-spec:Error:ERR_MODULE_NOT_FOUND|empty-spec:Error:ERR_MODULE_NOT_FOUND|symbol-spec:TypeError:ERR_INVALID_ARG_TYPE|base-null:TypeError:ERR_INVALID_ARG_TYPE|base-number:TypeError:ERR_INVALID_ARG_TYPE|base-url-object:ok:/workspace/package.json' || resolverLengths !== '4,3,1,2,3' || privateHelperMeta !== '_findPath::3:true:false:false:true:constructor:true|_nodeModulePaths::1:true:false:false:true:constructor:true|_resolveLookupPaths::2:true:false:false:true:constructor:true|_load::3:true:false:false:true:constructor:true|_resolveFilename::4:true:false:false:true:constructor:true|_initPaths::0:true:false:false:true:constructor:true|_preloadModules::1:true:false:false:true:constructor:true' || privateMeta !== '_stat:false:true:get:0:set:1:stat:1:true|_readPackage:false:true:get:0:set:1:_readPackage:1:false' || Object.keys(Module).includes('_stat') || Object.keys(Module).includes('_readPackage') || Object.getOwnPropertyNames(Module.SourceMap.prototype).join(',') !== 'constructor,payload,lineLengths,findEntry,findOrigin' || Object.keys(sourceMap).length !== 0 || Object.getOwnPropertyNames(sourceMap).length !== 0 || sourceMapAccessors !== 'payload:false:true:get payload:0:undefined|lineLengths:false:true:get lineLengths:0:undefined' || Module.SourceMap.prototype.findEntry.length !== 2 || Module.SourceMap.prototype.findOrigin.length !== 2 || sourceMap.payload.version !== 3 || sourceMap.lineLengths !== undefined || mappedEntryRows !== '{\"generatedLine\":0,\"generatedColumn\":0,\"originalSource\":\"orig.js\",\"originalLine\":0,\"originalColumn\":0,\"name\":\"foo\"}|{\"generatedLine\":1,\"generatedColumn\":0,\"originalSource\":\"orig.js\",\"originalLine\":1,\"originalColumn\":0,\"name\":\"foo\"}|{\"generatedLine\":1,\"generatedColumn\":0,\"originalSource\":\"orig.js\",\"originalLine\":1,\"originalColumn\":0,\"name\":\"foo\"}' || mappedOriginRows !== '{\"name\":\"foo\",\"fileName\":\"orig.js\",\"lineNumber\":2,\"columnNumber\":0}|{\"name\":\"foo\",\"fileName\":\"orig.js\",\"lineNumber\":2,\"columnNumber\":1}' || wrapDescriptor.enumerable || wrapDescriptor.configurable || typeof wrapDescriptor.get !== 'function' || typeof wrapDescriptor.set !== 'function' || Object.keys(Module).includes('wrap') || typeof Module.stripTypeScriptTypes !== 'function' || !stripped.includes('const user') || stripped.includes('interface User')) throw new Error('module probe failed'); const prototypeMethods = ['load','require','_compile']; const prototypeAccessors = ['constructor','isPreloading','parent']; const prototypeNames = Object.getOwnPropertyNames(Module.prototype).join(','); const prototypeKeys = Object.keys(Module.prototype).join(','); const prototypeMethodMeta = prototypeMethods.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(Module.prototype, name); return [name, descriptor?.value?.name, descriptor?.value?.length, descriptor?.enumerable, descriptor?.configurable, descriptor?.writable].join(':'); }).join('|'); const prototypeAccessorMeta = prototypeAccessors.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(Module.prototype, name); return [name, descriptor?.enumerable, descriptor?.configurable, descriptor.get.name, descriptor.get.length, Object.hasOwn(descriptor.get, 'prototype'), descriptor.set?.name ?? 'undefined', descriptor.set?.length ?? 'undefined', descriptor.set ? Object.hasOwn(descriptor.set, 'prototype') : 'undefined'].join(':'); }).join('|'); if (prototypeNames !== 'constructor,isPreloading,parent,load,require,_compile' || prototypeKeys !== 'load,require,_compile' || prototypeMethodMeta !== 'load::1:true:true:true|require::1:true:true:true|_compile::3:true:true:true' || prototypeAccessorMeta !== 'constructor:false:false:get:0:true:undefined:undefined:undefined|isPreloading:false:false:get:0:false:undefined:undefined:undefined|parent:false:false:deprecated:0:true:deprecated:1:true') throw new Error('module prototype probe failed'); const manualModule = new Module('/workspace/manual.js'); if (manualModule.loaded || !Array.isArray(manualModule.children) || Object.keys(manualModule).includes('parent') || manualModule.parent !== undefined || manualModule.isPreloading !== false || typeof manualModule.require('node:path').join !== 'function') throw new Error('module manual require probe failed'); manualModule._compile('module.exports = require(\"node:path\").basename(\"/tmp/file.txt\")', '/workspace/manual.js'); if (manualModule.exports !== 'file.txt') throw new Error('module manual compile probe failed'); const matrixSourceMapSymbols = Object.getOwnPropertySymbols(Module.SourceMap.prototype); const matrixSourceMapMappingsDescriptor = Object.getOwnPropertyDescriptor(Module.SourceMap.prototype, matrixSourceMapSymbols[0]); const matrixSourceMap = new Module.SourceMap({ version: 3, sources: ['in.js'], names: [], mappings: 'AAAA' }); const matrixSourceMapMappings = matrixSourceMap[matrixSourceMapSymbols[0]]; let matrixSourceMapPrototypeGetThrows = false; try { Module.SourceMap.prototype[matrixSourceMapSymbols[0]]; } catch (error) { matrixSourceMapPrototypeGetThrows = error.name === 'TypeError' && error.message.includes('private member'); } if (matrixSourceMapSymbols.map(String).join(',') !== 'Symbol(kMappings)' || !matrixSourceMapMappingsDescriptor || typeof matrixSourceMapMappingsDescriptor.get !== 'function' || matrixSourceMapMappingsDescriptor.get.name !== 'get [kMappings]' || matrixSourceMapMappingsDescriptor.get.length !== 0 || Object.hasOwn(matrixSourceMapMappingsDescriptor.get, 'prototype') || matrixSourceMapMappingsDescriptor.set !== undefined || matrixSourceMapMappingsDescriptor.enumerable !== false || matrixSourceMapMappingsDescriptor.configurable !== true || 'writable' in matrixSourceMapMappingsDescriptor || !Array.isArray(matrixSourceMapMappings) || matrixSourceMapMappings.length !== 1 || matrixSourceMapMappings[0][0] !== 0 || matrixSourceMapMappings[0][1] !== 0 || matrixSourceMapMappings[0][2] !== 'in.js' || matrixSourceMapMappings[0][3] !== 0 || matrixSourceMapMappings[0][4] !== 0 || matrixSourceMapMappings[0][5] !== undefined || !matrixSourceMapPrototypeGetThrows) throw new Error('module SourceMap Symbol(kMappings) failed');; fs.mkdirSync('/home/opencontainers/.node_modules/global-pkg', { recursive: true }); fs.writeFileSync('/home/opencontainers/.node_modules/global-pkg/index.js', \"module.exports = 'global-home';\"); const moduleGlobalInitial = JSON.stringify(Module.globalPaths); const moduleGlobalResolvePaths = resolverRequire.resolve.paths('global-pkg').slice(-3).join('|'); const moduleGlobalResolve = resolverRequire.resolve('global-pkg'); const moduleGlobalValue = resolverRequire('global-pkg'); Module.globalPaths.push('/mutated-global-path'); const moduleGlobalMutation = [Module.globalPaths.includes('/mutated-global-path'), resolverRequire.resolve.paths('global-pkg').includes('/mutated-global-path')].join(':'); Module._initPaths(); const moduleGlobalReset = [JSON.stringify(Module.globalPaths), resolverRequire.resolve.paths('global-pkg').includes('/mutated-global-path')].join(':'); const previousModuleHome = process.env.HOME; const previousModuleNodePath = process.env.NODE_PATH; process.env.HOME = '/home/demo'; process.env.NODE_PATH = '/node-path-root:/second-root'; fs.mkdirSync('/node-path-root/nodepath-pkg', { recursive: true }); fs.writeFileSync('/node-path-root/nodepath-pkg/package.json', JSON.stringify({ name: 'nodepath-pkg', main: 'main.js' })); fs.writeFileSync('/node-path-root/nodepath-pkg/main.js', \"module.exports = 'node-path';\"); Module._initPaths(); const moduleNodePathResolve = resolverRequire.resolve('nodepath-pkg'); const moduleNodePathRows = [JSON.stringify(Module.globalPaths), resolverRequire.resolve.paths('nodepath-pkg').slice(-5).join('|'), moduleNodePathResolve, resolverRequire('nodepath-pkg')].join('::'); if (previousModuleHome === undefined) delete process.env.HOME; else process.env.HOME = previousModuleHome; if (previousModuleNodePath === undefined) delete process.env.NODE_PATH; else process.env.NODE_PATH = previousModuleNodePath; Module._initPaths(); if (moduleGlobalInitial !== '[\"/home/opencontainers/.node_modules\",\"/home/opencontainers/.node_libraries\",\"/lib/node\"]' || moduleGlobalResolvePaths !== '/home/opencontainers/.node_modules|/home/opencontainers/.node_libraries|/lib/node' || moduleGlobalResolve !== '/home/opencontainers/.node_modules/global-pkg/index.js' || moduleGlobalValue !== 'global-home' || moduleGlobalMutation !== 'true:false' || moduleGlobalReset !== '[\"/home/opencontainers/.node_modules\",\"/home/opencontainers/.node_libraries\",\"/lib/node\"]:false' || moduleNodePathRows !== '[\"/node-path-root\",\"/second-root\",\"/home/demo/.node_modules\",\"/home/demo/.node_libraries\",\"/lib/node\"]::/node-path-root|/second-root|/home/demo/.node_modules|/home/demo/.node_libraries|/lib/node::/node-path-root/nodepath-pkg/main.js::node-path') throw new Error('module globalPaths failed')", "unsupported": { "code": "ERR_OPENCONTAINERS_NATIVE_ADDON_UNSUPPORTED", "reason": "Native .node add-ons require host ABI loading and are blocked in the browser runtime.", "probe": "require('node:fs').writeFileSync('/workspace/addon.node', ''); require('/workspace/addon.node')" } }, { "specifier": "node:perf_hooks", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Backed by host timing where available with OpenContainers mark/measure/function/resource observer delivery, mark/measure argument validation for missing names, missing marks, negative timestamps, and invalid option combinations, resource timing entries and buffer controls, PerformanceObserver option validation and native-hidden observer/list instance state, native-shaped Performance singleton/prototype/global metadata including custom inspect and toStringTag symbols, native-shaped PerformanceNodeTiming metadata and JSON shape, process-local performance entry state, native-shaped RecordableHistogram createHistogram probes, array option validation for monitorEventLoopDelay(), createHistogram(), and timerify(), module/performance timerify and eventLoopUtilization identity plus receiver-tolerant eventLoopUtilization calls, a dedicated timer-sampled ELDHistogram monitorEventLoopDelay handle without recordable histogram mutators plus Symbol.dispose metadata, native-shaped PerformanceObserver internal/custom inspect/toStringTag symbols, native-shaped constants, and browser-safe approximate event loop utilization.", "probe": "const ph = require('node:perf_hooks'); const { performance, Performance, PerformanceEntry, PerformanceMeasure, PerformanceObserver, PerformanceMark, PerformanceResourceTiming } = ph; const methodMeta = ['now','mark','measure','clearMarks','clearMeasures','markResourceTiming','clearResourceTimings','setResourceTimingBufferSize','getEntries','getEntriesByName','getEntriesByType','eventLoopUtilization','timerify'].map((name) => name + ':' + performance[name].name + ':' + performance[name].length).join('|'); const functionPrototypeMeta = ['monitorEventLoopDelay','eventLoopUtilization','timerify','createHistogram'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(ph[name], 'prototype'); return [name, Object.hasOwn(ph[name], 'prototype'), descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.getOwnPropertyNames(descriptor.value).join(',')].join(':') }).join('|'); const describePrototype = (prototype, names) => names.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(prototype, name); if ('value' in descriptor) return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype')].join(':'); return [name, descriptor.enumerable, descriptor.configurable, 'accessor', descriptor.get.name, descriptor.get.length, typeof descriptor.set].join(':') }).join('|'); const symbolMeta = (prototype) => Object.getOwnPropertySymbols(prototype).map((symbol) => { const descriptor = Object.getOwnPropertyDescriptor(prototype, symbol); return [String(symbol), typeof descriptor.value, descriptor.value?.name ?? '', descriptor.value?.length ?? '', descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.hasOwn(descriptor.value ?? {}, 'prototype'), typeof descriptor.value === 'string' ? descriptor.value : ''].join(':') }).join('|') || ''; const performanceSymbolMeta = symbolMeta(Performance.prototype); const performanceObserverSymbolMeta = symbolMeta(PerformanceObserver.prototype); const performancePrototypeMeta = [Object.keys(performance).join(',') || '', Object.getOwnPropertyNames(performance).join(',') || '', Object.getOwnPropertyNames(Performance.prototype).join(','), Object.keys(Performance.prototype).join(','), describePrototype(Performance.prototype, ['now','mark','markResourceTiming','eventLoopUtilization','timerify','timeOrigin','nodeTiming','onresourcetimingbufferfull'])].join(';'); const globalPerformanceRows = [globalThis.performance === performance, globalThis.Performance === Performance, performance instanceof globalThis.Performance, ph.performance === performance, ph.timerify === performance.timerify, ph.eventLoopUtilization === performance.eventLoopUtilization, typeof performance.eventLoopUtilization.call({}).active].join(':'); const nodeTiming = performance.nodeTiming; const nodeTimingPrototype = Object.getPrototypeOf(nodeTiming); const nodeTimingEntryPrototype = Object.getPrototypeOf(nodeTimingPrototype); const describeNodeTimingOwnDescriptor = (name) => { const descriptor = Object.getOwnPropertyDescriptor(nodeTiming, name); if ('value' in descriptor) return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value, typeof descriptor.get, typeof descriptor.set].join(':'); return [name, descriptor.enumerable, descriptor.configurable, 'accessor', descriptor.get.name, descriptor.get.length, typeof descriptor.set].join(':'); }; const nodeTimingToJSONDescriptor = Object.getOwnPropertyDescriptor(nodeTimingPrototype, 'toJSON'); const nodeTimingMeta = [nodeTiming.constructor.name, nodeTiming instanceof PerformanceEntry, Object.keys(nodeTiming).join(','), Object.getOwnPropertyNames(nodeTiming).join(','), Object.getOwnPropertyNames(nodeTimingPrototype).join(','), Object.keys(nodeTimingPrototype).join(',') || '', nodeTimingEntryPrototype.constructor.name, ['name','duration','nodeStart','uvMetricsInfo'].map(describeNodeTimingOwnDescriptor).join('|'), [nodeTimingToJSONDescriptor.enumerable, nodeTimingToJSONDescriptor.configurable, nodeTimingToJSONDescriptor.writable, nodeTimingToJSONDescriptor.value.name, nodeTimingToJSONDescriptor.value.length, Object.hasOwn(nodeTimingToJSONDescriptor.value, 'prototype')].join(':'), Object.keys(nodeTiming.toJSON()).join(','), nodeTiming.uvMetricsInfo === nodeTiming.uvMetricsInfo, Number.isFinite(nodeTiming.toJSON().duration)].join(';'); const entryPrototypeMeta = ['entry:' + Object.getOwnPropertyNames(PerformanceEntry.prototype).join(',') + ':' + Object.keys(PerformanceEntry.prototype).join(',') + ':' + describePrototype(PerformanceEntry.prototype, ['name','entryType','startTime','duration','toJSON']), 'mark:' + Object.getOwnPropertyNames(PerformanceMark.prototype).join(',') + ':' + Object.keys(PerformanceMark.prototype).join(',') + ':' + describePrototype(PerformanceMark.prototype, ['detail','toJSON']), 'measure:' + Object.getOwnPropertyNames(PerformanceMeasure.prototype).join(',') + ':' + Object.keys(PerformanceMeasure.prototype).join(',') + ':' + describePrototype(PerformanceMeasure.prototype, ['detail','toJSON']), 'resource:' + Object.getOwnPropertyNames(PerformanceResourceTiming.prototype).join(',') + ':' + Object.keys(PerformanceResourceTiming.prototype).join(',') + ':' + describePrototype(PerformanceResourceTiming.prototype, ['name','startTime','duration','initiatorType','workerStart','redirectStart','redirectEnd','fetchStart','domainLookupStart','domainLookupEnd','connectStart','connectEnd','secureConnectionStart','nextHopProtocol','requestStart','responseStart','responseEnd','encodedBodySize','decodedBodySize','transferSize','deliveryType','responseStatus','toJSON'])].join(';'); const observerShapeRows = (() => { let listShape = ''; const observer = new PerformanceObserver((list) => { listShape = [Object.keys(list).join(',') || '', Object.getOwnPropertyNames(list).join(',') || ''].join(':'); }); const ownShape = [Object.keys(observer).join(',') || '', Object.getOwnPropertyNames(observer).join(',') || ''].join(':'); observer.observe({ entryTypes: ['mark'] }); performance.mark('observer-shape-probe'); return new Promise((resolve) => setTimeout(() => resolve([ownShape, listShape].join('|')), 0)); })(); const observerValidationRows = [['ctor-missing', () => new PerformanceObserver()], ['ctor-null', () => new PerformanceObserver(null)], ['observe-missing', () => new PerformanceObserver(() => {}).observe()], ['observe-null', () => new PerformanceObserver(() => {}).observe(null)], ['observe-entryTypes-string', () => new PerformanceObserver(() => {}).observe({ entryTypes: 'mark' })], ['observe-type-plus-entryTypes', () => new PerformanceObserver(() => {}).observe({ type: 'mark', entryTypes: ['mark'] })]].map(([label, action]) => { try { action(); return label + ':ok' } catch (error) { return [label, error.name, error.code, error.message].join(':') } }).join('|'); const markMeasureValidationRows = [['mark-missing', () => performance.mark()], ['mark-options-string', () => performance.mark('x', 'bad')], ['mark-neg-start', () => performance.mark('neg', { startTime: -1 })], ['measure-missing', () => performance.measure()], ['measure-null-name', () => performance.measure(null)], ['measure-missing-start', () => performance.measure('m', 'missing')], ['measure-missing-option-start', () => performance.measure('m', { start: 'missing' })], ['measure-neg-option-start', () => performance.measure('m', { start: -1, duration: 1 })], ['measure-invalid-options', () => performance.measure('m', { start: 1, end: 5, duration: 2 })], ['measure-start-duration', () => performance.measure('m', { start: 1, duration: 2, detail: { ok: true } })]].map(([label, action]) => { try { const value = action(); return [label, 'ok', value.name, value.startTime, value.duration, JSON.stringify(value.detail), value.constructor.name].join(':') } catch (error) { return [label, error.name, error.code ?? 'none', error.message].join(':') } }).join('|'); const histogramOptionCodes = [() => ph.monitorEventLoopDelay(null), () => ph.monitorEventLoopDelay([]), () => ph.monitorEventLoopDelay({ resolution: '1' }), () => ph.monitorEventLoopDelay({ resolution: 0 }), () => ph.monitorEventLoopDelay({ resolution: 1.2 }), () => ph.monitorEventLoopDelay({ resolution: 1 }), () => ph.createHistogram(null), () => ph.createHistogram([]), () => ph.createHistogram({ lowest: '1' }), () => ph.createHistogram({ lowest: 0 }), () => ph.createHistogram({ lowest: 10, highest: 5 }), () => ph.createHistogram({ figures: '2' }), () => ph.createHistogram({ lowest: 1, highest: 10, figures: 2 }), () => ph.timerify(function timed() {}, [])].map((action) => { try { return action().constructor.name; } catch (error) { return error.code; } }).join(','); const eventLoopDelay = ph.monitorEventLoopDelay({ resolution: 1 }); const eventLoopDelayPrototype = Object.getPrototypeOf(eventLoopDelay); const eventLoopDelayReadoutPrototype = Object.getPrototypeOf(eventLoopDelayPrototype); const eventLoopDelaySymbolMeta = symbolMeta(eventLoopDelayPrototype); const eventLoopDelayShape = [eventLoopDelay.constructor.name, Object.keys(eventLoopDelay).join(\",\") || \"\", Object.getOwnPropertyNames(eventLoopDelay).join(\",\") || \"\", Object.getOwnPropertyNames(eventLoopDelayPrototype).join(\",\"), Object.keys(eventLoopDelayPrototype).join(\",\") || \"\", Object.getOwnPropertyNames(eventLoopDelayReadoutPrototype).join(\",\"), Object.keys(eventLoopDelayReadoutPrototype).join(\",\") || \"\", typeof eventLoopDelay.record, typeof eventLoopDelay.recordDelta, typeof eventLoopDelay.add, String(eventLoopDelay.enable()), String(eventLoopDelay.disable()), eventLoopDelay.count, eventLoopDelay.min, eventLoopDelay.max, String(eventLoopDelay.mean), String(eventLoopDelay.stddev), JSON.stringify([...eventLoopDelay.percentiles]), JSON.stringify(eventLoopDelay.toJSON())].join(\"|\"); const sampledDelay = ph.monitorEventLoopDelay({ resolution: 1 }); const sampledState = [sampledDelay.enable(), sampledDelay.enable()].join(':'); await new Promise((resolve) => setTimeout(resolve, 8)); const sampleStart = performance.now(); while (performance.now() - sampleStart < 5) {} await new Promise((resolve) => setTimeout(resolve, 8)); const sampledSummary = [sampledDelay.disable(), sampledDelay.disable(), sampledDelay.count > 0, sampledDelay.min !== 9223372036854776000, Number.isFinite(sampledDelay.mean), Number.isFinite(sampledDelay.stddev), sampledDelay.percentiles.has(100), sampledDelay.toJSON().count === sampledDelay.count, sampledDelay.max >= sampledDelay.min].join(':'); sampledDelay.reset(); const sampledReset = [sampledDelay.count, sampledDelay.min, String(sampledDelay.mean), JSON.stringify([...sampledDelay.percentiles])].join(':'); const mark = performance.mark('probe'); const measure = performance.measure('probe-measure', 'probe'); performance.clearResourceTimings(); performance.setResourceTimingBufferSize(250); performance.onresourcetimingbufferfull = null; const resourceTimingInfo = { startTime: 10, finalServiceWorkerStartTime: 11, redirectStartTime: 12, redirectEndTime: 13, postRedirectStartTime: 14, finalConnectionTimingInfo: { domainLookupStartTime: 15, domainLookupEndTime: 16, connectionStartTime: 17, connectionEndTime: 18, secureConnectionStartTime: 19, ALPNNegotiatedProtocol: 'h3' }, finalNetworkRequestStartTime: 20, finalNetworkResponseStartTime: 21, endTime: 22, encodedBodySize: 123, decodedBodySize: 456 }; const resource = performance.markResourceTiming(resourceTimingInfo, 'https://example.test/asset.js', 'fetch', globalThis, '', undefined, 206, 'cache'); const resourceMeta = [resource instanceof PerformanceResourceTiming, resource.entryType, resource.startTime, resource.duration, resource.initiatorType, resource.workerStart, resource.redirectStart, resource.redirectEnd, resource.fetchStart, resource.domainLookupStart, resource.domainLookupEnd, resource.connectStart, resource.connectEnd, resource.secureConnectionStart, resource.nextHopProtocol, resource.requestStart, resource.responseStart, resource.responseEnd, resource.encodedBodySize, resource.decodedBodySize, resource.transferSize, resource.deliveryType, resource.responseStatus, Object.keys(resource).join(',') || '', Object.getOwnPropertyNames(resource).join(',') || ''].join('|'); const resourceJson = JSON.stringify(resource.toJSON()); await new Promise((resolve) => setTimeout(resolve, 0)); let resourceBufferFull = 0; performance.onresourcetimingbufferfull = () => { resourceBufferFull++; }; performance.clearResourceTimings(); performance.setResourceTimingBufferSize(1); performance.markResourceTiming({ startTime: 1, endTime: 2, encodedBodySize: 1, decodedBodySize: 2 }, 'buffer-one', 'fetch', globalThis, '', undefined, 200); performance.markResourceTiming({ startTime: 2, endTime: 3, encodedBodySize: 3, decodedBodySize: 4 }, 'buffer-two', 'fetch', globalThis, '', undefined, 200); await new Promise((resolve) => setTimeout(resolve, 0)); const resourceBufferRow = [performance.getEntriesByType('resource').map((entry) => entry.name).join(','), resourceBufferFull].join(':'); performance.clearResourceTimings(); performance.setResourceTimingBufferSize(250); performance.onresourcetimingbufferfull = null; const constantsDescriptor = Object.getOwnPropertyDescriptor(ph, 'constants'); if (Object.keys(ph).join(',') !== 'Performance,PerformanceEntry,PerformanceMark,PerformanceMeasure,PerformanceObserver,PerformanceObserverEntryList,PerformanceResourceTiming,monitorEventLoopDelay,eventLoopUtilization,timerify,createHistogram,performance,constants' || !(performance instanceof Performance) || Performance.name !== 'Performance' || Performance.length !== 0 || performancePrototypeMeta !== ';;constructor,clearMarks,clearMeasures,clearResourceTimings,getEntries,getEntriesByName,getEntriesByType,mark,measure,now,setResourceTimingBufferSize,timeOrigin,toJSON,eventLoopUtilization,nodeTiming,markResourceTiming,timerify,onresourcetimingbufferfull;clearMarks,clearMeasures,clearResourceTimings,getEntries,getEntriesByName,getEntriesByType,mark,measure,now,setResourceTimingBufferSize,timeOrigin,toJSON,onresourcetimingbufferfull;now:true:true:true:now:0:false|mark:true:true:true:mark:1:false|markResourceTiming:false:true:true:markResourceTiming:7:true|eventLoopUtilization:false:true:true:eventLoopUtilization:2:true|timerify:false:true:true:timerify:1:true|timeOrigin:true:true:accessor:get timeOrigin:0:undefined|nodeTiming:false:true:true:node::false|onresourcetimingbufferfull:true:true:accessor:get onresourcetimingbufferfull:0:function' || globalPerformanceRows !== 'true:true:true:true:true:true:number' || nodeTimingMeta !== 'PerformanceNodeTiming;true;name,entryType,startTime,duration,nodeStart,v8Start,environment,loopStart,loopExit,bootstrapComplete,idleTime,uvMetricsInfo;name,entryType,startTime,duration,nodeStart,v8Start,environment,loopStart,loopExit,bootstrapComplete,idleTime,uvMetricsInfo;constructor,toJSON;;PerformanceEntry;name:true:true:false:string:undefined:undefined|duration:true:true:accessor:now:0:undefined|nodeStart:true:true:accessor:get:0:undefined|uvMetricsInfo:true:true:accessor:get:0:undefined;false:true:true:toJSON:0:false;name,entryType,startTime,duration,nodeStart,v8Start,bootstrapComplete,environment,loopStart,loopExit,idleTime;false;true' || methodMeta !== 'now:now:0|mark:mark:1|measure:measure:1|clearMarks:clearMarks:0|clearMeasures:clearMeasures:0|markResourceTiming:markResourceTiming:7|clearResourceTimings:clearResourceTimings:0|setResourceTimingBufferSize:setResourceTimingBufferSize:1|getEntries:getEntries:0|getEntriesByName:getEntriesByName:1|getEntriesByType:getEntriesByType:1|eventLoopUtilization:eventLoopUtilization:2|timerify:timerify:1' || performanceSymbolMeta !== 'Symbol(nodejs.util.inspect.custom):function:[nodejs.util.inspect.custom]:2:false:true:true:false:|Symbol(Symbol.toStringTag):string::11:false:true:false:false:Performance' || performanceObserverSymbolMeta !== 'Symbol(kMaybeBuffer):function:[kMaybeBuffer]:1:false:true:true:false:|Symbol(kDispatch):function:[kDispatch]:0:false:true:true:false:|Symbol(nodejs.util.inspect.custom):function:[nodejs.util.inspect.custom]:2:false:true:true:false:|Symbol(Symbol.toStringTag):string::19:false:true:false:false:PerformanceObserver' || eventLoopDelaySymbolMeta !== 'Symbol(Symbol.dispose):function:[Symbol.dispose]:0:false:true:true:false:' || functionPrototypeMeta !== 'monitorEventLoopDelay:true:false:false:true:constructor|eventLoopUtilization:true:false:false:true:constructor|timerify:true:false:false:true:constructor|createHistogram:true:false:false:true:constructor' || entryPrototypeMeta !== 'entry:constructor,name,entryType,startTime,duration,toJSON:name,entryType,startTime,duration,toJSON:name:true:true:accessor:get name:0:undefined|entryType:true:true:accessor:get entryType:0:undefined|startTime:true:true:accessor:get startTime:0:undefined|duration:true:true:accessor:get duration:0:undefined|toJSON:true:true:true:toJSON:0:false;mark:constructor,detail,toJSON:detail:detail:true:true:accessor:get detail:0:undefined|toJSON:false:true:true:toJSON:0:false;measure:constructor,detail,toJSON:detail:detail:true:true:accessor:get detail:0:undefined|toJSON:false:true:true:toJSON:0:false;resource:constructor,name,startTime,duration,initiatorType,workerStart,redirectStart,redirectEnd,fetchStart,domainLookupStart,domainLookupEnd,connectStart,connectEnd,secureConnectionStart,nextHopProtocol,requestStart,responseStart,responseEnd,encodedBodySize,decodedBodySize,transferSize,deliveryType,responseStatus,toJSON:initiatorType,workerStart,redirectStart,redirectEnd,fetchStart,domainLookupStart,domainLookupEnd,connectStart,connectEnd,secureConnectionStart,nextHopProtocol,requestStart,responseStart,responseEnd,encodedBodySize,decodedBodySize,transferSize,deliveryType,responseStatus,toJSON:name:false:true:accessor:get name:0:undefined|startTime:false:true:accessor:get startTime:0:undefined|duration:false:true:accessor:get duration:0:undefined|initiatorType:true:true:accessor:get initiatorType:0:undefined|workerStart:true:true:accessor:get workerStart:0:undefined|redirectStart:true:true:accessor:get redirectStart:0:undefined|redirectEnd:true:true:accessor:get redirectEnd:0:undefined|fetchStart:true:true:accessor:get fetchStart:0:undefined|domainLookupStart:true:true:accessor:get domainLookupStart:0:undefined|domainLookupEnd:true:true:accessor:get domainLookupEnd:0:undefined|connectStart:true:true:accessor:get connectStart:0:undefined|connectEnd:true:true:accessor:get connectEnd:0:undefined|secureConnectionStart:true:true:accessor:get secureConnectionStart:0:undefined|nextHopProtocol:true:true:accessor:get nextHopProtocol:0:undefined|requestStart:true:true:accessor:get requestStart:0:undefined|responseStart:true:true:accessor:get responseStart:0:undefined|responseEnd:true:true:accessor:get responseEnd:0:undefined|encodedBodySize:true:true:accessor:get encodedBodySize:0:undefined|decodedBodySize:true:true:accessor:get decodedBodySize:0:undefined|transferSize:true:true:accessor:get transferSize:0:undefined|deliveryType:true:true:accessor:get deliveryType:0:undefined|responseStatus:true:true:accessor:get responseStatus:0:undefined|toJSON:true:true:true:toJSON:0:false' || await observerShapeRows !== ':|:' || observerValidationRows !== 'ctor-missing:TypeError:ERR_INVALID_ARG_TYPE:The \"callback\" argument must be of type function. Received undefined|ctor-null:TypeError:ERR_INVALID_ARG_TYPE:The \"callback\" argument must be of type function. Received null|observe-missing:TypeError:ERR_MISSING_ARGS:The \"options.entryTypes\" and \"options.type\" arguments must be specified|observe-null:TypeError:ERR_INVALID_ARG_TYPE:The \"options\" argument must be of type object. Received null|observe-entryTypes-string:TypeError:ERR_INVALID_ARG_TYPE:The \"options.entryTypes\" property must be string[]. Received type string (\\'mark\\')|observe-type-plus-entryTypes:TypeError:ERR_INVALID_ARG_VALUE:The property \\'options.entryTypes\\' options.entryTypes can not set with options.type together. Received [ \\'mark\\' ]' || markMeasureValidationRows !== 'mark-missing:TypeError:ERR_MISSING_ARGS:The \"name\" argument must be specified|mark-options-string:TypeError:ERR_INVALID_ARG_TYPE:The \"options\" argument must be of type object. Received type string|mark-neg-start:TypeError:ERR_PERFORMANCE_INVALID_TIMESTAMP:-1 is not a valid timestamp|measure-missing:TypeError:ERR_MISSING_ARGS:The \"name\" argument must be specified|measure-null-name:TypeError:ERR_INVALID_ARG_TYPE:The \"name\" argument must be of type string. Received null|measure-missing-start:SyntaxError:12:The \"missing\" performance mark has not been set|measure-missing-option-start:SyntaxError:12:The \"missing\" performance mark has not been set|measure-neg-option-start:TypeError:ERR_PERFORMANCE_INVALID_TIMESTAMP:-1 is not a valid timestamp|measure-invalid-options:TypeError:ERR_PERFORMANCE_MEASURE_INVALID_OPTIONS:Must not have options.start, options.end, and options.duration specified|measure-start-duration:ok:m:1:2:{\"ok\":true}:PerformanceMeasure' || resourceMeta !== 'true|resource|10|12|fetch|11|12|13|14|15|16|17|18|19|h3|20|21|22|123|456|423|cache|206||' || resourceJson !== '{\"name\":\"https://example.test/asset.js\",\"entryType\":\"resource\",\"startTime\":10,\"duration\":12,\"initiatorType\":\"fetch\",\"nextHopProtocol\":\"h3\",\"workerStart\":11,\"redirectStart\":12,\"redirectEnd\":13,\"fetchStart\":14,\"domainLookupStart\":15,\"domainLookupEnd\":16,\"connectStart\":17,\"connectEnd\":18,\"secureConnectionStart\":19,\"requestStart\":20,\"responseStart\":21,\"responseEnd\":22,\"transferSize\":423,\"encodedBodySize\":123,\"decodedBodySize\":456,\"deliveryType\":\"cache\",\"responseStatus\":206}' || resourceBufferRow !== 'buffer-one:1' || PerformanceObserver.supportedEntryTypes.join(',') !== 'dns,function,gc,http,http2,mark,measure,net,quic,resource' || eventLoopDelayShape !== \"ELDHistogram|||constructor,enable,disable||constructor,count,countBigInt,min,minBigInt,max,maxBigInt,mean,exceeds,exceedsBigInt,stddev,percentile,percentileBigInt,percentiles,percentilesBigInt,reset,toJSON||undefined|undefined|undefined|true|true|0|9223372036854776000|0|NaN|NaN|[[100,0]]|{\\\"count\\\":0,\\\"min\\\":9223372036854776000,\\\"max\\\":0,\\\"mean\\\":null,\\\"exceeds\\\":0,\\\"stddev\\\":null,\\\"percentiles\\\":{\\\"100\\\":0}}\" || sampledState !== 'true:false' || sampledSummary !== 'true:false:true:true:true:true:true:true:true' || sampledReset !== '0:9223372036854776000:NaN:[[100,0]]' || histogramOptionCodes !== 'ERR_INVALID_ARG_TYPE,ERR_INVALID_ARG_TYPE,ERR_INVALID_ARG_TYPE,ERR_OUT_OF_RANGE,ERR_OUT_OF_RANGE,ELDHistogram,ERR_INVALID_ARG_TYPE,ERR_INVALID_ARG_TYPE,ERR_INVALID_ARG_TYPE,ERR_OUT_OF_RANGE,ERR_OUT_OF_RANGE,ERR_INVALID_ARG_TYPE,RecordableHistogram,ERR_INVALID_ARG_TYPE' || !(mark instanceof PerformanceMark) || measure.entryType !== 'measure' || typeof PerformanceObserver !== 'function' || typeof ph.monitorEventLoopDelay().enable !== 'function' || !constantsDescriptor.enumerable || constantsDescriptor.configurable || constantsDescriptor.writable) throw new Error('perf_hooks failed'); const recordableHistogram = ph.createHistogram(); const recordableOther = ph.createHistogram(); recordableHistogram.record(10); recordableHistogram.recordDelta(); recordableOther.record(20); recordableHistogram.add(recordableOther); const recordablePrototype = Object.getPrototypeOf(recordableHistogram); const recordableReadoutPrototype = Object.getPrototypeOf(recordablePrototype); const recordableShape = [recordableHistogram.constructor.name, Object.keys(recordableHistogram).join(',') || '', Object.getOwnPropertyNames(recordableHistogram).join(',') || '', Object.getOwnPropertyNames(recordablePrototype).join(','), Object.keys(recordablePrototype).join(',') || '', Object.getOwnPropertyNames(recordableReadoutPrototype).join(','), Object.keys(recordableReadoutPrototype).join(',') || '', typeof recordableHistogram.enable, typeof recordableHistogram.record, recordableHistogram.count].join('|'); if (recordableShape !== 'RecordableHistogram|constructor|constructor|constructor,record,recordDelta,add||constructor,count,countBigInt,min,minBigInt,max,maxBigInt,mean,exceeds,exceedsBigInt,stddev,percentile,percentileBigInt,percentiles,percentilesBigInt,reset,toJSON||undefined|function|3') throw new Error('RecordableHistogram createHistogram metadata failed')" }, { "specifier": "node:process", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs, tests/cjs-loader-parity.test.mjs", "limitation": "Process metadata, native-shaped CommonJS export and own-property order, expanded native-ordered process.versions dependency keys/read-only descriptors, native-shaped process.features values/property descriptors plus allowedNodeEnvironmentFlags/finalization/exitCode and sourceMapsEnabled/stdin/stdout/stderr/report accessor descriptor metadata, sourceMapsEnabled/report non-constructable getters, node -e argv and bad-option normalization, launch-mode process._eval/preload/exiting probes, script-mode process.mainModule parity, pid/argv0/preload identity descriptor metadata, Node-shaped process toStringTag/EventEmitter metadata without leaking the internal OpenContainers event storage symbol, readonly public runtime metadata descriptors, native-shaped process diagnostic helper names/arities/prototype metadata, POSIX identity/mutation helper names/arities/prototype metadata, selected process helper names/arities/prototype metadata, hidden OpenContainers internal lifecycle helpers, process.loadEnvFile, Node-shaped process.env assignment/defineProperty string coercion, Node-like allowedNodeEnvironmentFlags, process.domain probes, feature probes, refable helpers, signal-0 process probes, current-process virtual signal listener delivery, unhandled SIGINT termination metadata, cpuUsage/threadCpuUsage previous-sample validation, report generation/exclusion flags, common helpers, umask parsing, chdir target validation/cwd preservation, common argument validation, native escape-hatch metadata/validation for browser-blocked execve/dlopen/binding/abort/debug helpers, and Node-shaped exitCode assignment validation/coercion are virtualized; host-native signals, uid/gid, host real cwd semantics, native dlopen/addons, process replacement, and host debugger controls are constrained.", "probe": "const processModule = require('node:process'); const expectedProcessKeys = 'version,versions,arch,platform,release,_rawDebug,moduleLoadList,binding,_linkedBinding,_events,_eventsCount,_maxListeners,domain,_exiting,exitCode,config,dlopen,uptime,_getActiveRequests,_getActiveHandles,getActiveResourcesInfo,reallyExit,_kill,loadEnvFile,cpuUsage,threadCpuUsage,resourceUsage,memoryUsage,constrainedMemory,availableMemory,kill,exit,execve,ref,unref,finalization,hrtime,openStdin,getuid,geteuid,getgid,getegid,getgroups,allowedNodeEnvironmentFlags,features,_fatalException,setUncaughtExceptionCaptureCallback,addUncaughtExceptionCaptureCallback,hasUncaughtExceptionCaptureCallback,emitWarning,nextTick,_tickCallback,sourceMapsEnabled,setSourceMapsEnabled,getBuiltinModule,_debugProcess,_debugEnd,_startProfilerIdleNotifier,_stopProfilerIdleNotifier,stdout,stdin,stderr,abort,umask,chdir,cwd,initgroups,setgroups,setegid,seteuid,setgid,setuid,env,title,argv,execArgv,pid,ppid,execPath,debugPort,argv0,_preload_modules,report'; const processVersionKeys = Object.keys(process.versions).join(','); const expectedProcessVersionKeys = 'node,acorn,ada,amaro,ares,brotli,cldr,icu,libffi,lief,llhttp,merve,modules,napi,nbytes,ncrypto,nghttp2,nghttp3,ngtcp2,openssl,simdjson,simdutf,sqlite,tz,undici,unicode,uv,uvwasi,v8,zlib,zstd,opencontainers'; const processVersionRows = ['uv','openssl','zlib','undici','sqlite','zstd'].map((key) => key + ':' + typeof process.versions[key] + ':' + process.versions[key]).join('|'); const processVersionDescriptorRows = ['node','uv','openssl','opencontainers'].map((key) => { const versionDescriptor = Object.getOwnPropertyDescriptor(process.versions, key); return [key, versionDescriptor.enumerable, versionDescriptor.configurable, versionDescriptor.writable, typeof versionDescriptor.value].join(':'); }).join('|'); const processVersionsShape = [Object.isExtensible(process.versions), Object.isFrozen(process.versions), Object.getPrototypeOf(process.versions) === Object.prototype].join(':'); const descriptorRows = ['features','allowedNodeEnvironmentFlags','finalization','exitCode'].map((key) => { const descriptor = Object.getOwnPropertyDescriptor(process, key); return [key, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.get?.name, descriptor.set?.name, typeof descriptor.value].join(':') }).join('|'); const processDomainDescriptor = Object.getOwnPropertyDescriptor(process, 'domain'); const processDomainDescriptorRow = [processDomainDescriptor.enumerable, processDomainDescriptor.configurable, processDomainDescriptor.writable, typeof processDomainDescriptor.value, Object.hasOwn(processDomainDescriptor.get ?? {}, 'prototype'), Object.hasOwn(processDomainDescriptor.set ?? {}, 'prototype')].join(':'); const processAccessorRows = ['sourceMapsEnabled','stdout','stdin','stderr','report'].map((key) => { const descriptor = Object.getOwnPropertyDescriptor(process, key); return [key, descriptor.enumerable, descriptor.configurable, 'writable' in descriptor ? descriptor.writable : 'accessor', descriptor.get?.name, typeof descriptor.set, typeof descriptor.value].join(':') }).join('|'); const processAccessorPrototypeRows = ['sourceMapsEnabled','report'].map((key) => { const descriptor = Object.getOwnPropertyDescriptor(process, key); return key + ':' + Object.hasOwn(descriptor.get, 'prototype'); }).join('|'); const processEvalDescriptor = Object.getOwnPropertyDescriptor(process, '_eval'); const processEvalDescriptorRow = processEvalDescriptor ? [processEvalDescriptor.enumerable, processEvalDescriptor.configurable, processEvalDescriptor.writable, typeof processEvalDescriptor.value].join(':') : 'missing'; const processMainModuleDescriptor = Object.getOwnPropertyDescriptor(process, 'mainModule'); const processIdentityDescriptorRows = ['pid','ppid','argv0','_preload_modules','execArgv','moduleLoadList'].map((key) => { const descriptor = Object.getOwnPropertyDescriptor(process, key); return [key, descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value].join(':'); }).join('|'); const featureKeys = Object.keys(process.features).join(','); const featureValues = Object.keys(process.features).map((key) => key + ':' + process.features[key]).join('|'); const featureDescriptorRows = Object.keys(process.features).map((key) => { const descriptor = Object.getOwnPropertyDescriptor(process.features, key); return [key, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.get?.name, descriptor.get?.length, typeof descriptor.set, typeof descriptor.value].join(':') }).join('|'); process.features.__probe_extra = 1; const deletedProbeExtra = delete process.features.__probe_extra; const featureShape = [Object.isExtensible(process.features), Object.isSealed(process.features), Object.isFrozen(process.features), deletedProbeExtra, Object.hasOwn(process.features, '__probe_extra')].join(':'); const expectedFeatureKeys = 'inspector,debug,uv,ipv6,tls_alpn,tls_sni,tls_ocsp,tls,openssl_is_boringssl,cached_builtins,require_module,quic,typescript'; const expectedFeatureValues = 'inspector:true|debug:false|uv:true|ipv6:true|tls_alpn:true|tls_sni:true|tls_ocsp:true|tls:true|openssl_is_boringssl:false|cached_builtins:true|require_module:true|quic:false|typescript:strip'; const expectedFeatureDescriptorRows = 'inspector:true:true:true:::undefined:boolean|debug:true:true:true:::undefined:boolean|uv:true:true:true:::undefined:boolean|ipv6:true:true:true:::undefined:boolean|tls_alpn:true:true:true:::undefined:boolean|tls_sni:true:true:true:::undefined:boolean|tls_ocsp:true:true:true:::undefined:boolean|tls:true:true:true:::undefined:boolean|openssl_is_boringssl:true:true:true:::undefined:boolean|cached_builtins:true:true::get cached_builtins:0:undefined:undefined|require_module:true:true::get require_module:0:undefined:undefined|quic:true:true::get quic:0:undefined:undefined|typescript:true:true::get:0:undefined:undefined'; const processKeys = Reflect.ownKeys(process).map(String); const processEventEmitterShape = [['_events','_eventsCount','_maxListeners','Symbol(shapeMode)','Symbol(kCapture)','Symbol(Symbol.toStringTag)'].every((key) => processKeys.includes(key)), !processKeys.includes('Symbol(opencontainers.events)'), Object.getPrototypeOf(process._events) === null, typeof process._eventsCount, process._maxListeners === undefined].join(':'); const envKeys = ['OC_ENV_NULL','OC_ENV_UNDEF','OC_ENV_NUM','OC_ENV_BOOL','OC_ENV_OBJ','OC_ENV_BIG','OC_ENV_DEF','OC_ENV_DEF_UNDEF']; for (const key of envKeys) delete process.env[key]; process.env.OC_ENV_NULL = null; process.env.OC_ENV_UNDEF = undefined; process.env.OC_ENV_NUM = 42; process.env.OC_ENV_BOOL = false; process.env.OC_ENV_OBJ = { toString() { return 'obj-value'; } }; process.env.OC_ENV_BIG = 1n; let envSymbolSet; try { process.env[Symbol('s')] = 'sym-value'; envSymbolSet = 'ok'; } catch (error) { envSymbolSet = [error.name, error.code, error.message].join(':'); } Object.defineProperty(process.env, 'OC_ENV_DEF', { value: 99, enumerable: true, configurable: true, writable: true }); Object.defineProperty(process.env, 'OC_ENV_DEF_UNDEF', { value: undefined, enumerable: true, configurable: true, writable: true }); let envAccessorDefine; try { Object.defineProperty(process.env, 'OC_ENV_ACCESSOR', { get() { return 'x'; }, configurable: true }); envAccessorDefine = 'ok'; } catch (error) { envAccessorDefine = [error.name, error.code, error.message].join(':'); } const envMutationRows = envKeys.map((key) => { const envDescriptor = Object.getOwnPropertyDescriptor(process.env, key); return [key, Object.hasOwn(process.env, key), typeof process.env[key], String(process.env[key]), envDescriptor?.enumerable, envDescriptor?.configurable, envDescriptor?.writable].join(':'); }).join('|'); const descriptor = Object.getOwnPropertyDescriptor(process, 'exitCode'); const processHelperMeta = ['reallyExit','_kill','kill','exit','emitWarning','setSourceMapsEnabled'].map((name) => { const helperDescriptor = Object.getOwnPropertyDescriptor(process, name); return [name, process[name].name, process[name].length, helperDescriptor.enumerable, helperDescriptor.configurable, helperDescriptor.writable].join(':'); }).join('|'); const selectedProcessHelperPrototypeMeta = ['_kill','kill','openStdin','_fatalException','setUncaughtExceptionCaptureCallback','addUncaughtExceptionCaptureCallback','hasUncaughtExceptionCaptureCallback','emitWarning','nextTick','_tickCallback','getBuiltinModule','umask','chdir','cwd'].map((name) => { const helperDescriptor = Object.getOwnPropertyDescriptor(process, name); const helper = helperDescriptor.value; const prototypeDescriptor = Object.getOwnPropertyDescriptor(helper, 'prototype'); let constructable = 'no'; try { Reflect.construct(Object, [], helper); constructable = 'yes'; } catch (error) { constructable = error.message.includes('not a constructor') ? 'no' : error.code || error.name; } return [name, helper.name, helper.length, Object.hasOwn(helper, 'prototype'), helperDescriptor.enumerable, helperDescriptor.configurable, helperDescriptor.writable, prototypeDescriptor?.enumerable ?? '', prototypeDescriptor?.configurable ?? '', prototypeDescriptor?.writable ?? '', Object.getOwnPropertyNames(prototypeDescriptor?.value ?? {}).join(','), constructable].join(':'); }).join('|'); const processDiagnosticHelperMeta = ['_rawDebug','_getActiveRequests','_getActiveHandles','uptime','getActiveResourcesInfo','loadEnvFile','cpuUsage','threadCpuUsage','resourceUsage','memoryUsage','availableMemory','constrainedMemory','ref','unref','hrtime'].map((name) => { const helperDescriptor = Object.getOwnPropertyDescriptor(process, name); const helper = helperDescriptor.value; return [name, helper.name, helper.length, Object.hasOwn(helper, 'prototype'), helperDescriptor.enumerable, helperDescriptor.configurable, helperDescriptor.writable].join(':'); }).join('|'); const processDiagnosticNestedMeta = (() => { const memoryUsageRss = Object.getOwnPropertyDescriptor(process.memoryUsage, 'rss').value; const hrtimeBigInt = Object.getOwnPropertyDescriptor(process.hrtime, 'bigint').value; return [memoryUsageRss.name, memoryUsageRss.length, Object.hasOwn(memoryUsageRss, 'prototype'), hrtimeBigInt.name, hrtimeBigInt.length, Object.hasOwn(hrtimeBigInt, 'prototype')].join(':'); })(); if (Object.keys(process).join(',') !== expectedProcessKeys || Object.getOwnPropertyNames(process).join(',') !== expectedProcessKeys || processVersionKeys !== expectedProcessVersionKeys || processVersionRows !== 'uv:string:1.51.0|openssl:string:3.0.16|zlib:string:1.3.1|undici:string:7.10.0|sqlite:string:3.49.1|zstd:string:1.5.7' || processVersionDescriptorRows !== 'node:true:true:false:string|uv:true:true:false:string|openssl:true:true:false:string|opencontainers:true:true:false:string' || processVersionsShape !== 'true:false:true' || descriptorRows !== 'features:true:false:false:::object|allowedNodeEnvironmentFlags:true:true::get:set:undefined|finalization:true:true::get:set:undefined|exitCode:true:false::get:set:undefined' || !['true:true:true:object:false:false','true:true::undefined:true:true'].includes(processDomainDescriptorRow) || processAccessorRows !== 'sourceMapsEnabled:true:true:accessor:get:undefined:undefined|stdout:true:true:accessor:getStdout:undefined:undefined|stdin:true:true:accessor:getStdin:undefined:undefined|stderr:true:true:accessor:getStderr:undefined:undefined|report:true:true:accessor:get:undefined:undefined' || processAccessorPrototypeRows !== 'sourceMapsEnabled:false|report:false' || processEvalDescriptorRow !== 'missing' || processMainModuleDescriptor !== undefined || processIdentityDescriptorRows !== 'pid:true:true:false:number|ppid:true:true:true:number|argv0:true:false:false:string|_preload_modules:true:true:false:object|execArgv:true:true:true:object|moduleLoadList:true:true:false:object' || featureKeys !== expectedFeatureKeys || featureValues !== expectedFeatureValues || featureDescriptorRows !== expectedFeatureDescriptorRows || featureShape !== 'true:false:false:true:false' || envMutationRows !== 'OC_ENV_NULL:true:string:null:true:true:true|OC_ENV_UNDEF:true:string:undefined:true:true:true|OC_ENV_NUM:true:string:42:true:true:true|OC_ENV_BOOL:true:string:false:true:true:true|OC_ENV_OBJ:true:string:obj-value:true:true:true|OC_ENV_BIG:true:string:1:true:true:true|OC_ENV_DEF:true:string:99:true:true:true|OC_ENV_DEF_UNDEF:true:string:undefined:true:true:true' || envSymbolSet !== 'TypeError::Cannot convert a Symbol value to a string' || envAccessorDefine !== \"TypeError:ERR_INVALID_OBJECT_DEFINE_PROPERTY:'process.env' does not accept an accessor(getter/setter) descriptor\" || processEventEmitterShape !== 'true:true:true:number:true' || processModule.features !== process.features || !Object.keys(processModule).includes('exitCode') || !descriptor?.enumerable || typeof descriptor.get !== 'function' || typeof descriptor.set !== 'function' || processHelperMeta !== 'reallyExit:reallyExit:0:true:true:true|_kill:_kill:0:true:true:true|kill:kill:2:true:true:true|exit:exit:1:true:true:true|emitWarning:emitWarning:4:true:true:true|setSourceMapsEnabled:setSourceMapsEnabled:1:true:true:true' || selectedProcessHelperPrototypeMeta !== '_kill:_kill:0:false:true:true:true:::::no|kill:kill:2:true:true:true:true:false:false:true:constructor:yes|openStdin::0:true:true:true:true:false:false:true:constructor:yes|_fatalException::2:false:true:true:true:::::no|setUncaughtExceptionCaptureCallback:setUncaughtExceptionCaptureCallback:1:true:true:true:true:false:false:true:constructor:yes|addUncaughtExceptionCaptureCallback:addUncaughtExceptionCaptureCallback:1:true:true:true:true:false:false:true:constructor:yes|hasUncaughtExceptionCaptureCallback:hasUncaughtExceptionCaptureCallback:0:true:true:true:true:false:false:true:constructor:yes|emitWarning:emitWarning:4:true:true:true:true:false:false:true:constructor:yes|nextTick:nextTick:1:true:true:true:true:false:false:true:constructor:yes|_tickCallback:runNextTicks:0:true:true:true:true:false:false:true:constructor:yes|getBuiltinModule:getBuiltinModule:1:true:true:true:true:false:false:true:constructor:yes|umask:wrappedUmask:1:true:true:true:true:false:false:true:constructor:yes|chdir:wrappedChdir:1:true:true:true:true:false:false:true:constructor:yes|cwd:wrappedCwd:0:true:true:true:true:false:false:true:constructor:yes' || processDiagnosticHelperMeta !== '_rawDebug:_rawDebug:0:true:true:true:true|_getActiveRequests:_getActiveRequests:0:false:true:true:true|_getActiveHandles:_getActiveHandles:0:false:true:true:true|uptime:uptime:0:false:true:true:true|getActiveResourcesInfo:getActiveResourcesInfo:0:false:true:true:true|loadEnvFile:loadEnvFile:0:true:true:true:true|cpuUsage:cpuUsage:1:true:true:true:true|threadCpuUsage:threadCpuUsage:1:true:true:true:true|resourceUsage:resourceUsage:0:true:true:true:true|memoryUsage:memoryUsage:0:true:true:true:true|availableMemory:availableMemory:0:false:true:true:true|constrainedMemory:constrainedMemory:0:false:true:true:true|ref:ref:1:true:true:true:true|unref:unref:1:true:true:true:true|hrtime:hrtime:1:true:true:true:true' || processDiagnosticNestedMeta !== 'rss:0:false:hrtimeBigInt:0:true') throw new Error('process exitCode descriptor failed'); process.exitCode = '5'; if (process.exitCode !== 5) throw new Error('exitCode string failed'); process.exitCode = undefined; if (process.exitCode !== undefined) throw new Error('exitCode undefined failed'); process.exitCode = null; if (process.exitCode !== undefined) throw new Error('exitCode null failed'); process.exitCode = '0x10'; if (process.exitCode !== 16) throw new Error('exitCode hex failed'); process.exitCode = 4294967297; if (process.exitCode !== 1) throw new Error('exitCode int32 failed'); for (const [value, code] of [['bad', 'ERR_INVALID_ARG_TYPE'], ['', 'ERR_INVALID_ARG_TYPE'], [3.2, 'ERR_OUT_OF_RANGE'], [NaN, 'ERR_OUT_OF_RANGE'], [true, 'ERR_INVALID_ARG_TYPE'], [[], 'ERR_INVALID_ARG_TYPE']]) { try { process.exitCode = value; throw new Error('exitCode validation failed') } catch (error) { if (error.message === 'exitCode validation failed' || error.code !== code) throw error } } if (process.exitCode !== 1) throw new Error('exitCode preservation failed'); process.exitCode = 0; const chdirStart = process.cwd(); require('node:fs').writeFileSync('/workspace/chdir-file.txt', 'file'); const chdirValidationRows = [['missing', () => process.chdir('/workspace/chdir-missing')], ['file', () => process.chdir('/workspace/chdir-file.txt')]].map(([label, action]) => { try { action(); return [label, 'ok', process.cwd() === chdirStart].join(':') } catch (error) { return [label, error.name, error.code, error.errno, error.syscall, error.path === chdirStart, process.cwd() === chdirStart].join(':') } }).join('|'); if (chdirValidationRows !== 'missing:Error:ENOENT:-2:chdir:true:true|file:Error:ENOTDIR:-20:chdir:true:true') throw new Error('process chdir validation failed'); const nativeStubNames = ['execve','dlopen','binding','_linkedBinding','abort','_debugProcess','_debugEnd']; const nativeStubMeta = nativeStubNames.map((name) => { const nativeDescriptor = Object.getOwnPropertyDescriptor(process, name); return [name, typeof process[name], process[name]?.name, process[name]?.length, nativeDescriptor?.enumerable, nativeDescriptor?.configurable, nativeDescriptor?.writable, Object.hasOwn(process[name] ?? {}, 'prototype')].join(':'); }).join('|'); if (nativeStubMeta !== 'execve:function:execve:1:true:true:true:true|dlopen:function:dlopen:0:true:true:true:false|binding:function:binding:1:true:true:true:true|_linkedBinding:function:_linkedBinding:1:true:true:true:true|abort:function:abort:0:true:true:true:false|_debugProcess:function:_debugProcess:0:true:true:true:false|_debugEnd:function:_debugEnd:0:true:true:true:false') throw new Error('process native stub metadata failed'); const errorCode = (run) => { try { run(); return 'ok' } catch (error) { return error.name + ':' + error.code } }; const execveValidation = [() => process.execve(), () => process.execve(1), () => process.execve('/missing', 'bad'), () => process.execve('/missing', [1]), () => process.execve('/missing', ['probe'], 'bad'), () => process.execve('/missing', ['probe'], { A: 1 })].map(errorCode).join('|'); if (execveValidation !== 'TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_VALUE|TypeError:ERR_INVALID_ARG_TYPE|TypeError:ERR_INVALID_ARG_VALUE' || errorCode(() => process.execve('/missing', ['probe'], { PATH: '/bin' })) !== 'Error:ERR_OPENCONTAINERS_PROCESS_UNSUPPORTED') throw new Error('process execve validation failed')", "unsupported": { "probe": "require('node:process').execve('/missing', ['probe'], { PATH: '/bin' })", "code": "ERR_OPENCONTAINERS_PROCESS_UNSUPPORTED" } }, { "specifier": "node:tls", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "TLS API shape, Node-shaped CommonJS export order/descriptors without legacy createConnection/createSecurePair/parseCertString exports, connect argument validation, secure contexts, constructor/function arities, native constructor prototype descriptors, callable SecureContext/Server constructors, getCiphers no-own-prototype metadata and native ordered cipher-list parity, native DEFAULT_CIPHERS parity with crypto.constants.defaultCoreCipherList, constants, hostname identity checks, X509 certificate accessors, ALPN helpers, empty browser CA certificate helper stores, rootCertificates getter metadata, native-shaped TLSSocket/Server own-prototype metadata and prototype symbols, native-shaped TLSSocket/Server method-function own-prototype and constructability metadata, Server ticket-key Buffer copy/validation probes, unconnected TLSSocket cipher/protocol probes, inherited transport helper probes, and enumerable probe class methods are available; raw TLS sockets, OS certificate stores, and secure servers remain unavailable to browser JavaScript.", "probe": "const tls = require('node:tls'); const crypto = require('node:crypto'); const keys = 'CLIENT_RENEG_LIMIT,CLIENT_RENEG_WINDOW,DEFAULT_CIPHERS,DEFAULT_ECDH_CURVE,DEFAULT_MIN_VERSION,DEFAULT_MAX_VERSION,getCiphers,rootCertificates,getCACertificates,setDefaultCACertificates,convertALPNProtocols,checkServerIdentity,createSecureContext,SecureContext,TLSSocket,Server,createServer,connect'; const socketOwn = 'constructor,disableRenegotiation,_wrapHandle,_destroySSL,_init,renegotiate,exportKeyingMaterial,setMaxSendFragment,_handleTimeout,_emitTLSError,_tlsError,_releaseControl,_finishInit,_start,setServername,setSession,getPeerCertificate,getCertificate,getPeerX509Certificate,getX509Certificate,setKeyCert,getCipher,getSharedSigalgs,getEphemeralKeyInfo,getFinished,getPeerFinished,getProtocol,getSession,getTLSTicket,isSessionReused,enableTrace'; const serverOwn = 'constructor,setSecureContext,_getServerData,_setServerData,getTicketKeys,setTicketKeys,addContext'; const expectedTlsCiphers = 'aes128-gcm-sha256,aes128-sha,aes128-sha256,aes256-gcm-sha384,aes256-sha,aes256-sha256,dhe-psk-aes128-cbc-sha,dhe-psk-aes128-cbc-sha256,dhe-psk-aes128-gcm-sha256,dhe-psk-aes256-cbc-sha,dhe-psk-aes256-cbc-sha384,dhe-psk-aes256-gcm-sha384,dhe-psk-chacha20-poly1305,dhe-rsa-aes128-gcm-sha256,dhe-rsa-aes128-sha,dhe-rsa-aes128-sha256,dhe-rsa-aes256-gcm-sha384,dhe-rsa-aes256-sha,dhe-rsa-aes256-sha256,dhe-rsa-chacha20-poly1305,ecdhe-ecdsa-aes128-gcm-sha256,ecdhe-ecdsa-aes128-sha,ecdhe-ecdsa-aes128-sha256,ecdhe-ecdsa-aes256-gcm-sha384,ecdhe-ecdsa-aes256-sha,ecdhe-ecdsa-aes256-sha384,ecdhe-ecdsa-chacha20-poly1305,ecdhe-psk-aes128-cbc-sha,ecdhe-psk-aes128-cbc-sha256,ecdhe-psk-aes256-cbc-sha,ecdhe-psk-aes256-cbc-sha384,ecdhe-psk-chacha20-poly1305,ecdhe-rsa-aes128-gcm-sha256,ecdhe-rsa-aes128-sha,ecdhe-rsa-aes128-sha256,ecdhe-rsa-aes256-gcm-sha384,ecdhe-rsa-aes256-sha,ecdhe-rsa-aes256-sha384,ecdhe-rsa-chacha20-poly1305,psk-aes128-cbc-sha,psk-aes128-cbc-sha256,psk-aes128-gcm-sha256,psk-aes256-cbc-sha,psk-aes256-cbc-sha384,psk-aes256-gcm-sha384,psk-chacha20-poly1305,rsa-psk-aes128-cbc-sha,rsa-psk-aes128-cbc-sha256,rsa-psk-aes128-gcm-sha256,rsa-psk-aes256-cbc-sha,rsa-psk-aes256-cbc-sha384,rsa-psk-aes256-gcm-sha384,rsa-psk-chacha20-poly1305,srp-aes-128-cbc-sha,srp-aes-256-cbc-sha,srp-rsa-aes-128-cbc-sha,srp-rsa-aes-256-cbc-sha,tls_aes_128_ccm_8_sha256,tls_aes_128_ccm_sha256,tls_aes_128_gcm_sha256,tls_aes_256_gcm_sha384,tls_chacha20_poly1305_sha256'; const roots = Object.getOwnPropertyDescriptor(tls, 'rootCertificates'); const socket = new tls.TLSSocket(null, { servername: 'example.com' }); const server = tls.createServer({}, () => {}); const socketMethods = ['destroy','setTimeout','ref','unref'].every((name) => typeof socket[name] === 'function'); const serverMethods = ['close','address'].every((name) => typeof server[name] === 'function'); const ticketKeys = server.getTicketKeys(); const sourceTicketKeys = Buffer.alloc(48, 7); const setTicketKeysResult = server.setTicketKeys(sourceTicketKeys); const storedTicketKeys = server.getTicketKeys(); sourceTicketKeys.fill(9); const copiedTicketKeys = server.getTicketKeys(); server.setTicketKeys(new Uint8Array(48).fill(3)); const typedTicketKeys = server.getTicketKeys(); const ticketKeyValidationRows = [['missing', () => server.setTicketKeys()], ['arraybuffer', () => server.setTicketKeys(new ArrayBuffer(48))], ['short', () => server.setTicketKeys(Buffer.alloc(47))]].map(([label, action]) => { try { action(); return label + ':ok'; } catch (error) { return [label, error.code, error.message.split('\\n')[0]].join(':'); } }).join('|'); const constructorPrototypeRows = ['SecureContext','TLSSocket','Server'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(tls[name], 'prototype'); return [name, typeof descriptor.value, descriptor.value.constructor.name, descriptor.writable, descriptor.enumerable, descriptor.configurable].join(':'); }).join('|'); const prototypeSymbolRows = ['SecureContext','TLSSocket','Server'].map((name) => { const symbols = Object.getOwnPropertySymbols(tls[name].prototype).map(String).join(','); return name + ':' + (symbols || ''); }).join('|'); const prototypeSymbolDescriptorRows = ['TLSSocket','Server'].flatMap((name) => Object.getOwnPropertySymbols(tls[name].prototype).map((symbol) => { const descriptor = Object.getOwnPropertyDescriptor(tls[name].prototype, symbol); return [name, String(symbol), descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype')].join(':'); })).join('|'); const callableConstructorRows = [tls.SecureContext() instanceof tls.SecureContext, tls.Server() instanceof tls.Server].join(':'); const methodPrototypeSummary = (prototype, names) => { const failures = names.filter((name) => { const descriptor = Object.getOwnPropertyDescriptor(prototype, name); const value = descriptor?.value; const prototypeDescriptor = typeof value === 'function' ? Object.getOwnPropertyDescriptor(value, 'prototype') : undefined; const constructorDescriptor = prototypeDescriptor?.value ? Object.getOwnPropertyDescriptor(prototypeDescriptor.value, 'constructor') : undefined; let constructable = false; try { Reflect.construct(Object, [], value); constructable = true; } catch {} let notConstructorFailure = false; try { new value(); } catch (error) { notConstructorFailure = /not a constructor/.test(error.message); } return !(descriptor?.enumerable === true && descriptor?.configurable === true && descriptor?.writable === true && prototypeDescriptor?.enumerable === false && prototypeDescriptor?.configurable === false && prototypeDescriptor?.writable === true && Object.getOwnPropertyNames(prototypeDescriptor.value).join(',') === 'constructor' && constructorDescriptor?.value === value && constructorDescriptor?.enumerable === false && constructorDescriptor?.configurable === true && constructorDescriptor?.writable === true && constructable && !notConstructorFailure); }); return failures.join(',') || 'ok'; }; const socketMethodPrototypeSummary = methodPrototypeSummary(tls.TLSSocket.prototype, Object.keys(tls.TLSSocket.prototype)); const serverMethodPrototypeSummary = methodPrototypeSummary(tls.Server.prototype, Object.keys(tls.Server.prototype)); if (Object.keys(tls).join(',') !== keys || typeof tls.TLSSocket !== 'function' || tls.SecureContext.length !== 4 || tls.TLSSocket.length !== 2 || tls.Server.length !== 2 || constructorPrototypeRows !== 'SecureContext:object:SecureContext:true:false:false|TLSSocket:object:TLSSocket:true:false:false|Server:object:Server:true:false:false' || prototypeSymbolRows !== 'SecureContext:|TLSSocket:Symbol(kReinitializeHandle)|Server:Symbol(nodejs.rejection)' || prototypeSymbolDescriptorRows !== 'TLSSocket:Symbol(kReinitializeHandle):true:true:true:function:reinitializeHandle:1:true|Server:Symbol(nodejs.rejection):true:true:true:function::3:true' || callableConstructorRows !== 'true:true' || tls.createSecureContext.length !== 1 || tls.createServer.length !== 2 || !roots?.get || roots.enumerable !== true || roots.configurable !== false || Object.hasOwn(tls, 'parseCertString') || Object.hasOwn(tls, 'createSecurePair') || Object.hasOwn(tls.getCiphers, 'prototype') || tls.DEFAULT_CIPHERS !== crypto.constants.defaultCoreCipherList || !tls.DEFAULT_CIPHERS.includes('ECDHE-RSA-AES128-GCM-SHA256') || tls.getCiphers().join(',') !== expectedTlsCiphers || tls.getCiphers().length !== 62 || socket.getCipher() !== undefined || socket.getProtocol() !== 'TLSv1.3' || Object.getOwnPropertyNames(tls.TLSSocket.prototype).join(',') !== socketOwn || Object.keys(tls.TLSSocket.prototype).join(',') !== socketOwn.replace('constructor,', '') || socketMethodPrototypeSummary !== 'ok' || Object.getOwnPropertyNames(tls.Server.prototype).join(',') !== serverOwn || Object.keys(tls.Server.prototype).join(',') !== serverOwn.replace('constructor,', '') || serverMethodPrototypeSummary !== 'ok' || !Buffer.isBuffer(ticketKeys) || ticketKeys.length !== 48 || ticketKeys === server.getTicketKeys() || setTicketKeysResult !== undefined || !storedTicketKeys.equals(Buffer.alloc(48, 7)) || storedTicketKeys === sourceTicketKeys || !copiedTicketKeys.equals(Buffer.alloc(48, 7)) || !typedTicketKeys.equals(Buffer.alloc(48, 3)) || ticketKeyValidationRows !== 'missing:ERR_INVALID_ARG_TYPE:The \"buffer\" argument must be an instance of Buffer, TypedArray, or DataView. Received undefined|arraybuffer:ERR_INVALID_ARG_TYPE:The \"buffer\" argument must be an instance of Buffer, TypedArray, or DataView. Received an instance of ArrayBuffer|short:ERR_INTERNAL_ASSERTION:Session ticket keys must be a 48-byte buffer' || !socketMethods || !serverMethods) throw new Error('tls failed')", "unsupported": { "probe": "require('node:tls').connect(443, 'example.com')", "code": "ERR_OPENCONTAINERS_TLS_UNSUPPORTED" } }, { "specifier": "node:_tls_common", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Deprecated private TLS common module is exposed for package probes and aliases node:tls SecureContext/createSecureContext; peer certificate translation is a browser-safe pass-through with native-shaped helper own-prototype metadata.", "probe": "const tls = require('node:tls'); const common = require('node:_tls_common'); const row = (namespace, names) => names.map((name) => { const fn = namespace[name]; const descriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, fn.name, fn.length, Object.hasOwn(fn, 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(','), descriptor?.value?.constructor === fn].join(':'); }).join('|'); const helpers = 'translatePeerCertificate:translatePeerCertificate:1:true:false:false:true:constructor:true'; if (common.SecureContext !== tls.SecureContext || common.createSecureContext !== tls.createSecureContext || row(common, ['translatePeerCertificate']) !== helpers || typeof common.translatePeerCertificate({}) !== 'object') throw new Error('_tls_common failed')" }, { "specifier": "node:_tls_wrap", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Deprecated private TLS wrap module is exposed with native-shaped CommonJS export order for package probes and aliases node:tls Server, TLSSocket, connect, and createServer; raw TLS remains blocked by the public node:tls unsupported errors.", "probe": "const tls = require('node:tls'); const wrap = require('node:_tls_wrap'); if (Object.keys(wrap).join(',') !== 'TLSSocket,Server,createServer,connect' || wrap.Server !== tls.Server || wrap.TLSSocket !== tls.TLSSocket || wrap.connect !== tls.connect || wrap.createServer !== tls.createServer) throw new Error('_tls_wrap failed')" }, { "specifier": "node:util", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Common util APIs, native-shaped CommonJS export order, util.aborted accessor metadata, AsyncFunction branding, Node-shaped rejected-promise argument validation, and abort-event resolution, own function prototype metadata, MIME helpers, ignored public MIMEParams constructor arguments, receiver/iterator errors, and prototype metadata, native-shaped promisify custom markers/metadata, generic first-success-value behavior, callbackify wrapper metadata, env parsing, Node-shaped parseArgs validation/strict positional defaults/option-terminator tokens/loose unknown option handling, process signal conversion, legacy errno helpers, system error validation, transferable abort helper accessor metadata, color formatting, native styleText/inspect.colors bright/style alias table, native-shaped format token conversion, circular reference labels, %O depth semantics, and hidden %o inspection, native-shaped debuglog/deprecate wrapper metadata and callback/warning-event behavior, diff/getCallSites probes, shared util.types export identity, and native-shaped util.inspect defaultOptions accessor/sealed assignment behavior plus showHidden/sorted/maxArrayLength/maxStringLength/numericSeparator/getter-safe behavior are present; inspector-specific, proxy, and advanced layout internals are approximate.", "probe": "const util = require('node:util'); function legacy(value, callback) { callback(null, value); } function multiSuccess(value, callback) { callback(null, value, value + 1); } const promisified = util.promisify(legacy); const multiPromisified = util.promisify(multiSuccess); const constructedPromisified = new util.promisify(legacy); const promisifyDescriptor = Object.getOwnPropertyDescriptor(promisified, util.promisify.custom); function customFn() { return Promise.resolve('ok'); } function withCustom(callback) {} withCustom[util.promisify.custom] = customFn; const customPromisified = util.promisify(withCustom); const customDescriptor = Object.getOwnPropertyDescriptor(customPromisified, util.promisify.custom); function invalidCustom(callback) {} invalidCustom[util.promisify.custom] = 123; let invalidCustomCode = null; try { util.promisify(invalidCustom); } catch (error) { invalidCustomCode = error.code; } function pair(left, right) { return left + right; } const deprecatedPair = util.deprecate(pair, 'old pair', 'DEP_PAIR'); const debugLogger = util.debuglog('opencontainers'); const debugLoggerDescriptor = Object.getOwnPropertyDescriptor(debugLogger, 'enabled'); const warningRows = []; process.on('warning', (warning) => warningRows.push(warning.name + ':' + (warning.code ?? '') + ':' + warning.message)); util._extend({}, { a: 1 }); util._extend({}, { b: 2 }); util.deprecate(function noCode() {}, 'listener api')(); util.deprecate(function withCode() {}, 'listener api code', 'DEP_LISTENER')(); process.env.NODE_DEBUG = 'opencontainers'; const callbackRows = []; const callbackReturn = util.debuglog('opencontainers', (callbackDebug) => callbackRows.push(callbackDebug.name + ':' + callbackDebug.enabled + ':' + (callbackDebug === callbackReturn))); const disabledReturn = util.debuglog('disabled', (callbackDebug) => callbackRows.push(callbackDebug.name + ':' + callbackDebug.enabled + ':' + (callbackDebug === disabledReturn))); await new Promise((resolve) => queueMicrotask(resolve)); async function callbackifyNamed(a, b) { return a + b; } const callbackified = util.callbackify(callbackifyNamed); const callbackifiedAnonymous = util.callbackify(async (value) => value); const metadata = ['aborted','format','inspect','isDeepStrictEqual','styleText','setTraceSigInt','_errnoException','_exceptionWithHostPort','_extend','isArray'].map((name) => `${name}:${util[name].name}:${util[name].length}`).join('|'); const expectedUtilKeys = '_errnoException,_exceptionWithHostPort,_extend,callbackify,convertProcessSignalToExitCode,debug,debuglog,deprecate,format,styleText,formatWithOptions,getCallSites,getSystemErrorMap,getSystemErrorName,getSystemErrorMessage,inherits,inspect,isArray,isDeepStrictEqual,promisify,stripVTControlCharacters,toUSVString,transferableAbortSignal,transferableAbortController,aborted,types,parseEnv,parseArgs,TextDecoder,TextEncoder,MIMEType,MIMEParams,diff,setTraceSigInt'; const utilKeys = Object.keys(util).join(','); const abortedDescriptor = Object.getOwnPropertyDescriptor(util, 'aborted'); const invalidAlreadyAborted = new AbortController(); invalidAlreadyAborted.abort('done'); const abortedValidationRows = await Promise.all([['missing', () => util.aborted()], ['null-signal', () => util.aborted(null, {})], ['object-signal', () => util.aborted({}, {})], ['controller-signal', () => util.aborted(new AbortController(), {})], ['missing-resource', () => util.aborted(new AbortController().signal)], ['null-resource', () => util.aborted(new AbortController().signal, null)], ['number-resource', () => util.aborted(new AbortController().signal, 1)], ['string-resource', () => util.aborted(new AbortController().signal, 'x')], ['symbol-resource', () => util.aborted(new AbortController().signal, Symbol('x'))], ['already-aborted-string-resource', () => util.aborted(invalidAlreadyAborted.signal, 'x')]].map(async ([label, action]) => { try { const promise = action(); return await promise.then(() => label + ':resolved', (error) => [label, promise.constructor.name, error.name, error.code, error.message].join(':')); } catch (error) { return [label, 'throw', error.name, error.code, error.message].join(':'); } })); const expectedAbortedValidationRows = \"missing:Promise:TypeError:ERR_INVALID_ARG_TYPE:signal is not of type AbortSignal.|null-signal:Promise:TypeError:ERR_INVALID_ARG_TYPE:signal is not of type AbortSignal.|object-signal:Promise:TypeError:ERR_INVALID_ARG_TYPE:signal is not of type AbortSignal.|controller-signal:Promise:TypeError:ERR_INVALID_ARG_TYPE:signal is not of type AbortSignal.|missing-resource:Promise:TypeError:ERR_INVALID_ARG_TYPE:The \\\"resource\\\" argument must be of type object. Received undefined|null-resource:Promise:TypeError:ERR_INVALID_ARG_TYPE:The \\\"resource\\\" argument must be of type object. Received null|number-resource:Promise:TypeError:ERR_INVALID_ARG_TYPE:The \\\"resource\\\" argument must be of type object. Received type number (1)|string-resource:Promise:TypeError:ERR_INVALID_ARG_TYPE:The \\\"resource\\\" argument must be of type object. Received type string ('x')|symbol-resource:Promise:TypeError:ERR_INVALID_ARG_TYPE:The \\\"resource\\\" argument must be of type object. Received type symbol (Symbol(x))|already-aborted-string-resource:Promise:TypeError:ERR_INVALID_ARG_TYPE:The \\\"resource\\\" argument must be of type object. Received type string ('x')\"; const alreadyAborted = new AbortController(); alreadyAborted.abort('done'); const abortedAlreadyValue = await util.aborted(alreadyAborted.signal, {}); const futureAborted = new AbortController(); const futureAbortedValuePromise = util.aborted(futureAborted.signal, {}); futureAborted.abort('done'); const futureAbortedValue = await futureAbortedValuePromise; const abortedAsyncRow = [util.aborted.constructor.name, Object.prototype.toString.call(util.aborted), util.types.isAsyncFunction(util.aborted)].join(':'); const utilPrototypeRows = ['_errnoException','_exceptionWithHostPort','_extend','callbackify','debug','debuglog','deprecate','styleText','formatWithOptions','getSystemErrorMap','getSystemErrorName','getSystemErrorMessage','inherits','isArray','promisify','setTraceSigInt'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(util[name], 'prototype'); return name + ':' + [descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value].join(':'); }).join('|'); const utilNoPrototypeRows = ['aborted','isDeepStrictEqual','toUSVString','parseArgs'].map((name) => name + ':' + Object.hasOwn(util[name], 'prototype')).join('|'); const controllerDescriptor = Object.getOwnPropertyDescriptor(util, 'transferableAbortController'); const signalDescriptor = Object.getOwnPropertyDescriptor(util, 'transferableAbortSignal'); const mimeTypePrototypeNames = Object.getOwnPropertyNames(util.MIMEType.prototype).join(','); const mimeParamsPrototypeNames = Object.getOwnPropertyNames(util.MIMEParams.prototype).join(','); const mimeTypeToJSON = Object.getOwnPropertyDescriptor(util.MIMEType.prototype, 'toJSON'); const mimeParamsIterator = Object.getOwnPropertyDescriptor(util.MIMEParams.prototype, Symbol.iterator); const mime = new util.MIMEType('text/html;charset=UTF-8'); const mimeParamsIgnoredConstructors = [new util.MIMEParams({ a: '1' }), new util.MIMEParams([['a', '1']]), new util.MIMEParams('a=1')].map((value) => JSON.stringify(value.toString())).join(','); const mimeParamsReceiverRows = ['get','has','set','delete','toString'].map((name) => { try { util.MIMEParams.prototype[name].call({}); return name + ':ok'; } catch (error) { return [name, error.name, error.message].join(':'); } }).join('|'); const mimeParamsIteratorReceiverRows = ['entries','keys','values'].map((name) => { try { return name + ':' + Object.prototype.toString.call(util.MIMEParams.prototype[name].call({})); } catch (error) { return [name, error.name, error.message].join(':'); } }).join('|'); const mimeParamsIteratorNextRows = ['entries','keys','values'].map((name) => { try { util.MIMEParams.prototype[name].call({}).next(); return name + ':ok'; } catch (error) { return [name, error.name, error.message].join(':'); } }).join('|'); const utilFormatHidden = { visible: 1 }; Object.defineProperty(utilFormatHidden, 'hidden', { value: 2, enumerable: false }); const utilFormatCircular = { name: 'root' }; utilFormatCircular.self = utilFormatCircular; const utilFormatNested = { a: { b: { c: { d: { e: 1 } } } } }; const utilFormatRows = [['d-float', () => util.format('%d', 1.5)], ['d-negzero', () => util.format('%d', -0)], ['d-trailing', () => util.format('%d', '1.5x')], ['d-bigint', () => util.format('%d', 12n)], ['d-symbol', () => util.format('%d', Symbol('x'))], ['i-float', () => util.format('%i', 1.5)], ['i-trailing', () => util.format('%i', '1.5x')], ['i-bigint', () => util.format('%i', 12n)], ['i-symbol', () => util.format('%i', Symbol('x'))], ['f-trailing', () => util.format('%f', '1.5x')], ['f-bigint', () => util.format('%f', 12n)], ['f-symbol', () => util.format('%f', Symbol('x'))], ['j-circular', () => util.format('%j', utilFormatCircular)], ['j-bigint', () => util.format('%j', 12n)], ['j-symbol', () => util.format('%j', Symbol('x'))], ['o-circular', () => util.format('%o', utilFormatCircular)], ['O-circular', () => util.format('%O', utilFormatCircular)], ['o-hidden', () => util.format('%o', utilFormatHidden)], ['O-hidden', () => util.format('%O', utilFormatHidden)], ['with-o-hidden', () => util.formatWithOptions({ showHidden: false }, '%o', utilFormatHidden)], ['with-O-hidden', () => util.formatWithOptions({ showHidden: true }, '%O', utilFormatHidden)], ['O-deep', () => util.format('%O', utilFormatNested)], ['with-depth-O-deep', () => util.formatWithOptions({ depth: 1 }, '%O', utilFormatNested)], ['o-deep-leaf', () => util.format('%o', utilFormatNested).includes('e: 1')], ['s-bigint', () => util.format('%s', 12n)], ['s-symbol', () => util.format('%s', Symbol('x'))], ['s-object', () => util.format('%s', { a: 1 })], ['s-negzero', () => util.format('%s', -0)]].map(([label, action]) => { try { return label + ':' + JSON.stringify(action()); } catch (error) { return label + ':THROW:' + error.name + ':' + error.message; } }).join('|'); const utilStyleRows = ['blink','doubleunderline','framed','overlined','redBright','bgGray','bgWhiteBright','whiteBright','bgRedBright'].map((style) => { const styled = util.styleText(style, 'x', { validateStream: false }); return [style, JSON.stringify(styled), util.inspect.colors[style].join(',')].join(':'); }).join('|'); const utilColorKeys = Object.keys(util.inspect.colors).join(','); const utilColorAliases = ['grey','blackBright','bgGrey','bgBlackBright','faint','crossedout','strikeThrough','crossedOut','conceal','swapColors','swapcolors','doubleUnderline'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(util.inspect.colors, name); return [name, descriptor.enumerable, descriptor.configurable, typeof descriptor.get, descriptor.get.name, descriptor.get.length, typeof descriptor.set, descriptor.set.name, descriptor.set.length, util.inspect.colors[name].join(',')].join(':'); }).join('|'); const inspectDefaultDescriptor = Object.getOwnPropertyDescriptor(util.inspect, 'defaultOptions'); const inspectDefaultOptions = util.inspect.defaultOptions; const inspectDepthDescriptor = Object.getOwnPropertyDescriptor(inspectDefaultOptions, 'depth'); const previousInspectMaxArrayLength = inspectDefaultOptions.maxArrayLength; util.inspect.defaultOptions = { maxArrayLength: 1 }; const inspectSetterOk = inspectDefaultOptions === util.inspect.defaultOptions && util.inspect([1, 2, 3]) === '[ 1, ... 2 more items ]'; util.inspect.defaultOptions = { maxArrayLength: previousInspectMaxArrayLength }; const inspectInvalidCodes = [null, 1].map((value) => { try { util.inspect.defaultOptions = value; return 'ok'; } catch (error) { return error.code; } }).join(','); let inspectUnknownError; try { util.inspect.defaultOptions = { __opencontainersUnknown: true }; } catch (error) { inspectUnknownError = `${error.name}:${error.code}:${Object.hasOwn(inspectDefaultOptions, '__opencontainersUnknown')}`; } if (metadata !== 'aborted:aborted:2|format:format:0|inspect:inspect:2|isDeepStrictEqual:isDeepStrictEqual:3|styleText:styleText:3|setTraceSigInt:setTraceSigInt:1|_errnoException:_errnoException:0|_exceptionWithHostPort:_exceptionWithHostPort:0|_extend:deprecated:2|isArray:deprecated:1' || utilKeys !== expectedUtilKeys || !abortedDescriptor.enumerable || !abortedDescriptor.configurable || typeof abortedDescriptor.get !== 'function' || abortedDescriptor.get.name !== 'get aborted' || abortedDescriptor.get.length !== 0 || abortedDescriptor.set !== undefined || util.aborted !== util.aborted || Object.hasOwn(util.aborted, 'prototype') || abortedAsyncRow !== 'AsyncFunction:[object AsyncFunction]:true' || abortedValidationRows.join('|') !== expectedAbortedValidationRows || abortedAlreadyValue !== undefined || futureAbortedValue?.type !== 'abort' || utilPrototypeRows !== '_errnoException:false:false:true:object|_exceptionWithHostPort:false:false:true:object|_extend:false:false:true:object|callbackify:false:false:true:object|debug:false:false:true:object|debuglog:false:false:true:object|deprecate:false:false:true:object|styleText:false:false:true:object|formatWithOptions:false:false:true:object|getSystemErrorMap:false:false:true:object|getSystemErrorName:false:false:true:object|getSystemErrorMessage:false:false:true:object|inherits:false:false:true:object|isArray:false:false:true:object|promisify:false:false:true:object|setTraceSigInt:false:false:true:object' || utilNoPrototypeRows !== 'aborted:false|isDeepStrictEqual:false|toUSVString:false|parseArgs:false' || util.debug !== util.debuglog || !controllerDescriptor.enumerable || !controllerDescriptor.configurable || typeof controllerDescriptor.get !== 'function' || typeof controllerDescriptor.set !== 'undefined' || !signalDescriptor.enumerable || !signalDescriptor.configurable || typeof signalDescriptor.get !== 'function' || typeof signalDescriptor.set !== 'undefined' || util.transferableAbortController.name !== 'transferableAbortController' || util.transferableAbortSignal.length !== 1 || !Object.hasOwn(util.transferableAbortController, 'prototype') || mimeTypePrototypeNames !== 'constructor,type,subtype,essence,params,toString,toJSON' || mimeParamsPrototypeNames !== 'constructor,delete,get,has,set,entries,keys,values,toString,toJSON' || mimeTypeToJSON.value.name !== 'toString' || mimeParamsIterator.value.name !== 'entries' || mimeParamsIgnoredConstructors !== '\"\",\"\",\"\"' || mimeParamsReceiverRows !== 'get:TypeError:Receiver must be an instance of class MIMEParams|has:TypeError:Receiver must be an instance of class MIMEParams|set:TypeError:Receiver must be an instance of class MIMEParams|delete:TypeError:Receiver must be an instance of class MIMEParams|toString:TypeError:Receiver must be an instance of class MIMEParams' || mimeParamsIteratorReceiverRows !== 'entries:[object Generator]|keys:[object Generator]|values:[object Generator]' || mimeParamsIteratorNextRows !== 'entries:TypeError:Receiver must be an instance of class MIMEParams|keys:TypeError:Receiver must be an instance of class MIMEParams|values:TypeError:Receiver must be an instance of class MIMEParams' || mime.toJSON() !== 'text/html;charset=UTF-8' || inspectDefaultOptions !== util.inspect.defaultOptions || inspectDefaultDescriptor.enumerable || inspectDefaultDescriptor.configurable || typeof inspectDefaultDescriptor.get !== 'function' || inspectDefaultDescriptor.get.length !== 0 || typeof inspectDefaultDescriptor.set !== 'function' || inspectDefaultDescriptor.set.length !== 1 || Object.isExtensible(inspectDefaultOptions) || !Object.isSealed(inspectDefaultOptions) || !inspectDepthDescriptor.enumerable || inspectDepthDescriptor.configurable || !inspectDepthDescriptor.writable || !inspectSetterOk || inspectInvalidCodes !== 'ERR_INVALID_ARG_TYPE,ERR_INVALID_ARG_TYPE' || inspectUnknownError !== 'TypeError:undefined:false' || promisified.name !== 'legacy' || promisified.length !== 2 || await multiPromisified(41) !== 41 || typeof constructedPromisified !== 'function' || !promisifyDescriptor || promisifyDescriptor.enumerable || !promisifyDescriptor.configurable || promisifyDescriptor.writable || promisifyDescriptor.value !== promisified || util.promisify(promisified) !== promisified || customPromisified !== customFn || !customDescriptor || customDescriptor.enumerable || !customDescriptor.configurable || customDescriptor.writable || customDescriptor.value !== customPromisified || util.promisify(customPromisified) !== customPromisified || invalidCustomCode !== 'ERR_INVALID_ARG_TYPE' || callbackified.name !== 'callbackifyNamedCallbackified' || callbackified.length !== 3 || callbackifiedAnonymous.name !== 'Callbackified' || callbackifiedAnonymous.length !== 2 || deprecatedPair.name !== 'deprecated' || deprecatedPair.length !== 2 || debugLogger.name !== 'logger' || debugLogger.length !== 0 || !debugLoggerDescriptor.enumerable || !debugLoggerDescriptor.configurable || typeof debugLoggerDescriptor.get !== 'function' || typeof debugLoggerDescriptor.set !== 'undefined' || debugLogger.enabled !== false || warningRows.join('|') !== 'DeprecationWarning:DEP0060:The `util._extend` API is deprecated. Please use Object.assign() instead.|DeprecationWarning::listener api|DeprecationWarning:DEP_LISTENER:listener api code' || callbackRows.join('|') !== 'debug:true:false|noop:false:false' || utilFormatRows !== \"d-float:\\\"1.5\\\"|d-negzero:\\\"-0\\\"|d-trailing:\\\"NaN\\\"|d-bigint:\\\"12n\\\"|d-symbol:\\\"NaN\\\"|i-float:\\\"1\\\"|i-trailing:\\\"1\\\"|i-bigint:\\\"12n\\\"|i-symbol:\\\"NaN\\\"|f-trailing:\\\"1.5\\\"|f-bigint:\\\"12\\\"|f-symbol:\\\"NaN\\\"|j-circular:\\\"[Circular]\\\"|j-bigint:THROW:TypeError:Do not know how to serialize a BigInt|j-symbol:\\\"undefined\\\"|o-circular:\\\" { name: 'root', self: [Circular *1] }\\\"|O-circular:\\\" { name: 'root', self: [Circular *1] }\\\"|o-hidden:\\\"{ visible: 1, [hidden]: 2 }\\\"|O-hidden:\\\"{ visible: 1 }\\\"|with-o-hidden:\\\"{ visible: 1, [hidden]: 2 }\\\"|with-O-hidden:\\\"{ visible: 1, [hidden]: 2 }\\\"|O-deep:\\\"{ a: { b: { c: [Object] } } }\\\"|with-depth-O-deep:\\\"{ a: { b: [Object] } }\\\"|o-deep-leaf:true|s-bigint:\\\"12n\\\"|s-symbol:\\\"Symbol(x)\\\"|s-object:\\\"{ a: 1 }\\\"|s-negzero:\\\"-0\\\"\" || utilStyleRows !== \"blink:\\\"\\\\u001b[5mx\\\\u001b[25m\\\":5,25|doubleunderline:\\\"\\\\u001b[21mx\\\\u001b[24m\\\":21,24|framed:\\\"\\\\u001b[51mx\\\\u001b[54m\\\":51,54|overlined:\\\"\\\\u001b[53mx\\\\u001b[55m\\\":53,55|redBright:\\\"\\\\u001b[91mx\\\\u001b[39m\\\":91,39|bgGray:\\\"\\\\u001b[100mx\\\\u001b[49m\\\":100,49|bgWhiteBright:\\\"\\\\u001b[107mx\\\\u001b[49m\\\":107,49|whiteBright:\\\"\\\\u001b[97mx\\\\u001b[39m\\\":97,39|bgRedBright:\\\"\\\\u001b[101mx\\\\u001b[49m\\\":101,49\" || utilColorKeys !== \"reset,bold,dim,italic,underline,blink,inverse,hidden,strikethrough,doubleunderline,black,red,green,yellow,blue,magenta,cyan,white,bgBlack,bgRed,bgGreen,bgYellow,bgBlue,bgMagenta,bgCyan,bgWhite,framed,overlined,gray,redBright,greenBright,yellowBright,blueBright,magentaBright,cyanBright,whiteBright,bgGray,bgRedBright,bgGreenBright,bgYellowBright,bgBlueBright,bgMagentaBright,bgCyanBright,bgWhiteBright\" || utilColorAliases !== \"grey:false:true:function:get:0:function:set:1:90,39|blackBright:false:true:function:get:0:function:set:1:90,39|bgGrey:false:true:function:get:0:function:set:1:100,49|bgBlackBright:false:true:function:get:0:function:set:1:100,49|faint:false:true:function:get:0:function:set:1:2,22|crossedout:false:true:function:get:0:function:set:1:9,29|strikeThrough:false:true:function:get:0:function:set:1:9,29|crossedOut:false:true:function:get:0:function:set:1:9,29|conceal:false:true:function:get:0:function:set:1:8,28|swapColors:false:true:function:get:0:function:set:1:7,27|swapcolors:false:true:function:get:0:function:set:1:7,27|doubleUnderline:false:true:function:get:0:function:set:1:21,24\" || util.format('%s', 'ok') !== 'ok' || !util.isDeepStrictEqual({ a: [1] }, { a: [1] }) || util.getSystemErrorName(-2) !== 'ENOENT') throw new Error('util failed')" }, { "specifier": "node:util/types", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Type predicates cover common values, expose Node-shaped predicate export order/metadata, native-shaped typed-array predicate prototype/constructor metadata, spoof-resistant brand checks for package probes including async/generator functions and DOMException native errors, and KeyObject/CryptoKey probes; native V8 proxy/external detection remains unavailable in the browser sandbox.", "probe": "const util = require('node:util'); const types = require('node:util/types'); const crypto = require('node:crypto'); const expectedKeys = 'isArgumentsObject,isArrayBuffer,isAsyncFunction,isBigIntObject,isBooleanObject,isDate,isExternal,isGeneratorFunction,isGeneratorObject,isMap,isMapIterator,isModuleNamespaceObject,isNativeError,isNumberObject,isPromise,isProxy,isRegExp,isSet,isSetIterator,isSharedArrayBuffer,isStringObject,isSymbolObject,isWeakMap,isWeakSet,isAnyArrayBuffer,isBoxedPrimitive,isArrayBufferView,isDataView,isTypedArray,isUint8Array,isUint8ClampedArray,isUint16Array,isUint32Array,isInt8Array,isInt16Array,isInt32Array,isFloat16Array,isFloat32Array,isFloat64Array,isBigInt64Array,isBigUint64Array,isKeyObject,isCryptoKey'; const metadata = ['isArrayBufferView','isDataView','isTypedArray','isUint8Array','isUint8ClampedArray','isUint16Array','isUint32Array','isInt8Array','isInt16Array','isInt32Array','isFloat16Array','isFloat32Array','isFloat64Array','isBigInt64Array','isBigUint64Array','isKeyObject','isCryptoKey'].map((name) => name + ':' + types[name].name + ':' + types[name].length).join('|'); const descriptorRows = ['isCryptoKey','isKeyObject'].map((key) => { const descriptor = Object.getOwnPropertyDescriptor(types, key); return [descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value, descriptor.value.name, descriptor.value.length].join(':'); }).join('|'); const constructablePredicates = ['isDataView','isTypedArray','isUint8Array','isUint8ClampedArray','isUint16Array','isUint32Array','isInt8Array','isInt16Array','isInt32Array','isFloat16Array','isFloat32Array','isFloat64Array','isBigInt64Array','isBigUint64Array']; const prototypeRows = constructablePredicates.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(types[name], 'prototype'); const instance = new types[name](); return [name, descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(','), descriptor?.value?.constructor === types[name], instance instanceof types[name], types[name]()].join(':'); }).join('|'); const expectedPrototypeRows = 'isDataView:false:false:true:constructor:true:true:false|isTypedArray:false:false:true:constructor:true:true:false|isUint8Array:false:false:true:constructor:true:true:false|isUint8ClampedArray:false:false:true:constructor:true:true:false|isUint16Array:false:false:true:constructor:true:true:false|isUint32Array:false:false:true:constructor:true:true:false|isInt8Array:false:false:true:constructor:true:true:false|isInt16Array:false:false:true:constructor:true:true:false|isInt32Array:false:false:true:constructor:true:true:false|isFloat16Array:false:false:true:constructor:true:true:false|isFloat32Array:false:false:true:constructor:true:true:false|isFloat64Array:false:false:true:constructor:true:true:false|isBigInt64Array:false:false:true:constructor:true:true:false|isBigUint64Array:false:false:true:constructor:true:true:false'; async function asyncFunction() {} function* generatorFunction() {} const fakeAsyncFunction = { constructor: { name: 'AsyncFunction' } }; const fakeGeneratorFunction = { constructor: { name: 'GeneratorFunction' } }; const secret = crypto.createSecretKey(Buffer.from('x')); if (types !== util.types || Object.hasOwn(types, 'default') || Object.keys(types).join(',') !== expectedKeys || metadata !== 'isArrayBufferView:isView:1|isDataView:isDataView:1|isTypedArray:isTypedArray:1|isUint8Array:isUint8Array:1|isUint8ClampedArray:isUint8ClampedArray:1|isUint16Array:isUint16Array:1|isUint32Array:isUint32Array:1|isInt8Array:isInt8Array:1|isInt16Array:isInt16Array:1|isInt32Array:isInt32Array:1|isFloat16Array:isFloat16Array:1|isFloat32Array:isFloat32Array:1|isFloat64Array:isFloat64Array:1|isBigInt64Array:isBigInt64Array:1|isBigUint64Array:isBigUint64Array:1|isKeyObject:value:1|isCryptoKey:value:1' || descriptorRows !== 'true:false:false:function:value:1|true:false:false:function:value:1' || prototypeRows !== expectedPrototypeRows || !types.isArrayBuffer(new ArrayBuffer(1)) || !types.isArrayBufferView(new Uint8Array(1)) || !types.isTypedArray(new Uint8Array(1)) || types.isTypedArray(new DataView(new ArrayBuffer(1))) || !types.isKeyObject(secret) || types.isKeyObject({}) || types.isModuleNamespaceObject({ [Symbol.toStringTag]: 'Module' }) || !types.isAsyncFunction(asyncFunction) || types.isAsyncFunction(fakeAsyncFunction) || !types.isGeneratorFunction(generatorFunction) || types.isGeneratorFunction(fakeGeneratorFunction) || !types.isNativeError(new DOMException('probe'))) throw new Error('util/types failed')" }, { "specifier": "node:v8", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Heap stats and C++ heap statistics expose the native Node v26 field set and object shapes with browser-safe approximate values, while serialize/deserialize, stable nonzero cached-data version tag, Node-shaped CommonJS export order, Serializer/Deserializer/GCProfiler constructor and prototype metadata, native-shaped Serializer._getDataCloneError function prototype metadata and selected Serializer/Deserializer method own-prototype metadata, no-op CPU/heap/GC profiler handles, GCProfiler Symbol.dispose metadata, helper arities, native-shaped helper own-prototype metadata, nested promiseHooks/startupSnapshot helper own-prototype metadata, promise hook no-op stop functions and callback validation, queryObjects validation, isStringOneByteRepresentation input validation, deserialize input validation, Deserializer constructor validation, raw-byte serializer validation, raw-byte length validation, direct SharedArrayBuffer serialization rejection while preserving SAB-backed typed-array serialization, releaseBuffer empty/consume semantics, ArrayBuffer transfer validation, heap snapshot option/path validation, and startupSnapshot shape use browser-safe OpenContainers approximations; native V8 snapshots and heap inspection remain unavailable.", "probe": "const v8 = require('node:v8'); const keys = 'cachedDataVersionTag,getHeapSnapshot,getHeapStatistics,getHeapSpaceStatistics,getHeapCodeStatistics,getCppHeapStatistics,setFlagsFromString,Serializer,Deserializer,DefaultSerializer,DefaultDeserializer,deserialize,takeCoverage,stopCoverage,serialize,writeHeapSnapshot,promiseHooks,queryObjects,startupSnapshot,setHeapSnapshotNearHeapLimit,GCProfiler,isStringOneByteRepresentation,startCpuProfile,startHeapProfile'; const constructors = [v8.Serializer, v8.Deserializer, v8.DefaultSerializer, v8.DefaultDeserializer, v8.GCProfiler].map((value) => value.name + ':' + value.length).join('|'); const helpers = [v8.setFlagsFromString, v8.startCpuProfile, v8.startHeapProfile, v8.getHeapSnapshot, v8.setHeapSnapshotNearHeapLimit, v8.writeHeapSnapshot, v8.serialize, v8.deserialize, v8.queryObjects].map((value) => value.name + ':' + value.length).join('|'); const helperPrototypeMeta = ['cachedDataVersionTag','getHeapSnapshot','getHeapStatistics','getHeapSpaceStatistics','getHeapCodeStatistics','getCppHeapStatistics','setFlagsFromString','deserialize','takeCoverage','stopCoverage','serialize','writeHeapSnapshot','queryObjects','setHeapSnapshotNearHeapLimit','isStringOneByteRepresentation','startCpuProfile','startHeapProfile'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(v8[name], 'prototype'); return [name, Object.hasOwn(v8[name], 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, descriptor && Object.getOwnPropertyNames(descriptor.value).join(',')].join(':') }).join('|'); const serializerMethods = Object.keys(v8.Serializer.prototype).join(','); const deserializerMethods = Object.keys(v8.Deserializer.prototype).join(','); const serializerSelectedMethodMeta = ['writeValue','_getDataCloneError'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(v8.Serializer.prototype, name); const prototypeDescriptor = Object.getOwnPropertyDescriptor(descriptor.value, 'prototype'); return [name, descriptor.value.name, descriptor.value.length, descriptor.enumerable, Object.hasOwn(descriptor.value, 'prototype'), prototypeDescriptor?.enumerable, prototypeDescriptor?.configurable, prototypeDescriptor?.writable, Object.getOwnPropertyNames(prototypeDescriptor?.value ?? {}).join(',')].join(':') }).join('|'); const deserializerSelectedMethodMeta = ['_readRawBytes','readRawBytes'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(v8.Deserializer.prototype, name); const prototypeDescriptor = Object.getOwnPropertyDescriptor(descriptor.value, 'prototype'); return [name, descriptor.value.name, descriptor.value.length, descriptor.enumerable, Object.hasOwn(descriptor.value, 'prototype'), prototypeDescriptor?.enumerable, prototypeDescriptor?.configurable, prototypeDescriptor?.writable, Object.getOwnPropertyNames(prototypeDescriptor?.value ?? {}).join(',')].join(':') }).join('|'); const startup = ['addDeserializeCallback','addSerializeCallback','setDeserializeMainFunction','isBuildingSnapshot'].map((name) => name + ':' + v8.startupSnapshot[name].name + ':' + v8.startupSnapshot[name].length).join('|'); const nestedHelperPrototypeMeta = [...Object.keys(v8.promiseHooks).map((name) => ['promiseHooks', name, v8.promiseHooks[name]]), ...Object.keys(v8.startupSnapshot).map((name) => ['startupSnapshot', name, v8.startupSnapshot[name]])].map(([group, name, value]) => { const descriptor = Object.getOwnPropertyDescriptor(value, 'prototype'); return [group + '.' + name, value.name, value.length, Object.hasOwn(value, 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, descriptor && Object.getOwnPropertyNames(descriptor.value).join(',')].join(':') }).join('|'); const promiseHookStop = v8.promiseHooks.createHook({ init() {}, before() {}, after() {}, settled() {} }); const promiseHookDirectStops = [\"onInit\",\"onBefore\",\"onAfter\",\"onSettled\"].map((name) => { const stop = v8.promiseHooks[name](() => {}); return name + \":\" + stop.name + \":\" + stop.length + \":\" + stop(); }).join(\"|\"); const promiseHookErrors = [[\"createHook\", () => v8.promiseHooks.createHook({ init: 1 })], [\"onInit\", () => v8.promiseHooks.onInit(1)]].map(([label, action]) => { try { action(); return label + \":ok\" } catch (error) { return label + \":\" + error.code } }).join(\"|\"); const gcDisposeDescriptor = Object.getOwnPropertyDescriptor(v8.GCProfiler.prototype, Symbol.dispose); const gcDisposeProfile = new v8.GCProfiler(); gcDisposeProfile.start(); const gcDisposeRows = [Object.getOwnPropertySymbols(v8.GCProfiler.prototype).map(String).join(','), gcDisposeDescriptor.value.name, gcDisposeDescriptor.value.length, gcDisposeDescriptor.enumerable, gcDisposeDescriptor.configurable, gcDisposeDescriptor.writable, Object.hasOwn(gcDisposeDescriptor.value, 'prototype'), gcDisposeProfile[Symbol.dispose]()].join(':'); const profileHandleRows = [v8.startCpuProfile(), v8.startHeapProfile()].map((handle) => { const prototype = Object.getPrototypeOf(handle); const constructorDescriptor = Object.getOwnPropertyDescriptor(prototype, 'constructor'); const stopDescriptor = Object.getOwnPropertyDescriptor(prototype, 'stop'); const disposeDescriptor = Object.getOwnPropertyDescriptor(prototype, Symbol.dispose); const constructor = constructorDescriptor.value; const row = [constructor.name, constructor.length, constructorDescriptor.enumerable, constructorDescriptor.configurable, constructorDescriptor.writable, Object.hasOwn(constructor, 'prototype'), Object.getOwnPropertyNames(constructor.prototype).join(','), stopDescriptor.value.name, stopDescriptor.value.length, Object.hasOwn(stopDescriptor.value, 'prototype'), typeof disposeDescriptor.value, disposeDescriptor.value.name, disposeDescriptor.value.length].join(':'); handle.stop(); return row; }).join('|'); const cachedDataVersionTag = v8.cachedDataVersionTag(); const heapStatisticKeys = Object.keys(v8.getHeapStatistics()).join(','); const cppHeapStats = v8.getCppHeapStatistics(); const cppHeapSpace = cppHeapStats.space_statistics[0]; const cppHeapFreeList = cppHeapSpace.free_list_stats; const cppHeapRows = [Object.getPrototypeOf(cppHeapStats) === null, Object.keys(cppHeapStats).join(','), cppHeapStats.space_statistics.length, cppHeapStats.type_names.length, cppHeapStats.detail_level, Object.getPrototypeOf(cppHeapSpace) === null, Object.keys(cppHeapSpace).join(','), Array.isArray(cppHeapSpace.page_stats), Object.getPrototypeOf(cppHeapFreeList) === null, Object.keys(cppHeapFreeList).join(','), cppHeapFreeList.bucket_size.length, cppHeapFreeList.free_count.length, cppHeapFreeList.free_size.length, cppHeapStats.space_statistics.map((space) => space.name).join(','), cppHeapStats.type_names.join(',')].join(';'); const flagValidation = [[\"missing\", () => v8.setFlagsFromString()], [\"null\", () => v8.setFlagsFromString(null)], [\"number\", () => v8.setFlagsFromString(1)], [\"object\", () => v8.setFlagsFromString({})], [\"string-object\", () => v8.setFlagsFromString(new String('--expose-gc'))]].map(([label, action]) => { try { action(); return label + \":ok\" } catch (error) { return label + \":\" + error.code } }).join(\"|\"); const oneByteValidation = [[\"missing\", () => v8.isStringOneByteRepresentation()], [\"null\", () => v8.isStringOneByteRepresentation(null)], [\"number\", () => v8.isStringOneByteRepresentation(1)], [\"boolean\", () => v8.isStringOneByteRepresentation(true)], [\"object\", () => v8.isStringOneByteRepresentation({})], [\"symbol\", () => v8.isStringOneByteRepresentation(Symbol(\"x\"))]].map(([label, action]) => { try { action(); return label + \":ok\" } catch (error) { return label + \":\" + (error.code ?? error.name) } }).join(\"|\"); const heapLimitValidation = [[\"heap-limit-missing\", () => v8.setHeapSnapshotNearHeapLimit()], [\"heap-limit-string\", () => v8.setHeapSnapshotNearHeapLimit(\"1\")], [\"heap-limit-float\", () => v8.setHeapSnapshotNearHeapLimit(1.5)], [\"heap-limit-nan\", () => v8.setHeapSnapshotNearHeapLimit(NaN)], [\"heap-limit-zero\", () => v8.setHeapSnapshotNearHeapLimit(0)], [\"heap-limit-negative\", () => v8.setHeapSnapshotNearHeapLimit(-1)], [\"heap-limit-too-large\", () => v8.setHeapSnapshotNearHeapLimit(4294967296)], [\"heap-limit-valid\", () => v8.setHeapSnapshotNearHeapLimit(1)]].map(([label, action]) => { try { action(); return label + \":ok\" } catch (error) { return label + \":\" + error.code } }).join(\"|\"); const invalidValidation = [[\"deserialize-missing\", () => v8.deserialize()], [\"deserialize-null\", () => v8.deserialize(null)], [\"deserialize-string\", () => v8.deserialize(\"x\")], [\"deserialize-arraybuffer\", () => v8.deserialize(new ArrayBuffer(4))], [\"deserialize-invalid-data\", () => v8.deserialize(new DataView(new ArrayBuffer(4)))], [\"heap-options\", () => v8.getHeapSnapshot(\"bad\")], [\"heap-options-array\", () => v8.getHeapSnapshot([])], [\"write-options\", () => v8.writeHeapSnapshot(\"x\", \"bad\")], [\"write-path\", () => v8.writeHeapSnapshot(1)]].map(([label, action]) => { try { action(); return label + \":ok\" } catch (error) { return label + \":\" + (error.code ?? error.name) } }).join(\"|\"); const classValidation = [[\"deserializer-missing\", () => new v8.Deserializer()], [\"deserializer-null\", () => new v8.Deserializer(null)], [\"deserializer-string\", () => new v8.Deserializer(\"x\")], [\"deserializer-arraybuffer\", () => new v8.Deserializer(new ArrayBuffer(4))], [\"default-deserializer-missing\", () => new v8.DefaultDeserializer()], [\"default-deserializer-arraybuffer\", () => new v8.DefaultDeserializer(new ArrayBuffer(4))], [\"raw-missing\", () => new v8.Serializer().writeRawBytes()], [\"raw-string\", () => new v8.Serializer().writeRawBytes(\"hi\")], [\"raw-arraybuffer\", () => new v8.Serializer().writeRawBytes(new ArrayBuffer(2))], [\"raw-dataview\", () => new v8.Serializer().writeRawBytes(new DataView(new ArrayBuffer(2)))]].map(([label, action]) => { try { action(); return label + \":ok\" } catch (error) { return label + \":\" + (error.code ?? error.name) } }).join(\"|\"); const transferValidation = [[\"serializer-transfer-missing\", () => new v8.Serializer().transferArrayBuffer()], [\"serializer-transfer-typed-array\", () => new v8.Serializer().transferArrayBuffer(1, new Uint8Array(1))], [\"serializer-transfer-dataview\", () => new v8.Serializer().transferArrayBuffer(1, new DataView(new ArrayBuffer(1)))], [\"serializer-transfer-ok\", () => new v8.Serializer().transferArrayBuffer(\"loose-id\", new ArrayBuffer(1))], [\"deserializer-transfer-missing\", () => new v8.Deserializer(v8.serialize({})).transferArrayBuffer()], [\"deserializer-transfer-typed-array\", () => new v8.Deserializer(v8.serialize({})).transferArrayBuffer(1, new Uint8Array(1))], [\"deserializer-transfer-ok\", () => new v8.Deserializer(v8.serialize({})).transferArrayBuffer(\"loose-id\", new ArrayBuffer(1))]].map(([label, action]) => { try { action(); return label + \":ok\" } catch (error) { return label + \":\" + (error.code ?? error.name) } }).join(\"|\"); const rawReadValidation = (() => { const makeRawDeserializer = () => { const serializer = new v8.Serializer(); serializer.writeHeader(); serializer.writeRawBytes(new Uint8Array([0x68, 0x69])); const deserializer = new v8.Deserializer(serializer.releaseBuffer()); deserializer.readHeader(); return deserializer; }; return [[\"readRaw-negative\", () => makeRawDeserializer().readRawBytes(-1)], [\"_readRaw-negative\", () => makeRawDeserializer()._readRawBytes(-1)], [\"readRaw-after-negative\", () => { const deserializer = makeRawDeserializer(); try { deserializer.readRawBytes(-1); } catch {} return deserializer.readRawBytes(2).toString(\"hex\"); }]].map(([label, action]) => { try { return label + \":ok:\" + action() } catch (error) { return label + \":\" + (error.code ?? error.name) + \":\" + error.message } }).join(\"|\"); })(); const sharedArrayBufferSerializationRows = [[\"serialize-shared\", () => v8.serialize(new SharedArrayBuffer(1))], [\"write-shared\", () => { const serializer = new v8.Serializer(); serializer.writeValue(new SharedArrayBuffer(1)); return serializer.releaseBuffer(); }], [\"serialize-shared-view\", () => v8.serialize(new Uint8Array(new SharedArrayBuffer(2)))]].map(([label, action]) => { try { const result = action(); return [label, \"ok\", result.constructor.name, result.length > 0].join(\":\"); } catch (error) { return [label, error.constructor.name, error.code ?? \"\", error.message].join(\":\"); } }).join(\"|\"); const releaseBufferRows = (() => { const empty = new v8.Serializer(); const emptyRows = [\"empty\", empty.releaseBuffer().length, empty.releaseBuffer().length].join(\":\"); const failed = new v8.Serializer(); let failedRows; try { failed.writeValue(function f() {}); } catch (error) { failedRows = [\"failed\", error.constructor.name, error.message, failed.releaseBuffer().length].join(\":\"); } const header = new v8.Serializer(); header.writeHeader(); const headerRows = [\"header\", header.releaseBuffer().length > 0, header.releaseBuffer().length].join(\":\"); const value = new v8.Serializer(); value.writeHeader(); value.writeValue({ ok: true }); const released = value.releaseBuffer(); const deserializer = new v8.Deserializer(released); const valueRows = [\"value\", released.length > 0, value.releaseBuffer().length, deserializer.readHeader(), deserializer.readValue().ok].join(\":\"); return [emptyRows, failedRows, headerRows, valueRows].join(\"|\"); })(); if (Object.hasOwn(v8, 'default') || Object.keys(v8).join(',') !== keys || constructors !== 'Serializer:0|Deserializer:1|DefaultSerializer:0|DefaultDeserializer:0|GCProfiler:0' || helpers !== 'setFlagsFromString:1|startCpuProfile:1|startHeapProfile:1|getHeapSnapshot:1|setHeapSnapshotNearHeapLimit:1|writeHeapSnapshot:2|serialize:1|deserialize:1|queryObjects:1' || helperPrototypeMeta !== \"cachedDataVersionTag:false::::|getHeapSnapshot:true:false:false:true:constructor|getHeapStatistics:true:false:false:true:constructor|getHeapSpaceStatistics:true:false:false:true:constructor|getHeapCodeStatistics:true:false:false:true:constructor|getCppHeapStatistics:true:false:false:true:constructor|setFlagsFromString:true:false:false:true:constructor|deserialize:true:false:false:true:constructor|takeCoverage:false::::|stopCoverage:false::::|serialize:true:false:false:true:constructor|writeHeapSnapshot:true:false:false:true:constructor|queryObjects:true:false:false:true:constructor|setHeapSnapshotNearHeapLimit:true:false:false:true:constructor|isStringOneByteRepresentation:true:false:false:true:constructor|startCpuProfile:true:false:false:true:constructor|startHeapProfile:true:false:false:true:constructor\" || serializerMethods !== 'writeHeader,writeValue,releaseBuffer,transferArrayBuffer,writeUint32,writeUint64,writeDouble,writeRawBytes,_setTreatArrayBufferViewsAsHostObjects,_getDataCloneError' || deserializerMethods !== 'readHeader,readValue,getWireFormatVersion,transferArrayBuffer,readUint32,readUint64,readDouble,_readRawBytes,readRawBytes' || serializerSelectedMethodMeta !== 'writeValue:writeValue:0:true:false::::|_getDataCloneError:Error:1:true:true:false:false:false:constructor,name,message,toString' || deserializerSelectedMethodMeta !== '_readRawBytes:_readRawBytes:0:true:false::::|readRawBytes:readRawBytes:1:true:true:false:false:true:constructor' || startup !== 'addDeserializeCallback:addDeserializeCallback:2|addSerializeCallback:addSerializeCallback:2|setDeserializeMainFunction:setDeserializeMainFunction:2|isBuildingSnapshot:isBuildingSnapshot:0' || nestedHelperPrototypeMeta !== \"promiseHooks.createHook:createHook:0:true:false:false:true:constructor|promiseHooks.onInit::1:false::::|promiseHooks.onBefore::1:false::::|promiseHooks.onAfter::1:false::::|promiseHooks.onSettled::1:false::::|startupSnapshot.addDeserializeCallback:addDeserializeCallback:2:true:false:false:true:constructor|startupSnapshot.addSerializeCallback:addSerializeCallback:2:true:false:false:true:constructor|startupSnapshot.setDeserializeMainFunction:setDeserializeMainFunction:2:true:false:false:true:constructor|startupSnapshot.isBuildingSnapshot:isBuildingSnapshot:0:true:false:false:true:constructor\" || typeof promiseHookStop !== 'function' || promiseHookStop.name !== '' || promiseHookStop.length !== 0 || promiseHookStop() !== undefined || promiseHookDirectStops !== 'onInit:bound stop:0:undefined|onBefore:bound stop:0:undefined|onAfter:bound stop:0:undefined|onSettled:bound stop:0:undefined' || promiseHookErrors !== 'createHook:ERR_INVALID_ARG_TYPE|onInit:ERR_INVALID_ARG_TYPE' || gcDisposeRows !== 'Symbol(Symbol.dispose):[Symbol.dispose]:0:false:true:true:false:' || profileHandleRows !== 'SyncCPUProfileHandle:1:false:true:true:true:constructor,stop:stop:0:false:function:[Symbol.dispose]:0|SyncHeapProfileHandle:0:false:true:true:true:constructor,stop:stop:0:false:function:[Symbol.dispose]:0' || flagValidation !== 'missing:ERR_INVALID_ARG_TYPE|null:ERR_INVALID_ARG_TYPE|number:ERR_INVALID_ARG_TYPE|object:ERR_INVALID_ARG_TYPE|string-object:ERR_INVALID_ARG_TYPE' || oneByteValidation !== 'missing:ERR_INVALID_ARG_TYPE|null:ERR_INVALID_ARG_TYPE|number:ERR_INVALID_ARG_TYPE|boolean:ERR_INVALID_ARG_TYPE|object:ERR_INVALID_ARG_TYPE|symbol:ERR_INVALID_ARG_TYPE' || heapLimitValidation !== 'heap-limit-missing:ERR_INVALID_ARG_TYPE|heap-limit-string:ERR_INVALID_ARG_TYPE|heap-limit-float:ERR_OUT_OF_RANGE|heap-limit-nan:ERR_OUT_OF_RANGE|heap-limit-zero:ERR_OUT_OF_RANGE|heap-limit-negative:ERR_OUT_OF_RANGE|heap-limit-too-large:ERR_OUT_OF_RANGE|heap-limit-valid:ERR_OPENCONTAINERS_V8_UNSUPPORTED' || invalidValidation !== 'deserialize-missing:ERR_INVALID_ARG_TYPE|deserialize-null:ERR_INVALID_ARG_TYPE|deserialize-string:ERR_INVALID_ARG_TYPE|deserialize-arraybuffer:ERR_INVALID_ARG_TYPE|deserialize-invalid-data:Error|heap-options:ERR_INVALID_ARG_TYPE|heap-options-array:ERR_INVALID_ARG_TYPE|write-options:ERR_INVALID_ARG_TYPE|write-path:ERR_INVALID_ARG_TYPE' || classValidation !== 'deserializer-missing:ERR_INVALID_ARG_TYPE|deserializer-null:ERR_INVALID_ARG_TYPE|deserializer-string:ERR_INVALID_ARG_TYPE|deserializer-arraybuffer:ERR_INVALID_ARG_TYPE|default-deserializer-missing:ERR_INVALID_ARG_TYPE|default-deserializer-arraybuffer:ERR_INVALID_ARG_TYPE|raw-missing:ERR_INVALID_ARG_TYPE|raw-string:ERR_INVALID_ARG_TYPE|raw-arraybuffer:ERR_INVALID_ARG_TYPE|raw-dataview:ok' || transferValidation !== 'serializer-transfer-missing:ERR_INVALID_ARG_TYPE|serializer-transfer-typed-array:ERR_INVALID_ARG_TYPE|serializer-transfer-dataview:ERR_INVALID_ARG_TYPE|serializer-transfer-ok:ok|deserializer-transfer-missing:ERR_INVALID_ARG_TYPE|deserializer-transfer-typed-array:ERR_INVALID_ARG_TYPE|deserializer-transfer-ok:ok' || rawReadValidation !== 'readRaw-negative:Error:ReadRawBytes() failed|_readRaw-negative:Error:ReadRawBytes() failed|readRaw-after-negative:ok:6869' || sharedArrayBufferSerializationRows !== 'serialize-shared:Error::# could not be cloned.|write-shared:Error::# could not be cloned.|serialize-shared-view:ok:Buffer:true' || releaseBufferRows !== 'empty:0:0|failed:Error:function f() {} could not be cloned.:0|header:true:0|value:true:0:true:true' || !Number.isInteger(cachedDataVersionTag) || cachedDataVersionTag <= 0 || cachedDataVersionTag !== v8.cachedDataVersionTag() || heapStatisticKeys !== 'total_heap_size,total_heap_size_executable,total_physical_size,total_available_size,used_heap_size,heap_size_limit,malloced_memory,peak_malloced_memory,does_zap_garbage,number_of_native_contexts,number_of_detached_contexts,total_global_handles_size,used_global_handles_size,external_memory,total_allocated_bytes' || cppHeapRows !== 'true;committed_size_bytes,resident_size_bytes,used_size_bytes,space_statistics,type_names,detail_level;5;1;detailed;true;name,committed_size_bytes,resident_size_bytes,used_size_bytes,page_stats,free_list_stats;true;true;bucket_size,free_count,free_size;17;17;17;NormalPageSpace0,NormalPageSpace1,NormalPageSpace2,NormalPageSpace3,LargePageSpace;OpenContainers / VirtualRuntime' || v8.getHeapStatistics().heap_size_limit <= 0 || v8.getHeapSpaceStatistics()[0].space_name !== 'read_only_space' || !v8.isStringOneByteRepresentation('abc') || v8.isStringOneByteRepresentation('🙂')) throw new Error('v8 metadata failed'); const serializer = new v8.Serializer(); serializer.writeHeader(); serializer.writeUint32(42); serializer.writeUint64(1, 2); serializer.writeDouble(1.5); serializer.writeRawBytes(Buffer.from('hi')); const deserializer = new v8.Deserializer(serializer.releaseBuffer()); if (deserializer.readHeader() !== true || deserializer.readUint32() !== 42 || deserializer.readUint64().join(':') !== '1:2' || deserializer.readDouble() !== 1.5 || deserializer.readRawBytes(2).toString() !== 'hi') throw new Error('v8 serializer failed'); const restored = v8.deserialize(v8.serialize({ big: 123n, map: new Map([[1, 'one']]), set: new Set(['x']), buffer: Buffer.from('hi'), typed: new Uint16Array([7, 9]) })); const gcProfiler = new v8.GCProfiler(); const cpuProfile = JSON.parse(v8.startCpuProfile().stop()); if (typeof restored.big !== 'bigint' || restored.map.get(1) !== 'one' || !restored.set.has('x') || !Buffer.isBuffer(restored.buffer) || restored.buffer.toString() !== 'hi' || restored.typed.constructor.name !== 'Uint16Array' || restored.typed.join(',') !== '7,9' || gcProfiler.start() !== undefined || gcProfiler.stop().version !== 1 || cpuProfile.nodes[0].callFrame.functionName !== '(root)' || v8.queryObjects(Object) !== 0 || v8.startupSnapshot.isBuildingSnapshot() !== false) throw new Error('v8 behavior failed')", "unsupported": { "probe": "require('node:v8').getHeapSnapshot()", "code": "ERR_OPENCONTAINERS_V8_UNSUPPORTED" } }, { "specifier": "node:vm", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Runs in the virtual runtime context with native-shaped VM-module-enabled CommonJS export order and Node-shaped public helper names/arities, helper own-prototype descriptors, VM module prototype/accessor descriptors, and Module constructor name/arity; contextified sandboxes hide Node globals such as process and Buffer, but isolation is not equivalent to native Node vm contexts; cachedData APIs are synthetic no-op probes; SourceTextModule and SyntheticModule cover common linking and namespace workflows with native-shaped prototype order and empty enumerable instance surfaces, but without native V8 module isolation.", "probe": "const vm = require('node:vm'); const keys = 'Script,createContext,createScript,runInContext,runInNewContext,runInThisContext,isContext,compileFunction,measureMemory,constants,Module,SourceTextModule,SyntheticModule'; const helperPrototypeRows = ['createScript','measureMemory','Module'].map((name) => { const value = vm[name]; const descriptor = Object.getOwnPropertyDescriptor(value, 'prototype'); return [name, value.name, value.length, Object.hasOwn(value, 'prototype'), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, Object.getOwnPropertyNames(descriptor?.value ?? {}).join(',')].join(':'); }).join('|'); const modulePrototypeRows = ['Module','SourceTextModule','SyntheticModule'].map((name) => [name, Object.getOwnPropertyNames(vm[name].prototype).join(','), Object.keys(vm[name].prototype).join(',') || '', Object.getPrototypeOf(vm[name].prototype)?.constructor?.name].join(':')).join('|'); const moduleConstructorRows = ['Module','SourceTextModule','SyntheticModule'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(vm[name], 'prototype'); return [name, vm[name].name, vm[name].length, descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.hasOwn(vm[name], 'prototype')].join(':'); }).join('|'); const sourceModuleProbe = new vm.SourceTextModule('export const ok = true;'); const syntheticModuleProbe = new vm.SyntheticModule(['ok'], function () {}); const moduleInstanceRows = [Object.getOwnPropertyNames(sourceModuleProbe).join(',') || '', Object.keys(sourceModuleProbe).join(',') || '', Object.getOwnPropertyNames(syntheticModuleProbe).join(',') || '', Object.keys(syntheticModuleProbe).join(',') || '', syntheticModuleProbe.status, sourceModuleProbe.status].join(':'); if (Object.hasOwn(vm, 'default') || Object.keys(vm).join(',') !== keys || vm.Script.length !== 1 || vm.createContext.length !== 0 || vm.createScript.length !== 2 || vm.runInContext.length !== 3 || vm.runInNewContext.length !== 3 || vm.runInThisContext.length !== 2 || vm.isContext.length !== 1 || vm.compileFunction.length !== 2 || vm.measureMemory.length !== 0 || helperPrototypeRows !== 'createScript:createScript:2:true:false:false:true:constructor|measureMemory:measureMemory:0:true:false:false:true:constructor|Module:Module:1:true:false:false:false:constructor,identifier,context,namespace,status,error,link,evaluate' || modulePrototypeRows !== 'Module:constructor,identifier,context,namespace,status,error,link,evaluate::Object|SourceTextModule:constructor,linkRequests,instantiate,dependencySpecifiers,moduleRequests,status,error,hasAsyncGraph,hasTopLevelAwait,createCachedData::Module|SyntheticModule:constructor,link,setExport::Module' || moduleConstructorRows !== 'Module:Module:1:false:false:false:true|SourceTextModule:SourceTextModule:1:false:false:false:true|SyntheticModule:SyntheticModule:2:false:false:false:true' || moduleInstanceRows !== '::::linked:unlinked' || Object.getOwnPropertyNames(vm.Script.prototype).join(',') !== 'constructor,createCachedData,runInContext,runInNewContext,runInThisContext') throw new Error('vm metadata failed'); const sandbox = { value: 7, result: null }; vm.createContext(sandbox); const contextProbe = [\"typeof process\", \"typeof Buffer\", \"typeof Object\", \"typeof Function\", \"(globalThis === this)\", \"Function(\\\"return typeof process + ':' + (globalThis === this)\\\")()\"].join(\" + ':' + \"); const contextGlobals = vm.runInContext(contextProbe, sandbox); if (!vm.isContext(sandbox) || new vm.Script('value += 1; result = value * 6; result').runInContext(sandbox) !== 48 || sandbox.result !== 48 || contextGlobals !== 'undefined:undefined:function:function:true:undefined:true' || vm.runInNewContext('value * 6', { value: 7 }) !== 42 || typeof vm.runInThisContext('Buffer') !== 'function') throw new Error('vm context failed'); const cachedScript = new vm.Script('40 + 2', { filename: 'cached.js', produceCachedData: true }); const cachedData = cachedScript.createCachedData(); const reused = new vm.Script('40 + 2', { cachedData }); const fn = vm.compileFunction('return value + multiplier;', ['value'], { parsingContext: vm.createContext({ multiplier: 1 }), produceCachedData: true }); if (cachedScript.runInThisContext() !== 42 || !Buffer.isBuffer(cachedData) || cachedData.length === 0 || cachedScript.cachedDataProduced !== true || !Buffer.isBuffer(cachedScript.cachedData) || reused.cachedDataRejected !== false || fn(41) !== 42 || !Buffer.isBuffer(fn.cachedData)) throw new Error('vm cached/compile failed'); const memory = await vm.measureMemory({ mode: 'summary', execution: 'eager' }); if (typeof vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER !== 'symbol' || typeof vm.constants.DONT_CONTEXTIFY !== 'symbol' || typeof memory.total.jsMemoryEstimate !== 'number' || !Array.isArray(memory.total.jsMemoryRange)) throw new Error('vm constants failed'); const dependency = new vm.SyntheticModule(['value'], function () { this.setExport('value', 21); }, { identifier: '/workspace/dependency.js' }); const source = new vm.SourceTextModule('import { value } from \"dependency\"; export const doubled = value * 2; export default doubled + 1;', { identifier: '/workspace/source.js' }); if (source.status !== 'unlinked' || source.dependencySpecifiers.join(',') !== 'dependency') throw new Error('vm source metadata failed'); await source.link((specifier, referencingModule) => { if (specifier !== 'dependency' || referencingModule !== source) throw new Error('vm linker args failed'); return dependency; }); await source.evaluate(); if (dependency.status !== 'evaluated' || source.status !== 'evaluated' || source.namespace.doubled !== 42 || source.namespace.default !== 43 || Object.prototype.toString.call(source.namespace) !== '[object Module]') throw new Error('vm source evaluate failed'); const dynamicDependency = new vm.SyntheticModule(['value'], function () { this.setExport('value', 13); }); const dynamic = new vm.SourceTextModule('const dependency = await import(\"dynamic-dependency\"); export const value = dependency.value + 2;', { importModuleDynamically(specifier, referencingModule) { if (specifier !== 'dynamic-dependency' || referencingModule !== dynamic) throw new Error('vm dynamic args failed'); return dynamicDependency; } }); await dynamic.link(() => {}); await dynamic.evaluate(); if (dynamicDependency.status !== 'evaluated' || dynamic.namespace.value !== 15) throw new Error('vm dynamic import failed')" }, { "specifier": "node:wasi", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "WASI construction including preview1 and legacy unstable namespace selection, constructor/prototype metadata, Node-shaped constructor option validation for version/args/env/preopens/returnOnExit/stdin/stdout/stderr, Node-shaped CommonJS export shape, getImportObject(), lifecycle instance/export validation, initialize() _initialize invocation/validation, finalizeBindings/start handling, direct proc_exit sentinel throws, proc_exit exit-code returns for default/returnOnExit=true starts, and a wasi_snapshot_preview1 import table with Node-shaped import names/arities and native-shaped own/prototype function metadata, import order, constructor metadata, and selected native errno probes for package probes are present. Browser-safe memory-backed args, env, clock, random, sched_yield, buffered stdin fd_read, stdio fd_write, guest preopen metadata, read-only path_open/fd_read/fd_close for files under declared preopens, and native-shaped fd_fdstat_get imports are implemented after memory binding; WASI filesystem mutation, sockets, polling, and returnOnExit=false host process termination remain unsupported.", "probe": "const wasi = require('node:wasi'); const fs = require('node:fs'); fs.writeFileSync('/workspace/wasi-read.txt', 'hello-wasi'); const memory = () => new WebAssembly.Memory({ initial: 1 }); const runtime = new wasi.WASI({ version: 'preview1', args: ['app', '--flag'], env: { A: '1', B: 'two' } }); const imports = runtime.getImportObject().wasi_snapshot_preview1; const preStart = (() => { try { imports.args_get(); return 'ok'; } catch (error) { return error.name + ':' + error.code + ':' + error.message; } })(); const unstableRuntime = new wasi.WASI({ version: 'unstable' }); const unstableImportObject = unstableRuntime.getImportObject(); const unstablePreStart = (() => { try { unstableRuntime.wasiImport.args_get(); return 'ok'; } catch (error) { return error.name + ':' + error.code + ':' + error.message; } })(); const unstableNamespace = Object.keys(unstableImportObject).join(',') + ':' + (unstableImportObject.wasi_unstable === unstableRuntime.wasiImport) + ':' + unstablePreStart; const metadata = ['args_get','fd_fdstat_get','fd_write','path_open','random_get','sched_yield','proc_exit'].map((name) => name + ':' + imports[name].length + ':' + imports[name].name).join('|'); const importPrototype = Object.getPrototypeOf(imports); const importNames = Object.getOwnPropertyNames(imports).join(','); const importPrototypeNames = Object.getOwnPropertyNames(importPrototype).join(','); const importDescriptor = (object, name) => { const descriptor = Object.getOwnPropertyDescriptor(object, name); return [name, Boolean(descriptor), descriptor?.enumerable, descriptor?.configurable, descriptor?.writable, typeof descriptor?.value, descriptor?.value?.name, descriptor?.value?.length, Object.hasOwn(descriptor?.value ?? {}, 'prototype')].join(':') }; const importPrototypeMetadata = ['args_get','fd_write','proc_exit','constructor'].map((name) => importDescriptor(imports, name) + '|' + importDescriptor(importPrototype, name)).join(';'); const validOptions = new wasi.WASI({ version: 'preview1', returnOnExit: false, stdin: 0, stdout: 1, stderr: 2 }) instanceof wasi.WASI; const invalidCodes = [{ version: 'preview1', returnOnExit: 'yes' }, { version: 'preview1', stdin: '0' }, { version: 'preview1', stdout: 1.5 }, { version: 'preview1', stderr: -1 }, { version: 'preview1', stdin: 2147483648 }].map((options) => { try { new wasi.WASI(options); return 'ok'; } catch (error) { return error.code; } }).join(','); let initializeCalls = 0; const initializeResult = new wasi.WASI({ version: 'preview1' }).initialize({ exports: { memory: memory(), _initialize() { initializeCalls += 1; return 5; } } }); let initializeCode; try { new wasi.WASI({ version: 'preview1' }).initialize({ exports: { memory: memory(), _initialize: 1 } }); } catch (error) { initializeCode = error.code; } const exitRuntime = new wasi.WASI({ version: 'preview1' }); const exitCode = exitRuntime.start({ exports: { memory: memory(), _start() { exitRuntime.wasiImport.proc_exit(7); } } }); const exitRuntimeTrue = new wasi.WASI({ version: 'preview1', returnOnExit: true }); const exitCodeTrue = exitRuntimeTrue.start({ exports: { memory: memory(), _start() { exitRuntimeTrue.wasiImport.proc_exit(8); } } }); let directExit; try { new wasi.WASI({ version: 'preview1' }).wasiImport.proc_exit(9); } catch (error) { directExit = [typeof error, String(error), Object.getOwnPropertyNames(Object(error)).join(',') || ''].join(':'); } const backedMemory = memory(); const backed = new wasi.WASI({ version: 'preview1', args: ['app', '--flag'], env: { A: '1', B: 'two' }, preopens: { '/guest': '/workspace' } }); backed.finalizeBindings({ exports: { memory: backedMemory } }); const backedImports = backed.wasiImport; const view = new DataView(backedMemory.buffer); const bytes = new Uint8Array(backedMemory.buffer); const readCString = (offset) => { let end = offset; while (bytes[end] !== 0) end += 1; return new TextDecoder().decode(bytes.subarray(offset, end)); }; const argsSizes = [backedImports.args_sizes_get(0, 4), view.getUint32(0, true), view.getUint32(4, true)].join(':'); const argsGetResult = backedImports.args_get(16, 64); const argsValues = [argsGetResult, readCString(view.getUint32(16, true)), readCString(view.getUint32(20, true))].join(':'); const envSizes = [backedImports.environ_sizes_get(96, 100), view.getUint32(96, true), view.getUint32(100, true)].join(':'); const envGetResult = backedImports.environ_get(112, 160); const envValues = [envGetResult, readCString(view.getUint32(112, true)), readCString(view.getUint32(116, true))].join(':'); view.setBigUint64(240, 123n, true); const clockRows = [backedImports.clock_time_get(0, 0n, 224), view.getBigUint64(224, true) > 0n, backedImports.clock_res_get(0, 232), view.getBigUint64(232, true) > 0n, backedImports.clock_time_get(4, 0n, 240), backedImports.clock_time_get(0, 0, 240), view.getBigUint64(240, true).toString()].join(':'); bytes.fill(0, 256, 264); bytes.fill(7, 272, 280); const randomRows = [backedImports.random_get(256, 8), bytes.slice(256, 264).length, bytes.slice(256, 264).some((byte) => byte !== 0), backedImports.random_get(65533, 4), Array.from(bytes.slice(272, 280)).join(',')].join(':'); bytes.fill(0, 400, 440); view.setUint32(336, 400, true); view.setUint32(340, 4, true); view.setUint32(344, 416, true); view.setUint32(348, 16, true); process.stdin.write('wasi-input'); const fdReadResult = backedImports.fd_read(0, 336, 2, 356); const fdReadLength = view.getUint32(356, true); const fdReadText = new TextDecoder().decode(bytes.subarray(400, 404)) + new TextDecoder().decode(bytes.subarray(416, 416 + fdReadLength - 4)); const fdReadRows = [fdReadResult, fdReadLength, fdReadText, backedImports.fd_read(0, 336, 1, 356), view.getUint32(356, true), backedImports.fd_read(9, 336, 1, 356), backedImports.fd_read(0, 65533, 1, 356), backedImports.fd_read(0, 336, 1, 65533)].join(':'); bytes.fill(0, 360, 380); const preopenResult = backedImports.fd_prestat_get(3, 360); const preopenLength = view.getUint32(364, true); const preopenNameResult = backedImports.fd_prestat_dir_name(3, 368, preopenLength); const preopenName = new TextDecoder().decode(bytes.subarray(368, 368 + preopenLength)); const preopenRows = [preopenResult, view.getUint8(360), preopenLength, preopenNameResult, preopenName, backedImports.fd_prestat_get(2, 360), backedImports.fd_prestat_get(4, 360), backedImports.fd_prestat_dir_name(3, 368, preopenLength - 1), backedImports.fd_prestat_dir_name(3, 65533, preopenLength)].join(':'); const fdstat = (fd, ptr = 448) => { bytes.fill(255, ptr, ptr + 24); const result = backedImports.fd_fdstat_get(fd, ptr); return result + ':' + Array.from(bytes.slice(ptr, ptr + 24)).join(','); }; const fdstatRows = [fdstat(0), fdstat(1), fdstat(2), fdstat(3), backedImports.fd_fdstat_get(4, 448), backedImports.fd_fdstat_get(-1, 448), backedImports.fd_fdstat_get(0, 65520)].join('|'); const openPath = new TextEncoder().encode('wasi-read.txt'); bytes.set(openPath, 600); const openResult = backedImports.path_open(3, 0, 600, openPath.byteLength, 0, 0n, 0n, 0, 620); const openedFd = view.getUint32(620, true); view.setUint32(624, 640, true); view.setUint32(628, 5, true); bytes.fill(0, 640, 660); const firstReadResult = backedImports.fd_read(openedFd, 624, 1, 636); const firstReadLength = view.getUint32(636, true); const firstReadText = new TextDecoder().decode(bytes.subarray(640, 640 + firstReadLength)); view.setUint32(628, 16, true); bytes.fill(0, 640, 660); const secondReadResult = backedImports.fd_read(openedFd, 624, 1, 636); const secondReadLength = view.getUint32(636, true); const secondReadText = new TextDecoder().decode(bytes.subarray(640, 640 + secondReadLength)); const fdstatFile = fdstat(openedFd, 672); const closeRows = [backedImports.fd_close(openedFd), backedImports.fd_read(openedFd, 624, 1, 636), backedImports.fd_close(openedFd)].join(':'); const missingPath = new TextEncoder().encode('missing.txt'); bytes.set(missingPath, 704); const escapePath = new TextEncoder().encode('../secret.txt'); bytes.set(escapePath, 724); const pathOpenRows = [openResult, openedFd > 3, firstReadResult, firstReadLength, firstReadText, secondReadResult, secondReadLength, secondReadText, fdstatFile, closeRows, backedImports.path_open(3, 0, 704, missingPath.byteLength, 0, 0n, 0n, 0, 620), backedImports.path_open(3, 0, 724, escapePath.byteLength, 0, 0n, 0n, 0, 620), backedImports.path_open(0, 0, 704, missingPath.byteLength, 0, 0n, 0n, 0, 620), backedImports.path_open(3, 0, 65533, 4, 0, 0n, 0n, 0, 620), backedImports.path_open(3, 0, 704, missingPath.byteLength, 1, 0n, 0n, 0, 620)].join('|'); view.setUint32(288, 320, true); view.setUint32(292, 0, true); const fdRows = [backedImports.fd_write(9, 288, 1, 296), backedImports.fd_write(1, 288, 1, 296), view.getUint32(296, true)].join(':'); const unsupportedRows = [backedImports.fd_prestat_get(4, 304), backedImports.sock_send(3, 0, 0, 0, 304)].join(':'); if (Object.keys(wasi).join(',') !== 'WASI' || Object.hasOwn(wasi, 'default') || wasi.WASI.length !== 0 || Object.getOwnPropertyNames(wasi.WASI.prototype).join(',') !== 'constructor,finalizeBindings,start,initialize,getImportObject' || preStart !== 'Error:ERR_WASI_NOT_STARTED:wasi.start() has not been called' || unstableNamespace !== 'wasi_unstable:true:Error:ERR_WASI_NOT_STARTED:wasi.start() has not been called' || typeof imports.proc_exit !== 'function' || metadata !== 'args_get:2:bound args_get|fd_fdstat_get:2:bound fd_fdstat_get|fd_write:4:bound fd_write|path_open:9:bound path_open|random_get:2:bound random_get|sched_yield:0:bound sched_yield|proc_exit:1:bound wasiReturnOnProcExit' || importNames !== 'args_get,args_sizes_get,clock_res_get,clock_time_get,environ_get,environ_sizes_get,fd_advise,fd_allocate,fd_close,fd_datasync,fd_fdstat_get,fd_fdstat_set_flags,fd_fdstat_set_rights,fd_filestat_get,fd_filestat_set_size,fd_filestat_set_times,fd_pread,fd_prestat_get,fd_prestat_dir_name,fd_pwrite,fd_read,fd_readdir,fd_renumber,fd_seek,fd_sync,fd_tell,fd_write,path_create_directory,path_filestat_get,path_filestat_set_times,path_link,path_open,path_readlink,path_remove_directory,path_rename,path_symlink,path_unlink_file,poll_oneoff,proc_exit,proc_raise,random_get,sched_yield,sock_accept,sock_recv,sock_send,sock_shutdown' || importPrototypeNames !== 'args_get,args_sizes_get,clock_res_get,clock_time_get,environ_get,environ_sizes_get,fd_advise,fd_allocate,fd_close,fd_datasync,fd_fdstat_get,fd_fdstat_set_flags,fd_fdstat_set_rights,fd_filestat_get,fd_filestat_set_size,fd_filestat_set_times,fd_pread,fd_prestat_get,fd_prestat_dir_name,fd_pwrite,fd_read,fd_readdir,fd_renumber,fd_seek,fd_sync,fd_tell,fd_write,path_create_directory,path_filestat_get,path_filestat_set_times,path_link,path_open,path_readlink,path_remove_directory,path_rename,path_symlink,path_unlink_file,poll_oneoff,proc_exit,proc_raise,random_get,sched_yield,sock_accept,sock_recv,sock_send,sock_shutdown,constructor' || importPrototypeMetadata !== \"args_get:true:true:true:true:function:bound args_get:2:false|args_get:true:true:true:true:function:args_get:2:false;fd_write:true:true:true:true:function:bound fd_write:4:false|fd_write:true:true:true:true:function:fd_write:4:false;proc_exit:true:true:true:true:function:bound wasiReturnOnProcExit:1:false|proc_exit:true:true:true:true:function:proc_exit:1:false;constructor:false::::undefined:::false|constructor:true:false:true:true:function:WASI:0:true\" || !validOptions || invalidCodes !== 'ERR_INVALID_ARG_TYPE,ERR_INVALID_ARG_TYPE,ERR_OUT_OF_RANGE,ERR_OUT_OF_RANGE,ERR_OUT_OF_RANGE' || initializeResult !== undefined || initializeCalls !== 1 || initializeCode !== 'ERR_INVALID_ARG_TYPE' || exitCode !== 7 || exitCodeTrue !== 8 || directExit !== 'symbol:Symbol(kExitCode):' || argsSizes !== '0:2:11' || argsValues !== '0:app:--flag' || envSizes !== '0:2:10' || envValues !== '0:A=1:B=two' || clockRows !== '0:true:0:true:28:28:123' || !randomRows.startsWith('0:8:true:61:7,7,7,7,7,7,7,7') || backedImports.sched_yield() !== 0 || fdReadRows !== '0:10:wasi-input:0:0:8:61:61' || preopenRows !== '0:0:6:0:/guest:28:8:42:61' || fdstatRows !== '0:4,255,0,0,255,255,255,255,255,1,224,8,0,0,0,0,0,0,0,0,0,0,0,0|0:6,255,5,0,255,255,255,255,74,0,32,56,0,0,0,0,255,255,255,63,0,0,0,0|0:6,255,5,0,255,255,255,255,74,0,32,56,0,0,0,0,255,255,255,63,0,0,0,0|0:3,255,0,0,255,255,255,255,152,254,191,15,0,0,0,0,255,255,255,15,0,0,0,0|8|28|61' || pathOpenRows !== '0|true|0|5|hello|0|5|-wasi|0:4,255,0,0,255,255,255,255,38,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0|0:8:8|44|76|76|61|52' || fdRows !== '8:0:0' || unsupportedRows !== '8:28') throw new Error('wasi failed')" }, { "specifier": "node:worker_threads", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Worker-compatible behavior is browser-backed with native-shaped CommonJS export order; eval/file URL workers, argv/env options, native-keyed SHARE_ENV, thread names, environment data, normalized resourceLimits metadata as accepted no-op limits, native-shaped Worker prototype accessors, synthetic worker heap/cpu/profile probe helpers, main-thread workerData nullability, stdin writable piping, stdout/stderr readable streams with truthy capture options and default forwarding, MessageChannel call/prototype metadata, ArrayBuffer and MessagePort transferList detachment/validation/close-event behavior, native-shaped MessagePort prototype order/accessor/function metadata, moveMessagePortToContext validation and moved-port wrapper probes, receiveMessageOnPort, BroadcastChannel accessor metadata, lock probes including callback validation, postMessageToThread timeout validation-before-unsupported behavior, object marking helpers including markAsUncloneable clone rejection, and Node-shaped helper prototype metadata are supported, but native worker features remain limited.", "probe": "const vm = require('node:vm'); const wt = require('node:worker_threads'); const expectedKeys = 'isInternalThread,isMainThread,MessagePort,MessageChannel,markAsUncloneable,markAsUntransferable,isMarkedAsUntransferable,moveMessagePortToContext,receiveMessageOnPort,resourceLimits,postMessageToThread,threadId,threadName,SHARE_ENV,Worker,parentPort,workerData,BroadcastChannel,setEnvironmentData,getEnvironmentData,locks'; if (Object.keys(wt).join(',') !== expectedKeys) throw new Error('worker_threads export order failed'); if (String(wt.SHARE_ENV) !== 'Symbol(nodejs.worker_threads.SHARE_ENV)' || Symbol.keyFor(wt.SHARE_ENV) !== 'nodejs.worker_threads.SHARE_ENV') throw new Error('worker_threads SHARE_ENV failed'); if (wt.workerData !== null) throw new Error('workerData main thread failed'); const helperPrototypeNames = ['MessageChannel','markAsUncloneable','markAsUntransferable','isMarkedAsUntransferable','setEnvironmentData','getEnvironmentData','receiveMessageOnPort','moveMessagePortToContext','postMessageToThread']; const constructTag = (fn) => { try { const instance = new fn(); instance.port1?.close?.(); instance.port2?.close?.(); return 'ok'; } catch (error) { return error.code || (String(error.message).includes('not a constructor') ? 'notConstructor' : error.name); } }; const functionPrototypeRow = (fn) => { const prototypeDescriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [fn?.name, fn?.length, Object.hasOwn(fn, 'prototype'), prototypeDescriptor?.enumerable, prototypeDescriptor?.configurable, prototypeDescriptor?.writable, Object.getOwnPropertyNames(prototypeDescriptor?.value ?? {}).join(','), constructTag(fn)].join(':') }; const expectedHelperPrototypes = 'MessageChannel:MessageChannel:0:true:false:false:true:constructor:ok|markAsUncloneable:markAsUncloneable:1:true:false:false:true:constructor:ok|markAsUntransferable:markAsUntransferable:1:true:false:false:true:constructor:ok|isMarkedAsUntransferable:isMarkedAsUntransferable:1:true:false:false:true:constructor:ok|setEnvironmentData:setEnvironmentData:2:true:false:false:true:constructor:ok|getEnvironmentData:getEnvironmentData:1:true:false:false:true:constructor:ok|receiveMessageOnPort:receiveMessageOnPort:1:true:false:false:true:constructor:ERR_INVALID_ARG_TYPE|moveMessagePortToContext:moveMessagePortToContext:0:false:::::notConstructor|postMessageToThread:postMessageToThread:4:false:::::notConstructor'; const accessorFunctionPrototypeRow = (fn) => { const prototypeDescriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [fn?.name, fn?.length, Object.hasOwn(fn, 'prototype'), prototypeDescriptor?.enumerable, prototypeDescriptor?.configurable, prototypeDescriptor?.writable, Object.getOwnPropertyNames(prototypeDescriptor?.value ?? {}).join(',')].join(':') }; const broadcastAccessorRows = ['onmessage','onmessageerror'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(wt.BroadcastChannel.prototype, name); return [name, descriptor.enumerable, descriptor.configurable, accessorFunctionPrototypeRow(descriptor.get), accessorFunctionPrototypeRow(descriptor.set)].join(':') }).join('|'); const expectedBroadcastAccessors = 'onmessage:true:true:get onmessage:0:true:false:false:true:constructor:set onmessage:1:true:false:false:true:constructor|onmessageerror:true:true:get onmessageerror:0:true:false:false:true:constructor:set onmessageerror:1:true:false:false:true:constructor'; if (helperPrototypeNames.map((name) => name + ':' + functionPrototypeRow(wt[name])).join('|') !== expectedHelperPrototypes) throw new Error('worker_threads helper prototypes failed'); if (broadcastAccessorRows !== expectedBroadcastAccessors) throw new Error('worker_threads BroadcastChannel accessors failed'); try { wt.MessageChannel(); throw new Error('MessageChannel call failed') } catch (error) { if (error.message === 'MessageChannel call failed' || error.code !== 'ERR_CONSTRUCT_CALL_REQUIRED') throw error } const object = {}; wt.markAsUntransferable(object); if (!wt.isMarkedAsUntransferable(object) || wt.isMarkedAsUntransferable({})) throw new Error('markAsUntransferable failed'); const { port1, port2 } = new wt.MessageChannel(); if (!(port1 instanceof wt.MessagePort) || Object.getPrototypeOf(port1) !== wt.MessagePort.prototype || port1.hasRef() !== false || port1.unref() !== undefined || port1.hasRef() !== false || port1.ref() !== undefined || port1.hasRef() !== true) throw new Error('MessagePort metadata failed'); const postDescriptor = Object.getOwnPropertyDescriptor(wt.MessagePort.prototype, 'postMessage'); const onmessageDescriptor = Object.getOwnPropertyDescriptor(wt.MessagePort.prototype, 'onmessage'); const messagePortPrototypeRow = (name) => { const descriptor = Object.getOwnPropertyDescriptor(wt.MessagePort.prototype, name); const functionPrototypeRow = (fn) => { const prototypeDescriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [fn?.name, fn?.length, Object.hasOwn(fn, 'prototype'), prototypeDescriptor?.enumerable, prototypeDescriptor?.configurable, prototypeDescriptor?.writable, Object.getOwnPropertyNames(prototypeDescriptor?.value ?? {}).join(',')].join(':') }; if ('value' in descriptor) return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, functionPrototypeRow(descriptor.value)].join(':'); return [name, descriptor.enumerable, descriptor.configurable, 'get', functionPrototypeRow(descriptor.get), 'set', functionPrototypeRow(descriptor.set)].join(':') }; const expectedMessagePortNames = 'postMessage,start,constructor,ref,unref,hasRef,onmessage,onmessageerror,close'; const expectedMessagePortMetadata = 'postMessage:true:true:true:postMessage:0:false::::|start:true:true:true:start:0:false::::|constructor:false:true:true:MessagePort:0:true:false:false:true:postMessage,start,constructor,ref,unref,hasRef,onmessage,onmessageerror,close|ref:true:true:true:ref:0:false::::|unref:true:true:true:unref:0:false::::|hasRef:true:true:true:hasRef:0:true:false:false:true:constructor|onmessage:true:true:get:get onmessage:0:true:false:false:true:constructor:set:set onmessage:1:true:false:false:true:constructor|onmessageerror:true:true:get:get onmessageerror:0:true:false:false:true:constructor:set:set onmessageerror:1:true:false:false:true:constructor|close:true:true:true:close:1:true:false:false:true:constructor'; const messagePortMetadata = Object.getOwnPropertyNames(wt.MessagePort.prototype).map(messagePortPrototypeRow).join('|'); if (!postDescriptor?.enumerable || wt.MessagePort.prototype.postMessage.length !== 0 || typeof onmessageDescriptor?.get !== 'function' || typeof onmessageDescriptor?.set !== 'function' || !onmessageDescriptor.enumerable || Object.getOwnPropertyNames(wt.MessagePort.prototype).join(',') !== expectedMessagePortNames || Object.keys(wt.MessagePort.prototype).join(',') !== 'postMessage,start,ref,unref,hasRef,onmessage,onmessageerror,close' || messagePortMetadata !== expectedMessagePortMetadata) throw new Error('MessagePort descriptors failed'); try { new wt.MessagePort(); throw new Error('MessagePort constructor failed') } catch (error) { if (error.message === 'MessagePort constructor failed' || error.code !== 'ERR_CONSTRUCT_CALL_INVALID') throw error } port1.postMessage({ ok: true }); const received = wt.receiveMessageOnPort(port2); if (received?.message?.ok !== true || wt.receiveMessageOnPort(port2) !== undefined) throw new Error('receiveMessageOnPort failed'); const transferBuffer = new ArrayBuffer(2); new Uint8Array(transferBuffer).set([1, 2]); port1.postMessage({ buffer: transferBuffer }, [transferBuffer]); const transferred = wt.receiveMessageOnPort(port2)?.message?.buffer; if (transferBuffer.byteLength !== 0 || transferred?.byteLength !== 2 || Array.from(new Uint8Array(transferred)).join(',') !== '1,2') throw new Error('ArrayBuffer transferList failed'); const { port1: transferPort, port2: transferPeer } = new wt.MessageChannel(); port1.postMessage({ port: transferPort }, [transferPort]); const movedPort = wt.receiveMessageOnPort(port2)?.message?.port; movedPort.postMessage('moved'); transferPort.postMessage('stale'); if (!(movedPort instanceof wt.MessagePort) || wt.receiveMessageOnPort(transferPeer)?.message !== 'moved' || wt.receiveMessageOnPort(transferPeer) !== undefined) throw new Error('MessagePort transferList failed'); try { port1.postMessage({ port: transferPeer }); throw new Error('missing port transfer failed') } catch (error) { if (error.message === 'missing port transfer failed' || error.name !== 'DataCloneError') throw error } movedPort.close(); transferPeer.close(); const duplicate = new ArrayBuffer(1); try { port1.postMessage('duplicate', [duplicate, duplicate]); throw new Error('duplicate transfer failed') } catch (error) { if (error.message === 'duplicate transfer failed' || error.name !== 'DataCloneError') throw error } const marked = new ArrayBuffer(1); wt.markAsUntransferable(marked); try { port1.postMessage('marked', [marked]); throw new Error('marked transfer failed') } catch (error) { if (error.message === 'marked transfer failed' || error.name !== 'DataCloneError' || marked.byteLength !== 1) throw error } const cloneErrorRow = (label, action) => { try { action(); return label + ':ok' } catch (error) { return [label, error.constructor.name, error.name, error.code, error.message].join(':') } }; const markedPlainClone = { ok: true }; const markedNestedClone = { ok: true }; const markedNullPrototypeClone = Object.assign(Object.create(null), { ok: true }); class MarkedCloneClass { constructor() { this.ok = true; } } const markedClassClone = new MarkedCloneClass(); const markedErrorClone = new Error('marked'); const allowedMarkedArray = [1, 2]; const allowedMarkedDate = new Date(0); const allowedMarkedRegExp = /marked/gi; const allowedMarkedMap = new Map([['entry', { ok: true }]]); const allowedMarkedSet = new Set([{ ok: true }]); const allowedMarkedBuffer = new ArrayBuffer(2); const allowedMarkedTypedArray = new Uint8Array([3, 4]); [markedPlainClone, markedNestedClone, markedNullPrototypeClone, markedClassClone, markedErrorClone, allowedMarkedArray, allowedMarkedDate, allowedMarkedRegExp, allowedMarkedMap, allowedMarkedSet, allowedMarkedBuffer, allowedMarkedTypedArray].forEach((value) => wt.markAsUncloneable(value)); const markedCloneRows = [cloneErrorRow('plain', () => port1.postMessage(markedPlainClone)), cloneErrorRow('nested', () => port1.postMessage({ markedNestedClone })), cloneErrorRow('null-proto', () => port1.postMessage(markedNullPrototypeClone)), cloneErrorRow('class', () => port1.postMessage(markedClassClone)), cloneErrorRow('error', () => port1.postMessage(markedErrorClone))].join('|'); port1.postMessage(allowedMarkedArray); port1.postMessage(allowedMarkedDate); port1.postMessage(allowedMarkedRegExp); port1.postMessage(allowedMarkedMap); port1.postMessage(allowedMarkedSet); port1.postMessage(allowedMarkedBuffer); port1.postMessage(allowedMarkedTypedArray); const allowedArrayClone = wt.receiveMessageOnPort(port2).message; const allowedDateClone = wt.receiveMessageOnPort(port2).message; const allowedRegExpClone = wt.receiveMessageOnPort(port2).message; const allowedMapClone = wt.receiveMessageOnPort(port2).message; const allowedSetClone = wt.receiveMessageOnPort(port2).message; const allowedBufferClone = wt.receiveMessageOnPort(port2).message; const allowedTypedClone = wt.receiveMessageOnPort(port2).message; const allowedMarkedCloneRows = [Array.isArray(allowedArrayClone), allowedArrayClone.join(','), allowedDateClone.getTime(), allowedRegExpClone.source + '/' + allowedRegExpClone.flags, allowedMapClone.get('entry').ok, allowedSetClone.values().next().value.ok, allowedBufferClone.byteLength, Array.from(allowedTypedClone).join(',')].join(':'); const markedWorkerDataClone = { workerData: true }; wt.markAsUncloneable(markedWorkerDataClone); const markedWorkerDataRow = cloneErrorRow('workerData', () => new wt.Worker('', { eval: true, workerData: markedWorkerDataClone })); const markedPostWorker = new wt.Worker('setInterval(() => {}, 1000)', { eval: true }); await new Promise((resolve, reject) => { markedPostWorker.once('online', resolve); markedPostWorker.once('error', reject); }); const markedWorkerPostClone = { post: true }; wt.markAsUncloneable(markedWorkerPostClone); const markedWorkerPostRow = cloneErrorRow('worker-post', () => markedPostWorker.postMessage(markedWorkerPostClone)); await markedPostWorker.terminate(); if (markedCloneRows !== 'plain:DOMException:DataCloneError:25:Cannot clone object of unsupported type.|nested:DOMException:DataCloneError:25:Cannot clone object of unsupported type.|null-proto:DOMException:DataCloneError:25:Cannot clone object of unsupported type.|class:DOMException:DataCloneError:25:Cannot clone object of unsupported type.|error:DOMException:DataCloneError:25:Cannot clone object of unsupported type.' || allowedMarkedCloneRows !== 'true:1,2:0:marked/gi:true:true:2:3,4' || markedWorkerDataRow !== 'workerData:DOMException:DataCloneError:25:Cannot clone object of unsupported type.' || markedWorkerPostRow !== 'worker-post:DOMException:DataCloneError:25:Cannot clone object of unsupported type.') throw new Error('markAsUncloneable clone rejection failed'); try { wt.receiveMessageOnPort({}); throw new Error('receiveMessageOnPort invalid failed') } catch (error) { if (error.message === 'receiveMessageOnPort invalid failed' || error.code !== 'ERR_INVALID_ARG_TYPE') throw error } port1.close(); port2.close(); const { port1: contextPort, port2: contextPeer } = new wt.MessageChannel(); const contextMovedPort = wt.moveMessagePortToContext(contextPort, vm.createContext({})); const movedRows = [contextMovedPort !== contextPort, contextMovedPort instanceof wt.MessagePort, Object.getPrototypeOf(contextMovedPort) === wt.MessagePort.prototype, contextMovedPort.constructor.name, typeof contextMovedPort.on, typeof contextMovedPort.addEventListener, typeof contextMovedPort.postMessage, typeof contextMovedPort.start, typeof contextMovedPort.ref, typeof contextMovedPort.close, Object.getOwnPropertyNames(contextMovedPort).join(','), Object.getOwnPropertySymbols(contextMovedPort).length, Object.getOwnPropertyNames(Object.getPrototypeOf(contextMovedPort)).join(','), Object.getOwnPropertyNames(Object.getPrototypeOf(Object.getPrototypeOf(contextMovedPort))).join(','), Object.keys(Object.getPrototypeOf(contextMovedPort)).join(',')].join(':'); contextMovedPort.postMessage('to-peer'); const movedPeerMessage = wt.receiveMessageOnPort(contextPeer)?.message; contextPeer.postMessage('to-moved'); const movedReceived = wt.receiveMessageOnPort(contextMovedPort)?.message; const movedEmpty = wt.receiveMessageOnPort(contextMovedPort); const movedRefRows = [contextMovedPort.hasRef(), contextMovedPort.ref(), contextMovedPort.hasRef(), contextMovedPort.unref(), contextMovedPort.hasRef()].join(':'); const movedValidationRows = [['missing', () => wt.moveMessagePortToContext()], ['nonport', () => wt.moveMessagePortToContext({}, vm.createContext({}))], ['missing-context', () => wt.moveMessagePortToContext(contextPeer)], ['non-context', () => wt.moveMessagePortToContext(contextPeer, {})]].map(([label, action]) => { try { action(); return label + ':ok'; } catch (error) { return [label, error.name, error.code, error.message].join(':'); } }).join('|'); contextMovedPort.close(); contextPeer.close(); if (movedRows !== 'true:false:false:MessagePort:undefined:undefined:function:function:function:function::0:postMessage,start,constructor:close,hasRef,ref,unref,constructor:postMessage,start' || movedPeerMessage !== 'to-peer' || movedReceived !== 'to-moved' || movedEmpty !== undefined || movedRefRows !== 'false::true::false' || movedValidationRows !== 'missing:TypeError:ERR_INVALID_ARG_TYPE:The \"port\" argument must be a MessagePort instance|nonport:TypeError:ERR_INVALID_ARG_TYPE:The \"port\" argument must be a MessagePort instance|missing-context:TypeError:ERR_INVALID_ARG_TYPE:Invalid context argument|non-context:TypeError:ERR_INVALID_ARG_TYPE:Invalid context argument') throw new Error('moveMessagePortToContext failed'); const name = 'worker-probe-' + Date.now(); const first = new wt.BroadcastChannel(name); const second = new wt.BroadcastChannel(name); const gotMessage = await new Promise((resolve) => { second.onmessage = (event) => resolve(event.data.ok); first.postMessage({ ok: true }); }); first.close(); second.close(); if (!gotMessage) throw new Error('BroadcastChannel failed'); const lockResult = await wt.locks.request('resource', async (lock) => lock.name + ':' + lock.mode); if (lockResult !== 'resource:exclusive' || (await wt.locks.query()).held.length !== 0) throw new Error('locks failed'); try { await wt.postMessageToThread(999999, 'x'); throw new Error('postMessageToThread failed') } catch (error) { if (error.message === 'postMessageToThread failed' || error.code !== 'ERR_WORKER_MESSAGING_FAILED') throw error } const stdioWorker = new wt.Worker(\"console.log('stdio out'); console.error('stdio err')\", { eval: true, stdout: true, stderr: true }); if (typeof stdioWorker.stdout?.on !== 'function' || typeof stdioWorker.stderr?.on !== 'function' || stdioWorker.stdin !== null) throw new Error('Worker stdio stream shape failed'); let stdioOut = ''; let stdioErr = ''; stdioWorker.stdout.on('data', (chunk) => { stdioOut += chunk; }); stdioWorker.stderr.on('data', (chunk) => { stdioErr += chunk; }); const stdioExit = await new Promise((resolve, reject) => { stdioWorker.on('error', reject); stdioWorker.on('exit', resolve); }); if (stdioExit !== 0 || stdioOut !== 'stdio out\\n' || stdioErr !== 'stdio err\\n') throw new Error('Worker stdio capture failed'); const stdinWorker = new wt.Worker(\"process.stdin.setEncoding('utf8'); let body = ''; process.stdin.on('data', (chunk) => { body += chunk; }); process.stdin.on('end', () => { console.log(JSON.stringify({ body, hasFd: Object.hasOwn(process.stdin, 'fd'), hasIsTTY: Object.hasOwn(process.stdin, 'isTTY') })); });\", { eval: true, stdin: 1, stdout: true }); if (typeof stdinWorker.stdin?.write !== 'function' || typeof stdinWorker.stdin?.end !== 'function') throw new Error('Worker stdin stream shape failed'); let stdinOut = ''; stdinWorker.stdout.on('data', (chunk) => { stdinOut += chunk; }); stdinWorker.stdin.write('a'); stdinWorker.stdin.write(Buffer.from('b')); stdinWorker.stdin.end('c'); const stdinExit = await new Promise((resolve, reject) => { stdinWorker.on('error', reject); stdinWorker.on('exit', resolve); }); const stdinReport = JSON.parse(stdinOut); if (stdinExit !== 0 || stdinReport.body !== 'abc' || stdinReport.hasFd !== false || stdinReport.hasIsTTY !== false) throw new Error('Worker stdin piping failed'); const truthyCapture = new wt.Worker(\"console.log('truthy out'); console.error('truthy err')\", { eval: true, stdout: 1, stderr: 'yes' }); let truthyOut = ''; let truthyErr = ''; truthyCapture.stdout.on('data', (chunk) => { truthyOut += chunk; }); truthyCapture.stderr.on('data', (chunk) => { truthyErr += chunk; }); const truthyExit = await new Promise((resolve, reject) => { truthyCapture.on('error', reject); truthyCapture.on('exit', resolve); }); if (truthyExit !== 0 || truthyOut !== 'truthy out\\n' || truthyErr !== 'truthy err\\n') throw new Error('Worker truthy stdio capture failed'); const resourceDescriptor = Object.getOwnPropertyDescriptor(wt.Worker.prototype, 'resourceLimits'); if (JSON.stringify(wt.resourceLimits) !== '{}' || typeof resourceDescriptor?.get !== 'function' || resourceDescriptor.set !== undefined || resourceDescriptor.enumerable !== false || resourceDescriptor.configurable !== true) throw new Error('Worker resourceLimits descriptor failed'); const resourceWorker = new wt.Worker(\"const { parentPort, resourceLimits } = require('node:worker_threads'); parentPort.postMessage({ resourceLimits, keys: Object.keys(resourceLimits) });\", { eval: true, resourceLimits: { maxYoungGenerationSizeMb: 8, maxOldGenerationSizeMb: 'bad', codeRangeSizeMb: 64, stackSizeMb: 2, ignored: 99 } }); const resourceInitial = resourceWorker.resourceLimits; resourceInitial.maxYoungGenerationSizeMb = 12345; const resourceAfterCopy = resourceWorker.resourceLimits; const resourceMessage = await new Promise((resolve, reject) => { resourceWorker.on('message', resolve); resourceWorker.on('error', reject); }); const resourceExit = await new Promise((resolve) => resourceWorker.on('exit', resolve)); const resourceExpected = '{\"maxYoungGenerationSizeMb\":8,\"maxOldGenerationSizeMb\":-1,\"codeRangeSizeMb\":64,\"stackSizeMb\":2}'; if (JSON.stringify(resourceAfterCopy) !== resourceExpected || JSON.stringify(resourceMessage.resourceLimits) !== resourceExpected || resourceMessage.keys.join(',') !== 'maxYoungGenerationSizeMb,maxOldGenerationSizeMb,codeRangeSizeMb,stackSizeMb' || resourceExit !== 0 || JSON.stringify(resourceWorker.resourceLimits) !== '{}') throw new Error('Worker resourceLimits failed'); const workerPrototypeNames = Object.getOwnPropertyNames(wt.Worker.prototype).join(','); const workerPrototypeKeys = Object.keys(wt.Worker.prototype).join(','); const workerAccessorMeta = ['threadId','threadName','stdin','stdout','stderr','resourceLimits'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(wt.Worker.prototype, name); return [name, typeof descriptor.get, typeof descriptor.set, descriptor.enumerable, descriptor.configurable, descriptor.get.name, descriptor.get.length].join(':') }).join('|'); const workerMethodMeta = ['postMessage','terminate','ref','unref','getHeapSnapshot','getHeapStatistics','cpuUsage','startCpuProfile','startHeapProfile'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(wt.Worker.prototype, name); return [name, descriptor.value.name, descriptor.value.length, descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.hasOwn(descriptor.value, 'prototype')].join(':') }).join('|'); if (workerPrototypeNames !== 'constructor,postMessage,terminate,ref,unref,threadId,threadName,stdin,stdout,stderr,resourceLimits,getHeapSnapshot,getHeapStatistics,cpuUsage,startCpuProfile,startHeapProfile' || workerPrototypeKeys !== '' || workerAccessorMeta !== 'threadId:function:undefined:false:true:get threadId:0|threadName:function:undefined:false:true:get threadName:0|stdin:function:undefined:false:true:get stdin:0|stdout:function:undefined:false:true:get stdout:0|stderr:function:undefined:false:true:get stderr:0|resourceLimits:function:undefined:false:true:get resourceLimits:0' || workerMethodMeta !== 'postMessage:postMessage:0:false:true:true:false|terminate:terminate:0:false:true:true:false|ref:ref:0:false:true:true:false|unref:unref:0:false:true:true:false|getHeapSnapshot:getHeapSnapshot:1:false:true:true:false|getHeapStatistics:getHeapStatistics:0:false:true:true:false|cpuUsage:cpuUsage:1:false:true:true:false|startCpuProfile:startCpuProfile:1:false:true:true:false|startHeapProfile:startHeapProfile:1:false:true:true:false') throw new Error('Worker prototype introspection metadata failed'); const workerProbe = new wt.Worker('setInterval(() => {}, 1000)', { eval: true, name: 'probe', stdin: true, stdout: true, stderr: true, resourceLimits: { maxYoungGenerationSizeMb: 4 } }); await new Promise((resolve, reject) => { workerProbe.once('online', resolve); workerProbe.once('error', reject); }); const workerHeapStats = await workerProbe.getHeapStatistics(); const workerBaseUsage = await workerProbe.cpuUsage(); const workerUsageDelta = await workerProbe.cpuUsage(workerBaseUsage); let workerSnapshotBody = ''; for await (const chunk of await workerProbe.getHeapSnapshot()) workerSnapshotBody += String(chunk); const workerSnapshot = JSON.parse(workerSnapshotBody); const workerCpuProfile = await workerProbe.startCpuProfile(); const workerHeapProfile = await workerProbe.startHeapProfile(); const workerCpuProfileData = JSON.parse(await workerCpuProfile.stop()); const workerHeapProfileData = JSON.parse(await workerHeapProfile.stop()); const workerValidation = [['heap-options', () => workerProbe.getHeapSnapshot('bad')], ['heap-array', () => workerProbe.getHeapSnapshot([])], ['cpu-prev', () => workerProbe.cpuUsage('bad')], ['cpu-prev-user', () => workerProbe.cpuUsage({ system: 0 })], ['start-cpu', () => workerProbe.startCpuProfile('bad')], ['start-heap', () => workerProbe.startHeapProfile('bad')]].map(([label, action]) => { try { action(); return label + ':ok' } catch (error) { return label + ':' + error.code } }).join('|'); const workerAccessorsOk = typeof workerProbe.threadId === 'number' && workerProbe.threadName === 'probe' && typeof workerProbe.stdin.write === 'function' && typeof workerProbe.stdout.on === 'function' && typeof workerProbe.stderr.on === 'function' && !Object.hasOwn(workerProbe, 'threadId') && !Object.hasOwn(workerProbe, 'stdin') && JSON.stringify(workerProbe.resourceLimits) === '{\"maxYoungGenerationSizeMb\":4,\"maxOldGenerationSizeMb\":-1,\"codeRangeSizeMb\":-1,\"stackSizeMb\":4}'; const workerIntrospectionOk = Object.keys(workerHeapStats).join(',') === 'total_heap_size,total_heap_size_executable,total_physical_size,total_available_size,used_heap_size,heap_size_limit,malloced_memory,peak_malloced_memory,does_zap_garbage,number_of_native_contexts,number_of_detached_contexts,total_global_handles_size,used_global_handles_size,external_memory,total_allocated_bytes' && typeof workerHeapStats.used_heap_size === 'number' && Object.keys(workerBaseUsage).join(',') === 'user,system' && typeof workerBaseUsage.user === 'number' && typeof workerUsageDelta.system === 'number' && Object.keys(workerSnapshot).join(',') === 'snapshot,nodes,edges,strings' && workerSnapshot.snapshot.node_count === 0 && workerCpuProfile.constructor.name === 'CPUProfileHandle' && Object.getOwnPropertyNames(Object.getPrototypeOf(workerCpuProfile)).join(',') === 'constructor,stop' && typeof workerCpuProfile[Symbol.dispose] === 'function' && workerHeapProfile.constructor.name === 'HeapProfileHandle' && Object.getOwnPropertyNames(Object.getPrototypeOf(workerHeapProfile)).join(',') === 'constructor,stop' && typeof workerHeapProfile[Symbol.dispose] === 'function' && workerCpuProfileData.nodes[0].callFrame.functionName === '(root)' && Array.isArray(workerCpuProfileData.samples) && workerHeapProfileData.head.callFrame.functionName === '(root)' && Array.isArray(workerHeapProfileData.samples) && workerValidation === 'heap-options:ERR_INVALID_ARG_TYPE|heap-array:ERR_INVALID_ARG_TYPE|cpu-prev:ERR_INVALID_ARG_TYPE|cpu-prev-user:ERR_INVALID_ARG_TYPE|start-cpu:ERR_INVALID_ARG_TYPE|start-heap:ERR_INVALID_ARG_TYPE'; await workerProbe.terminate(); const workerAfterCpu = await workerProbe.cpuUsage().catch((error) => error.code); const workerAfterHeap = await workerProbe.getHeapStatistics().catch((error) => error.code); if (!workerAccessorsOk || !workerIntrospectionOk || JSON.stringify(workerProbe.resourceLimits) !== '{}' || workerAfterCpu !== 'ERR_WORKER_NOT_RUNNING' || workerAfterHeap !== 'ERR_WORKER_NOT_RUNNING') throw new Error('Worker introspection probe helpers failed'); const ocWorkerValidationRow = async (label, action) => { try { await action(); return label + ':ok'; } catch (error) { return [label, error.name, error.code, error.message].join(':'); } }; const ocWorkerLocksValidation = (await Promise.all([ocWorkerValidationRow('missing', () => wt.locks.request('resource')), ocWorkerValidationRow('number', () => wt.locks.request('resource', 1)), ocWorkerValidationRow('object', () => wt.locks.request('resource', {}))])).join('|'); const ocWorkerPostValidation = (await Promise.all([ocWorkerValidationRow('timeout-array', () => wt.postMessageToThread(999999, { ok: true }, [], [])), ocWorkerValidationRow('timeout-string', () => wt.postMessageToThread(999999, { ok: true }, [], '5')), ocWorkerValidationRow('timeout-negative', () => wt.postMessageToThread(999999, { ok: true }, [], -1)), ocWorkerValidationRow('timeout-nan', () => wt.postMessageToThread(999999, { ok: true }, [], NaN)), ocWorkerValidationRow('timeout-zero', () => wt.postMessageToThread(999999, { ok: true }, [], 0))])).join('|'); const ocWorkerExpectedLocksValidation = \"missing:TypeError:ERR_INVALID_ARG_TYPE:The \\\"callback\\\" argument must be of type function. Received undefined|number:TypeError:ERR_INVALID_ARG_TYPE:The \\\"callback\\\" argument must be of type function. Received type number (1)|object:TypeError:ERR_INVALID_ARG_TYPE:The \\\"callback\\\" argument must be of type function. Received an instance of Object\"; const ocWorkerExpectedPostValidation = \"timeout-array:TypeError:ERR_INVALID_ARG_TYPE:The \\\"timeout\\\" argument must be of type number. Received an instance of Array|timeout-string:TypeError:ERR_INVALID_ARG_TYPE:The \\\"timeout\\\" argument must be of type number. Received type string ('5')|timeout-negative:RangeError:ERR_OUT_OF_RANGE:The value of \\\"timeout\\\" is out of range. It must be >= 0. Received -1|timeout-nan:RangeError:ERR_OUT_OF_RANGE:The value of \\\"timeout\\\" is out of range. It must be >= 0. Received NaN|timeout-zero:Error:ERR_WORKER_MESSAGING_TIMEOUT:Sending a message to another thread timed out\"; if (ocWorkerLocksValidation !== ocWorkerExpectedLocksValidation || ocWorkerPostValidation !== ocWorkerExpectedPostValidation) throw new Error('worker_threads validation failed')" }, { "specifier": "node:inspector", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Session constructor/prototype shape, hidden connection state, Node-shaped CommonJS export order/top-level function metadata, duplicate-connect, truthy non-function callback validation before connection checks, main-thread connectToMainThread rejection, Node-shaped event-silent manual disconnect, eventing, Runtime.evaluate/getProperties with native-shaped invalid-parameter and invalid remote object protocol errors, synthetic Profiler.start/stop CPU profiles, native-ordered, toStringTag-aligned no-op console and native-ordered Network/DOMStorage/NetworkResources namespace probes with native-shaped helper names/arities/prototype metadata, no-op domain enable/disable, and Schema.getDomains are present; the real browser inspector protocol is not exposed to sandboxed code.", "unsupported": { "probe": "require('node:inspector').open()", "code": "ERR_OPENCONTAINERS_INSPECTOR_UNSUPPORTED" }, "probe": "const inspector = require('node:inspector'); const keys = 'open,close,url,waitForDebugger,console,Session,Network,NetworkResources,DOMStorage'; const inspectorConsoleKeys = 'debug,error,info,log,warn,dir,dirxml,table,trace,group,groupCollapsed,groupEnd,clear,count,countReset,assert,profile,profileEnd,time,timeLog,timeEnd,timeStamp,context'; const inspectorNetworkKeys = 'requestWillBeSent,responseReceived,loadingFinished,loadingFailed,dataSent,dataReceived,webSocketCreated,webSocketClosed,webSocketHandshakeResponseReceived'; const inspectorDomStorageKeys = 'domStorageItemAdded,domStorageItemRemoved,domStorageItemUpdated,domStorageItemsCleared,registerStorage'; const inspectorConsoleTag = Object.getOwnPropertyDescriptor(inspector.console, Symbol.toStringTag); const inspectorConsoleTagRows = [inspectorConsoleTag?.value, inspectorConsoleTag?.enumerable, inspectorConsoleTag?.configurable, inspectorConsoleTag?.writable, Object.prototype.toString.call(inspector.console)].join(':'); const functionDescriptorRows = ['open','close','url','waitForDebugger'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(inspector, name); const fn = inspector[name]; return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, fn.name, fn.length, Object.hasOwn(fn, 'prototype')].join(':'); }).join('|'); const scopedRows = (namespace, names) => names.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(namespace, name); const fn = descriptor.value; const prototypeDescriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, fn.name, fn.length, Object.hasOwn(fn, 'prototype'), prototypeDescriptor?.enumerable ?? 'missing', prototypeDescriptor?.configurable ?? 'missing', prototypeDescriptor?.writable ?? 'missing', Object.getOwnPropertyNames(prototypeDescriptor?.value ?? {}).join(','), prototypeDescriptor?.value?.constructor === fn].join(':'); }).join('|'); const inspectorConsoleRows = scopedRows(inspector.console, Object.keys(inspector.console)); const inspectorNetworkRows = scopedRows(inspector.Network, Object.keys(inspector.Network)); const inspectorDomStorageRows = scopedRows(inspector.DOMStorage, Object.keys(inspector.DOMStorage).sort()); const inspectorNetworkResourcesRows = scopedRows(inspector.NetworkResources, Object.keys(inspector.NetworkResources).sort()); if (Object.keys(inspector).join(',') !== keys || Object.keys(inspector.console).join(',') !== inspectorConsoleKeys || Object.keys(inspector.Network).join(',') !== inspectorNetworkKeys || Object.keys(inspector.DOMStorage).sort().join(',') !== inspectorDomStorageKeys || Object.keys(inspector.NetworkResources).sort().join(',') !== 'put' || inspectorConsoleTagRows !== 'console:false:true:false:[object console]' || functionDescriptorRows !== 'open:true:true:true:inspectorOpen:3:true|close:true:true:true:_debugEnd:0:false|url:true:true:true:url:0:false|waitForDebugger:true:true:true:inspectorWaitForDebugger:0:true' || inspectorConsoleRows !== 'debug:true:true:true:debug:0:false:missing:missing:missing::false|error:true:true:true:error:0:false:missing:missing:missing::false|info:true:true:true:info:0:false:missing:missing:missing::false|log:true:true:true:log:0:false:missing:missing:missing::false|warn:true:true:true:warn:0:false:missing:missing:missing::false|dir:true:true:true:dir:0:false:missing:missing:missing::false|dirxml:true:true:true:dirxml:0:false:missing:missing:missing::false|table:true:true:true:table:0:false:missing:missing:missing::false|trace:true:true:true:trace:0:false:missing:missing:missing::false|group:true:true:true:group:0:false:missing:missing:missing::false|groupCollapsed:true:true:true:groupCollapsed:0:false:missing:missing:missing::false|groupEnd:true:true:true:groupEnd:0:false:missing:missing:missing::false|clear:true:true:true:clear:0:false:missing:missing:missing::false|count:true:true:true:count:0:false:missing:missing:missing::false|countReset:true:true:true:countReset:0:false:missing:missing:missing::false|assert:true:true:true:assert:0:false:missing:missing:missing::false|profile:true:true:true:profile:0:false:missing:missing:missing::false|profileEnd:true:true:true:profileEnd:0:false:missing:missing:missing::false|time:true:true:true:time:0:false:missing:missing:missing::false|timeLog:true:true:true:timeLog:0:false:missing:missing:missing::false|timeEnd:true:true:true:timeEnd:0:false:missing:missing:missing::false|timeStamp:true:true:true:timeStamp:0:false:missing:missing:missing::false|context:true:true:true:context:1:false:missing:missing:missing::false' || inspectorNetworkRows !== 'requestWillBeSent:true:true:true:requestWillBeSent:1:false:missing:missing:missing::false|responseReceived:true:true:true:responseReceived:1:false:missing:missing:missing::false|loadingFinished:true:true:true:loadingFinished:1:false:missing:missing:missing::false|loadingFailed:true:true:true:loadingFailed:1:false:missing:missing:missing::false|dataSent:true:true:true:dataSent:1:false:missing:missing:missing::false|dataReceived:true:true:true:dataReceived:1:false:missing:missing:missing::false|webSocketCreated:true:true:true:webSocketCreated:1:false:missing:missing:missing::false|webSocketClosed:true:true:true:webSocketClosed:1:false:missing:missing:missing::false|webSocketHandshakeResponseReceived:true:true:true:webSocketHandshakeResponseReceived:1:false:missing:missing:missing::false' || inspectorDomStorageRows !== 'domStorageItemAdded:true:true:true:domStorageItemAdded:1:false:missing:missing:missing::false|domStorageItemRemoved:true:true:true:domStorageItemRemoved:1:false:missing:missing:missing::false|domStorageItemUpdated:true:true:true:domStorageItemUpdated:1:false:missing:missing:missing::false|domStorageItemsCleared:true:true:true:domStorageItemsCleared:1:false:missing:missing:missing::false|registerStorage:true:true:true:registerStorage:1:false:missing:missing:missing::false' || inspectorNetworkResourcesRows !== 'put:true:true:true:put:2:true:false:false:true:constructor:true' || typeof inspector.Session !== 'function' || inspector.open.length !== 3 || inspector.url() !== undefined || !Object.keys(inspector.Network).includes('requestWillBeSent')) throw new Error('inspector metadata failed'); const session = new inspector.Session(); let disconnectEvents = 0; session.on('disconnect', () => { disconnectEvents += 1; }); try { session.connectToMainThread(); throw new Error('connectToMainThread should fail') } catch (error) { if (error.message === 'connectToMainThread should fail' || error.code !== 'ERR_INSPECTOR_NOT_WORKER') throw error } let invalidDisconnectedCallback; try { session.post('Runtime.evaluate', {}, 1); } catch (error) { invalidDisconnectedCallback = error; } session.connect(); let duplicateError; try { session.connect(); } catch (error) { duplicateError = error; } let invalidConnectedCallback; try { session.post('Runtime.evaluate', {}, 1); } catch (error) { invalidConnectedCallback = error; } const value = await new Promise((resolve, reject) => session.post('Runtime.evaluate', { expression: '1 + 2', returnByValue: true }, (error, result) => error ? reject(error) : resolve(result.result.value))); const profilerStart = await new Promise((resolve, reject) => session.post('Profiler.start', {}, (error, result) => error ? reject(error) : resolve(result))); const profilerStop = await new Promise((resolve, reject) => session.post('Profiler.stop', {}, (error, result) => error ? reject(error) : resolve(result))); const commandError = await new Promise((resolve) => session.post('Runtime.nope', {}, (error) => resolve(error))); session.disconnect(); if (invalidDisconnectedCallback?.code !== 'ERR_INVALID_ARG_TYPE' || invalidConnectedCallback?.code !== 'ERR_INVALID_ARG_TYPE' || duplicateError?.code !== 'ERR_INSPECTOR_ALREADY_CONNECTED' || value !== 3 || Object.keys(profilerStart).length !== 0 || !Array.isArray(profilerStop.profile?.nodes) || typeof profilerStop.profile?.startTime !== 'number' || profilerStop.profile?.nodes?.[0]?.callFrame?.functionName !== '(root)' || commandError?.code !== 'ERR_INSPECTOR_COMMAND' || disconnectEvents !== 0) throw new Error('inspector behavior failed')" }, { "specifier": "node:inspector/promises", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Promise-based Session wraps the same browser-safe inspector subset as node:inspector, including Node-shaped CommonJS export order/top-level function metadata, native-shaped enumerable and constructable Session.post with own-prototype metadata, inherited connect/disconnect, duplicate-connect, truthy non-function callback validation before connection checks, main-thread connectToMainThread rejection, Node-shaped event-silent manual disconnect, Runtime.evaluate/getProperties with native-shaped invalid-parameter and invalid remote object protocol rejections, synthetic Profiler.start/stop CPU profiles, native-ordered, toStringTag-aligned no-op console and native-ordered Network/DOMStorage/NetworkResources namespace probes with native-shaped helper names/arities/prototype metadata, no-op domain probes, and Node-shaped promise rejection for unsupported commands; the real browser inspector protocol is not exposed to sandboxed code.", "unsupported": { "probe": "require('node:inspector/promises').open()", "code": "ERR_OPENCONTAINERS_INSPECTOR_UNSUPPORTED" }, "probe": "const inspector = require('node:inspector/promises'); const keys = 'open,close,url,waitForDebugger,console,Session,Network,NetworkResources,DOMStorage'; const inspectorConsoleKeys = 'debug,error,info,log,warn,dir,dirxml,table,trace,group,groupCollapsed,groupEnd,clear,count,countReset,assert,profile,profileEnd,time,timeLog,timeEnd,timeStamp,context'; const inspectorNetworkKeys = 'requestWillBeSent,responseReceived,loadingFinished,loadingFailed,dataSent,dataReceived,webSocketCreated,webSocketClosed,webSocketHandshakeResponseReceived'; const inspectorDomStorageKeys = 'domStorageItemAdded,domStorageItemRemoved,domStorageItemUpdated,domStorageItemsCleared,registerStorage'; const inspectorConsoleTag = Object.getOwnPropertyDescriptor(inspector.console, Symbol.toStringTag); const inspectorConsoleTagRows = [inspectorConsoleTag?.value, inspectorConsoleTag?.enumerable, inspectorConsoleTag?.configurable, inspectorConsoleTag?.writable, Object.prototype.toString.call(inspector.console)].join(':'); const functionDescriptorRows = ['open','close','url','waitForDebugger'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(inspector, name); const fn = inspector[name]; return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, fn.name, fn.length, Object.hasOwn(fn, 'prototype')].join(':'); }).join('|'); const scopedRows = (namespace, names) => names.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(namespace, name); const fn = descriptor.value; const prototypeDescriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'); return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, fn.name, fn.length, Object.hasOwn(fn, 'prototype'), prototypeDescriptor?.enumerable ?? 'missing', prototypeDescriptor?.configurable ?? 'missing', prototypeDescriptor?.writable ?? 'missing', Object.getOwnPropertyNames(prototypeDescriptor?.value ?? {}).join(','), prototypeDescriptor?.value?.constructor === fn].join(':'); }).join('|'); const inspectorConsoleRows = scopedRows(inspector.console, Object.keys(inspector.console)); const inspectorNetworkRows = scopedRows(inspector.Network, Object.keys(inspector.Network)); const inspectorDomStorageRows = scopedRows(inspector.DOMStorage, Object.keys(inspector.DOMStorage).sort()); const inspectorNetworkResourcesRows = scopedRows(inspector.NetworkResources, Object.keys(inspector.NetworkResources).sort()); const session = new inspector.Session(); let disconnectEvents = 0; session.on('disconnect', () => { disconnectEvents += 1; }); const descriptor = Object.getOwnPropertyDescriptor(inspector.Session.prototype, 'post'); const postPrototypeDescriptor = Object.getOwnPropertyDescriptor(descriptor.value, 'prototype'); const postPrototypeMeta = [Object.hasOwn(descriptor.value, 'prototype'), postPrototypeDescriptor?.enumerable, postPrototypeDescriptor?.configurable, postPrototypeDescriptor?.writable, Object.getOwnPropertyNames(postPrototypeDescriptor?.value ?? {}).join(','), postPrototypeDescriptor?.value?.constructor === descriptor.value].join(':'); const constructedPost = new descriptor.value(() => {}); const constructedPostError = await constructedPost.catch((error) => error); if (Object.keys(inspector).join(',') !== keys || Object.keys(inspector.console).join(',') !== inspectorConsoleKeys || Object.keys(inspector.Network).join(',') !== inspectorNetworkKeys || Object.keys(inspector.DOMStorage).sort().join(',') !== inspectorDomStorageKeys || Object.keys(inspector.NetworkResources).sort().join(',') !== 'put' || inspectorConsoleTagRows !== 'console:false:true:false:[object console]' || functionDescriptorRows !== 'open:true:true:true:inspectorOpen:3:true|close:true:true:true:_debugEnd:0:false|url:true:true:true:url:0:false|waitForDebugger:true:true:true:inspectorWaitForDebugger:0:true' || inspectorConsoleRows !== 'debug:true:true:true:debug:0:false:missing:missing:missing::false|error:true:true:true:error:0:false:missing:missing:missing::false|info:true:true:true:info:0:false:missing:missing:missing::false|log:true:true:true:log:0:false:missing:missing:missing::false|warn:true:true:true:warn:0:false:missing:missing:missing::false|dir:true:true:true:dir:0:false:missing:missing:missing::false|dirxml:true:true:true:dirxml:0:false:missing:missing:missing::false|table:true:true:true:table:0:false:missing:missing:missing::false|trace:true:true:true:trace:0:false:missing:missing:missing::false|group:true:true:true:group:0:false:missing:missing:missing::false|groupCollapsed:true:true:true:groupCollapsed:0:false:missing:missing:missing::false|groupEnd:true:true:true:groupEnd:0:false:missing:missing:missing::false|clear:true:true:true:clear:0:false:missing:missing:missing::false|count:true:true:true:count:0:false:missing:missing:missing::false|countReset:true:true:true:countReset:0:false:missing:missing:missing::false|assert:true:true:true:assert:0:false:missing:missing:missing::false|profile:true:true:true:profile:0:false:missing:missing:missing::false|profileEnd:true:true:true:profileEnd:0:false:missing:missing:missing::false|time:true:true:true:time:0:false:missing:missing:missing::false|timeLog:true:true:true:timeLog:0:false:missing:missing:missing::false|timeEnd:true:true:true:timeEnd:0:false:missing:missing:missing::false|timeStamp:true:true:true:timeStamp:0:false:missing:missing:missing::false|context:true:true:true:context:1:false:missing:missing:missing::false' || inspectorNetworkRows !== 'requestWillBeSent:true:true:true:requestWillBeSent:1:false:missing:missing:missing::false|responseReceived:true:true:true:responseReceived:1:false:missing:missing:missing::false|loadingFinished:true:true:true:loadingFinished:1:false:missing:missing:missing::false|loadingFailed:true:true:true:loadingFailed:1:false:missing:missing:missing::false|dataSent:true:true:true:dataSent:1:false:missing:missing:missing::false|dataReceived:true:true:true:dataReceived:1:false:missing:missing:missing::false|webSocketCreated:true:true:true:webSocketCreated:1:false:missing:missing:missing::false|webSocketClosed:true:true:true:webSocketClosed:1:false:missing:missing:missing::false|webSocketHandshakeResponseReceived:true:true:true:webSocketHandshakeResponseReceived:1:false:missing:missing:missing::false' || inspectorDomStorageRows !== 'domStorageItemAdded:true:true:true:domStorageItemAdded:1:false:missing:missing:missing::false|domStorageItemRemoved:true:true:true:domStorageItemRemoved:1:false:missing:missing:missing::false|domStorageItemUpdated:true:true:true:domStorageItemUpdated:1:false:missing:missing:missing::false|domStorageItemsCleared:true:true:true:domStorageItemsCleared:1:false:missing:missing:missing::false|registerStorage:true:true:true:registerStorage:1:false:missing:missing:missing::false' || inspectorNetworkResourcesRows !== 'put:true:true:true:put:2:true:false:false:true:constructor:true' || Object.hasOwn(inspector, 'default') || session.post.length !== 3 || !descriptor.enumerable || postPrototypeMeta !== 'true:false:false:true:constructor:true' || !(constructedPost instanceof Promise) || constructedPostError?.code !== 'ERR_INVALID_ARG_TYPE' || !constructedPostError?.message.includes('Received function') || typeof session.connect !== 'function' || typeof session.disconnect !== 'function') throw new Error('inspector/promises metadata failed'); const notConnected = await session.post('Runtime.evaluate', { expression: '1 + 1', returnByValue: true }).catch((error) => error); const invalidDisconnectedCallback = await session.post('Runtime.evaluate', {}, 1).catch((error) => error); session.connect(); let duplicateError; try { session.connect(); } catch (error) { duplicateError = error; } const invalidConnectedCallback = await session.post('Runtime.evaluate', {}, 1).catch((error) => error); const result = await session.post('Runtime.evaluate', { expression: '1 + 2', returnByValue: true }); const profilerStart = await session.post('Profiler.start', {}); const profilerStop = await session.post('Profiler.stop', {}); const commandError = await session.post('Runtime.nope', {}).catch((error) => error); const invalidError = await session.post('Runtime.evaluate', () => {}).catch((error) => error); session.disconnect(); if (notConnected?.code !== 'ERR_INSPECTOR_NOT_CONNECTED' || invalidDisconnectedCallback?.code !== 'ERR_INVALID_ARG_TYPE' || invalidConnectedCallback?.code !== 'ERR_INVALID_ARG_TYPE' || duplicateError?.code !== 'ERR_INSPECTOR_ALREADY_CONNECTED' || result.result.value !== 3 || Object.keys(profilerStart).length !== 0 || !Array.isArray(profilerStop.profile?.nodes) || typeof profilerStop.profile?.startTime !== 'number' || profilerStop.profile?.nodes?.[0]?.callFrame?.functionName !== '(root)' || commandError?.code !== 'ERR_INSPECTOR_COMMAND' || invalidError?.code !== 'ERR_INVALID_ARG_TYPE' || disconnectEvents !== 0) throw new Error('inspector/promises behavior failed')" }, { "specifier": "node:test", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Basic in-process test callbacks, describe/it suites, lifecycle hooks, active getTestContext tracking, mocks, mock methods/properties/accessors, per-test t.assert helpers including native-shaped snapshot/fileSnapshot metadata with Node-shaped invalid-state errors, root assert/snapshot null-prototype helper metadata and validation probes, native-shaped mock tracker/timer prototype metadata including root own-property order and no-own-prototype mock method/getter descriptors, MockFunctionContext descriptors, call snapshot accessors, indexed mockImplementationOnce behavior, past onCall validation, undefined function mock implementation mutator returns, mock { times } validation, function implementation restoration, and method/getter/setter auto-restore, MockPropertyContext descriptors, access snapshot accessors, indexed property mockImplementationOnce behavior and primitive onAccess validation, virtual Date/timer advancement, test.run() TestsStream Readable metadata/event emission, native-shaped CommonJS export order/function metadata, root accessor descriptors without own getter prototypes, and Node-shaped node:test/reporters adapters with native-shaped CommonJS export order/descriptors plus native-named async-iterable spec/lcov transforms are available; process isolation parity and real snapshot file generation/update semantics are not complete.", "probe": "const test = require('node:test'); const keys = 'expectFailure,skip,todo,only,after,afterEach,before,beforeEach,describe,getTestContext,it,run,suite,test,mock,snapshot,assert'; const rootOwnNames = Object.getOwnPropertyNames(test).join(','); const rootAccessorMeta = ['mock','snapshot','assert'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(test, name); return [name, descriptor.get.name, descriptor.get.length, Object.hasOwn(descriptor.get, 'prototype'), descriptor.enumerable, descriptor.configurable, typeof descriptor.set].join(':') }).join('|'); const rootHelperValueMeta = (object, name) => { const descriptor = Object.getOwnPropertyDescriptor(object, name); return [name, descriptor.value.name, descriptor.value.length, descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.hasOwn(descriptor.value, 'prototype')].join(':') }; const rootHelperValidation = (label, action) => { try { action(); return label + ':ok'; } catch (error) { return [label, error.name, error.code, error.message].join(':'); } }; const rootHelperMeta = [Object.getPrototypeOf(test.snapshot) === null, Object.getPrototypeOf(test.assert) === null, ['setDefaultSnapshotSerializers','setResolveSnapshotPath'].map((name) => rootHelperValueMeta(test.snapshot, name)).join('|'), rootHelperValueMeta(test.assert, 'register'), [rootHelperValidation('serializers-number', () => test.snapshot.setDefaultSnapshotSerializers(1)), rootHelperValidation('serializers-array-number', () => test.snapshot.setDefaultSnapshotSerializers([1])), rootHelperValidation('resolve-number', () => test.snapshot.setResolveSnapshotPath(1)), rootHelperValidation('assert-name-number', () => test.assert.register(1, () => {})), rootHelperValidation('assert-fn-number', () => test.assert.register('x', 1))].join('|')].join(';'); const stream = require('node:stream'); const runResult = test.run(); const runPrototype = Object.getPrototypeOf(runResult); const runPrototypeMethods = Object.getOwnPropertyNames(runPrototype).filter((name) => name !== 'constructor'); const runPrototypeMeta = runPrototypeMethods.map((name) => { const descriptor = Object.getOwnPropertyDescriptor(runPrototype, name); return [name, descriptor.value.name, descriptor.value.length, descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.hasOwn(descriptor.value, 'prototype')].join(':'); }).join('|'); const runStreamMethods = ['on','once','off','pipe','destroy','compose','map','filter'].map((name) => typeof runResult[name]).join(','); const runEmittedEvents = []; for (const type of ['test:diagnostic','test:plan','test:interrupted']) runResult.on(type, (data) => runEmittedEvents.push(type + ':' + (data.message ?? data.count ?? data.reason))); const runEvents = []; runResult.diagnostic(0, 'hello', 1); runResult.plan(0, 2, 1); runResult.interrupted('stop'); runResult.end(); for await (const event of runResult) runEvents.push(event.type + ':' + (event.data.message ?? event.data.count ?? event.data.reason)); if (Object.keys(test).join(',') !== keys || Object.hasOwn(test, 'default') || Object.hasOwn(test, 'prototype') || test.name !== 'test' || test.length !== 3 || Object.keys(test.describe).join(',') !== 'expectFailure,skip,todo,only' || test.describe.name !== 'test' || test.describe.length !== 3 || test.it !== test.test || test.describe !== test.suite || test.getTestContext.name !== 'getTestContext' || test.getTestContext.length !== 0 || !Object.hasOwn(test.getTestContext, 'prototype') || test.run.name !== 'run' || test.run.length !== 0 || runResult.constructor.name !== 'TestsStream' || !(runResult instanceof stream.Readable) || runResult.readableObjectMode !== true || runResult.readableHighWaterMark !== Number.MAX_SAFE_INTEGER || Object.getOwnPropertyNames(runPrototype).join(',') !== 'constructor,_read,fail,ok,complete,plan,getSkip,getTodo,getXFail,enqueue,dequeue,start,diagnostic,coverage,summary,interrupted,end' || Object.keys(runPrototype).join(',') !== '' || runStreamMethods !== 'function,function,function,function,function,function,function,function' || runPrototypeMeta !== '_read:_read:0:false:true:true:false|fail:fail:9:false:true:true:false|ok:ok:9:false:true:true:false|complete:complete:9:false:true:true:false|plan:plan:3:false:true:true:false|getSkip:getSkip:0:false:true:true:false|getTodo:getTodo:0:false:true:true:false|getXFail:getXFail:0:false:true:true:false|enqueue:enqueue:7:false:true:true:false|dequeue:dequeue:7:false:true:true:false|start:start:6:false:true:true:false|diagnostic:diagnostic:3:false:true:true:false|coverage:coverage:3:false:true:true:false|summary:summary:5:false:true:true:false|interrupted:interrupted:1:false:true:true:false|end:end:0:false:true:true:false' || runEmittedEvents.join('|') !== 'test:diagnostic:hello|test:plan:2|test:interrupted:stop' || runEvents.join('|') !== 'test:diagnostic:hello|test:plan:2|test:interrupted:stop' || rootAccessorMeta !== 'mock:get:0:false:true:true:undefined|snapshot:get:0:false:true:true:undefined|assert:get:0:false:true:true:undefined' || rootOwnNames !== 'length,name,expectFailure,skip,todo,only,after,afterEach,before,beforeEach,describe,getTestContext,it,run,suite,test,mock,snapshot,assert' || rootHelperMeta !== \"true;true;setDefaultSnapshotSerializers:setDefaultSnapshotSerializers:1:true:true:true:true|setResolveSnapshotPath:setResolveSnapshotPath:1:true:true:true:true;register:register:2:true:true:true:true;serializers-number:TypeError:ERR_INVALID_ARG_TYPE:The \\\"serializers\\\" argument must be an instance of Array. Received type number (1)|serializers-array-number:TypeError:ERR_INVALID_ARG_TYPE:The \\\"serializers[0]\\\" argument must be of type function. Received type number (1)|resolve-number:TypeError:ERR_INVALID_ARG_TYPE:The \\\"fn\\\" argument must be of type function. Received type number (1)|assert-name-number:TypeError:ERR_INVALID_ARG_TYPE:The \\\"name\\\" argument must be of type string. Received type number (1)|assert-fn-number:TypeError:ERR_INVALID_ARG_TYPE:The \\\"fn\\\" argument must be of type function. Received type number (1)\" || Object.keys(test.assert).join(',') !== 'register' || Object.keys(test.snapshot).join(',') !== 'setDefaultSnapshotSerializers,setResolveSnapshotPath') throw new Error('test failed'); if (test.getTestContext() !== undefined) throw new Error('test getTestContext outside failed'); await test('context', async (t) => { if (test.getTestContext() !== t || test.getTestContext().name !== 'context') throw new Error('test getTestContext active failed'); await t.test('child context', (child) => { if (test.getTestContext() !== child || test.getTestContext().name !== 'child context') throw new Error('test getTestContext child failed') }); if (test.getTestContext() !== t) throw new Error('test getTestContext restore failed'); }); await test('snapshot assertions', (t) => { const assertKeys = 'deepEqual,deepStrictEqual,doesNotMatch,doesNotReject,doesNotThrow,equal,fail,ifError,match,notDeepEqual,notDeepStrictEqual,notEqual,notStrictEqual,partialDeepStrictEqual,rejects,strictEqual,throws,snapshot,fileSnapshot,ok'; const describeAssert = (name) => { const descriptor = Object.getOwnPropertyDescriptor(t.assert, name); return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype')].join(':'); }; const selectedAssertMeta = ['deepEqual','snapshot','fileSnapshot','ok'].map(describeAssert).join('|'); const snapshotErrors = [['snapshot', () => t.assert.snapshot('value')], ['fileSnapshot', () => t.assert.fileSnapshot('value', 'snapshot.txt')], ['fileSnapshotMissingPath', () => t.assert.fileSnapshot('value')]].map(([label, action]) => { try { action(); return label + ':ok'; } catch (error) { return [label, error.name, error.code, error.message].join(':'); } }).join('|'); if (Object.getPrototypeOf(t.assert) !== null || Object.keys(t.assert).join(',') !== assertKeys || selectedAssertMeta !== 'deepEqual:true:true:true::0:false|snapshot:true:true:true::0:false|fileSnapshot:true:true:true::0:false|ok:true:true:true:ok:0:true' || snapshotErrors !== 'snapshot:Error:ERR_INVALID_STATE:Invalid state: Invalid snapshot filename.|fileSnapshot:Error:ERR_INVALID_STATE:Invalid state: Cannot read snapshot file \\'snapshot.txt.\\' Missing snapshots can be generated by rerunning the command with the --test-update-snapshots flag.|fileSnapshotMissingPath:TypeError:ERR_INVALID_ARG_TYPE:The \"path\" argument must be of type string. Received undefined') throw new Error('test context assert failed'); }); const desc = (object, name) => { const descriptor = Object.getOwnPropertyDescriptor(object, name); if ('value' in descriptor) return [name, descriptor.value.name, descriptor.value.length, descriptor.enumerable, descriptor.configurable, descriptor.writable].join(':'); return [name, descriptor.get?.name, descriptor.enumerable, descriptor.configurable, typeof descriptor.set].join(':'); }; const mockFn = test.mock.fn(function original(a, b) { return a + b; }); mockFn.call({ ctx: true }, 1, 2); const mockFnPrototype = Object.getPrototypeOf(mockFn.mock); const mockFnCall = mockFn.mock.calls[0]; const mockFnCallsSnapshot = mockFn.mock.calls; mockFn.mock.resetCalls(); const mockFnContextMeta = [JSON.stringify(Object.keys(mockFn.mock)), JSON.stringify(Object.getOwnPropertyNames(mockFn.mock)), mockFnPrototype.constructor.name, Object.getOwnPropertyNames(mockFnPrototype).join(',')].join(':'); const mockFnDescriptorMeta = ['calls','callCount','mockImplementation','mockImplementationOnce','restore','resetCalls'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(mockFnPrototype, name); if ('value' in descriptor) return [name, descriptor.value.name, descriptor.value.length, descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.hasOwn(descriptor.value, 'prototype')].join(':'); return [name, descriptor.get.name, descriptor.get.length, typeof descriptor.set, descriptor.enumerable, descriptor.configurable].join(':'); }).join('|'); const mockFnCallMeta = [Object.keys(mockFnCall).join(','), Object.getOwnPropertyNames(mockFnCall).join(','), JSON.stringify(mockFnCall.arguments), mockFnCall.result, mockFnCall.error, typeof mockFnCall.stack, mockFnCall.target, mockFnCallsSnapshot.length, mockFn.mock.callCount(), mockFnCallsSnapshot === mockFn.mock.calls].join(':'); const indexedMock = test.mock.fn(() => 'base'); indexedMock.mock.mockImplementationOnce(() => 'two', 2); indexedMock.mock.mockImplementationOnce(() => 'zero'); indexedMock.mock.mockImplementationOnce(() => 'override-zero'); const indexedMockRows = [indexedMock(), indexedMock(), indexedMock(), indexedMock()].join(','); const propertyTarget = { value: 1 }; const propertyMock = test.mock.property(propertyTarget, 'value', 2); propertyTarget.value; propertyMock.value = 4; propertyMock.mock.mockImplementationOnce(5); propertyTarget.value; propertyTarget.value; propertyMock.mock.mockImplementation(6); propertyTarget.value; const propertyMockPrototype = Object.getPrototypeOf(propertyMock.mock); const propertyFirstAccess = propertyMock.mock.accesses[0]; const propertyAccessSnapshot = propertyMock.mock.accesses; propertyMock.mock.resetAccesses(); propertyMock.mock.mockImplementationOnce(7, 1); propertyMock.mock.mockImplementationOnce(8); propertyMock.mock.mockImplementationOnce(9); const propertyIndexedRows = [propertyTarget.value, propertyTarget.value, propertyTarget.value].join(','); const invalidPropertyOnAccessMessages = [['string','2'], ['bigint',1n], ['symbol',Symbol('x')], ['boolean',true]].map(([label, onAccess]) => { try { propertyMock.mock.mockImplementationOnce(1, onAccess); return label + ':ok'; } catch (error) { return label + ':' + error.message; } }).join('|'); const propertyMockContextMeta = [JSON.stringify(Object.keys(propertyMock.mock)), JSON.stringify(Object.getOwnPropertyNames(propertyMock.mock)), propertyMockPrototype.constructor.name, Object.getOwnPropertyNames(propertyMockPrototype).join(','), Object.keys(propertyMock).join(','), Object.getOwnPropertyNames(propertyMock).join(','), 'mock' in propertyMock, Object.hasOwn(propertyMock, 'mock')].join(':'); const propertyMockDescriptorMeta = ['accesses','accessCount','mockImplementation','mockImplementationOnce','resetAccesses','restore'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(propertyMockPrototype, name); if ('value' in descriptor) return [name, descriptor.value.name, descriptor.value.length, descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.hasOwn(descriptor.value, 'prototype')].join(':'); return [name, descriptor.get.name, descriptor.get.length, typeof descriptor.set, descriptor.enumerable, descriptor.configurable].join(':'); }).join('|'); const propertyMockAccessMeta = [Object.keys(propertyFirstAccess).join(','), Object.getOwnPropertyNames(propertyFirstAccess).join(','), propertyFirstAccess.type, propertyFirstAccess.value, typeof propertyFirstAccess.stack, propertyAccessSnapshot.length, propertyMock.mock.accessCount(), propertyAccessSnapshot === propertyMock.mock.accesses].join(':'); const mockPrototype = Object.getPrototypeOf(test.mock); const timerPrototype = Object.getPrototypeOf(test.mock.timers); const mockMethodMeta = ['timers','fn','method','getter','setter','property','reset','restoreAll'].map((name) => desc(mockPrototype, name)).join('|'); const mockMethodPrototypeMeta = ['timers','fn','method','getter','setter','property','reset','restoreAll'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(mockPrototype, name); const fn = descriptor.value ?? descriptor.get; return name + ':' + Object.hasOwn(fn, 'prototype'); }).join('|'); const mockConstructorMeta = desc(mockPrototype, 'constructor'); const timerConstructorMeta = desc(timerPrototype, 'constructor'); const timerMethodMeta = ['enable','reset','tick','runAll','setTime'].map((name) => desc(timerPrototype, name)).join('|'); if (rootAccessorMeta !== 'mock:get:0:false:true:true:undefined|snapshot:get:0:false:true:true:undefined|assert:get:0:false:true:true:undefined' || Object.getOwnPropertyNames(test.mock).join(',') !== '' || Object.getOwnPropertyNames(mockPrototype).join(',') !== 'constructor,timers,fn,method,getter,setter,property,reset,restoreAll' || mockConstructorMeta !== 'constructor:MockTracker:0:false:true:true' || mockMethodMeta !== 'timers:get timers:false:true:undefined|fn:fn:0:false:true:true|method:method:2:false:true:true|getter:getter:2:false:true:true|setter:setter:2:false:true:true|property:property:3:false:true:true|reset:reset:0:false:true:true|restoreAll:restoreAll:0:false:true:true' || mockMethodPrototypeMeta !== 'timers:false|fn:false|method:false|getter:false|setter:false|property:false|reset:false|restoreAll:false' || timerConstructorMeta !== 'constructor:MockTimers:0:false:true:true' || mockFnContextMeta !== '[]:[]:MockFunctionContext:constructor,calls,callCount,mockImplementation,mockImplementationOnce,restore,resetCalls' || mockFnDescriptorMeta !== 'calls:get calls:0:undefined:false:true|callCount:callCount:0:false:true:true:false|mockImplementation:mockImplementation:1:false:true:true:false|mockImplementationOnce:mockImplementationOnce:2:false:true:true:false|restore:restore:0:false:true:true:false|resetCalls:resetCalls:0:false:true:true:false' || mockFnCallMeta !== 'arguments,error,result,stack,target,this:arguments,error,result,stack,target,this:[1,2]:3::object::1:0:false' || indexedMockRows !== 'override-zero,base,two,base' || propertyMockContextMeta !== '[]:[]:MockPropertyContext:constructor,accesses,accessCount,mockImplementation,mockImplementationOnce,resetAccesses,restore:value:value:false:false' || propertyMockDescriptorMeta !== 'accesses:get accesses:0:undefined:false:true|accessCount:accessCount:0:false:true:true:false|mockImplementation:mockImplementation:1:false:true:true:false|mockImplementationOnce:mockImplementationOnce:2:false:true:true:false|resetAccesses:resetAccesses:0:false:true:true:false|restore:restore:0:false:true:true:false' || propertyMockAccessMeta !== 'type,value,stack:type,value,stack:get:2:object:6:3:false' || propertyIndexedRows !== '9,7,6' || invalidPropertyOnAccessMessages !== 'string:The \"onAccess\" argument must be of type number. Received type string (\\'2\\')|bigint:The \"onAccess\" argument must be of type number. Received type bigint (1n)|symbol:The \"onAccess\" argument must be of type number. Received type symbol (Symbol(x))|boolean:The \"onAccess\" argument must be of type number. Received type boolean (true)' || Object.getOwnPropertyNames(test.mock.timers).join(',') !== '' || Object.getOwnPropertyNames(timerPrototype).join(',') !== 'constructor,enable,reset,tick,runAll,setTime' || timerMethodMeta !== 'enable:enable:0:false:true:true|reset:reset:0:false:true:true|tick:tick:0:false:true:true|runAll:runAll:0:false:true:true|setTime:setTime:0:false:true:true') throw new Error('test mock metadata failed')" }, { "specifier": "node:test/reporters", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Common reporter adapters expose Node v26.3.0-shaped CommonJS export keys, descriptors, native-named async-iterable spec/lcov transform instances, native-shaped SpecReporter/LcovReporter prototype ownership for _transform/_flush, basic stream state metadata, and basic event output; deeper native test-runner reporter semantics remain tied to the partial node:test implementation.", "probe": "const reporters = require('node:test/reporters'); const keys = 'dot,junit,spec,tap,lcov'; const descriptorSummary = ['dot','junit','spec','tap','lcov'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(reporters, name); const callable = descriptor.get ?? descriptor.value; return [name, descriptor.get ? 'accessor' : 'value', typeof callable, descriptor.writable === false ? 'readonly' : 'n/a', descriptor.enumerable, descriptor.configurable].join(':'); }).join('|'); const streamSummary = (stream) => [stream.constructor.name, typeof stream.on, typeof stream[Symbol.asyncIterator], stream.readableObjectMode, stream.writableObjectMode, stream._readableState?.objectMode, stream._writableState?.objectMode].join(':'); const reporterPrototypeSummary = (stream) => { const prototype = Object.getPrototypeOf(stream); return [Object.getOwnPropertyNames(prototype).join(','), Object.keys(prototype).join(',') || '', Object.getOwnPropertyNames(prototype).map((name) => { const descriptor = Object.getOwnPropertyDescriptor(prototype, name); return [name, descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype')].join(':'); }).join('|')].join(';'); }; const spec = reporters.spec(); const lcov = reporters.lcov(); const prototypeRows = reporterPrototypeSummary(spec) + '||' + reporterPrototypeSummary(lcov); const ownTransformRows = [Object.hasOwn(spec, '_transform'), Object.hasOwn(spec, '_flush'), Object.hasOwn(lcov, '_transform'), Object.hasOwn(lcov, '_flush')].join(':'); if (Object.keys(reporters).join(',') !== keys || Object.hasOwn(reporters, 'default') || descriptorSummary !== 'dot:accessor:function:n/a:true:true|junit:accessor:function:n/a:true:true|spec:value:function:readonly:true:true|tap:accessor:function:n/a:true:true|lcov:value:function:readonly:true:true' || streamSummary(spec) !== 'SpecReporter:function:function:false:true:false:true' || streamSummary(lcov) !== 'LcovReporter:function:function:false:true:false:true' || prototypeRows !== 'constructor,_transform,_flush;;constructor:false:true:true:SpecReporter:0:true|_transform:false:true:true:_transform:3:false|_flush:false:true:true:_flush:1:false||constructor,_transform;;constructor:false:true:true:LcovReporter:1:true|_transform:false:true:true:_transform:3:false' || ownTransformRows !== 'false:false:false:false') throw new Error('test/reporters metadata failed')" }, { "specifier": "node:repl", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "REPLServer, start, writer, syntax helpers, Recoverable constructor with native-shaped own-property metadata, Node-shaped CommonJS export order/helper metadata, writer.options defaults, legacy positional start/REPLServer arguments, replMode/breakEvalOnSigint option state and eval-config validation, runtime-global useGlobal contexts, including helper own-prototype metadata, native-shaped REPLServer prototype metadata, Node-shaped builtin module accessors without getter/setter own prototypes and with native REPL builtin list filtering, prompt/control helpers, recoverable multiline input buffering, context reset, basic completion, built-in dot commands, command registration, history callbacks, terminal-aware history recording, and simple input evaluation exist; full terminal integration is host-owned.", "probe": "const repl = require('node:repl'); const builtinDescriptor = Object.getOwnPropertyDescriptor(repl, 'builtinModules'); const libsDescriptor = Object.getOwnPropertyDescriptor(repl, '_builtinLibs'); const output = []; const server = repl.start({ prompt: 'oc> ', output: { write: chunk => output.push(String(chunk)) } }); server.close(); const recoverable = new repl.Recoverable(new SyntaxError('Unexpected end of input')); const recoverableNames = Object.getOwnPropertyNames(recoverable).filter((name) => name !== 'stack').join(','); const ownNames = Object.getOwnPropertyNames(repl).join(','); const accessorMeta = ['builtinModules','_builtinLibs'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(repl, name); return [name, descriptor.enumerable, descriptor.configurable, descriptor.get.name, descriptor.get.length, descriptor.set.name, descriptor.set.length, Object.hasOwn(descriptor.get, 'prototype'), Object.hasOwn(descriptor.set, 'prototype')].join(':'); }).join('|'); const helperMeta = ['writer','isValidSyntax','start','REPLServer','Recoverable'].map((name) => name + ':' + repl[name].name + ':' + repl[name].length + ':' + Object.hasOwn(repl[name], 'prototype')).join('|'); const writerOptionsDescriptor = Object.getOwnPropertyDescriptor(repl.writer, 'options'); const writerOptionsRows = [writerOptionsDescriptor.enumerable, writerOptionsDescriptor.configurable, writerOptionsDescriptor.writable, Object.getPrototypeOf(repl.writer.options) === Object.prototype, Object.isExtensible(repl.writer.options), Object.keys(repl.writer.options).join(','), JSON.stringify(repl.writer.options)].join('|'); const writerColors = repl.writer.options.colors; repl.writer.options.colors = true; const writerColorRows = JSON.stringify(repl.writer({ a: 1 })); repl.writer.options.colors = writerColors; const expectedReplBuiltinModules = 'assert,assert/strict,async_hooks,buffer,child_process,cluster,console,constants,crypto,dgram,diagnostics_channel,dns,dns/promises,domain,events,fs,fs/promises,http,http2,https,inspector,inspector/promises,module,net,os,path,path/posix,path/win32,perf_hooks,process,punycode,querystring,readline,readline/promises,repl,stream,stream/consumers,stream/promises,stream/web,string_decoder,sys,timers,timers/promises,tls,trace_events,tty,url,util,util/types,v8,vm,wasi,worker_threads,zlib'; const replBuiltinRows = [repl.builtinModules.join(',') === expectedReplBuiltinModules, repl.builtinModules.length, repl.builtinModules[0], repl.builtinModules.at(-1), repl.builtinModules.includes('_http_agent'), repl.builtinModules.includes('node:test'), repl.builtinModules.includes('node:sqlite')].join(':'); const prototypeNames = Object.getOwnPropertyNames(repl.REPLServer.prototype).join(','); const prototypeKeys = Object.keys(repl.REPLServer.prototype).join(','); const desc = (name) => { const descriptor = Object.getOwnPropertyDescriptor(repl.REPLServer.prototype, name); return [name, descriptor.value.name, descriptor.value.length, descriptor.enumerable, descriptor.configurable, descriptor.writable].join(':'); }; const prototypeMeta = Object.getOwnPropertyNames(repl.REPLServer.prototype).map(desc).join('|'); const { EventEmitter } = require('node:events'); const makeReplStream = () => { const stream = new EventEmitter(); stream.output = ''; stream.write = (chunk) => { stream.output += String(chunk); return true; }; stream.resume = () => {}; stream.pause = () => {}; stream.setRawMode = () => {}; stream.isTTY = false; return stream; }; const legacyEval = (code, context, filename, callback) => callback(null, undefined); const positionalStream = makeReplStream(); const positionalServer = repl.start('p> ', positionalStream, legacyEval, false, true, repl.REPL_MODE_STRICT); const constructedStream = makeReplStream(); const constructedServer = new repl.REPLServer('c> ', constructedStream, legacyEval, false, true, repl.REPL_MODE_STRICT); const optionsInput = makeReplStream(); const optionsOutput = makeReplStream(); const optionServer = repl.start({ prompt: 'o> ', input: optionsInput, output: optionsOutput, terminal: false, useGlobal: true, ignoreUndefined: true, replMode: repl.REPL_MODE_STRICT, breakEvalOnSigint: true }); const defaultInput = makeReplStream(); const defaultOutput = makeReplStream(); const defaultServer = repl.start({ input: defaultInput, output: defaultOutput, terminal: false }); const legacyReplRows = [JSON.stringify([positionalServer._prompt, positionalServer._initialPrompt, positionalServer.input === positionalStream, positionalServer.output === positionalStream, positionalServer.ignoreUndefined, positionalServer.useGlobal, positionalServer.replMode === repl.REPL_MODE_STRICT, positionalServer.breakEvalOnSigint, positionalServer.context === globalThis, typeof positionalServer.eval, positionalServer.terminal, positionalStream.output]), JSON.stringify([constructedServer._prompt, constructedServer._initialPrompt, constructedServer.input === constructedStream, constructedServer.output === constructedStream, constructedServer.ignoreUndefined, constructedServer.useGlobal, constructedServer.replMode === repl.REPL_MODE_STRICT, constructedServer.breakEvalOnSigint, constructedServer.context === globalThis, constructedStream.output]), JSON.stringify([optionServer._prompt, optionServer._initialPrompt, optionServer.input === optionsInput, optionServer.output === optionsOutput, optionServer.ignoreUndefined, optionServer.useGlobal, optionServer.replMode === repl.REPL_MODE_STRICT, optionServer.breakEvalOnSigint, optionServer.context === globalThis, optionServer.terminal, optionsOutput.output]), JSON.stringify([defaultServer.replMode === repl.REPL_MODE_SLOPPY, defaultServer.replMode === repl.REPL_MODE_STRICT, defaultServer.breakEvalOnSigint, defaultServer.useGlobal, defaultServer.ignoreUndefined, Object.hasOwn(defaultServer, 'replMode'), Object.hasOwn(defaultServer, 'breakEvalOnSigint'), defaultOutput.output])].join('|'); positionalServer.close(); constructedServer.close(); optionServer.close(); defaultServer.close(); const evalConfigRow = (() => { try { repl.start({ input: makeReplStream(), output: makeReplStream(), breakEvalOnSigint: true, eval: legacyEval }); return 'ok'; } catch (error) { return [error.constructor.name, error.code, error.message].join(':'); } })(); const historyRows = []; for (const terminal of [false, true]) { const input = new EventEmitter(); const replOutput = []; const historyServer = repl.start({ prompt: 'h> ', input, output: { write: chunk => replOutput.push(String(chunk)) }, terminal, useColors: false }); input.emit('data', '1 + 2\\n'); await new Promise((resolve) => setTimeout(resolve, 0)); historyRows.push([terminal, JSON.stringify(historyServer.history), JSON.stringify(historyServer.line), replOutput.join('').includes('3\\nh> ')].join(':')); historyServer.close(); } const runReplInput = async (lines, options = {}) => { const input = makeReplStream(); const replOutput = []; const inputServer = repl.start({ prompt: 'oc> ', input, output: { write: chunk => replOutput.push(String(chunk)) }, terminal: false, ...options }); for (const line of lines) { input.emit('data', line + '\\n'); await new Promise((resolve) => setTimeout(resolve, 0)); } inputServer.close(); return replOutput.join(''); }; const recoverableLog = []; const multilineRows = [JSON.stringify(await runReplInput(['function f() {', 'return 3;', '}', 'f()'])), JSON.stringify(await runReplInput(['({', 'a: 1', '})'])), JSON.stringify(await runReplInput(['1 +', '2'])), JSON.stringify(await runReplInput(['function h() {', '.break', '1 + 1'])), JSON.stringify(await runReplInput(['function h() {', '.clear', '1 + 1'])), JSON.stringify(await runReplInput(['first', 'second'], { eval(code, context, filename, callback) { recoverableLog.push(JSON.stringify(code)); if (recoverableLog.length === 1) { callback(new repl.Recoverable(new SyntaxError('more input'))); return; } callback(null, code.replace(/\\n/g, '|')); } })), JSON.stringify(recoverableLog)].join('|'); const historySummary = historyRows.join('|'); if (Object.keys(repl).join(',') !== 'start,writer,REPLServer,REPL_MODE_SLOPPY,REPL_MODE_STRICT,Recoverable,isValidSyntax' || ownNames !== 'start,writer,REPLServer,REPL_MODE_SLOPPY,REPL_MODE_STRICT,Recoverable,isValidSyntax,builtinModules,_builtinLibs' || accessorMeta !== 'builtinModules:false:true::0::1:false:false|_builtinLibs:false:true::0::1:false:false' || replBuiltinRows !== 'true:54:assert:zlib:false:false:false' || repl._builtinLibs !== repl.builtinModules || Object.hasOwn(repl, 'default') || repl.start.name !== 'start' || repl.start.length !== 6 || repl.REPLServer.name !== 'REPLServer' || repl.REPLServer.length !== 6 || repl.writer.name !== 'writer' || repl.writer.length !== 1 || repl.isValidSyntax.name !== 'isValidSyntax' || repl.isValidSyntax.length !== 1 || repl.Recoverable.length !== 1 || helperMeta !== 'writer:writer:1:false|isValidSyntax:isValidSyntax:1:true|start:start:6:true|REPLServer:REPLServer:6:true|Recoverable:Recoverable:1:true' || writerOptionsRows !== 'true|true|true|true|true|showHidden,depth,colors,customInspect,showProxy,maxArrayLength,maxStringLength,breakLength,compact,sorted,getters,numericSeparator|{\"showHidden\":false,\"depth\":2,\"colors\":false,\"customInspect\":true,\"showProxy\":true,\"maxArrayLength\":100,\"maxStringLength\":10000,\"breakLength\":80,\"compact\":3,\"sorted\":false,\"getters\":false,\"numericSeparator\":false}' || writerColorRows !== JSON.stringify('{ a: \\x1b[33m1\\x1b[39m }') || recoverable.name !== 'SyntaxError' || recoverable.message !== '' || Object.hasOwn(recoverable, 'name') || Object.hasOwn(recoverable, 'message') || Object.keys(recoverable).join(',') !== 'err' || recoverableNames !== 'err' || prototypeNames !== 'constructor,setupHistory,clearBufferedCommand,_handleError,close,createContext,resetContext,displayPrompt,setPrompt,complete,completeOnEditorMode,defineCommand' || prototypeKeys !== '' || prototypeMeta !== 'constructor:REPLServer:6:false:true:true|setupHistory:setupHistory:0:false:true:true|clearBufferedCommand:clearBufferedCommand:0:false:true:true|_handleError:_handleError:1:false:true:true|close:close:0:false:true:true|createContext:createContext:0:false:true:true|resetContext:resetContext:0:false:true:true|displayPrompt:displayPrompt:1:false:true:true|setPrompt:setPrompt:1:false:true:true|complete:complete:0:false:true:true|completeOnEditorMode:completeOnEditorMode:1:false:true:true|defineCommand:defineCommand:2:false:true:true' || Object.hasOwn(server, 'prompt') || typeof server.prompt !== 'function' || builtinDescriptor.enumerable || libsDescriptor.enumerable || typeof builtinDescriptor.get !== 'function' || !output.join('').includes('oc> ') || legacyReplRows !== '[\"p> \",\"p> \",true,true,true,false,true,false,false,\"function\",false,\"p> \"]|[\"c> \",\"c> \",true,true,true,false,true,false,false,\"c> \"]|[\"o> \",\"o> \",true,true,true,true,true,true,true,false,\"o> \"]|[true,false,false,false,false,true,true,\"> \"]' || evalConfigRow !== 'TypeError:ERR_INVALID_REPL_EVAL_CONFIG:Cannot specify both \"breakEvalOnSigint\" and \"eval\" for REPL' || historySummary !== 'false:[]:\"\":true|true:[\"1 + 2\"]:\"\":true' || multilineRows !== '\"oc> | | undefined\\\\noc> 3\\\\noc> \"|\"oc> | | { a: 1 }\\\\noc> \"|\"oc> | 3\\\\noc> \"|\"oc> | oc> 2\\\\noc> \"|\"oc> | Clearing context...\\\\noc> 2\\\\noc> \"|\"oc> | \\'first|second|\\'\\\\noc> \"|[\"\\\\\\\"first\\\\\\\\n\\\\\\\"\",\"\\\\\\\"first\\\\\\\\nsecond\\\\\\\\n\\\\\\\"\"]') throw new Error('repl failed')" }, { "specifier": "node:sea", "targetStatus": "stubbed", "currentStatus": "stubbed", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Single executable application probes are exposed with node:-only builtin metadata, native-shaped CommonJS export order, native accessor names/arities/own-prototype metadata, key and getAsset encoding argument validation with native-shaped received-value wording and coded String(error) output, and isSea() false; asset accessors throw Node's ERR_NOT_IN_SINGLE_EXECUTABLE_APPLICATION because OpenContainers is not packaged as a native SEA binary.", "probe": "const sea = require('node:sea'); const helperMeta = Object.keys(sea).map((key) => key + ':' + sea[key].name + ':' + sea[key].length + ':' + Object.hasOwn(sea[key], 'prototype')).join('|'); const descriptorMeta = Object.keys(sea).map((key) => { const descriptor = Object.getOwnPropertyDescriptor(sea, key); return key + ':' + descriptor.enumerable + ':' + descriptor.configurable + ':' + descriptor.writable }).join('|'); const errorRow = (key, args) => { try { sea[key](...args); return key + ':ok' } catch (error) { return [key, error.code, error.message, String(error)].join(':') } }; const unavailableMessages = [['getAsset', ['missing']], ['getAssetAsBlob', ['missing']], ['getRawAsset', ['missing']], ['getAssetKeys', []]].map(([key, args]) => errorRow(key, args)).join('|'); const validationMessages = [['getAsset', []], ['getAsset', [1]], ['getAsset', [Symbol('x')]], ['getAsset', [true]], ['getAsset', [1n]], ['getAsset', ['missing', 1]], ['getAsset', ['missing', null]], ['getAsset', ['missing', Symbol('x')]], ['getAssetAsBlob', []], ['getAssetAsBlob', [Symbol('x')]], ['getRawAsset', []], ['getRawAsset', [Symbol('x')]]].map(([key, args]) => errorRow(key, args)).join('|'); const expectedUnavailable = 'getAsset:ERR_NOT_IN_SINGLE_EXECUTABLE_APPLICATION:Operation cannot be invoked when not in a single-executable application:Error [ERR_NOT_IN_SINGLE_EXECUTABLE_APPLICATION]: Operation cannot be invoked when not in a single-executable application|getAssetAsBlob:ERR_NOT_IN_SINGLE_EXECUTABLE_APPLICATION:Operation cannot be invoked when not in a single-executable application:Error [ERR_NOT_IN_SINGLE_EXECUTABLE_APPLICATION]: Operation cannot be invoked when not in a single-executable application|getRawAsset:ERR_NOT_IN_SINGLE_EXECUTABLE_APPLICATION:Operation cannot be invoked when not in a single-executable application:Error [ERR_NOT_IN_SINGLE_EXECUTABLE_APPLICATION]: Operation cannot be invoked when not in a single-executable application|getAssetKeys:ERR_NOT_IN_SINGLE_EXECUTABLE_APPLICATION:Operation cannot be invoked when not in a single-executable application:Error [ERR_NOT_IN_SINGLE_EXECUTABLE_APPLICATION]: Operation cannot be invoked when not in a single-executable application'; const expectedValidation = 'getAsset:ERR_INVALID_ARG_TYPE:The \"key\" argument must be of type string. Received undefined:TypeError [ERR_INVALID_ARG_TYPE]: The \"key\" argument must be of type string. Received undefined|getAsset:ERR_INVALID_ARG_TYPE:The \"key\" argument must be of type string. Received type number (1):TypeError [ERR_INVALID_ARG_TYPE]: The \"key\" argument must be of type string. Received type number (1)|getAsset:ERR_INVALID_ARG_TYPE:The \"key\" argument must be of type string. Received type symbol (Symbol(x)):TypeError [ERR_INVALID_ARG_TYPE]: The \"key\" argument must be of type string. Received type symbol (Symbol(x))|getAsset:ERR_INVALID_ARG_TYPE:The \"key\" argument must be of type string. Received type boolean (true):TypeError [ERR_INVALID_ARG_TYPE]: The \"key\" argument must be of type string. Received type boolean (true)|getAsset:ERR_INVALID_ARG_TYPE:The \"key\" argument must be of type string. Received type bigint (1n):TypeError [ERR_INVALID_ARG_TYPE]: The \"key\" argument must be of type string. Received type bigint (1n)|getAsset:ERR_INVALID_ARG_TYPE:The \"encoding\" argument must be of type string. Received type number (1):TypeError [ERR_INVALID_ARG_TYPE]: The \"encoding\" argument must be of type string. Received type number (1)|getAsset:ERR_INVALID_ARG_TYPE:The \"encoding\" argument must be of type string. Received null:TypeError [ERR_INVALID_ARG_TYPE]: The \"encoding\" argument must be of type string. Received null|getAsset:ERR_INVALID_ARG_TYPE:The \"encoding\" argument must be of type string. Received type symbol (Symbol(x)):TypeError [ERR_INVALID_ARG_TYPE]: The \"encoding\" argument must be of type string. Received type symbol (Symbol(x))|getAssetAsBlob:ERR_INVALID_ARG_TYPE:The \"key\" argument must be of type string. Received undefined:TypeError [ERR_INVALID_ARG_TYPE]: The \"key\" argument must be of type string. Received undefined|getAssetAsBlob:ERR_INVALID_ARG_TYPE:The \"key\" argument must be of type string. Received type symbol (Symbol(x)):TypeError [ERR_INVALID_ARG_TYPE]: The \"key\" argument must be of type string. Received type symbol (Symbol(x))|getRawAsset:ERR_INVALID_ARG_TYPE:The \"key\" argument must be of type string. Received undefined:TypeError [ERR_INVALID_ARG_TYPE]: The \"key\" argument must be of type string. Received undefined|getRawAsset:ERR_INVALID_ARG_TYPE:The \"key\" argument must be of type string. Received type symbol (Symbol(x)):TypeError [ERR_INVALID_ARG_TYPE]: The \"key\" argument must be of type string. Received type symbol (Symbol(x))'; if (Object.keys(sea).join(',') !== 'isSea,getAsset,getRawAsset,getAssetAsBlob,getAssetKeys' || sea.isSea() !== false || helperMeta !== 'isSea:isSea:0:false|getAsset:getAsset:2:true|getRawAsset:getRawAsset:1:true|getAssetAsBlob:getAssetAsBlob:2:true|getAssetKeys:getAssetKeys:0:true' || descriptorMeta !== 'isSea:true:true:true|getAsset:true:true:true|getRawAsset:true:true:true|getAssetAsBlob:true:true:true|getAssetKeys:true:true:true' || unavailableMessages !== expectedUnavailable || validationMessages !== expectedValidation) throw new Error('sea metadata failed');", "unsupported": { "probe": "require('node:sea').getAsset('missing')", "code": "ERR_NOT_IN_SINGLE_EXECUTABLE_APPLICATION" } }, { "specifier": "node:sqlite", "targetStatus": "stubbed", "currentStatus": "stubbed", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Exports constructible inert DatabaseSync plus non-constructible StatementSync and Session probe handles, backup, native-shaped extensible SQLite conflict/authorizer constants, default-free CommonJS export shape, and Node-shaped export/constant/prototype ordering and metadata including constructor prototype descriptors, no-new and illegal-constructor error codes, DatabaseSync path/options validation, open/close/isOpen state probes, anonymous DatabaseSync accessor metadata, limits metadata, createTagStore with non-exported SQLTagStore accessor/prototype shape, location() state and dbName validation, empty applyChangeset no-op behavior, validation-before-unsupported for SQL/changeset/backup helpers, backup option validation, backup Promise-return parity, backup/prototype-method own-prototype parity, and DatabaseSync/Session Symbol.dispose metadata with DatabaseSync close semantics; database operations, statement/session methods, backups, non-empty changesets, and SQLite execution throw ERR_OPENCONTAINERS_SQLITE_UNSUPPORTED until a WASM-backed adapter exists.", "probe": "const sqlite = require(\"node:sqlite\"); const constantsPrefix = \"SQLITE_CHANGESET_OMIT,SQLITE_CHANGESET_REPLACE,SQLITE_CHANGESET_ABORT,SQLITE_CHANGESET_DATA,SQLITE_CHANGESET_NOTFOUND,SQLITE_CHANGESET_CONFLICT,SQLITE_CHANGESET_CONSTRAINT,SQLITE_CHANGESET_FOREIGN_KEY,SQLITE_OK,SQLITE_DENY,SQLITE_IGNORE\"; const databaseMethods = \"open,close,prepare,exec,function,createTagStore,location,aggregate,createSession,applyChangeset,enableLoadExtension,enableDefensive,loadExtension,serialize,deserialize,setAuthorizer\"; const statementMethods = \"iterate,all,get,run,columns,setAllowBareNamedParameters,setAllowUnknownNamedParameters,setReadBigInts,setReturnArrays\"; const okDescriptor = Object.getOwnPropertyDescriptor(sqlite.constants, \"SQLITE_OK\"); sqlite.constants.__probe = 1; const constantsMetadata = [Object.isExtensible(sqlite.constants), Object.isFrozen(sqlite.constants), Object.getPrototypeOf(sqlite.constants) === Object.prototype, sqlite.constants.__probe, okDescriptor?.enumerable, okDescriptor?.configurable, okDescriptor?.writable, typeof okDescriptor?.value].join(\":\"); delete sqlite.constants.__probe; const constructorPrototypeMetadata = [\"DatabaseSync\",\"StatementSync\",\"Session\"].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(sqlite[name], \"prototype\"); return [name, sqlite[name].name, sqlite[name].length, descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.getOwnPropertyNames(descriptor.value).at(-1)].join(\":\"); }).join(\"|\"); const errorRow = (label, run) => { try { run(); return label + \"|ok\"; } catch (error) { return [label, error.constructor.name, error.name, error.code, error.message, String(error)].join(\"|\"); } }; const database = new sqlite.DatabaseSync(\":memory:\"); const databaseAccessorMetadata = [\"isOpen\",\"isTransaction\",\"limits\"].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(database, name); return [name, descriptor.get.name, descriptor.get.length, typeof descriptor.set, descriptor.enumerable, descriptor.configurable, Object.hasOwn(descriptor.get, \"prototype\")].join(\":\"); }).join(\"|\"); const instanceMetadata = [database instanceof sqlite.DatabaseSync, Object.keys(database).join(\",\"), database.isOpen, database.isTransaction, typeof database.limits, Object.getPrototypeOf(database.limits) === Object.prototype, Object.keys(database.limits).join(\",\"), database.limits.length, database.limits.variableNumber, databaseAccessorMetadata].join(\":\"); const tagStore = database.createTagStore(); const tagStorePrototype = Object.getPrototypeOf(tagStore); const tagStoreMetadata = [tagStore.constructor.name, typeof sqlite.SQLTagStore, Object.keys(tagStore).join(\",\"), Object.getOwnPropertyNames(tagStore).join(\",\"), tagStore.capacity, tagStore.size, tagStore.db === database, Object.getOwnPropertyNames(tagStorePrototype).join(\",\"), Object.keys(tagStorePrototype).join(\",\")].join(\":\"); const tagStoreMethodMetadata = [\"get\",\"all\",\"iterate\",\"run\",\"clear\",\"constructor\"].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(tagStorePrototype, name); return [name, descriptor.value.name, descriptor.value.length, descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.hasOwn(descriptor.value, \"prototype\")].join(\":\"); }).join(\"|\"); const tagStoreAccessorMetadata = [\"capacity\", \"db\", \"size\"].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(tagStore, name); return [name, descriptor.get.name, descriptor.get.length, typeof descriptor.set, descriptor.enumerable, descriptor.configurable].join(\":\"); }).join(\"|\"); const validationRows = [[\"path-undefined\", () => new sqlite.DatabaseSync()], [\"path-null\", () => new sqlite.DatabaseSync(null)], [\"path-nul-buffer\", () => new sqlite.DatabaseSync(new Uint8Array([0]))], [\"path-https-url\", () => new sqlite.DatabaseSync(new URL(\"https://example.com/x\"))], [\"options-undefined\", () => new sqlite.DatabaseSync(\":memory:\", undefined)], [\"options-open-string\", () => new sqlite.DatabaseSync(\":memory:\", { open: \"yes\" })], [\"prepare-missing\", () => database.prepare()], [\"exec-missing\", () => database.exec()], [\"location-number\", () => database.location(1)], [\"apply-missing\", () => database.applyChangeset()], [\"apply-arraybuffer\", () => database.applyChangeset(new ArrayBuffer(0))], [\"apply-options-number\", () => database.applyChangeset(new Uint8Array(), 1)], [\"apply-options-filter-undefined\", () => database.applyChangeset(new Uint8Array(), { filter: undefined })], [\"apply-options-conflict\", () => database.applyChangeset(new Uint8Array(), { onConflict: null })], [\"tag-store-string\", () => tagStore.get(\"select 1\")], [\"backup-missing\", () => sqlite.backup()], [\"backup-path-missing\", () => sqlite.backup(database)], [\"backup-path-url\", () => sqlite.backup(database, new URL(\"https://example.com/x\"))], [\"backup-options-number\", () => sqlite.backup(database, \"backup.db\", 1)], [\"backup-options-rate\", () => sqlite.backup(database, \"backup.db\", { rate: 1.5 })], [\"backup-options-progress\", () => sqlite.backup(database, \"backup.db\", { progress: null })]].map(([label, run]) => errorRow(label, run)).join(\"\\n\"); const expectedValidationRows = [\"path-undefined|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"path\\\" argument must be a string, Uint8Array, or URL without null bytes.|TypeError: The \\\"path\\\" argument must be a string, Uint8Array, or URL without null bytes.\", \"path-null|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"path\\\" argument must be a string, Uint8Array, or URL without null bytes.|TypeError: The \\\"path\\\" argument must be a string, Uint8Array, or URL without null bytes.\", \"path-nul-buffer|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"path\\\" argument must be a string, Uint8Array, or URL without null bytes.|TypeError: The \\\"path\\\" argument must be a string, Uint8Array, or URL without null bytes.\", \"path-https-url|TypeError|TypeError|ERR_INVALID_URL_SCHEME|The URL must be of scheme file:|TypeError: The URL must be of scheme file:\", \"options-undefined|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options\\\" argument must be an object.|TypeError: The \\\"options\\\" argument must be an object.\", \"options-open-string|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options.open\\\" argument must be a boolean.|TypeError: The \\\"options.open\\\" argument must be a boolean.\", \"prepare-missing|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"sql\\\" argument must be a string.|TypeError: The \\\"sql\\\" argument must be a string.\", \"exec-missing|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"sql\\\" argument must be a string.|TypeError: The \\\"sql\\\" argument must be a string.\", \"location-number|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"dbName\\\" argument must be a string.|TypeError: The \\\"dbName\\\" argument must be a string.\", \"apply-missing|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"changeset\\\" argument must be a Uint8Array.|TypeError: The \\\"changeset\\\" argument must be a Uint8Array.\", \"apply-arraybuffer|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"changeset\\\" argument must be a Uint8Array.|TypeError: The \\\"changeset\\\" argument must be a Uint8Array.\", \"apply-options-number|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options\\\" argument must be an object.|TypeError: The \\\"options\\\" argument must be an object.\", \"apply-options-filter-undefined|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options.filter\\\" argument must be a function.|TypeError: The \\\"options.filter\\\" argument must be a function.\", \"apply-options-conflict|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options.onConflict\\\" argument must be a function.|TypeError: The \\\"options.onConflict\\\" argument must be a function.\", \"tag-store-string|TypeError|TypeError|ERR_INVALID_ARG_TYPE|First argument must be an array of strings (template literal).|TypeError: First argument must be an array of strings (template literal).\", \"backup-missing|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"sourceDb\\\" argument must be an object.|TypeError: The \\\"sourceDb\\\" argument must be an object.\", \"backup-path-missing|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"path\\\" argument must be a string, Uint8Array, or URL without null bytes.|TypeError: The \\\"path\\\" argument must be a string, Uint8Array, or URL without null bytes.\", \"backup-path-url|TypeError|TypeError|ERR_INVALID_URL_SCHEME|The URL must be of scheme file:|TypeError: The URL must be of scheme file:\", \"backup-options-number|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options\\\" argument must be an object.|TypeError: The \\\"options\\\" argument must be an object.\", \"backup-options-rate|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options.rate\\\" argument must be an integer.|TypeError: The \\\"options.rate\\\" argument must be an integer.\", \"backup-options-progress|TypeError|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options.progress\\\" argument must be a function.|TypeError: The \\\"options.progress\\\" argument must be a function.\"].join(\"\\n\"); const stateDatabase = new sqlite.DatabaseSync(\":memory:\", { open: false }); const stateRows = [stateDatabase.isOpen, stateDatabase.isTransaction, errorRow(\"limits\", () => stateDatabase.limits), errorRow(\"closed-location\", () => stateDatabase.location()), errorRow(\"closed-apply\", () => stateDatabase.applyChangeset()), errorRow(\"closed-tag-store\", () => stateDatabase.createTagStore())].join(\":\"); stateDatabase.open(); const stateTagStore = stateDatabase.createTagStore(); stateDatabase.close(); const closedTagRows = [errorRow(\"closed-tag\", () => stateTagStore.get([\"select 1\"])), errorRow(\"closed-clear\", () => stateTagStore.clear())].join(\"|\"); const backupPromise = sqlite.backup(new sqlite.DatabaseSync(\":memory:\"), \"backup.db\"); const backupMetadata = [backupPromise.constructor.name, typeof backupPromise.then].join(\":\"); backupPromise.catch(() => {}); const unsupportedRows = [[\"DatabaseSync.prepare\", () => new sqlite.DatabaseSync(\":memory:\").prepare(\"select 1\")], [\"DatabaseSync.exec\", () => new sqlite.DatabaseSync(\":memory:\").exec(\"select 1\")], [\"DatabaseSync.applyChangeset\", () => new sqlite.DatabaseSync(\":memory:\").applyChangeset(new Uint8Array([1]))], [\"SQLTagStore.get\", () => new sqlite.DatabaseSync(\":memory:\").createTagStore().get([\"select 1\"])], [\"SQLTagStore.run\", () => new sqlite.DatabaseSync(\":memory:\").createTagStore().run([\"select 1\"])], [\"Session.changeset\", () => sqlite.Session.prototype.changeset.call({})], [\"StatementSync.run\", () => sqlite.StatementSync.prototype.run.call({})], [\"Session.dispose\", () => sqlite.Session.prototype[Symbol.dispose].call({})]].map(([label, run]) => { try { run(); return label + \":ok\"; } catch (error) { return [label, error.code, error.message].join(\":\"); } }).join(\"|\"); const expectedLimits = \"length,sqlLength,column,exprDepth,compoundSelect,vdbeOp,functionArg,attach,likePatternLength,variableNumber,triggerDepth\"; if (Object.hasOwn(sqlite, \"default\") || Object.keys(sqlite).join(\",\") !== \"DatabaseSync,StatementSync,Session,constants,backup\" || Object.keys(sqlite.constants).slice(0, 11).join(\",\") !== constantsPrefix || constantsMetadata !== \"true:false:true:1:true:false:false:number\" || sqlite.constants.SQLITE_OK !== 0 || sqlite.constants.SQLITE_CHANGESET_ABORT !== 2 || sqlite.constants.SQLITE_RECURSIVE !== 33 || sqlite.backup.name !== \"backup\" || sqlite.backup.length !== 2 || constructorPrototypeMetadata !== \"DatabaseSync:DatabaseSync:0:false:false:true:constructor|StatementSync:StatementSync:0:false:false:true:constructor|Session:Session:0:false:false:true:constructor\" || sqlite.DatabaseSync.length !== 0 || sqlite.StatementSync.length !== 0 || sqlite.Session.length !== 0 || Object.keys(sqlite.DatabaseSync.prototype).join(\",\") !== databaseMethods || Object.keys(sqlite.StatementSync.prototype).join(\",\") !== statementMethods || Object.keys(sqlite.Session.prototype).join(\",\") !== \"changeset,patchset,close\" || Object.getOwnPropertySymbols(sqlite.DatabaseSync.prototype).map(String).join(\",\") !== \"Symbol(Symbol.dispose)\" || Object.getOwnPropertySymbols(sqlite.Session.prototype).map(String).join(\",\") !== \"Symbol(Symbol.dispose)\" || instanceMetadata !== \"true:isOpen,isTransaction,limits:true:false:object:true:\" + expectedLimits + \":1000000000:32766:isOpen::0:undefined:true:false:false|isTransaction::0:undefined:true:false:false|limits::0:undefined:true:false:false\" || tagStoreMetadata !== \"SQLTagStore:undefined:capacity,db,size:capacity,db,size:1000:0:true:get,all,iterate,run,clear,constructor:get,all,iterate,run,clear\" || tagStoreMethodMetadata !== \"get:get:0:true:true:true:false|all:all:0:true:true:true:false|iterate:iterate:0:true:true:true:false|run:run:0:true:true:true:false|clear:clear:0:true:true:true:false|constructor:SQLTagStore:0:false:true:true:true\" || tagStoreAccessorMetadata !== \"capacity::0:undefined:true:false|db::0:undefined:true:false|size::0:undefined:true:false\" || database.location() !== null || database.location(\"main\") !== null || database.location(\"temp\") !== null || database.applyChangeset(new Uint8Array()) !== true || database.applyChangeset(Buffer.alloc(0)) !== true || validationRows !== expectedValidationRows || stateRows !== \"false:false:limits|Error|Error|ERR_INVALID_STATE|database is not open|Error: database is not open:closed-location|Error|Error|ERR_INVALID_STATE|database is not open|Error: database is not open:closed-apply|Error|Error|ERR_INVALID_STATE|database is not open|Error: database is not open:closed-tag-store|Error|Error|ERR_INVALID_STATE|database is not open|Error: database is not open\" || closedTagRows !== \"closed-tag|Error|Error|ERR_INVALID_STATE|database is not open|Error: database is not open|closed-clear|ok\" || backupMetadata !== \"Promise:function\" || unsupportedRows !== \"DatabaseSync.prepare:ERR_OPENCONTAINERS_SQLITE_UNSUPPORTED:node:sqlite DatabaseSync.prepare is not supported in OpenContainers V1|DatabaseSync.exec:ERR_OPENCONTAINERS_SQLITE_UNSUPPORTED:node:sqlite DatabaseSync.exec is not supported in OpenContainers V1|DatabaseSync.applyChangeset:ERR_OPENCONTAINERS_SQLITE_UNSUPPORTED:node:sqlite DatabaseSync.applyChangeset is not supported in OpenContainers V1|SQLTagStore.get:ERR_OPENCONTAINERS_SQLITE_UNSUPPORTED:node:sqlite SQLTagStore.get is not supported in OpenContainers V1|SQLTagStore.run:ERR_OPENCONTAINERS_SQLITE_UNSUPPORTED:node:sqlite SQLTagStore.run is not supported in OpenContainers V1|Session.changeset:ERR_OPENCONTAINERS_SQLITE_UNSUPPORTED:node:sqlite Session.changeset is not supported in OpenContainers V1|StatementSync.run:ERR_OPENCONTAINERS_SQLITE_UNSUPPORTED:node:sqlite StatementSync.run is not supported in OpenContainers V1|Session.dispose:ERR_OPENCONTAINERS_SQLITE_UNSUPPORTED:node:sqlite Session.Symbol(Symbol.dispose) is not supported in OpenContainers V1\") throw new Error(\"sqlite shape failed\");", "unsupported": { "probe": "new (require('node:sqlite').DatabaseSync)(':memory:').applyChangeset(new Uint8Array([1]))", "code": "ERR_OPENCONTAINERS_SQLITE_UNSUPPORTED" } }, { "specifier": "node:trace_events", "targetStatus": "partial", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/process-builtin.test.mjs", "limitation": "Tracing APIs expose Node-shaped CommonJS export shape, constructable createTracing(), Tracing handle prototype metadata including custom inspect and constructor descriptors, option/category validation with native-shaped error messages and bracketed String(error) codes, whitespace-preserving category strings, and ref-counted no-op category controls for package probes; native runtime tracing is unavailable in the browser sandbox.", "probe": "const traceEvents = require('node:trace_events'); const tracing = traceEvents.createTracing({ categories: ['node'] }); const constructed = new traceEvents.createTracing({ categories: ['node.constructed'] }); const createTracingPrototype = Object.getOwnPropertyDescriptor(traceEvents.createTracing, 'prototype'); const createTracingPrototypeMeta = [Object.hasOwn(traceEvents.createTracing, 'prototype'), createTracingPrototype.enumerable, createTracingPrototype.configurable, createTracingPrototype.writable, createTracingPrototype.value.constructor === traceEvents.createTracing, Object.getOwnPropertyNames(createTracingPrototype.value).join(',')].join(':'); const tracePrototype = Object.getPrototypeOf(tracing); const traceSymbolMeta = Object.getOwnPropertySymbols(tracePrototype).map((symbol) => { const descriptor = Object.getOwnPropertyDescriptor(tracePrototype, symbol); return [String(symbol), typeof descriptor.value, descriptor.value?.name ?? '', descriptor.value?.length ?? '', descriptor.enumerable, descriptor.configurable, descriptor.writable, Object.hasOwn(descriptor.value ?? {}, 'prototype')].join(':') }).join('|'); const traceDescriptor = (object, name) => { const descriptor = Object.getOwnPropertyDescriptor(object, name); if ('value' in descriptor && typeof descriptor.value === 'function') return [name, 'value', descriptor.enumerable, descriptor.configurable, descriptor.writable, descriptor.value.name, descriptor.value.length, Object.hasOwn(descriptor.value, 'prototype')].join(':'); if ('value' in descriptor) return [name, 'value', descriptor.enumerable, descriptor.configurable, descriptor.writable, typeof descriptor.value].join(':'); return [name, 'accessor', descriptor.enumerable, descriptor.configurable, typeof descriptor.get, typeof descriptor.set].join(':'); }; const createTracingOwnMeta = ['name','length','prototype'].map((name) => traceDescriptor(traceEvents.createTracing, name)).join('|'); const traceConstructorMeta = traceDescriptor(tracePrototype, 'constructor'); const spaced = traceEvents.createTracing({ categories: [' node ', 'v8 '] }); const whitespace = traceEvents.createTracing({ categories: [' '] }); const sparse = traceEvents.createTracing({ categories: ['', 'node', ''] }); const comma = traceEvents.createTracing({ categories: ['node, v8'] }); const validationRows = [['missing-options', () => traceEvents.createTracing()], ['null-options', () => traceEvents.createTracing(null)], ['boolean-options', () => traceEvents.createTracing(true)], ['string-options', () => traceEvents.createTracing('node')], ['array-options', () => traceEvents.createTracing([])], ['function-options', () => traceEvents.createTracing(Object.assign(function traceOptions() {}, { categories: ['node'] }))], ['empty-options', () => traceEvents.createTracing({})], ['empty-categories', () => traceEvents.createTracing({ categories: [] })], ['string-categories', () => traceEvents.createTracing({ categories: 'node' })], ['number-categories', () => traceEvents.createTracing({ categories: 1 })], ['boolean-category', () => traceEvents.createTracing({ categories: [true] })], ['null-category', () => traceEvents.createTracing({ categories: [null] })], ['object-category', () => traceEvents.createTracing({ categories: [{}] })], ['symbol-category', () => traceEvents.createTracing({ categories: [Symbol('x')] })]].map(([label, action]) => { try { action(); return label + ':ok' } catch (error) { return [label, error.name, error.code, error.message, String(error)].join('|') } }).join('\\n'); const enabledFor = (entry) => { entry.enable(); const value = traceEvents.getEnabledCategories(); entry.disable(); return value; }; if (Object.getOwnPropertyNames(tracePrototype).join(',') !== 'constructor,enable,disable,enabled,categories' || traceSymbolMeta !== 'Symbol(nodejs.util.inspect.custom):function:[nodejs.util.inspect.custom]:2:false:true:true:false' || createTracingOwnMeta !== 'name:value:false:true:false:string|length:value:false:true:false:number|prototype:value:false:false:true:object' || traceConstructorMeta !== 'constructor:value:false:true:true:Tracing:1:true' || createTracingPrototypeMeta !== 'true:false:false:true:true:constructor' || constructed.constructor.name !== 'Tracing' || constructed.categories !== 'node.constructed' || constructed.enabled !== false || tracing.categories !== 'node' || spaced.categories !== ' node ,v8 ' || whitespace.categories !== ' ' || sparse.categories !== ',node,' || comma.categories !== 'node, v8' || validationRows !== \"missing-options|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options\\\" argument must be of type object. Received undefined|TypeError [ERR_INVALID_ARG_TYPE]: The \\\"options\\\" argument must be of type object. Received undefined\\nnull-options|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options\\\" argument must be of type object. Received null|TypeError [ERR_INVALID_ARG_TYPE]: The \\\"options\\\" argument must be of type object. Received null\\nboolean-options|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options\\\" argument must be of type object. Received type boolean (true)|TypeError [ERR_INVALID_ARG_TYPE]: The \\\"options\\\" argument must be of type object. Received type boolean (true)\\nstring-options|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options\\\" argument must be of type object. Received type string ('node')|TypeError [ERR_INVALID_ARG_TYPE]: The \\\"options\\\" argument must be of type object. Received type string ('node')\\narray-options|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options\\\" argument must be of type object. Received an instance of Array|TypeError [ERR_INVALID_ARG_TYPE]: The \\\"options\\\" argument must be of type object. Received an instance of Array\\nfunction-options|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options\\\" argument must be of type object. Received function traceOptions|TypeError [ERR_INVALID_ARG_TYPE]: The \\\"options\\\" argument must be of type object. Received function traceOptions\\nempty-options|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options.categories\\\" property must be an instance of Array. Received undefined|TypeError [ERR_INVALID_ARG_TYPE]: The \\\"options.categories\\\" property must be an instance of Array. Received undefined\\nempty-categories|TypeError|ERR_TRACE_EVENTS_CATEGORY_REQUIRED|At least one category is required|TypeError [ERR_TRACE_EVENTS_CATEGORY_REQUIRED]: At least one category is required\\nstring-categories|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options.categories\\\" property must be an instance of Array. Received type string ('node')|TypeError [ERR_INVALID_ARG_TYPE]: The \\\"options.categories\\\" property must be an instance of Array. Received type string ('node')\\nnumber-categories|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options.categories\\\" property must be an instance of Array. Received type number (1)|TypeError [ERR_INVALID_ARG_TYPE]: The \\\"options.categories\\\" property must be an instance of Array. Received type number (1)\\nboolean-category|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options.categories[0]\\\" property must be of type string. Received type boolean (true)|TypeError [ERR_INVALID_ARG_TYPE]: The \\\"options.categories[0]\\\" property must be of type string. Received type boolean (true)\\nnull-category|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options.categories[0]\\\" property must be of type string. Received null|TypeError [ERR_INVALID_ARG_TYPE]: The \\\"options.categories[0]\\\" property must be of type string. Received null\\nobject-category|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options.categories[0]\\\" property must be of type string. Received an instance of Object|TypeError [ERR_INVALID_ARG_TYPE]: The \\\"options.categories[0]\\\" property must be of type string. Received an instance of Object\\nsymbol-category|TypeError|ERR_INVALID_ARG_TYPE|The \\\"options.categories[0]\\\" property must be of type string. Received type symbol (Symbol(x))|TypeError [ERR_INVALID_ARG_TYPE]: The \\\"options.categories[0]\\\" property must be of type string. Received type symbol (Symbol(x))\" || enabledFor(whitespace) !== ' ' || enabledFor(spaced) !== ' node ,v8 ' || enabledFor(sparse) !== 'node' || enabledFor(comma) !== 'node, v8') throw new Error('trace_events category shape failed'); const overlapA = traceEvents.createTracing({ categories: ['node', 'v8'] }); const overlapB = traceEvents.createTracing({ categories: ['node', 'node.async_hooks'] }); overlapA.enable(); overlapB.enable(); if (!overlapA.enabled || !overlapB.enabled || traceEvents.getEnabledCategories() !== 'node,node.async_hooks,v8') throw new Error('trace_events enable failed'); overlapA.disable(); if (overlapA.enabled || !overlapB.enabled || traceEvents.getEnabledCategories() !== 'node,node.async_hooks') throw new Error('trace_events refcount failed'); overlapB.disable(); if (traceEvents.getEnabledCategories() !== undefined) throw new Error('trace_events disable failed')" }, { "specifier": "node:sys", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Alias to node:util for legacy package probes.", "probe": "if (require('node:sys') !== require('node:util')) throw new Error('sys alias failed')" } ], "globals": [ { "name": "AbortController", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "typeof globalThis.AbortController === 'function' && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'AbortController'); return descriptor?.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('AbortController') === false; })()" }, { "name": "AbortSignal", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "typeof globalThis.AbortSignal === 'function' && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'AbortSignal'); return descriptor?.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('AbortSignal') === false; })()" }, { "name": "Blob", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.Blob === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'Blob'); return descriptor?.value === globalThis.Blob && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('Blob') === false; })()" }, { "name": "Buffer", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Global Buffer exposes a Node-shaped non-enumerable configurable get/set descriptor and remains assignable for package probes.", "probe": "(() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'Buffer'); const original = globalThis.Buffer; try { globalThis.Buffer = 'replacement-buffer'; return descriptor?.enumerable === false && descriptor.configurable === true && !('value' in descriptor) && descriptor.get.name === 'get' && descriptor.get.length === 0 && descriptor.set.name === 'set' && descriptor.set.length === 1 && Object.keys(globalThis).includes('Buffer') === false && Buffer === 'replacement-buffer' && globalThis.Buffer === 'replacement-buffer'; } finally { globalThis.Buffer = original; } })()" }, { "name": "ByteLengthQueuingStrategy", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(new ByteLengthQueuingStrategy({ highWaterMark: 3 }).size(Buffer.from('abc')) === 3) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'ByteLengthQueuingStrategy'); return descriptor?.value === globalThis.ByteLengthQueuingStrategy && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('ByteLengthQueuingStrategy') === false; })()" }, { "name": "CountQueuingStrategy", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(new CountQueuingStrategy({ highWaterMark: 2 }).size({}) === 1) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'CountQueuingStrategy'); return descriptor?.value === globalThis.CountQueuingStrategy && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('CountQueuingStrategy') === false; })()" }, { "name": "__dirname", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "CommonJS module-scoped global.", "probe": "typeof __dirname === 'string'" }, { "name": "__filename", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "CommonJS module-scoped global.", "probe": "typeof __filename === 'string'" }, { "name": "atob", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Base64 helper exposes Node-shaped function metadata.", "probe": "atob.name === 'atob' && atob.length === 1 && (atob(btoa('OpenContainers')) === 'OpenContainers')" }, { "name": "btoa", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Base64 helper exposes Node-shaped function metadata.", "probe": "btoa.name === 'btoa' && btoa.length === 1 && (btoa('OpenContainers') === 'T3BlbkNvbnRhaW5lcnM=')" }, { "name": "Atomics", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Host-provided shared-memory primitive with native-shaped global descriptor; depends on page isolation support. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "((() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'Atomics'); if (!descriptor) return true; if (descriptor.value !== Atomics || descriptor.enumerable !== false || descriptor.configurable !== true || descriptor.writable !== true) return false; if (typeof SharedArrayBuffer !== 'function') return typeof Atomics.load === 'function'; const array = new Int32Array(new SharedArrayBuffer(4)); return Atomics.add(array, 0, 2) === 0 && Atomics.load(array, 0) === 2 && Atomics.compareExchange(array, 0, 2, 5) === 2 && Atomics.load(array, 0) === 5; })()) && (Object.keys(globalThis).includes('Atomics') === false)" }, { "name": "BroadcastChannel", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(await new Promise((resolve, reject) => { const name = '__oc_bc_probe__' + Date.now(); const first = new BroadcastChannel(name); const second = new BroadcastChannel(name); const timer = setTimeout(() => { first.close(); second.close(); reject(new Error('BroadcastChannel timeout')); }, 100); second.onmessage = (event) => { clearTimeout(timer); first.close(); second.close(); resolve(event.data?.ok === true); }; first.postMessage({ ok: true }); })) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'BroadcastChannel'); return descriptor?.value === globalThis.BroadcastChannel && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('BroadcastChannel') === false; })()" }, { "name": "clearImmediate", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "", "probe": "typeof globalThis.clearImmediate === 'function'" }, { "name": "setImmediate", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "", "probe": "typeof globalThis.setImmediate === 'function'" }, { "name": "clearInterval", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "", "probe": "typeof globalThis.clearInterval === 'function'" }, { "name": "setInterval", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "", "probe": "typeof globalThis.setInterval === 'function'" }, { "name": "clearTimeout", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "", "probe": "typeof globalThis.clearTimeout === 'function'" }, { "name": "setTimeout", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "", "probe": "typeof globalThis.setTimeout === 'function'" }, { "name": "CompressionStream", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Host-provided compression stream constructor with native-shaped global descriptor where available. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "((() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'CompressionStream'); return !descriptor || (descriptor.value === CompressionStream && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && CompressionStream.name === 'CompressionStream' && CompressionStream.length === 1); })()) && (Object.keys(globalThis).includes('CompressionStream') === false)" }, { "name": "DecompressionStream", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Host-provided decompression stream constructor with native-shaped global descriptor where available. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "((() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'DecompressionStream'); return !descriptor || (descriptor.value === DecompressionStream && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && DecompressionStream.name === 'DecompressionStream' && DecompressionStream.length === 1); })()) && (Object.keys(globalThis).includes('DecompressionStream') === false)" }, { "name": "console", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Console global is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.console?.log === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'console'); return descriptor?.value === globalThis.console && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('console') === false; })()" }, { "name": "Crypto", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Host WebCrypto constructor with native-shaped global descriptor where available. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "((() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'Crypto'); return !descriptor || (descriptor.value === Crypto && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Crypto.name === 'Crypto' && Crypto.length === 0); })()) && (Object.keys(globalThis).includes('Crypto') === false)" }, { "name": "SubtleCrypto", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Host WebCrypto constructor with native-shaped global descriptor where available. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "((() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'SubtleCrypto'); return !descriptor || (descriptor.value === SubtleCrypto && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && SubtleCrypto.name === 'SubtleCrypto' && SubtleCrypto.length === 0); })()) && (Object.keys(globalThis).includes('SubtleCrypto') === false)" }, { "name": "CryptoKey", "targetStatus": "full", "currentStatus": "partial", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Host WebCrypto key constructor with native-shaped global descriptor where available. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "((() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'CryptoKey'); return !descriptor || (descriptor.value === CryptoKey && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && CryptoKey.name === 'CryptoKey' && CryptoKey.length === 0); })()) && (Object.keys(globalThis).includes('CryptoKey') === false)" }, { "name": "CustomEvent", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(new CustomEvent('opencontainers', { detail: 42 }).detail === 42) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'CustomEvent'); return descriptor?.value === globalThis.CustomEvent && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('CustomEvent') === false; })()" }, { "name": "DOMException", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Host DOMException is preferred; OpenContainers fallback preserves Node-shaped name/message/code accessors, legacy constants, Error inheritance, and [object DOMException] branding when the host constructor is unavailable. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "((() => { const error = new DOMException('denied', 'SecurityError'); return error.name === 'SecurityError' && error.message === 'denied' && error.code === 18 && DOMException.SECURITY_ERR === 18 && Object.prototype.toString.call(error) === '[object DOMException]'; })()) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'DOMException'); return descriptor?.value === globalThis.DOMException && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('DOMException') === false; })()" }, { "name": "Event", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.Event === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'Event'); return descriptor?.value === globalThis.Event && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('Event') === false; })()" }, { "name": "EventTarget", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.EventTarget === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'EventTarget'); return descriptor?.value === globalThis.EventTarget && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('EventTarget') === false; })()" }, { "name": "exports", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "CommonJS module-scoped global.", "probe": "typeof exports === 'object'" }, { "name": "module", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "CommonJS module-scoped global.", "probe": "typeof module === 'object'" }, { "name": "require", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "CommonJS module-scoped global.", "probe": "typeof require === 'function'" }, { "name": "fetch", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs, tests/compat-matrix.test.mjs", "limitation": "Virtual/browser fetch with OpenContainers network policy and native-shaped global function metadata.", "probe": "typeof globalThis.fetch === 'function' && globalThis.fetch.name === 'fetch' && globalThis.fetch.length === 1 && Object.getOwnPropertyDescriptor(globalThis, 'fetch')?.enumerable === true" }, { "name": "Headers", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs, tests/compat-matrix.test.mjs", "limitation": "Fetch constructor global is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.Headers === 'function' && Object.getOwnPropertyDescriptor(globalThis, 'Headers')?.enumerable === false) && (Object.keys(globalThis).includes('Headers') === false)" }, { "name": "Request", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs, tests/compat-matrix.test.mjs", "limitation": "Fetch constructor global is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.Request === 'function' && Object.getOwnPropertyDescriptor(globalThis, 'Request')?.enumerable === false) && (Object.keys(globalThis).includes('Request') === false)" }, { "name": "Response", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs, tests/compat-matrix.test.mjs", "limitation": "Fetch constructor global is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.Response === 'function' && Object.getOwnPropertyDescriptor(globalThis, 'Response')?.enumerable === false) && (Object.keys(globalThis).includes('Response') === false)" }, { "name": "FormData", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs, tests/compat-matrix.test.mjs", "limitation": "Fetch constructor global is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.FormData === 'function' && Object.getOwnPropertyDescriptor(globalThis, 'FormData')?.enumerable === false) && (Object.keys(globalThis).includes('FormData') === false)" }, { "name": "global", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "", "probe": "global === globalThis" }, { "name": "globalThis", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "The globalThis self-reference is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis === 'object') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'globalThis'); return descriptor?.value === globalThis.globalThis && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('globalThis') === false; })()" }, { "name": "MessageChannel", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "OpenContainers worker thread message channel implementation. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.MessageChannel === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'MessageChannel'); return descriptor?.value === globalThis.MessageChannel && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('MessageChannel') === false; })()" }, { "name": "MessageEvent", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(new MessageEvent('message', { data: 'ready' }).data === 'ready') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'MessageEvent'); return descriptor?.value === globalThis.MessageEvent && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('MessageEvent') === false; })()" }, { "name": "MessagePort", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "OpenContainers worker thread message port implementation. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.MessagePort === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'MessagePort'); return descriptor?.value === globalThis.MessagePort && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('MessagePort') === false; })()" }, { "name": "PerformanceEntry", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(performance.mark('__oc_entry_probe__') instanceof PerformanceEntry) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'PerformanceEntry'); return descriptor?.value === globalThis.PerformanceEntry && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('PerformanceEntry') === false; })()" }, { "name": "PerformanceMark", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(performance.mark('__oc_mark_probe__') instanceof PerformanceMark) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'PerformanceMark'); return descriptor?.value === globalThis.PerformanceMark && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('PerformanceMark') === false; })()" }, { "name": "PerformanceMeasure", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "((performance.mark('__oc_measure_start__'), performance.measure('__oc_measure_probe__', '__oc_measure_start__') instanceof PerformanceMeasure)) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'PerformanceMeasure'); return descriptor?.value === globalThis.PerformanceMeasure && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('PerformanceMeasure') === false; })()" }, { "name": "PerformanceObserver", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(new PerformanceObserver(() => {}) instanceof PerformanceObserver) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'PerformanceObserver'); return descriptor?.value === globalThis.PerformanceObserver && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('PerformanceObserver') === false; })()" }, { "name": "PerformanceObserverEntryList", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "((() => { try { new PerformanceObserverEntryList(); return false; } catch (error) { return typeof PerformanceObserverEntryList === \"function\" && error.code === \"ERR_ILLEGAL_CONSTRUCTOR\"; } })()) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'PerformanceObserverEntryList'); return descriptor?.value === globalThis.PerformanceObserverEntryList && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('PerformanceObserverEntryList') === false; })()" }, { "name": "PerformanceResourceTiming", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "((() => { try { new PerformanceResourceTiming(); return false; } catch (error) { return typeof PerformanceResourceTiming === \"function\" && error.code === \"ERR_ILLEGAL_CONSTRUCTOR\"; } })()) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'PerformanceResourceTiming'); return descriptor?.value === globalThis.PerformanceResourceTiming && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('PerformanceResourceTiming') === false; })()" }, { "name": "performance", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Runtime performance object is exposed through a Node-shaped enumerable configurable get/set global descriptor and remains assignable for package probes.", "probe": "(() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'performance'); const original = globalThis.performance; try { globalThis.performance = { marker: 'replacement-performance' }; return descriptor?.enumerable === true && descriptor.configurable === true && !('value' in descriptor) && descriptor.get.name === 'get performance' && descriptor.get.length === 0 && descriptor.set.name === 'set performance' && descriptor.set.length === 1 && Object.keys(globalThis).includes('performance') === true && performance.marker === 'replacement-performance' && globalThis.performance.marker === 'replacement-performance'; } finally { globalThis.performance = original; } })() && typeof performance.now() === 'number' && performance.mark('__oc_performance_probe__') instanceof PerformanceMark" }, { "name": "process", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Virtual process object is exposed through a Node-shaped non-enumerable configurable get/set global descriptor and remains assignable for package probes.", "probe": "(() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'process'); const original = globalThis.process; try { globalThis.process = { marker: 'replacement-process' }; return descriptor?.enumerable === false && descriptor.configurable === true && !('value' in descriptor) && descriptor.get.name === 'get' && descriptor.get.length === 0 && descriptor.set.name === 'set' && descriptor.set.length === 1 && Object.keys(globalThis).includes('process') === false && process.marker === 'replacement-process' && globalThis.process.marker === 'replacement-process'; } finally { globalThis.process = original; } })()" }, { "name": "queueMicrotask", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "", "probe": "typeof globalThis.queueMicrotask === 'function'" }, { "name": "ReadableStream", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Host Web Streams are preferred; OpenContainers provides fallback default stream constructors, readers, writers, transforms, and queueing strategies when host constructors are missing. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(await new ReadableStream({ start(controller) { controller.enqueue('ok'); controller.close(); } }).getReader().read().then(({ value }) => value === 'ok')) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'ReadableStream'); return descriptor?.value === globalThis.ReadableStream && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('ReadableStream') === false; })()" }, { "name": "ReadableByteStreamController", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Host Web Streams are preferred; OpenContainers fallback byte streams support native-shaped constructor metadata, byte-stream controllers, BYOB requests, queued byte reads, and native-style BYOB source-buffer detachment for the tracked surface; advanced backpressure remains simplified. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(await (async () => { let seen = false; const target = new Uint8Array(4); const expectedLength = target.byteLength; const reader = new ReadableStream({ type: 'bytes', pull(controller) { const request = controller.byobRequest; seen = controller instanceof ReadableByteStreamController && request instanceof ReadableStreamBYOBRequest && request.view.byteLength === expectedLength; request.view[0] = 65; request.view[1] = 66; request.respond(2); controller.close(); } }).getReader({ mode: 'byob' }); const result = await reader.read(target); return seen && result.value.byteLength === 2 && result.value[0] === 65 && result.value[1] === 66 && result.value.buffer !== target.buffer && target.byteLength === 0 && target.buffer.byteLength === 0; })()) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'ReadableByteStreamController'); return descriptor?.value === globalThis.ReadableByteStreamController && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('ReadableByteStreamController') === false; })()" }, { "name": "ReadableStreamBYOBReader", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Host Web Streams are preferred; OpenContainers fallback byte streams support native-shaped constructor metadata, byte-stream controllers, BYOB requests, queued byte reads, and native-style BYOB source-buffer detachment for the tracked surface; advanced backpressure remains simplified. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(await (async () => { const target = new Uint8Array(2); const reader = new ReadableStream({ type: 'bytes', start(controller) { controller.enqueue(new Uint8Array([67, 68, 69])); controller.close(); } }).getReader({ mode: 'byob' }); const first = await reader.read(target); return reader instanceof ReadableStreamBYOBReader && first.value.byteLength === 2 && first.value[0] === 67 && first.value[1] === 68 && first.value.buffer !== target.buffer && target.byteLength === 0; })()) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'ReadableStreamBYOBReader'); return descriptor?.value === globalThis.ReadableStreamBYOBReader && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('ReadableStreamBYOBReader') === false; })()" }, { "name": "ReadableStreamBYOBRequest", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Host Web Streams are preferred; OpenContainers fallback byte streams support native-shaped constructor metadata, byte-stream controllers, BYOB requests, queued byte reads, and native-style BYOB source-buffer detachment for the tracked surface; advanced backpressure remains simplified. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(await (async () => { let requestOk = false; const target = new Uint8Array(4); const expectedLength = target.byteLength; const reader = new ReadableStream({ type: 'bytes', pull(controller) { const request = controller.byobRequest; requestOk = request instanceof ReadableStreamBYOBRequest && typeof request.respond === 'function' && typeof request.respondWithNewView === 'function' && request.view.byteLength === expectedLength; request.view[0] = 70; request.respond(1); controller.close(); } }).getReader({ mode: 'byob' }); const result = await reader.read(target); return requestOk && result.value.byteLength === 1 && result.value[0] === 70 && target.byteLength === 0; })()) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'ReadableStreamBYOBRequest'); return descriptor?.value === globalThis.ReadableStreamBYOBRequest && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('ReadableStreamBYOBRequest') === false; })()" }, { "name": "ReadableStreamDefaultController", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Host Web Streams are preferred; OpenContainers provides fallback default stream constructors, readers, writers, transforms, and queueing strategies when host constructors are missing. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(await new Promise((resolve) => { new ReadableStream({ start(controller) { resolve(typeof controller.enqueue === 'function' && typeof controller.close === 'function'); } }); })) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'ReadableStreamDefaultController'); return descriptor?.value === globalThis.ReadableStreamDefaultController && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('ReadableStreamDefaultController') === false; })()" }, { "name": "ReadableStreamDefaultReader", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Host Web Streams are preferred; OpenContainers provides fallback default stream constructors, readers, writers, transforms, and queueing strategies when host constructors are missing. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof new ReadableStream({ start(controller) { controller.close(); } }).getReader().read === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'ReadableStreamDefaultReader'); return descriptor?.value === globalThis.ReadableStreamDefaultReader && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('ReadableStreamDefaultReader') === false; })()" }, { "name": "structuredClone", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Structured clone helper exposes Node-shaped function metadata.", "probe": "structuredClone.name === 'structuredClone' && (typeof globalThis.structuredClone === 'function')" }, { "name": "TextDecoder", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.TextDecoder === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'TextDecoder'); return descriptor?.value === globalThis.TextDecoder && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('TextDecoder') === false; })()" }, { "name": "TextDecoderStream", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.TextDecoderStream === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'TextDecoderStream'); return descriptor?.value === globalThis.TextDecoderStream && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('TextDecoderStream') === false; })()" }, { "name": "TextEncoder", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.TextEncoder === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'TextEncoder'); return descriptor?.value === globalThis.TextEncoder && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('TextEncoder') === false; })()" }, { "name": "TextEncoderStream", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.TextEncoderStream === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'TextEncoderStream'); return descriptor?.value === globalThis.TextEncoderStream && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('TextEncoderStream') === false; })()" }, { "name": "TransformStream", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Host Web Streams are preferred; OpenContainers provides fallback default stream constructors, readers, writers, transforms, and queueing strategies when host constructors are missing. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(await (async () => { const transformed = new ReadableStream({ start(controller) { controller.enqueue('ok'); controller.close(); } }).pipeThrough(new TransformStream({ transform(chunk, controller) { controller.enqueue(chunk.toUpperCase()); } })); const { value } = await transformed.getReader().read(); return value === 'OK'; })()) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'TransformStream'); return descriptor?.value === globalThis.TransformStream && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('TransformStream') === false; })()" }, { "name": "TransformStreamDefaultController", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Host Web Streams are preferred; OpenContainers provides fallback default stream constructors, readers, writers, transforms, and queueing strategies when host constructors are missing. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(await (async () => { let seen = false; new TransformStream({ transform(_chunk, controller) { seen = typeof controller.enqueue === 'function' && typeof controller.terminate === 'function'; } }); return typeof TransformStreamDefaultController === 'function' || seen === false; })()) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'TransformStreamDefaultController'); return descriptor?.value === globalThis.TransformStreamDefaultController && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('TransformStreamDefaultController') === false; })()" }, { "name": "URL", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.URL === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'URL'); return descriptor?.value === globalThis.URL && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('URL') === false; })()" }, { "name": "URLSearchParams", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.URLSearchParams === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'URLSearchParams'); return descriptor?.value === globalThis.URLSearchParams && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('URLSearchParams') === false; })()" }, { "name": "WebAssembly", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/compat-matrix.test.mjs", "limitation": "Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof globalThis.WebAssembly === 'object') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'WebAssembly'); return descriptor?.value === globalThis.WebAssembly && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('WebAssembly') === false; })()" }, { "name": "WritableStream", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Host Web Streams are preferred; OpenContainers provides fallback default stream constructors, readers, writers, transforms, and queueing strategies when host constructors are missing. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(await (async () => { const chunks = []; const writer = new WritableStream({ write(chunk) { chunks.push(chunk); } }).getWriter(); await writer.write('ok'); await writer.close(); return chunks.join('') === 'ok'; })()) && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'WritableStream'); return descriptor?.value === globalThis.WritableStream && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('WritableStream') === false; })()" }, { "name": "WritableStreamDefaultController", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Host Web Streams are preferred; OpenContainers provides fallback default stream constructors, readers, writers, transforms, and queueing strategies when host constructors are missing. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof WritableStreamDefaultController === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'WritableStreamDefaultController'); return descriptor?.value === globalThis.WritableStreamDefaultController && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('WritableStreamDefaultController') === false; })()" }, { "name": "WritableStreamDefaultWriter", "targetStatus": "full", "currentStatus": "full", "owner": "runtime-node", "test": "tests/globals-isolation.test.mjs", "limitation": "Host Web Streams are preferred; OpenContainers provides fallback default stream constructors, readers, writers, transforms, and queueing strategies when host constructors are missing. Global constructor is exposed with Node-shaped non-enumerable descriptor metadata.", "probe": "(typeof new WritableStream().getWriter().write === 'function') && (() => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'WritableStreamDefaultWriter'); return descriptor?.value === globalThis.WritableStreamDefaultWriter && descriptor.enumerable === false && descriptor.configurable === true && descriptor.writable === true && Object.keys(globalThis).includes('WritableStreamDefaultWriter') === false; })()" } ] }