mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-31 07:23:06 +08:00
Expand Node 24 callback and promise adapter compatibility
This commit is contained in:
@@ -2,6 +2,6 @@
|
||||
"schemaVersion": 3,
|
||||
"nodeVersion": "24.15.0",
|
||||
"nodeCommit": "848430679556aed0bd073f2bc263331ad84fa119",
|
||||
"artifactVersion": "3c31fba8150926a20ac8",
|
||||
"artifactVersion": "18ed68d47d451a20f50c",
|
||||
"rowCount": 3662
|
||||
}
|
||||
|
||||
@@ -84848,7 +84848,7 @@
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "partial",
|
||||
"detail": "Available through the embedded Node compatibility shim; exact member and overload coverage may be narrower.",
|
||||
"detail": "Adapts callbacks and promises with receiver preservation, custom promisify hooks, function metadata, and Node-compatible argument and rejection handling; scheduling follows the island microtask queue.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
@@ -85520,7 +85520,7 @@
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "partial",
|
||||
"detail": "Available through the embedded Node compatibility shim; exact member and overload coverage may be narrower.",
|
||||
"detail": "Adapts callbacks and promises with receiver preservation, custom promisify hooks, function metadata, and Node-compatible argument and rejection handling; scheduling follows the island microtask queue.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"wasi": "by-design"
|
||||
},
|
||||
"features": [
|
||||
{ "chapter": "util", "symbols": ["util.promisify", "util.callbackify"], "status": "partial", "evidence": ["tests/fixtures/npm/cases/util-shims/main.ts", "tests/fixtures/npm/cases/node24-util-adapters/main.ts"] },
|
||||
{ "chapter": "util", "symbols": ["util.parseArgs", "parseArgs"], "status": "partial", "evidence": ["tests/fixtures/npm/cases/util-shims/main.ts", "tests/fixtures/npm/cases/node24-parseargs/main.ts"] },
|
||||
{ "chapter": "buffer", "symbols": ["buffer.isAscii", "buffer.isUtf8", "buffer.transcode"], "status": "partial", "evidence": ["tests/fixtures/npm/cases/node24-text-encoding/main.ts"] },
|
||||
{ "chapter": "util", "parent": "Class: `util.TextEncoder`", "signatures": ["`textEncoder.encodeInto(src, dest)`", "`encoding` Type: {string}"], "status": "partial", "evidence": ["tests/fixtures/npm/cases/node24-text-encoding/main.ts"] },
|
||||
|
||||
@@ -94721,9 +94721,10 @@
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-export:node:util.callbackify",
|
||||
"source": "island-feature:util.util.callbackify",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/util-shims/main.ts"
|
||||
"tests/fixtures/npm/cases/util-shims/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-util-adapters/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -95561,9 +95562,10 @@
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-export:node:util.promisify",
|
||||
"source": "island-feature:util.util.promisify",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/util-shims/main.ts"
|
||||
"tests/fixtures/npm/cases/util-shims/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-util-adapters/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111045,6 +111045,7 @@
|
||||
"tests/fixtures/npm/cases/node24-env/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-parseargs/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-text-encoding/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-util-adapters/main.ts",
|
||||
"tests/fixtures/npm/cases/util-shims/main.ts"
|
||||
]
|
||||
},
|
||||
@@ -112010,9 +112011,10 @@
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "partial",
|
||||
"evidence": "island-export:node:util.callbackify",
|
||||
"evidence": "island-feature:util.util.callbackify",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/util-shims/main.ts"
|
||||
"tests/fixtures/npm/cases/util-shims/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-util-adapters/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
@@ -112833,9 +112835,10 @@
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "partial",
|
||||
"evidence": "island-export:node:util.promisify",
|
||||
"evidence": "island-feature:util.util.promisify",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/util-shims/main.ts"
|
||||
"tests/fixtures/npm/cases/util-shims/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-util-adapters/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
|
||||
@@ -678,6 +678,9 @@ function publicDetail(tier) {
|
||||
return "No dynamic-island implementation exists for this Node API family yet.";
|
||||
}
|
||||
if (source.startsWith("island-feature:")) {
|
||||
if (/^island-feature:util\.util\.(?:promisify|callbackify)$/.test(source)) {
|
||||
return "Adapts callbacks and promises with receiver preservation, custom promisify hooks, function metadata, and Node-compatible argument and rejection handling; scheduling follows the island microtask queue.";
|
||||
}
|
||||
if (/^island-feature:util\.(?:util\.)?parseArgs$/.test(source)) {
|
||||
return "Parses command-line options, positionals, defaults, and tokens with Node-compatible configuration validation.";
|
||||
}
|
||||
|
||||
@@ -13408,6 +13408,12 @@
|
||||
"<repo>/tests/fixtures/npm/cases/node24-parseargs/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/fixtures/npm/cases/node24-util-adapters/main.ts": {
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/node24-util-adapters/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2059
-2067
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
// @dynamic
|
||||
// @stderr
|
||||
import { report } from "node24-util-adapters-fixture";
|
||||
report();
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"module"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export function report(): Promise<void>;
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
import { promisify, callbackify } from 'node:util';
|
||||
|
||||
export async function report() {
|
||||
const line = (name, value) => console.log(name, JSON.stringify(value));
|
||||
const error = (name, fn) => {
|
||||
try { fn(); line(name, 'no error'); }
|
||||
catch (e) { line(name, [e.name, e.code, e.message]); }
|
||||
};
|
||||
const descriptor = (fn, key) => {
|
||||
const d = Object.getOwnPropertyDescriptor(fn, key);
|
||||
return [d.value, d.writable, d.enumerable, d.configurable];
|
||||
};
|
||||
for (const value of [undefined, null, false, 42, -0, 2n, Symbol('x'), 'no', "can't", 'a'.repeat(29), {}, [], Object.create(null)]) {
|
||||
error('promisify invalid', () => promisify(value));
|
||||
error('callbackify invalid', () => callbackify(value));
|
||||
}
|
||||
const metadata = Symbol('metadata');
|
||||
function sum(a, b, cb) { cb(null, this.base + a + b, 'ignored'); }
|
||||
Object.defineProperty(sum, 'detail', { get() { return 17; }, enumerable: true });
|
||||
sum[metadata] = 'symbol';
|
||||
const customPrototype = Object.create(Function.prototype);
|
||||
Object.setPrototypeOf(sum, customPrototype);
|
||||
const wrapped = promisify(sum);
|
||||
line('promisify metadata', [descriptor(wrapped, 'name'), descriptor(wrapped, 'length'), wrapped.detail, wrapped[metadata], Object.getPrototypeOf(wrapped) === customPrototype]);
|
||||
line('promisify identity', [promisify(wrapped) === wrapped, wrapped[promisify.custom] === wrapped, Symbol.for('nodejs.util.promisify.custom') === promisify.custom]);
|
||||
line('promisify receiver', await wrapped.call({ base: 10 }, 2, 3));
|
||||
line('promisify no result', await promisify(cb => cb(null))() === undefined);
|
||||
line('promisify falsy error', await promisify(cb => cb(0, 'ok'))());
|
||||
line('promisify first settlement', await promisify(cb => { cb(null, 1); cb(new Error('late')); throw new Error('later'); })());
|
||||
const boom = new Error('sync');
|
||||
line('promisify sync throw', await promisify(() => { throw boom; })().catch(e => e === boom));
|
||||
function custom() {}
|
||||
custom[promisify.custom] = function chosen() { return this.value; };
|
||||
const chosen = promisify(custom);
|
||||
line('custom', [chosen === custom[promisify.custom], promisify(chosen) === chosen, chosen.call({ value: 23 })]);
|
||||
for (const value of [true, 'wrong', {}, 5, 3n, Symbol('bad')]) {
|
||||
custom[promisify.custom] = value;
|
||||
error('invalid custom', () => promisify(custom));
|
||||
}
|
||||
custom[promisify.custom] = false;
|
||||
line('falsy custom ignored', typeof promisify(custom));
|
||||
|
||||
async function add(a, b) { return this.base + a + b; }
|
||||
Object.setPrototypeOf(add, customPrototype);
|
||||
add[metadata] = 'async symbol';
|
||||
const callback = callbackify(add);
|
||||
line('callbackify metadata', [descriptor(callback, 'name'), descriptor(callback, 'length'), callback[metadata], Object.getPrototypeOf(callback) === Function.prototype]);
|
||||
await new Promise(resolve => {
|
||||
let synchronous = true;
|
||||
const receiver = { base: 20 };
|
||||
const returned = callback.call(receiver, 2, 3, function(err, result) {
|
||||
line('callbackify success', [err, result, this === receiver, synchronous, arguments.length]); resolve();
|
||||
});
|
||||
line('callbackify return', returned === undefined);
|
||||
synchronous = false;
|
||||
});
|
||||
for (const value of [undefined, null, 1, 'callback', {}, Symbol('cb')]) error('invalid callback', () => callback(value));
|
||||
for (const reason of [undefined, null, false, 0, -0, NaN, '', 0n, 1, true, 'failure', 2n, Symbol('failure'), {}, new Error('failure')]) {
|
||||
await new Promise(resolve => callbackify(() => Promise.reject(reason))(function(err, result) {
|
||||
line('callbackify rejection', [typeof reason, !reason, err === reason, err?.code ?? null, Object.is(err?.reason, reason), arguments.length, result === undefined, err instanceof Error, err?.message ?? null, Object.hasOwn(Object(err), 'reason')]); resolve();
|
||||
}));
|
||||
}
|
||||
await new Promise(resolve => {
|
||||
const order = [];
|
||||
callbackify(() => ({ then(fulfilled) { order.push('then'); fulfilled(8); } }))(function(err, value) {
|
||||
order.push('callback'); line('thenable asynchronous', [order, err, value]); resolve();
|
||||
});
|
||||
order.push('returned');
|
||||
});
|
||||
error('callbackify sync throw', () => callbackify(() => { throw new Error('sync failure'); })(() => {}));
|
||||
for (const values of [[7, 'renamed'], ['strange', 12], [NaN, '']]) {
|
||||
function altered() { return Promise.resolve(1); }
|
||||
Object.defineProperty(altered, 'length', { value: values[0] });
|
||||
Object.defineProperty(altered, 'name', { value: values[1] });
|
||||
const p = promisify(altered), c = callbackify(altered);
|
||||
line('altered metadata', [descriptor(p, 'name'), descriptor(p, 'length'), descriptor(c, 'name'), descriptor(c, 'length')]);
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"name":"node24-util-adapters-fixture","version":"1.0.0","type":"module","main":"index.js","types":"index.d.ts"}
|
||||
Reference in New Issue
Block a user