mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-31 07:23:06 +08:00
Add Node 24 Web Stream pipelines and streaming encoding (#660)
This commit is contained in:
@@ -207,7 +207,7 @@ Uncaught exceptions print `Uncaught <value>` to stderr instead of Node.js's stac
|
||||
|
||||
In a TypeScript `--dynamic` build, `const host: any = globalThis` or `(globalThis as any).TextDecoder` accesses the engine's global object. Its Node globals use those shims even without an embedded npm package. For example, the engine's `TextDecoder` supports UTF-8 labels only. Optional capabilities such as `fetch` are installed only when the build links their bridge.
|
||||
|
||||
Embedded Web Streams support default readable streams, writable streams and their writers/controllers, count and byte-length queuing strategies, transform streams, and UTF-8 decoder streams. Writable sinks serialize queued writes, wait for asynchronous start/close/abort callbacks, and expose queue backpressure through `ready` and `desiredSize`. Transform streams still run without readable-side backpressure. Byte streams, BYOB readers, `tee()`, `pipeTo()`, stream transfer, and piping with AbortSignal remain unsupported. These embedded APIs do not broaden the separate static Web Streams surface.
|
||||
Embedded Web Streams support default readable and writable streams, their writer and transform-controller APIs, count and byte-length queuing strategies, transform streams, and UTF-8 encoder/decoder streams. Writable sinks serialize queued writes and wait for asynchronous start/close/abort callbacks. Transforms honor readable-side backpressure and asynchronous start/transform/flush/cancel callbacks. Default-stream `pipeTo()` and `pipeThrough()` honor `preventClose`, `preventAbort`, `preventCancel`, and AbortSignal, propagate cleanup errors, and release their locks when piping settles. Byte streams, BYOB readers, `tee()`, and stream transfer remain unsupported. These embedded APIs do not broaden the separate static Web Streams surface.
|
||||
|
||||
Static tasks drain before engine jobs run at event-loop quiescence. A static `await` racing a package promise can therefore resolve in a different order from Node.js.
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"schemaVersion": 3,
|
||||
"nodeVersion": "24.15.0",
|
||||
"nodeCommit": "848430679556aed0bd073f2bc263331ad84fa119",
|
||||
"artifactVersion": "60361b544f92e9e4378a",
|
||||
"artifactVersion": "ab49b98a2d4f6853980e",
|
||||
"rowCount": 3662
|
||||
}
|
||||
|
||||
@@ -491,9 +491,9 @@
|
||||
},
|
||||
"dynamic": {
|
||||
"supported": 0,
|
||||
"partial": 38,
|
||||
"partial": 40,
|
||||
"refused": 0,
|
||||
"not-implemented": 54,
|
||||
"not-implemented": 52,
|
||||
"by-design": 0,
|
||||
"unreviewed": 0,
|
||||
"not-applicable": 0
|
||||
@@ -1331,9 +1331,9 @@
|
||||
},
|
||||
"dynamic": {
|
||||
"supported": 0,
|
||||
"partial": 27,
|
||||
"partial": 40,
|
||||
"refused": 0,
|
||||
"not-implemented": 61,
|
||||
"not-implemented": 48,
|
||||
"by-design": 0,
|
||||
"unreviewed": 0,
|
||||
"not-applicable": 0
|
||||
@@ -44202,9 +44202,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "Verified absent from the embedded engine's web/global compatibility layer.",
|
||||
"verification": "verified-absence"
|
||||
"status": "partial",
|
||||
"detail": "Provided by the embedded engine's web/global compatibility layer.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -44258,9 +44258,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "Verified absent from the embedded engine's web/global compatibility layer.",
|
||||
"verification": "verified-absence"
|
||||
"status": "partial",
|
||||
"detail": "Provided by the embedded engine's web/global compatibility layer.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -94335,9 +94335,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "This API is not implemented by the dynamic-island shim.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented embedded module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -94363,9 +94363,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "This API is not implemented by the dynamic-island shim.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented embedded module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -95651,9 +95651,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "This API is not implemented by the dynamic-island shim.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented embedded module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -95679,9 +95679,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "This API is not implemented by the dynamic-island shim.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented embedded module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -95707,9 +95707,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "This API is not implemented by the dynamic-island shim.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Available through the embedded Node compatibility shim; exact member and overload coverage may be narrower.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -95735,9 +95735,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "This API is not implemented by the dynamic-island shim.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented embedded module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -95763,9 +95763,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "This API is not implemented by the dynamic-island shim.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented embedded module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -95791,9 +95791,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "This API is not implemented by the dynamic-island shim.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented embedded module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -95819,9 +95819,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "This API is not implemented by the dynamic-island shim.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented embedded module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -96015,9 +96015,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "This API is not implemented by the dynamic-island shim.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Available through the embedded Node compatibility shim; exact member and overload coverage may be narrower.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -96043,9 +96043,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "This API is not implemented by the dynamic-island shim.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented embedded module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -96071,9 +96071,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "This API is not implemented by the dynamic-island shim.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented embedded module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -96099,9 +96099,9 @@
|
||||
"verification": "registry-gap"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"detail": "This API is not implemented by the dynamic-island shim.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented embedded module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
"wasi": "by-design"
|
||||
},
|
||||
"features": [
|
||||
{"chapter": "webstreams", "symbols": ["readableStream.pipeTo", "readableStream.pipeThrough"], "status": "partial", "evidence": ["tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts", "tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts", "tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts"]},
|
||||
{"chapter": "webstreams", "parent": "Class: `TransformStream`", "symbols": ["readable", "writable"], "status": "partial", "evidence": ["tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts", "tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts"]},
|
||||
{"chapter": "webstreams", "symbols": ["transformStreamDefaultController.enqueue", "transformStreamDefaultController.error", "transformStreamDefaultController.terminate"], "status": "partial", "evidence": ["tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts"]},
|
||||
{"chapter": "webstreams", "parent": "Class: `TransformStreamDefaultController`", "symbols": ["desiredSize"], "status": "partial", "evidence": ["tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts"]},
|
||||
{"chapter": "webstreams", "parent": "Class: `TextEncoderStream`", "symbols": ["encoding", "readable", "writable"], "status": "partial", "evidence": ["tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"]},
|
||||
{"chapter": "webstreams", "symbols": ["writableStream.abort", "writableStream.close", "writableStream.getWriter", "writableStreamDefaultWriter.abort", "writableStreamDefaultWriter.close", "writableStreamDefaultWriter.releaseLock", "writableStreamDefaultWriter.write", "writableStreamDefaultController.error"], "status": "partial", "evidence": ["tests/fixtures/npm/cases/node24-web-stream-queues/main.ts", "tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts", "tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"]},
|
||||
{"chapter": "webstreams", "parent": "Class: `WritableStream`", "status": "partial", "evidence": ["tests/fixtures/npm/cases/node24-web-stream-queues/main.ts", "tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts", "tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"], "symbols": ["locked"]},
|
||||
{"chapter": "webstreams", "parent": "Class: `WritableStreamDefaultWriter`", "status": "partial", "evidence": ["tests/fixtures/npm/cases/node24-web-stream-queues/main.ts", "tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts", "tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"], "symbols": ["closed", "desiredSize", "ready"]},
|
||||
@@ -109,15 +114,15 @@
|
||||
"stream": { "exports": ["Stream", "Readable", "Writable", "Duplex", "Transform", "PassThrough", "pipeline", "finished", "addAbortSignal", "promises", "isErrored", "isDestroyed", "isReadable", "isWritable"], "members": ["stream.Readable.from", "readable.read", "readable.push", "readable.unshift", "readable.pause", "readable.resume", "readable.isPaused", "readable.setEncoding", "readable.pipe", "readable.unpipe", "readable.destroy", "writable.write", "writable.end", "writable.cork", "writable.uncork", "writable.setDefaultEncoding", "writable.destroy", "transform.destroy"], "refusedMembers": ["readable.wrap"], "evidence": ["tests/fixtures/npm/cases/stream-shims/main.ts"] },
|
||||
"stream/promises": { "exports": ["pipeline", "finished"], "evidence": ["tests/fixtures/npm/cases/stream-shims/main.ts"] },
|
||||
"stream/consumers": { "exports": ["text", "buffer", "arrayBuffer", "json", "blob"], "evidence": ["tests/fixtures/npm/cases/stream-shims/main.ts"] },
|
||||
"stream/web": { "exports": ["ReadableStream", "TransformStream", "TextDecoderStream", "WritableStream", "WritableStreamDefaultWriter", "WritableStreamDefaultController", "CountQueuingStrategy", "ByteLengthQueuingStrategy"], "evidence": ["tests/fixtures/npm/cases/web-streams/main.ts", "tests/fixtures/npm/cases/node24-web-stream-queues/main.ts", "tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts", "tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"] },
|
||||
"stream/web": {"exports": ["ReadableStream", "TransformStream", "TextDecoderStream", "WritableStream", "WritableStreamDefaultWriter", "WritableStreamDefaultController", "CountQueuingStrategy", "ByteLengthQueuingStrategy", "TransformStreamDefaultController", "TextEncoderStream"], "evidence": ["tests/fixtures/npm/cases/web-streams/main.ts", "tests/fixtures/npm/cases/node24-web-stream-queues/main.ts", "tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts", "tests/fixtures/npm/cases/node24-web-stream-errors/main.ts", "tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts", "tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts", "tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts", "tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts", "tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"]},
|
||||
"crypto": { "exports": ["createHash", "createHmac", "hash", "Hash", "Hmac", "randomBytes", "randomFillSync", "randomFill", "randomInt", "randomUUID", "getRandomValues", "timingSafeEqual", "pbkdf2", "pbkdf2Sync", "getHashes", "getCiphers", "getCurves", "webcrypto", "subtle", "constants", "KeyObject", "createCipheriv", "createDecipheriv", "createSign", "createVerify", "createDiffieHellman", "createECDH", "createPublicKey", "createPrivateKey", "createSecretKey", "diffieHellman", "generateKeyPair", "generateKeyPairSync", "generateKey", "generateKeySync", "sign", "verify", "publicEncrypt", "publicDecrypt", "privateEncrypt", "privateDecrypt", "scrypt", "scryptSync", "hkdf", "hkdfSync", "X509Certificate", "Certificate", "checkPrime", "checkPrimeSync", "generatePrime", "generatePrimeSync", "secureHeapUsed", "setEngine", "setFips", "getFips"], "refused": ["KeyObject", "createCipheriv", "createDecipheriv", "createSign", "createVerify", "createDiffieHellman", "createECDH", "createPublicKey", "createPrivateKey", "createSecretKey", "diffieHellman", "generateKeyPair", "generateKeyPairSync", "generateKey", "generateKeySync", "sign", "verify", "publicEncrypt", "publicDecrypt", "privateEncrypt", "privateDecrypt", "X509Certificate", "Certificate", "checkPrime", "checkPrimeSync", "generatePrime", "generatePrimeSync", "secureHeapUsed", "setEngine"], "members": ["hash.copy", "hash.digest", "hash.update", "hmac.digest", "hmac.update"], "evidence": ["tests/fixtures/npm/cases/crypto-shims/main.ts", "tests/fixtures/npm/cases/node24-crypto-kdf/main.ts"] },
|
||||
"util": { "exports": ["getSystemErrorName", "getSystemErrorMessage", "getSystemErrorMap", "parseEnv", "format", "formatWithOptions", "inspect", "inherits", "promisify", "callbackify", "deprecate", "debuglog", "debug", "types", "isDeepStrictEqual", "stripVTControlCharacters", "styleText", "parseArgs", "toUSVString", "_extend", "TextEncoder", "TextDecoder", "MIMEType", "MIMEParams", "isArray"], "evidence": ["tests/fixtures/npm/cases/util-shims/main.ts"] },
|
||||
"util/types": { "exports": ["isAnyArrayBuffer", "isArrayBufferView", "isArgumentsObject", "isArrayBuffer", "isAsyncFunction", "isBigInt64Array", "isBigUint64Array", "isBooleanObject", "isBoxedPrimitive", "isBigIntObject", "isCryptoKey", "isDataView", "isDate", "isExternal", "isFloat16Array", "isFloat32Array", "isFloat64Array", "isGeneratorFunction", "isGeneratorObject", "isInt8Array", "isInt16Array", "isInt32Array", "isKeyObject", "isMap", "isMapIterator", "isModuleNamespaceObject", "isNativeError", "isNumberObject", "isPromise", "isProxy", "isRegExp", "isSet", "isSetIterator", "isSharedArrayBuffer", "isStringObject", "isSymbolObject", "isTypedArray", "isUint8Array", "isUint8ClampedArray", "isUint16Array", "isUint32Array", "isWeakMap", "isWeakSet"], "evidence": ["tests/fixtures/npm/cases/util-shims/main.ts", "tests/fixtures/npm/cases/node24-util-types/main.ts"] }
|
||||
},
|
||||
"globals": {
|
||||
"supported": ["atob", "btoa", "clearImmediate", "clearInterval", "clearTimeout", "queueMicrotask", "setImmediate", "setInterval", "setTimeout", "structuredClone", "AbortController", "AbortSignal", "Blob", "CustomEvent", "DOMException", "Event", "EventTarget", "File", "Headers", "MessageChannel", "MessageEvent", "MessagePort", "Request", "Response", "TextDecoder", "TextDecoderStream", "TextEncoder", "TransformStream", "URLSearchParams", "ReadableStream", "WritableStream", "WritableStreamDefaultWriter", "WritableStreamDefaultController", "CountQueuingStrategy", "ByteLengthQueuingStrategy"],
|
||||
"supported": ["atob", "btoa", "clearImmediate", "clearInterval", "clearTimeout", "queueMicrotask", "setImmediate", "setInterval", "setTimeout", "structuredClone", "AbortController", "AbortSignal", "Blob", "CustomEvent", "DOMException", "Event", "EventTarget", "File", "Headers", "MessageChannel", "MessageEvent", "MessagePort", "Request", "Response", "TextDecoder", "TextDecoderStream", "TextEncoder", "TextEncoderStream", "TransformStream", "TransformStreamDefaultController", "URLSearchParams", "ReadableStream", "WritableStream", "WritableStreamDefaultWriter", "WritableStreamDefaultController", "CountQueuingStrategy", "ByteLengthQueuingStrategy"],
|
||||
"npmSupported": ["Buffer", "URL"],
|
||||
"absent": ["BroadcastChannel", "CloseEvent", "CompressionStream", "CryptoKey", "DecompressionStream", "EventSource", "FormData", "Navigator", "ReadableByteStreamController", "ReadableStreamBYOBReader", "ReadableStreamBYOBRequest", "Storage", "SubtleCrypto", "TextEncoderStream", "TransformStreamDefaultController", "URLPattern", "WebAssembly", "WebSocket"],
|
||||
"absent": ["BroadcastChannel", "CloseEvent", "CompressionStream", "CryptoKey", "DecompressionStream", "EventSource", "FormData", "Navigator", "ReadableByteStreamController", "ReadableStreamBYOBReader", "ReadableStreamBYOBRequest", "Storage", "SubtleCrypto", "URLPattern", "WebAssembly", "WebSocket"],
|
||||
"evidence": ["tests/harness/web-globals.test.ts"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
"implement": 80
|
||||
},
|
||||
"dynamic": {
|
||||
"audit-partial": 885,
|
||||
"verify-gap": 2145,
|
||||
"audit-partial": 900,
|
||||
"verify-gap": 2132,
|
||||
"replace-refusal": 112,
|
||||
"implement": 208
|
||||
"implement": 206
|
||||
}
|
||||
},
|
||||
"priorities": {
|
||||
@@ -45608,11 +45608,11 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "implement",
|
||||
"verification": "verified-absence",
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-global-absent:TextEncoderStream",
|
||||
"source": "island-global:TextEncoderStream",
|
||||
"tests": [
|
||||
"tests/harness/web-globals.test.ts"
|
||||
]
|
||||
@@ -45678,11 +45678,11 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "implement",
|
||||
"verification": "verified-absence",
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-global-absent:TransformStreamDefaultController",
|
||||
"source": "island-global:TransformStreamDefaultController",
|
||||
"tests": [
|
||||
"tests/harness/web-globals.test.ts"
|
||||
]
|
||||
@@ -104244,7 +104244,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -104372,12 +104377,16 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "island-unmatched:webstreams",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-feature:webstreams.readableStream.pipeThrough",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -104405,12 +104414,16 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "island-unmatched:webstreams",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-feature:webstreams.readableStream.pipeTo",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -105376,7 +105389,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -105562,7 +105580,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -105859,7 +105882,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -105971,7 +105999,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -106000,12 +106033,15 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "island-unmatched:webstreams",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-feature:webstreams.readable",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -106033,12 +106069,15 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "island-unmatched:webstreams",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-feature:webstreams.writable",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -106066,12 +106105,22 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "island-unmatched:webstreams",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-export:node:stream/web.TransformStreamDefaultController",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -106099,12 +106148,14 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "island-unmatched:webstreams",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-feature:webstreams.transformStreamDefaultController.enqueue",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -106132,12 +106183,14 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "island-unmatched:webstreams",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-feature:webstreams.transformStreamDefaultController.error",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -106165,12 +106218,14 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "island-unmatched:webstreams",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-feature:webstreams.transformStreamDefaultController.terminate",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -106198,12 +106253,14 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "island-unmatched:webstreams",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-feature:webstreams.desiredSize",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -106240,7 +106297,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -106352,7 +106414,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -106455,12 +106522,22 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "island-unmatched:webstreams",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-export:node:stream/web.TextEncoderStream",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -106488,12 +106565,14 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "island-unmatched:webstreams",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-feature:webstreams.encoding",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -106521,12 +106600,14 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "island-unmatched:webstreams",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-feature:webstreams.readable",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -106554,12 +106635,14 @@
|
||||
"tests": []
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "island-unmatched:webstreams",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "island-feature:webstreams.writable",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -106596,7 +106679,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,9 +540,9 @@
|
||||
},
|
||||
"dynamic": {
|
||||
"supported": 0,
|
||||
"partial": 38,
|
||||
"partial": 40,
|
||||
"refused": 0,
|
||||
"not-implemented": 54,
|
||||
"not-implemented": 52,
|
||||
"by-design": 0,
|
||||
"unreviewed": 0,
|
||||
"not-applicable": 0
|
||||
@@ -1452,9 +1452,9 @@
|
||||
},
|
||||
"dynamic": {
|
||||
"supported": 0,
|
||||
"partial": 27,
|
||||
"partial": 40,
|
||||
"refused": 0,
|
||||
"not-implemented": 61,
|
||||
"not-implemented": 48,
|
||||
"by-design": 0,
|
||||
"unreviewed": 0,
|
||||
"not-applicable": 0
|
||||
@@ -61620,8 +61620,8 @@
|
||||
"evidence": "compiler-unmatched:globals"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-global-absent:TextEncoderStream",
|
||||
"status": "partial",
|
||||
"evidence": "island-global:TextEncoderStream",
|
||||
"tests": [
|
||||
"tests/harness/web-globals.test.ts"
|
||||
]
|
||||
@@ -61680,8 +61680,8 @@
|
||||
"evidence": "compiler-unmatched:globals"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-global-absent:TransformStreamDefaultController",
|
||||
"status": "partial",
|
||||
"evidence": "island-global:TransformStreamDefaultController",
|
||||
"tests": [
|
||||
"tests/harness/web-globals.test.ts"
|
||||
]
|
||||
@@ -122757,9 +122757,14 @@
|
||||
"status": "partial",
|
||||
"evidence": "derived:descendants",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts"
|
||||
]
|
||||
},
|
||||
@@ -123063,7 +123068,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
@@ -123198,8 +123208,13 @@
|
||||
"evidence": "compiler-unmatched:webstreams"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-unmatched:webstreams"
|
||||
"status": "partial",
|
||||
"evidence": "island-feature:webstreams.readableStream.pipeThrough",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
},
|
||||
@@ -123225,8 +123240,13 @@
|
||||
"evidence": "compiler-unmatched:webstreams"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-unmatched:webstreams"
|
||||
"status": "partial",
|
||||
"evidence": "island-feature:webstreams.readableStream.pipeTo",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
},
|
||||
@@ -124021,7 +124041,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
@@ -124209,7 +124234,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
@@ -124466,7 +124496,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
@@ -124563,7 +124598,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
@@ -124617,8 +124657,12 @@
|
||||
"evidence": "compiler-unmatched:webstreams"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-unmatched:webstreams"
|
||||
"status": "partial",
|
||||
"evidence": "island-feature:webstreams.readable",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "ancestor"
|
||||
},
|
||||
@@ -124644,8 +124688,12 @@
|
||||
"evidence": "compiler-unmatched:webstreams"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-unmatched:webstreams"
|
||||
"status": "partial",
|
||||
"evidence": "island-feature:webstreams.writable",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "ancestor"
|
||||
},
|
||||
@@ -124671,8 +124719,19 @@
|
||||
"evidence": "compiler-unmatched:webstreams"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-unmatched:webstreams"
|
||||
"status": "partial",
|
||||
"evidence": "island-export:node:stream/web.TransformStreamDefaultController",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
},
|
||||
@@ -124698,8 +124757,11 @@
|
||||
"evidence": "compiler-unmatched:webstreams"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-unmatched:webstreams"
|
||||
"status": "partial",
|
||||
"evidence": "island-feature:webstreams.transformStreamDefaultController.enqueue",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
},
|
||||
@@ -124725,8 +124787,11 @@
|
||||
"evidence": "compiler-unmatched:webstreams"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-unmatched:webstreams"
|
||||
"status": "partial",
|
||||
"evidence": "island-feature:webstreams.transformStreamDefaultController.error",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
},
|
||||
@@ -124752,8 +124817,11 @@
|
||||
"evidence": "compiler-unmatched:webstreams"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-unmatched:webstreams"
|
||||
"status": "partial",
|
||||
"evidence": "island-feature:webstreams.transformStreamDefaultController.terminate",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
},
|
||||
@@ -124779,8 +124847,11 @@
|
||||
"evidence": "compiler-unmatched:webstreams"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-unmatched:webstreams"
|
||||
"status": "partial",
|
||||
"evidence": "island-feature:webstreams.desiredSize",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "ancestor"
|
||||
},
|
||||
@@ -124812,7 +124883,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
@@ -124909,7 +124985,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
@@ -125000,8 +125081,19 @@
|
||||
"evidence": "compiler-unmatched:webstreams"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-unmatched:webstreams"
|
||||
"status": "partial",
|
||||
"evidence": "island-export:node:stream/web.TextEncoderStream",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
},
|
||||
@@ -125027,8 +125119,11 @@
|
||||
"evidence": "compiler-unmatched:webstreams"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-unmatched:webstreams"
|
||||
"status": "partial",
|
||||
"evidence": "island-feature:webstreams.encoding",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "ancestor"
|
||||
},
|
||||
@@ -125054,8 +125149,11 @@
|
||||
"evidence": "compiler-unmatched:webstreams"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-unmatched:webstreams"
|
||||
"status": "partial",
|
||||
"evidence": "island-feature:webstreams.readable",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "ancestor"
|
||||
},
|
||||
@@ -125081,8 +125179,11 @@
|
||||
"evidence": "compiler-unmatched:webstreams"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "island-unmatched:webstreams"
|
||||
"status": "partial",
|
||||
"evidence": "island-feature:webstreams.writable",
|
||||
"tests": [
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "ancestor"
|
||||
},
|
||||
@@ -125114,7 +125215,12 @@
|
||||
"tests/fixtures/npm/cases/web-streams/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-queues/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-lifecycle/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
"tests/fixtures/npm/cases/node24-web-stream-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts",
|
||||
"tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
|
||||
@@ -13811,6 +13811,36 @@
|
||||
"<repo>/tests/fixtures/npm/cases/node24-web-stream-errors/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts": {
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/node24-web-stream-pipes/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts": {
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/node24-web-stream-pipe-errors/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts": {
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/node24-web-stream-pipe-abort/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts": {
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/node24-web-stream-transforms/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts": {
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/node24-web-stream-encoding/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7536,7 +7536,8 @@ static const char isl_modules_bootstrap[] =
|
||||
" const g = globalThis;\n"
|
||||
" const w = {\n"
|
||||
" ReadableStream: g.ReadableStream, TransformStream: g.TransformStream,\n"
|
||||
" TextDecoderStream: g.TextDecoderStream,\n"
|
||||
" TextDecoderStream: g.TextDecoderStream, TextEncoderStream: g.TextEncoderStream,\n"
|
||||
" TransformStreamDefaultController: g.TransformStreamDefaultController,\n"
|
||||
" WritableStream: g.WritableStream, WritableStreamDefaultWriter: g.WritableStreamDefaultWriter,\n"
|
||||
" WritableStreamDefaultController: g.WritableStreamDefaultController,\n"
|
||||
" CountQueuingStrategy: g.CountQueuingStrategy, ByteLengthQueuingStrategy: g.ByteLengthQueuingStrategy,\n"
|
||||
|
||||
@@ -131,7 +131,8 @@ static const struct {
|
||||
"text,buffer,arrayBuffer,json,blob"},
|
||||
{"node:stream/web",
|
||||
"ReadableStream,TransformStream,TextDecoderStream,WritableStream,WritableStreamDefaultWri"
|
||||
"ter,WritableStreamDefaultController,CountQueuingStrategy,ByteLengthQueuingStrategy"},
|
||||
"ter,WritableStreamDefaultController,CountQueuingStrategy,ByteLengthQueuingStrategy,Trans"
|
||||
"formStreamDefaultController,TextEncoderStream"},
|
||||
{"node:crypto",
|
||||
"createHash,createHmac,hash,Hash,Hmac,randomBytes,randomFillSync,randomFill,randomInt,ran"
|
||||
"domUUID,getRandomValues,timingSafeEqual,pbkdf2,pbkdf2Sync,getHashes,getCiphers,getCurves"
|
||||
|
||||
+246
-73
@@ -426,6 +426,7 @@ static const char web_prelude[] =
|
||||
" g[C.name] = C;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" const readableStreams = new WeakSet();\n"
|
||||
" class ReadableStream {\n"
|
||||
" constructor(source, strategy) {\n"
|
||||
" if (source === undefined) source = {};\n"
|
||||
@@ -439,7 +440,7 @@ static const char web_prelude[] =
|
||||
" this._highWaterMark = sizing.highWaterMark;\n"
|
||||
" this._size = sizing.size;\n"
|
||||
" this._queueSize = 0;\n"
|
||||
" this._src = source;\n"
|
||||
" this._src = source; readableStreams.add(this);\n"
|
||||
" this._queue = [];\n"
|
||||
" this._state = 'readable';\n"
|
||||
" this._storedError = undefined;\n"
|
||||
@@ -540,7 +541,7 @@ static const char web_prelude[] =
|
||||
" this._closeRequested = true;\n"
|
||||
" this._finishClose();\n"
|
||||
" const src = this._src;\n"
|
||||
" return Promise.resolve(src.cancel ? src.cancel(reason) : undefined).then(() => undefined);\n"
|
||||
" return writableInvoke(src.cancel, src, [reason]).then(() => undefined);\n"
|
||||
" }\n"
|
||||
" getReader(options) {\n"
|
||||
" if (options !== undefined && options !== null && options.mode !== undefined) {\n"
|
||||
@@ -687,96 +688,237 @@ static const char web_prelude[] =
|
||||
" });\n"
|
||||
" }\n"
|
||||
" pipeThrough(transform, options) {\n"
|
||||
" if (transform === null || typeof transform !== 'object' || !transform.writable || !transform.readable) {\n"
|
||||
" throw new TypeError('pipeThrough requires a { writable, readable } pair');\n"
|
||||
" }\n"
|
||||
" if (options !== undefined && options !== null && options.signal !== undefined) {\n"
|
||||
" throw new Error('scriptc: AbortSignal is not supported by island streams yet');\n"
|
||||
" }\n"
|
||||
" pump(this, transform.writable);\n"
|
||||
" return transform.readable;\n"
|
||||
" if (!readableStreams.has(this)) throw streamInvalidThis('ReadableStream');\n"
|
||||
" const readable = transform?.readable;\n"
|
||||
" if (!readableStreams.has(readable)) throw streamArgument('transform.readable', 'an instance of ReadableStream', readable);\n"
|
||||
" const writable = transform?.writable;\n"
|
||||
" if (!writableStreams.has(writable)) throw streamArgument('transform.writable', 'an instance of WritableStream', writable);\n"
|
||||
" const opts = pipeOptions(options); pipeLocks(this, writable);\n"
|
||||
" pipeStreams(this, writable, opts).catch(() => {});\n"
|
||||
" return readable;\n"
|
||||
" }\n"
|
||||
" pipeTo() {\n"
|
||||
" throw new Error('ReadableStream.pipeTo is not supported in the scriptc island (use pipeThrough or a reader)');\n"
|
||||
" pipeTo(destination, options) {\n"
|
||||
" try {\n"
|
||||
" if (!readableStreams.has(this)) throw streamInvalidThis('ReadableStream');\n"
|
||||
" if (!writableStreams.has(destination)) throw streamArgument('transform.writable', 'an instance of WritableStream', destination);\n"
|
||||
" const opts = pipeOptions(options); pipeLocks(this, destination);\n"
|
||||
" return pipeStreams(this, destination, opts);\n"
|
||||
" } catch (e) { return Promise.reject(e); }\n"
|
||||
" }\n"
|
||||
" tee() {\n"
|
||||
" throw new Error('ReadableStream.tee is not supported in the scriptc island');\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" const pump = (rs, ws) => {\n"
|
||||
" const reader = rs.getReader();\n"
|
||||
" const writer = ws.getWriter();\n"
|
||||
" const step = () =>\n"
|
||||
" reader.read().then((r) => {\n"
|
||||
" if (r.done) return writer.close();\n"
|
||||
" return writer.write(r.value).then(step);\n"
|
||||
" const pipeOptions = (options) => {\n"
|
||||
" if (options !== undefined && options !== null && typeof options !== 'object' && typeof options !== 'function') throw streamArgument('options', 'of type object', options);\n"
|
||||
" const preventAbort = options?.preventAbort, preventCancel = options?.preventCancel, preventClose = options?.preventClose, signal = options?.signal;\n"
|
||||
" if (signal !== undefined && (signal === null || typeof signal !== 'object' || !('aborted' in signal))) throw streamArgument('options.signal', 'an instance of AbortSignal', signal);\n"
|
||||
" return { preventAbort: !!preventAbort, preventCancel: !!preventCancel, preventClose: !!preventClose, signal };\n"
|
||||
" };\n"
|
||||
" const pipeLocks = (source, dest) => {\n"
|
||||
" if (source._locked) throw streamInvalidState('The ReadableStream is locked');\n"
|
||||
" if (writableStreams.get(dest).writer !== undefined) throw streamInvalidState('The WritableStream is locked');\n"
|
||||
" };\n"
|
||||
" const pipeStreams = (source, dest, { preventClose, preventAbort, preventCancel, signal }) => {\n"
|
||||
" const reader = ReadableStream.prototype.getReader.call(source), writer = new WritableStreamDefaultWriter(dest), sink = writableStreams.get(dest);\n"
|
||||
" const completion = streamDeferred();\n"
|
||||
" let shuttingDown = false, currentWrite = Promise.resolve(), listening = false;\n"
|
||||
" const finalize = (rejected, error) => {\n"
|
||||
" writer.releaseLock(); reader.releaseLock();\n"
|
||||
" if (listening) signal.removeEventListener('abort', abort);\n"
|
||||
" if (rejected) completion.reject(error); else completion.resolve();\n"
|
||||
" };\n"
|
||||
" const waitForWrites = async () => {\n"
|
||||
" let write;\n"
|
||||
" do { write = currentWrite; await write; } while (write !== currentWrite);\n"
|
||||
" };\n"
|
||||
" const shutdown = (action, rejected = false, error) => {\n"
|
||||
" if (shuttingDown) return;\n"
|
||||
" shuttingDown = true;\n"
|
||||
" const waiting = sink.state === 'writable' && !sink.closeRequest ? waitForWrites() : Promise.resolve();\n"
|
||||
" waiting.then(() => action ? action() : undefined).then(\n"
|
||||
" () => finalize(rejected, error), (e) => finalize(true, e));\n"
|
||||
" };\n"
|
||||
" const abort = () => {\n"
|
||||
" const reason = signal.reason;\n"
|
||||
" shutdown(() => {\n"
|
||||
" const actions = [];\n"
|
||||
" if (!preventAbort && sink.state === 'writable') actions.push(writer.abort(reason));\n"
|
||||
" if (!preventCancel && source._state === 'readable') actions.push(reader.cancel(reason));\n"
|
||||
" return Promise.all(actions);\n"
|
||||
" }, true, reason);\n"
|
||||
" };\n"
|
||||
" const writeChunk = (chunk) => { currentWrite = writer.write(chunk); currentWrite.catch(() => {}); };\n"
|
||||
" // Buffered reads register their write before source.closed observers run. Pending\n"
|
||||
" // reads queue the write during enqueue, ahead of a subsequent close notification.\n"
|
||||
" const step = async () => {\n"
|
||||
" if (shuttingDown) return true;\n"
|
||||
" if (sink.backpressure) { await writer.ready; if (shuttingDown) return true; }\n"
|
||||
" if (source._state === 'readable' && source._queue.length) {\n"
|
||||
" while (source._queue.length) {\n"
|
||||
" if (shuttingDown) return true;\n"
|
||||
" const queued = source._queue.shift();\n"
|
||||
" source._queueSize = Math.max(0, source._queueSize - queued.size);\n"
|
||||
" if (source._closeRequested && !source._queue.length) source._finishClose();\n"
|
||||
" writeChunk(queued.chunk);\n"
|
||||
" if (sink.backpressure || sink.state !== 'writable' || sink.closeRequest) break;\n"
|
||||
" }\n"
|
||||
" source._maybePull();\n"
|
||||
" return source._state === 'closed';\n"
|
||||
" }\n"
|
||||
" if (source._state === 'closed') return true;\n"
|
||||
" if (source._state === 'errored') throw source._storedError;\n"
|
||||
" return new Promise((resolve, reject) => {\n"
|
||||
" source._reads.push({ resolve(r) {\n"
|
||||
" if (r.done) resolve(true);\n"
|
||||
" else Promise.resolve().then(() => { writeChunk(r.value); resolve(false); });\n"
|
||||
" }, reject });\n"
|
||||
" source._maybePull();\n"
|
||||
" });\n"
|
||||
" step().catch((e) => {\n"
|
||||
" writer.abort(e).catch(() => {});\n"
|
||||
" reader.cancel(e).catch(() => {});\n"
|
||||
" };\n"
|
||||
" if (signal !== undefined) {\n"
|
||||
" if (signal.aborted) { abort(); return completion.promise; }\n"
|
||||
" signal.addEventListener('abort', abort, { once: true, [Symbol.for('scriptc.events.resistStopPropagation')]: true });\n"
|
||||
" listening = true;\n"
|
||||
" }\n"
|
||||
" (async () => { while (!await step()); })().catch(() => {});\n"
|
||||
" const sourceError = (e) => shutdown(preventAbort ? undefined : () => writer.abort(e), true, e);\n"
|
||||
" const sinkError = (e) => shutdown(preventCancel ? undefined : () => reader.cancel(e), true, e);\n"
|
||||
" const sourceClose = () => shutdown(preventClose ? undefined : () => {\n"
|
||||
" if (sink.closeRequest || sink.state === 'closed') return;\n"
|
||||
" if (sink.state === 'errored') throw sink.error;\n"
|
||||
" return writer.close();\n"
|
||||
" });\n"
|
||||
" if (source._state === 'errored') sourceError(source._storedError); else reader.closed.catch(sourceError);\n"
|
||||
" if (sink.state === 'errored') sinkError(sink.error); else writer.closed.catch(sinkError);\n"
|
||||
" if (source._state === 'closed') sourceClose(); else reader.closed.then(sourceClose, () => {});\n"
|
||||
" if (sink.closeRequest || sink.state === 'closed') {\n"
|
||||
" const e = streamInvalidState('Destination WritableStream is closed');\n"
|
||||
" shutdown(preventCancel ? undefined : () => reader.cancel(e), true, e);\n"
|
||||
" }\n"
|
||||
" return completion.promise;\n"
|
||||
" };\n"
|
||||
"\n"
|
||||
" class TransformStream {\n"
|
||||
" constructor(transformer, ws, rs) {\n"
|
||||
" if (transformer === undefined || transformer === null) transformer = {};\n"
|
||||
" if (transformer.readableType !== undefined || transformer.writableType !== undefined) {\n"
|
||||
" throw new RangeError('readableType/writableType are not supported in the scriptc island');\n"
|
||||
" const transformStreams = new WeakMap(), transformControllers = new WeakMap();\n"
|
||||
" const transformToken = Symbol('TransformStreamDefaultController');\n"
|
||||
" const transformPressure = (s, pressure) => {\n"
|
||||
" if (s.change) s.change.resolve();\n"
|
||||
" s.change = streamDeferred(); s.backpressure = pressure;\n"
|
||||
" };\n"
|
||||
" const transformClear = (s) => { s.transform = s.flush = s.cancel = undefined; };\n"
|
||||
" const transformUnblock = (s) => { if (s.backpressure) transformPressure(s, false); };\n"
|
||||
" const transformErrorWritable = (s, e) => {\n"
|
||||
" transformClear(s);\n"
|
||||
" const w = writableStreams.get(s.writable);\n"
|
||||
" if (w.state === 'writable') { writableClear(w); writableError(w, e); }\n"
|
||||
" transformUnblock(s);\n"
|
||||
" };\n"
|
||||
" const transformError = (s, e) => { s.readable._errorStream(e); transformErrorWritable(s, e); };\n"
|
||||
" const transformFinish = (s, kind, reason) => {\n"
|
||||
" if (s.finish) return s.finish;\n"
|
||||
" const d = streamDeferred(); s.finish = d.promise;\n"
|
||||
" const result = writableInvoke(kind === 'close' ? s.flush : s.cancel, s.transformer, kind === 'close' ? [s.controller] : [reason]);\n"
|
||||
" transformClear(s);\n"
|
||||
" result.then(() => {\n"
|
||||
" if (kind === 'cancel') {\n"
|
||||
" const w = writableStreams.get(s.writable);\n"
|
||||
" if (w.state === 'errored') { d.reject(w.error); return; }\n"
|
||||
" transformErrorWritable(s, reason);\n"
|
||||
" } else {\n"
|
||||
" if (s.readable._state === 'errored') { d.reject(s.readable._storedError); return; }\n"
|
||||
" if (kind === 'close') { if (s.readable._state === 'readable' && !s.readable._closeRequested) s.readable._controller.close(); }\n"
|
||||
" else s.readable._errorStream(reason);\n"
|
||||
" }\n"
|
||||
" const t = transformer;\n"
|
||||
" const self = this;\n"
|
||||
" let rc = null;\n"
|
||||
" this._readable = new ReadableStream({\n"
|
||||
" start(c) { rc = c; },\n"
|
||||
" cancel(reason) { writableError(writableStreams.get(self._writable), reason); },\n"
|
||||
" }, rs == null ? { highWaterMark: 0 } : rs);\n"
|
||||
" const tc = {\n"
|
||||
" enqueue(chunk) { rc.enqueue(chunk); },\n"
|
||||
" error(e) {\n"
|
||||
" self._readable._errorStream(e);\n"
|
||||
" writableError(writableStreams.get(self._writable), e);\n"
|
||||
" },\n"
|
||||
" terminate() {\n"
|
||||
" if (self._readable._state === 'readable' && !self._readable._closeRequested) rc.close();\n"
|
||||
" writableError(writableStreams.get(self._writable), new TypeError('The transform stream has been terminated'));\n"
|
||||
" },\n"
|
||||
" get desiredSize() { return rc.desiredSize; },\n"
|
||||
" };\n"
|
||||
" this._controller = tc;\n"
|
||||
" d.resolve();\n"
|
||||
" }, (e) => {\n"
|
||||
" if (kind === 'cancel') transformErrorWritable(s, e); else s.readable._errorStream(e);\n"
|
||||
" d.reject(e);\n"
|
||||
" }).catch((e) => d.reject(e));\n"
|
||||
" return s.finish;\n"
|
||||
" };\n"
|
||||
" class TransformStreamDefaultController {\n"
|
||||
" constructor(token, stream) {\n"
|
||||
" if (token !== transformToken) throw streamError(TypeError, 'ERR_ILLEGAL_CONSTRUCTOR', 'Illegal constructor');\n"
|
||||
" transformControllers.set(this, stream);\n"
|
||||
" }\n"
|
||||
" get desiredSize() {\n"
|
||||
" const s = transformControllers.get(this);\n"
|
||||
" if (!s) throw streamInvalidThis('TransformStreamDefaultController');\n"
|
||||
" return s.readable._controller.desiredSize;\n"
|
||||
" }\n"
|
||||
" enqueue(chunk) {\n"
|
||||
" const s = transformControllers.get(this);\n"
|
||||
" if (!s) throw streamInvalidThis('TransformStreamDefaultController');\n"
|
||||
" const r = s.readable;\n"
|
||||
" if (r._state !== 'readable' || r._closeRequested) throw streamInvalidState('Unable to enqueue');\n"
|
||||
" try { r._controller.enqueue(chunk); }\n"
|
||||
" catch (e) { transformErrorWritable(s, e); throw r._storedError; }\n"
|
||||
" if (!r._reads.length && r._controller.desiredSize <= 0 && !s.backpressure) transformPressure(s, true);\n"
|
||||
" }\n"
|
||||
" error(e) {\n"
|
||||
" const s = transformControllers.get(this);\n"
|
||||
" if (!s) throw streamInvalidThis('TransformStreamDefaultController');\n"
|
||||
" transformError(s, e);\n"
|
||||
" }\n"
|
||||
" terminate() {\n"
|
||||
" const s = transformControllers.get(this);\n"
|
||||
" if (!s) throw streamInvalidThis('TransformStreamDefaultController');\n"
|
||||
" if (s.readable._state === 'readable' && !s.readable._closeRequested) s.readable._controller.close();\n"
|
||||
" transformErrorWritable(s, streamInvalidState('TransformStream has been terminated'));\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" class TransformStream {\n"
|
||||
" constructor(transformer = {}, ws, rs) {\n"
|
||||
" if (transformer === null || (typeof transformer !== 'object' && typeof transformer !== 'function')) throw streamArgument('transformer', 'of type object', transformer);\n"
|
||||
" for (const [name, value] of [['writableStrategy', ws], ['readableStrategy', rs]]) {\n"
|
||||
" if (value !== undefined && value !== null && typeof value !== 'object' && typeof value !== 'function') throw streamArgument(name, 'of type object', value);\n"
|
||||
" }\n"
|
||||
" const readableType = transformer.readableType, writableType = transformer.writableType, start = transformer.start;\n"
|
||||
" if (readableType !== undefined) throw streamInvalidValue('transformer.readableType', readableType);\n"
|
||||
" if (writableType !== undefined) throw streamInvalidValue('transformer.writableType', writableType);\n"
|
||||
" const readableSizing = streamStrategy(rs, 0), writableSizing = streamStrategy(ws, 1);\n"
|
||||
" const s = { transformer, finish: undefined, backpressure: true };\n"
|
||||
" transformPressure(s, true); transformStreams.set(this, s);\n"
|
||||
" let resolveStart;\n"
|
||||
" const startGate = new Promise((resolve) => { resolveStart = resolve; });\n"
|
||||
" this._writable = new WritableStream({\n"
|
||||
" s.writable = new WritableStream({\n"
|
||||
" start() { return startGate; },\n"
|
||||
" /* Eager transform: writes run the transformer immediately (no\n"
|
||||
" * readable-side backpressure) — order-exact, documented. */\n"
|
||||
" write(chunk) {\n"
|
||||
" let r;\n"
|
||||
" try { r = t.transform ? t.transform(chunk, tc) : tc.enqueue(chunk); } catch (e) { tc.error(e); throw e; }\n"
|
||||
" return Promise.resolve(r).catch((e) => { tc.error(e); throw e; });\n"
|
||||
" async write(chunk) {\n"
|
||||
" if (s.backpressure) {\n"
|
||||
" await s.change.promise;\n"
|
||||
" const w = writableStreams.get(s.writable);\n"
|
||||
" if (w.state === 'erroring' || w.state === 'errored') throw w.error;\n"
|
||||
" }\n"
|
||||
" try { if (s.transform) await s.transform.call(transformer, chunk, s.controller); }\n"
|
||||
" catch (e) { transformError(s, e); throw e; }\n"
|
||||
" },\n"
|
||||
" close() {\n"
|
||||
" let r;\n"
|
||||
" try { r = t.flush ? t.flush(tc) : undefined; } catch (e) { tc.error(e); throw e; }\n"
|
||||
" return Promise.resolve(r).then(\n"
|
||||
" () => {\n"
|
||||
" if (self._readable._state === 'readable' && !self._readable._closeRequested) rc.close();\n"
|
||||
" },\n"
|
||||
" (e) => { tc.error(e); throw e; },\n"
|
||||
" );\n"
|
||||
" },\n"
|
||||
" abort(e) { self._readable._errorStream(e); },\n"
|
||||
" }, ws);\n"
|
||||
" const startResult = t.start ? t.start(tc) : undefined; // synchronous invocation\n"
|
||||
" resolveStart(Promise.resolve(startResult).catch((e) => { tc.error(e); throw e; }));\n"
|
||||
" close() { return transformFinish(s, 'close'); },\n"
|
||||
" abort(reason) { return transformFinish(s, 'abort', reason); },\n"
|
||||
" }, writableSizing);\n"
|
||||
" s.readable = new ReadableStream({\n"
|
||||
" start() { return startGate; },\n"
|
||||
" pull() { transformPressure(s, false); return s.change.promise; },\n"
|
||||
" cancel(reason) { return transformFinish(s, 'cancel', reason); },\n"
|
||||
" }, readableSizing);\n"
|
||||
" s.controller = new TransformStreamDefaultController(transformToken, s);\n"
|
||||
" const transform = transformer.transform, flush = transformer.flush, cancel = transformer.cancel;\n"
|
||||
" for (const [name, fn] of [['transform', transform], ['flush', flush], ['cancel', cancel]]) {\n"
|
||||
" if (fn && typeof fn !== 'function') throw streamArgument('transformer.' + name, 'of type function', fn);\n"
|
||||
" }\n"
|
||||
" s.transform = transform || ((chunk, controller) => controller.enqueue(chunk)); s.flush = flush; s.cancel = cancel;\n"
|
||||
" const startResult = start === undefined ? undefined : start.call(transformer, s.controller);\n"
|
||||
" resolveStart(Promise.resolve(startResult).catch((e) => { transformError(s, e); throw e; }));\n"
|
||||
" }\n"
|
||||
" get readable() { return this._readable; }\n"
|
||||
" get writable() { return this._writable; }\n"
|
||||
" get readable() { const s = transformStreams.get(this); if (!s) throw streamInvalidThis('TransformStream'); return s.readable; }\n"
|
||||
" get writable() { const s = transformStreams.get(this); if (!s) throw streamInvalidThis('TransformStream'); return s.writable; }\n"
|
||||
" }\n"
|
||||
" for (const C of [TransformStream, TransformStreamDefaultController]) {\n"
|
||||
" Object.defineProperty(C.prototype, Symbol.toStringTag, { value: C.name, configurable: true });\n"
|
||||
" for (const name of Object.getOwnPropertyNames(C.prototype)) if (name !== 'constructor') Object.defineProperty(C.prototype, name, { enumerable: true });\n"
|
||||
" g[C.name] = C;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" g.ReadableStream = ReadableStream;\n"
|
||||
" g.TransformStream = TransformStream;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" const textEncoders = new WeakSet();\n"
|
||||
" class TextEncoder {\n"
|
||||
@@ -916,6 +1058,37 @@ static const char web_prelude[] =
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" class TextEncoderStream {\n"
|
||||
" #transform;\n"
|
||||
" constructor() {\n"
|
||||
" const encoder = new TextEncoder();\n"
|
||||
" let pending = null;\n"
|
||||
" this.#transform = new TransformStream({\n"
|
||||
" transform(chunk, controller) {\n"
|
||||
" chunk = String(chunk);\n"
|
||||
" let text = '';\n"
|
||||
" for (let i = 0; i < chunk.length; i++) {\n"
|
||||
" const unit = chunk.charCodeAt(i), item = chunk[i];\n"
|
||||
" if (pending !== null) {\n"
|
||||
" const high = pending; pending = null;\n"
|
||||
" if (unit >= 0xdc00 && unit <= 0xdfff) { text += high + item; continue; }\n"
|
||||
" text += '\\ufffd';\n"
|
||||
" }\n"
|
||||
" if (unit >= 0xd800 && unit <= 0xdbff) pending = item;\n"
|
||||
" else text += unit >= 0xdc00 && unit <= 0xdfff ? '\\ufffd' : item;\n"
|
||||
" }\n"
|
||||
" if (text) controller.enqueue(encoder.encode(text));\n"
|
||||
" },\n"
|
||||
" flush(controller) { if (pending !== null) controller.enqueue(new Uint8Array([0xef, 0xbf, 0xbd])); },\n"
|
||||
" });\n"
|
||||
" }\n"
|
||||
" get encoding() { this.#transform; return 'utf-8'; }\n"
|
||||
" get readable() { return this.#transform.readable; }\n"
|
||||
" get writable() { return this.#transform.writable; }\n"
|
||||
" }\n"
|
||||
" for (const name of ['encoding', 'readable', 'writable']) Object.defineProperty(TextEncoderStream.prototype, name, { enumerable: true });\n"
|
||||
" g.TextEncoderStream = TextEncoderStream;\n"
|
||||
"\n"
|
||||
" class TextDecoderStream extends g.TransformStream {\n"
|
||||
" constructor(label, options) {\n"
|
||||
" const dec = new TextDecoder(label, options);\n"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// @dynamic
|
||||
// @stderr
|
||||
import { reportEncoding } from "node24-web-stream-fixture/encoding.js";
|
||||
reportEncoding();
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"module"}
|
||||
@@ -0,0 +1,4 @@
|
||||
// @dynamic
|
||||
// @stderr
|
||||
import { reportPipeAbort } from "node24-web-stream-fixture/pipe-abort.js";
|
||||
reportPipeAbort();
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"module"}
|
||||
@@ -0,0 +1,4 @@
|
||||
// @dynamic
|
||||
// @stderr
|
||||
import { reportPipeErrors } from "node24-web-stream-fixture/pipe-errors.js";
|
||||
reportPipeErrors();
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"module"}
|
||||
@@ -0,0 +1,4 @@
|
||||
// @dynamic
|
||||
// @stderr
|
||||
import { reportPipes } from "node24-web-stream-fixture/pipes.js";
|
||||
reportPipes();
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"module"}
|
||||
@@ -0,0 +1,4 @@
|
||||
// @dynamic
|
||||
// @stderr
|
||||
import { reportTransforms } from "node24-web-stream-fixture/transforms.js";
|
||||
reportTransforms();
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"module"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export declare function reportEncoding(): void;
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import { ReadableStream, WritableStream, TextEncoderStream, TextDecoderStream, TransformStream } from "node:stream/web";
|
||||
import { out, result, sameError, launch } from "./helpers.js";
|
||||
|
||||
export function reportEncoding() { launch(async () => {
|
||||
const encode = async (values) => {
|
||||
const got = [];
|
||||
await ReadableStream.from(values).pipeThrough(new TextEncoderStream()).pipeTo(new WritableStream({ write(v) { got.push([...v].join(",")); } }));
|
||||
return got.join(" | ");
|
||||
};
|
||||
const encoder = new TextEncoderStream();
|
||||
out("encoder", TextEncoderStream === globalThis.TextEncoderStream, encoder.encoding, encoder.readable instanceof ReadableStream, encoder.writable instanceof WritableStream, encoder instanceof TransformStream, Object.prototype.toString.call(encoder), Object.keys(TextEncoderStream.prototype).join(","));
|
||||
await encoder.writable.close();
|
||||
out("ascii", await encode(["hello", "", " world"]));
|
||||
out("surrogate", await encode(["A\ud83d", "", "\ude00B", "\ud800", "x\udc00", "\udbff"]));
|
||||
out("surrogate-pairs", await encode(["\ud800", "\ud801", "\udc00", "\udc01"]));
|
||||
out("empty", await encode(["", ""]));
|
||||
out("coercion", await encode([undefined, null, false, 42, 3n, Symbol("x"), { toString() { return "object"; } }]));
|
||||
{
|
||||
const got = [];
|
||||
await ReadableStream.from(["Hello ", "\ud83d", "\ude00", "!"]).pipeThrough(new TextEncoderStream()).pipeThrough(new TextDecoderStream()).pipeTo(new WritableStream({ write(v) { got.push(v); } }));
|
||||
out("roundtrip", got.join(""));
|
||||
}
|
||||
{
|
||||
const reason = new Error("coercion"), t = new TextEncoderStream(), w = t.writable.getWriter(), r = t.readable.getReader();
|
||||
const read = sameError(r.read(), reason), write = sameError(w.write({ toString() { throw reason; } }), reason);
|
||||
out("encoding-error", await write, await read, await sameError(w.closed, reason), await sameError(r.closed, reason));
|
||||
}
|
||||
for (const name of ["encoding", "readable", "writable"]) {
|
||||
try { Object.getOwnPropertyDescriptor(TextEncoderStream.prototype, name).get.call({}); out("brand", name, false); }
|
||||
catch (e) { out("brand", name, e instanceof TypeError); }
|
||||
}
|
||||
}); }
|
||||
+1
@@ -0,0 +1 @@
|
||||
export declare function reportPipeAbort(): void;
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
import { ReadableStream, WritableStream, TransformStream } from "node:stream/web";
|
||||
import { out, deferred, sameError, launch } from "./helpers.js";
|
||||
|
||||
export function reportPipeAbort() { launch(async () => {
|
||||
for (const preventAbort of [false, true]) for (const preventCancel of [false, true]) {
|
||||
const controller = new AbortController(), reason = new Error("pre-abort"), log = [];
|
||||
controller.abort(reason);
|
||||
const source = new ReadableStream({ cancel(e) { log.push("cancel:" + (e === reason)); } }, { highWaterMark: 0 });
|
||||
const sink = new WritableStream({ write() { log.push("write"); }, abort(e) { log.push("abort:" + (e === reason)); } });
|
||||
out("pre-abort", preventAbort, preventCancel, await sameError(source.pipeTo(sink, { signal: controller.signal, preventAbort, preventCancel }), reason), log.sort().join(","), source.locked, sink.locked);
|
||||
if (preventCancel) await source.cancel(); if (preventAbort) await sink.close();
|
||||
}
|
||||
{
|
||||
const controller = new AbortController(), source = new ReadableStream({ pull() { throw new Error("read before destination capacity"); } }, { highWaterMark: 0 });
|
||||
let writes = 0;
|
||||
const sink = new WritableStream({ write() { writes++; } }, { highWaterMark: 0 });
|
||||
const p = source.pipeTo(sink, { signal: controller.signal });
|
||||
await new Promise(resolve => setTimeout(resolve, 0)); controller.abort();
|
||||
out("zero-sink", await sameError(p, controller.signal.reason), controller.signal.reason.name, writes, source.locked, sink.locked);
|
||||
}
|
||||
{
|
||||
const entered = deferred(), controller = new AbortController(), reason = new Error("pending-read"), log = [];
|
||||
controller.signal.addEventListener("abort", e => { log.push("stopped"); e.stopImmediatePropagation(); });
|
||||
const source = new ReadableStream({ pull() { entered.resolve(); }, cancel(e) { log.push("cancel:" + (e === reason)); } }, { highWaterMark: 0 });
|
||||
const sink = new WritableStream({ abort(e) { log.push("abort:" + (e === reason)); } });
|
||||
const p = source.pipeTo(sink, { signal: controller.signal }); await entered.promise; controller.abort(reason);
|
||||
out("read-abort", await sameError(p, reason), log.sort().join(","), source.locked, sink.locked);
|
||||
}
|
||||
{
|
||||
const entered = deferred(), gate = deferred(), controller = new AbortController(), reason = new Error("pending-write"), log = [];
|
||||
const source = new ReadableStream({ start(c) { c.enqueue("a"); c.enqueue("b"); }, cancel(e) { log.push("cancel:" + (e === reason)); } });
|
||||
const sink = new WritableStream({ async write(v) { log.push("write:" + v); entered.resolve(); await gate.promise; log.push("written"); }, abort(e) { log.push("abort:" + (e === reason)); } });
|
||||
const p = source.pipeTo(sink, { signal: controller.signal }); await entered.promise; controller.abort(reason);
|
||||
await Promise.resolve(); out("write-abort-waits", log.join(","), source.locked, sink.locked);
|
||||
gate.resolve(); out("write-abort", await sameError(p, reason), log.sort().join(","), source.locked, sink.locked);
|
||||
}
|
||||
for (const fails of ["abort", "cancel"]) {
|
||||
const controller = new AbortController(), reason = new Error("reason"), cleanup = new Error("cleanup");
|
||||
const source = new ReadableStream({ cancel() { if (fails === "cancel") return Promise.reject(cleanup); } });
|
||||
const sink = new WritableStream({ abort() { if (fails === "abort") return Promise.reject(cleanup); } });
|
||||
controller.abort(reason);
|
||||
out("abort-cleanup", fails, await sameError(source.pipeTo(sink, { signal: controller.signal }), cleanup), source.locked, sink.locked);
|
||||
}
|
||||
{
|
||||
const controller = new AbortController(), reason = new Error("through-abort"), entered = deferred();
|
||||
const source = new ReadableStream({ pull() { entered.resolve(); }, cancel(e) { out("through-cancel", e === reason); } }, { highWaterMark: 0 });
|
||||
const t = new TransformStream(), output = source.pipeThrough(t, { signal: controller.signal });
|
||||
const reader = output.getReader(), read = sameError(reader.read(), reason);
|
||||
await entered.promise; controller.abort(reason); out("through-abort", await read, await sameError(reader.closed, reason));
|
||||
reader.releaseLock(); await new Promise(resolve => setTimeout(resolve, 0));
|
||||
out("through-unlocked", source.locked, t.writable.locked);
|
||||
}
|
||||
}); }
|
||||
+1
@@ -0,0 +1 @@
|
||||
export declare function reportPipeErrors(): void;
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
import { ReadableStream, WritableStream } from "node:stream/web";
|
||||
import { out, deferred, result, sameError, launch } from "./helpers.js";
|
||||
|
||||
export function reportPipeErrors() { launch(async () => {
|
||||
for (const preventAbort of [false, true]) for (const cleanupFails of [false, true]) {
|
||||
const reason = new Error("source"), cleanup = new Error("abort"), log = [];
|
||||
const source = new ReadableStream({ start(c) { c.error(reason); } });
|
||||
const sink = new WritableStream({ abort(e) { log.push(e === reason); if (cleanupFails) throw cleanup; } });
|
||||
const p = source.pipeTo(sink, { preventAbort });
|
||||
out("source-error", preventAbort, cleanupFails, await sameError(p, cleanupFails && !preventAbort ? cleanup : reason), log.join(","), source.locked, sink.locked);
|
||||
if (preventAbort) await sink.close();
|
||||
}
|
||||
for (const preventCancel of [false, true]) for (const cleanupFails of [false, true]) {
|
||||
const reason = new Error("sink"), cleanup = new Error("cancel"), log = [];
|
||||
const source = new ReadableStream({ start(c) { c.enqueue("chunk"); }, cancel(e) { log.push(e === reason); if (cleanupFails) throw cleanup; } });
|
||||
const sink = new WritableStream({ write() { throw reason; } });
|
||||
out("sink-error", preventCancel, cleanupFails, await sameError(source.pipeTo(sink, { preventCancel }), cleanupFails && !preventCancel ? cleanup : reason), log.join(","), source.locked, sink.locked);
|
||||
if (preventCancel) await result(source.cancel());
|
||||
}
|
||||
{
|
||||
const reason = new Error("already"), source = new ReadableStream({ cancel(e) { out("initial-cancel", e === reason); } });
|
||||
const sink = new WritableStream({ start(c) { c.error(reason); } });
|
||||
out("initial-error", await sameError(source.pipeTo(sink), reason), source.locked, sink.locked);
|
||||
}
|
||||
{
|
||||
const entered = deferred(), gate = deferred(), log = []; let controller;
|
||||
const reason = new Error("during-write");
|
||||
const source = new ReadableStream({ start(c) { controller = c; c.enqueue("a"); } });
|
||||
const sink = new WritableStream({ async write(v) { log.push(v); entered.resolve(); await gate.promise; log.push("written"); }, abort(e) { log.push("abort:" + (e === reason)); } });
|
||||
const p = sameError(source.pipeTo(sink), reason); await entered.promise; controller.error(reason);
|
||||
await Promise.resolve(); out("error-waits", log.join(","), source.locked, sink.locked);
|
||||
gate.resolve(); out("error-done", await p, log.join(","), source.locked, sink.locked);
|
||||
}
|
||||
{
|
||||
let controller; const entered = deferred(), reason = new Error("idle-destination");
|
||||
const source = new ReadableStream({ pull() { entered.resolve(); }, cancel(e) { out("idle-cancel", e === reason); } }, { highWaterMark: 0 });
|
||||
const sink = new WritableStream({ start(c) { controller = c; } });
|
||||
const p = source.pipeTo(sink); await entered.promise; controller.error(reason);
|
||||
out("idle-error", await sameError(p, reason), source.locked, sink.locked);
|
||||
}
|
||||
{
|
||||
const reason = new Error("close"), source = ReadableStream.from(["last"]);
|
||||
const sink = new WritableStream({ write(v) { out("close-last", v); }, close() { throw reason; } });
|
||||
out("close-error", await sameError(source.pipeTo(sink), reason), source.locked, sink.locked);
|
||||
}
|
||||
}); }
|
||||
+1
@@ -0,0 +1 @@
|
||||
export declare function reportPipes(): void;
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
import { ReadableStream, WritableStream, TransformStream } from "node:stream/web";
|
||||
import { out, deferred, result, caught, launch } from "./helpers.js";
|
||||
|
||||
export function reportPipes() { launch(async () => {
|
||||
for (const highWaterMark of [1, 4]) {
|
||||
const log = [];
|
||||
const source = new ReadableStream({ start(c) { for (const v of [1, 2, 3]) c.enqueue(v); c.close(); } });
|
||||
const sink = new WritableStream({ write(v) { log.push(v); }, close() { log.push("closed"); } }, { highWaterMark });
|
||||
const p = source.pipeTo(sink);
|
||||
out("locks", highWaterMark, source.locked, sink.locked);
|
||||
out("pipe", await p, log.join(","), source.locked, sink.locked);
|
||||
}
|
||||
{
|
||||
let controller;
|
||||
const source = new ReadableStream({ start(c) { controller = c; } }, { highWaterMark: 0 });
|
||||
const got = [], sink = new WritableStream({ write(v) { got.push(v); }, close() { got.push("close"); } });
|
||||
const p = source.pipeTo(sink);
|
||||
controller.enqueue("last"); controller.close(); await p;
|
||||
out("pending-last", got.join(","), source.locked, sink.locked);
|
||||
}
|
||||
{
|
||||
const entered = deferred(), gate = deferred(), log = [];
|
||||
const source = new ReadableStream({ start(c) { c.enqueue("last"); c.close(); } });
|
||||
const sink = new WritableStream({ async write(v) { log.push(v); entered.resolve(); await gate.promise; log.push("written"); }, close() { log.push("closed"); } });
|
||||
const p = source.pipeTo(sink); await entered.promise;
|
||||
out("final-inflight", log.join(","), source.locked, sink.locked);
|
||||
gate.resolve(); await p; out("final-settled", log.join(","), source.locked, sink.locked);
|
||||
}
|
||||
{
|
||||
const entered = deferred(), gate = deferred(); let pulls = 0;
|
||||
const source = new ReadableStream({ pull(c) { c.enqueue(++pulls); if (pulls === 3) c.close(); } }, { highWaterMark: 0 });
|
||||
const got = [], sink = new WritableStream({ async write(v) { got.push(v); if (v === 1) { entered.resolve(); await gate.promise; } } });
|
||||
const p = source.pipeTo(sink); await entered.promise;
|
||||
out("pipe-demand", pulls, got.join(",")); gate.resolve(); await p;
|
||||
out("pipe-drain", pulls, got.join(","));
|
||||
}
|
||||
for (const preventClose of [false, true]) {
|
||||
const log = [], source = ReadableStream.from(["a", "b"]);
|
||||
const sink = new WritableStream({ write(v) { log.push(v); }, close() { log.push("close"); } });
|
||||
await source.pipeTo(sink, { preventClose });
|
||||
out("prevent-close", preventClose, log.join(","), source.locked, sink.locked);
|
||||
const w = sink.getWriter(); out("after-pipe", await result(w.write("later")));
|
||||
if (preventClose) await w.close(); w.releaseLock();
|
||||
}
|
||||
{
|
||||
const source = ReadableStream.from([1, 2]);
|
||||
const twice = new TransformStream({ transform(v, c) { c.enqueue(v * 2); } });
|
||||
const plus = new TransformStream({ transform(v, c) { c.enqueue(v + 1); }, flush(c) { c.enqueue("flush"); } });
|
||||
const got = [], sink = new WritableStream({ write(v) { got.push(v); } });
|
||||
const output = source.pipeThrough(twice).pipeThrough(plus);
|
||||
out("chain-locked", source.locked, twice.writable.locked, twice.readable.locked, plus.writable.locked, output === plus.readable);
|
||||
await output.pipeTo(sink);
|
||||
out("chain", got.join(","), ...[source, twice.writable, twice.readable, plus.writable, plus.readable, sink].map(s => s.locked));
|
||||
}
|
||||
{
|
||||
const source = ReadableStream.from(["kept-open"]), t = new TransformStream();
|
||||
const output = source.pipeThrough(t, { preventClose: true }), reader = output.getReader();
|
||||
out("through-prevent-close", (await reader.read()).value);
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
out("through-released", source.locked, t.writable.locked);
|
||||
await t.writable.close(); out("through-manual-close", (await reader.read()).done); reader.releaseLock();
|
||||
}
|
||||
{
|
||||
const got = [], source = ReadableStream.from(["internal"]), sink = new WritableStream({ write(v) { got.push(v); } });
|
||||
source.getReader = sink.getWriter = () => { throw new Error("public acquisition override"); };
|
||||
await source.pipeTo(sink); out("internal-locks", got.join(","), source.locked, sink.locked);
|
||||
}
|
||||
{
|
||||
const order = [], source = new ReadableStream({ start(c) { c.close(); } }), sink = new WritableStream();
|
||||
const options = Object.fromEntries(["preventAbort", "preventCancel", "preventClose", "signal"].map(name => [name, undefined]));
|
||||
for (const name of Object.keys(options)) Object.defineProperty(options, name, { get() { order.push(name); return undefined; } });
|
||||
await source.pipeTo(sink, options); out("option-order", order.join(","));
|
||||
}
|
||||
for (const options of [null, [], () => {}]) {
|
||||
const source = new ReadableStream({ start(c) { c.close(); } });
|
||||
out("option-object", await result(source.pipeTo(new WritableStream(), options)));
|
||||
}
|
||||
out("invalid-source", await result(ReadableStream.prototype.pipeTo.call({}, new WritableStream())));
|
||||
out("invalid-destination", await result(new ReadableStream().pipeTo({})));
|
||||
out("invalid-options", await result(new ReadableStream().pipeTo(new WritableStream(), 1)));
|
||||
out("invalid-signal", await result(new ReadableStream().pipeTo(new WritableStream(), { signal: null })));
|
||||
out("invalid-through", caught(() => new ReadableStream().pipeThrough({})), caught(() => new ReadableStream().pipeThrough({ readable: new ReadableStream(), writable: {} })));
|
||||
{
|
||||
const source = new ReadableStream(), sink = new WritableStream(), r = source.getReader();
|
||||
out("locked-source", await result(source.pipeTo(sink)), caught(() => source.pipeThrough({ readable: new ReadableStream(), writable: sink })), sink.locked);
|
||||
r.releaseLock(); const w = sink.getWriter();
|
||||
out("locked-sink", await result(source.pipeTo(sink)), source.locked); w.releaseLock();
|
||||
}
|
||||
for (const closing of [false, true]) {
|
||||
const gate = deferred(), reason = deferred();
|
||||
const sink = new WritableStream({ close() { return gate.promise; } });
|
||||
const close = sink.close(); if (!closing) { gate.resolve(); await close; }
|
||||
const source = new ReadableStream({ cancel(e) { reason.resolve(e); } });
|
||||
const p = source.pipeTo(sink);
|
||||
out("closed-destination", closing, await result(p), (await reason.promise).code, source.locked, sink.locked);
|
||||
gate.resolve(); await close;
|
||||
}
|
||||
}); }
|
||||
+1
@@ -0,0 +1 @@
|
||||
export declare function reportTransforms(): void;
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
import { TransformStream, TransformStreamDefaultController, ByteLengthQueuingStrategy } from "node:stream/web";
|
||||
import { out, deferred, result, caught, sameError, launch } from "./helpers.js";
|
||||
|
||||
export function reportTransforms() { launch(async () => {
|
||||
out("controller-export", TransformStreamDefaultController === globalThis.TransformStreamDefaultController, caught(() => new TransformStreamDefaultController()));
|
||||
out("controller-brand", ...["enqueue", "error", "terminate"].map(name => caught(() => TransformStreamDefaultController.prototype[name].call({}))), caught(() => Object.getOwnPropertyDescriptor(TransformStreamDefaultController.prototype, "desiredSize").get.call({})));
|
||||
out("transform-brand", ...["readable", "writable"].map(name => caught(() => Object.getOwnPropertyDescriptor(TransformStream.prototype, name).get.call({}))));
|
||||
{
|
||||
let controller, transformed = 0;
|
||||
const t = new TransformStream({ start(c) { controller = c; }, transform(v, c) { transformed++; c.enqueue(v); } });
|
||||
const w = t.writable.getWriter(), r = t.readable.getReader();
|
||||
const first = w.write("a"), second = w.write("b");
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
out("no-demand", transformed, controller.desiredSize, w.desiredSize, controller instanceof TransformStreamDefaultController, Object.prototype.toString.call(controller));
|
||||
out("first-demand", (await r.read()).value); await first;
|
||||
out("one-demand", transformed, controller.desiredSize);
|
||||
out("second-demand", (await r.read()).value); await second;
|
||||
await w.close(); out("demand-closed", (await r.read()).done, controller.desiredSize, await result(w.closed));
|
||||
out("enqueue-closed", caught(() => controller.enqueue("late")));
|
||||
}
|
||||
{
|
||||
const entered = deferred(); let controller, transformed = 0;
|
||||
const t = new TransformStream({ start(c) { controller = c; }, transform(v, c) { transformed++; c.enqueue(v); if (transformed === 2) entered.resolve(); } }, undefined, new ByteLengthQueuingStrategy({ highWaterMark: 4 }));
|
||||
const w = t.writable.getWriter(), r = t.readable.getReader();
|
||||
const writes = [w.write(new Uint8Array(3)), w.write(new Uint8Array(2)), w.write(new Uint8Array(1))];
|
||||
await entered.promise; await writes[1];
|
||||
out("transform-capacity", transformed, controller.desiredSize);
|
||||
out("sized-read", (await r.read()).value.byteLength); await writes[2];
|
||||
out("transform-resumed", transformed, controller.desiredSize);
|
||||
const close = w.close(), got = []; for (;;) { const v = await r.read(); if (v.done) break; got.push(v.value.byteLength); } await close;
|
||||
out("sized-rest", got.join(","));
|
||||
}
|
||||
{
|
||||
const start = deferred(), flush = deferred(), entered = deferred(), log = [];
|
||||
const transformer = { start(c) { log.push("start:" + (this === transformer)); c.enqueue("start"); return start.promise; }, transform(v, c) { log.push("transform:" + (this === transformer)); c.enqueue(v); }, async flush(c) { log.push("flush:" + (this === transformer)); entered.resolve(); await flush.promise; c.enqueue("flush"); } };
|
||||
const t = new TransformStream(transformer), w = t.writable.getWriter(), r = t.readable.getReader();
|
||||
transformer.transform = () => { throw new Error("changed"); }; transformer.flush = transformer.transform;
|
||||
const write = w.write("value"); out("start-buffer", (await r.read()).value, log.join(","));
|
||||
const read = r.read(); start.resolve(); out("start-release", (await read).value); await write;
|
||||
const close = w.close(); await entered.promise; out("flush-pending", log.join(","));
|
||||
const final = r.read(); flush.resolve(); out("flush-value", (await final).value); await close; out("flush-done", (await r.read()).done);
|
||||
}
|
||||
for (const kind of ["error", "terminate", "cancel"]) {
|
||||
let c; const reason = new Error("controller-error");
|
||||
const t = new TransformStream({ start(controller) { c = controller; } });
|
||||
const w = t.writable.getWriter(), r = t.readable.getReader();
|
||||
const write = result(w.write("blocked")); await new Promise(resolve => setTimeout(resolve, 0));
|
||||
if (kind === "error") c.error(reason);
|
||||
if (kind === "terminate") c.terminate();
|
||||
if (kind === "cancel") await r.cancel(reason);
|
||||
out("unblock", kind, await write, await result(w.closed), await result(r.read()), c.desiredSize);
|
||||
}
|
||||
for (const kind of ["transform", "flush", "start"]) {
|
||||
const reason = new Error(kind), t = new TransformStream({ [kind]() { return Promise.reject(reason); } });
|
||||
const w = t.writable.getWriter(), r = t.readable.getReader(), read = sameError(r.read(), reason);
|
||||
if (kind === "transform") out("transform-failure", await sameError(w.write("x"), reason));
|
||||
if (kind === "flush") out("flush-failure", await sameError(w.close(), reason));
|
||||
out("both-error", kind, await read, await sameError(w.closed, reason), await sameError(r.closed, reason));
|
||||
}
|
||||
for (const direction of ["readable", "writable"]) for (const fails of [false, true]) {
|
||||
const entered = deferred(), gate = deferred(), reason = new Error("cancel"), failure = new Error("cancel-failure"), log = [];
|
||||
const transformer = { cancel(e) { log.push(this === transformer && e === reason); entered.resolve(); return gate.promise; } };
|
||||
const t = new TransformStream(transformer), w = t.writable.getWriter(), r = t.readable.getReader();
|
||||
transformer.cancel = () => { throw new Error("changed"); };
|
||||
const end = direction === "readable" ? r.cancel(reason) : w.abort(reason);
|
||||
await entered.promise; out("cancel-wait", direction, fails, log.join(","));
|
||||
if (fails) gate.reject(failure); else gate.resolve();
|
||||
out("cancel-end", direction, fails, await result(end), await sameError(direction === "readable" ? w.closed : r.closed, fails ? failure : reason));
|
||||
}
|
||||
{
|
||||
const entered = deferred(), gate = deferred(), reason = new Error("race"), log = [];
|
||||
const t = new TransformStream({ async flush() { log.push("flush"); entered.resolve(); await gate.promise; }, cancel() { log.push("cancel"); } });
|
||||
const w = t.writable.getWriter(), r = t.readable.getReader(), close = result(w.close());
|
||||
await entered.promise; const cancel = result(r.cancel(reason)); gate.resolve();
|
||||
out("flush-cancel-race", await close, await cancel, log.join(","), await result(w.closed), (await r.read()).done);
|
||||
}
|
||||
}); }
|
||||
@@ -136,16 +136,16 @@ describe(`island web globals (scriptc-only${sanitize ? ", sanitized" : ""})`, ()
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.stderr).toBe("");
|
||||
expect(result.stdout.trimEnd()).toBe(
|
||||
"function function function function function function function true false true true false false true",
|
||||
"function function function function function function function true true true true false false true",
|
||||
);
|
||||
});
|
||||
|
||||
test("writable stream constructors and strategies are installed without an npm graph", async () => {
|
||||
test("stream constructors and strategies are installed without an npm graph", async () => {
|
||||
const out = await islandEval(
|
||||
"web-writable-presence",
|
||||
`[typeof WritableStream, typeof WritableStreamDefaultWriter, typeof WritableStreamDefaultController, typeof CountQueuingStrategy, typeof ByteLengthQueuingStrategy].join(' ')`,
|
||||
`[typeof WritableStream, typeof WritableStreamDefaultWriter, typeof WritableStreamDefaultController, typeof CountQueuingStrategy, typeof ByteLengthQueuingStrategy, typeof TransformStreamDefaultController, typeof TextEncoderStream].join(' ')`,
|
||||
);
|
||||
expect(out).toBe("function function function function function");
|
||||
expect(out).toBe("function function function function function function function");
|
||||
});
|
||||
|
||||
test("structuredClone clones deep (cycles included) and validates options like Node", async () => {
|
||||
@@ -201,14 +201,13 @@ describe(`island web globals (scriptc-only${sanitize ? ", sanitized" : ""})`, ()
|
||||
expect(out).toBe("function function true true");
|
||||
});
|
||||
|
||||
test("tee, pipeTo, BYOB readers, and byte streams are fenced with clear errors", async () => {
|
||||
test("tee, BYOB readers, and byte streams are fenced with clear errors", async () => {
|
||||
const out = await islandEval(
|
||||
"web-fences",
|
||||
`(() => {
|
||||
const grab = (f) => { try { f(); return 'no-throw'; } catch (e) { return e.message; } };
|
||||
return [
|
||||
grab(() => new ReadableStream().tee()),
|
||||
grab(() => new ReadableStream().pipeTo({})),
|
||||
grab(() => new ReadableStream().getReader({ mode: 'byob' })),
|
||||
grab(() => new ReadableStream({ type: 'bytes' })),
|
||||
].join(' | ');
|
||||
@@ -217,7 +216,6 @@ describe(`island web globals (scriptc-only${sanitize ? ", sanitized" : ""})`, ()
|
||||
expect(out).toBe(
|
||||
[
|
||||
"ReadableStream.tee is not supported in the scriptc island",
|
||||
"ReadableStream.pipeTo is not supported in the scriptc island (use pipeThrough or a reader)",
|
||||
"BYOB readers are not supported in the scriptc island",
|
||||
"byte streams (type: 'bytes') are not supported in the scriptc island",
|
||||
].join(" | "),
|
||||
|
||||
Reference in New Issue
Block a user