diff --git a/JS/wasm/assets/wasmjs/wit/http-types.wit b/JS/wasm/assets/wasmjs/wit/http-types.wit index 2f5f9d9a6..41c3ecee1 100644 --- a/JS/wasm/assets/wasmjs/wit/http-types.wit +++ b/JS/wasm/assets/wasmjs/wit/http-types.wit @@ -38,4 +38,8 @@ enum http-error { internal-error, timeout, redirect-loop, -} \ No newline at end of file +} +enum file-error { + not-found, + invalid-path, +} diff --git a/JS/wasm/assets/wasmjs/wit/http.wit b/JS/wasm/assets/wasmjs/wit/http.wit index 36450be50..df2a5f05b 100644 --- a/JS/wasm/assets/wasmjs/wit/http.wit +++ b/JS/wasm/assets/wasmjs/wit/http.wit @@ -1,2 +1,4 @@ use * from http-types send-http-request: func(request: http-request) -> expected +parse-jsonnet: func(file: string) -> expected +read-bytes: func(file: string) -> expected diff --git a/JS/wasm/crates/wasmjs-engine/Cargo.lock b/JS/wasm/crates/wasmjs-engine/Cargo.lock index 36caa85ca..f950d0ccb 100644 --- a/JS/wasm/crates/wasmjs-engine/Cargo.lock +++ b/JS/wasm/crates/wasmjs-engine/Cargo.lock @@ -13,19 +13,19 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "59d2a3357dde987206219e78ecfbbb6e8dad06cbb65292758d3270e6254f7355" [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.42", ] [[package]] @@ -218,11 +218,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -478,9 +478,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" [[package]] name = "proc-macro2" @@ -677,7 +677,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.42", ] [[package]] @@ -720,9 +720,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.41" +version = "2.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" +checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8" dependencies = [ "proc-macro2", "quote", diff --git a/JS/wasm/crates/wasmjs-engine/package-lock.json b/JS/wasm/crates/wasmjs-engine/package-lock.json index 42532ba21..706944852 100644 --- a/JS/wasm/crates/wasmjs-engine/package-lock.json +++ b/JS/wasm/crates/wasmjs-engine/package-lock.json @@ -1,6 +1,6 @@ { - "name": "wasmjs-engine", - "lockfileVersion": 3, - "requires": true, - "packages": {} + "name": "wasmjs-engine", + "lockfileVersion": 3, + "requires": true, + "packages": {} } diff --git a/JS/wasm/crates/wasmjs-engine/shims/build.js b/JS/wasm/crates/wasmjs-engine/shims/build.js index 152ed75b8..87f18d436 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/build.js +++ b/JS/wasm/crates/wasmjs-engine/shims/build.js @@ -1,55 +1,68 @@ -import { build } from "esbuild"; +import { build } from 'esbuild' // Build for index.js build({ - entryPoints: ["src/index.js"], - bundle: true, - outfile: "dist/index.js", - format: "esm", - target: "esnext", - platform: "node", - treeShaking: false, + entryPoints: ['src/index.js'], + bundle: true, + outfile: 'dist/index.js', + format: "esm", + target: "esnext", + platform: "node", + treeShaking: false }).catch((error) => { - console.error(error); - process.exit(1); -}); + console.error(error) + process.exit(1) +}) // Build for buffer.js build({ - entryPoints: ["src/buffer.js"], - bundle: true, - outfile: "dist/buffer.js", - format: "esm", - target: "esnext", - platform: "node", - treeShaking: false, + entryPoints: ['src/buffer.js'], + bundle: true, + outfile: 'dist/buffer.js', + format: "esm", + target: "esnext", + platform: "node", + treeShaking: false }).catch((error) => { - console.error(error); - process.exit(1); -}); + console.error(error) + process.exit(1) +}) build({ - entryPoints: ["src/path.js"], - bundle: true, - outfile: "dist/path.js", - format: "esm", - target: "esnext", - platform: "node", - treeShaking: false, + entryPoints: ['src/path.js'], + bundle: true, + outfile: 'dist/path.js', + format: "esm", + target: "esnext", + platform: "node", + treeShaking: false }).catch((error) => { - console.error(error); - process.exit(1); -}); + console.error(error) + process.exit(1) +}) build({ - entryPoints: ["src/crypto.ts"], - bundle: true, - outfile: "dist/crypto.js", - format: "esm", - target: "esnext", - platform: "node", - treeShaking: false, + entryPoints: ['src/crypto.ts'], + bundle: true, + outfile: 'dist/crypto.js', + format: "esm", + target: "esnext", + platform: "node", + treeShaking: false }).catch((error) => { - console.error(error); - process.exit(1); -}); + console.error(error) + process.exit(1) +}) + +build({ + entryPoints: ['src/arakoo-jsonnet.js'], + bundle: true, + outfile: 'dist/arakoo-jsonnet.js', + format: "esm", + target: "esnext", + platform: "node", + treeShaking: false +}).catch((error) => { + console.error(error) + process.exit(1) +}) diff --git a/JS/wasm/crates/wasmjs-engine/shims/package.json b/JS/wasm/crates/wasmjs-engine/shims/package.json index da05da7b5..6d90997f4 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/package.json +++ b/JS/wasm/crates/wasmjs-engine/shims/package.json @@ -14,7 +14,7 @@ "buffer": "^6.0.3", "esbuild": "^0.19", "http-status": "^1.7", - "query-string": "^7.1.1", + "query-string": "^7.1.1", "sjcl": "^1.0.8", "url-parse": "^1.5.10" }, diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/arakoo-jsonnet.js b/JS/wasm/crates/wasmjs-engine/shims/src/arakoo-jsonnet.js new file mode 100644 index 000000000..bbb4e9df9 --- /dev/null +++ b/JS/wasm/crates/wasmjs-engine/shims/src/arakoo-jsonnet.js @@ -0,0 +1,5 @@ +const parseJsonnet = globalThis.parseJsonnet + +export { + parseJsonnet, +} diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/buffer.js b/JS/wasm/crates/wasmjs-engine/shims/src/buffer.js index 5d9131bf5..1dd28191f 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/buffer.js +++ b/JS/wasm/crates/wasmjs-engine/shims/src/buffer.js @@ -1,12 +1,19 @@ + import { constants, kMaxLength, kStringMaxLength, Buffer, SlowBuffer, -} from "./internal/internal_buffer"; +} from './internal/internal_buffer'; -export { constants, kMaxLength, kStringMaxLength, Buffer, SlowBuffer }; +export { + constants, + kMaxLength, + kStringMaxLength, + Buffer, + SlowBuffer, +}; export default { constants, @@ -14,4 +21,4 @@ export default { kStringMaxLength, Buffer, SlowBuffer, -}; +} \ No newline at end of file diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/crypto.ts b/JS/wasm/crates/wasmjs-engine/shims/src/crypto.ts index f176cf637..0d504c138 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/crypto.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/crypto.ts @@ -1,4 +1,6 @@ -import { ERR_METHOD_NOT_IMPLEMENTED } from "./internal/internal_errors"; +import { + ERR_METHOD_NOT_IMPLEMENTED +} from './internal/internal_errors'; // export const getRandomValues = crypto.getRandomValues; // export const subtle = crypto.subtle; @@ -6,236 +8,209 @@ import { ERR_METHOD_NOT_IMPLEMENTED } from "./internal/internal_errors"; // export const webcrypto = crypto; import { - DiffieHellman, - DiffieHellmanGroup, - createDiffieHellman, - createDiffieHellmanGroup, - getDiffieHellman, -} from "./internal/crypto_dh"; + DiffieHellman, + DiffieHellmanGroup, + createDiffieHellman, + createDiffieHellmanGroup, + getDiffieHellman, +} from './internal/crypto_dh'; import { - randomBytes, - randomFillSync, - randomFill, - randomInt, - randomUUID, - PrimeNum, - GeneratePrimeOptions, - CheckPrimeOptions, - generatePrime, - generatePrimeSync, - checkPrime, - checkPrimeSync, -} from "./internal/crypto_random"; + randomBytes, + randomFillSync, + randomFill, + randomInt, + randomUUID, + PrimeNum, + GeneratePrimeOptions, + CheckPrimeOptions, + generatePrime, + generatePrimeSync, + checkPrime, + checkPrimeSync, +} from './internal/crypto_random'; -import { createHash, createHmac, Hash, HashOptions, Hmac } from "./internal/crypto_hash"; +import { + createHash, + createHmac, + Hash, + HashOptions, + Hmac, +} from './internal/crypto_hash'; -import { hkdf, hkdfSync } from "./internal/crypto_hkdf"; +import { + hkdf, + hkdfSync, +} from './internal/crypto_hkdf'; -import { pbkdf2, pbkdf2Sync, ArrayLike } from "./internal/crypto_pbkdf2"; +import { + pbkdf2, + pbkdf2Sync, + ArrayLike, +} from './internal/crypto_pbkdf2'; import { - KeyObject, - PublicKeyObject, - PrivateKeyObject, - SecretKeyObject, - generateKey, - generateKeyPair, - generateKeyPairSync, - generateKeySync, - createPrivateKey, - createPublicKey, - createSecretKey, -} from "./internal/crypto_keys"; + KeyObject, + PublicKeyObject, + PrivateKeyObject, + SecretKeyObject, + generateKey, + generateKeyPair, + generateKeyPairSync, + generateKeySync, + createPrivateKey, + createPublicKey, + createSecretKey, +} from './internal/crypto_keys'; export { - // DH - DiffieHellman, - DiffieHellmanGroup, - createDiffieHellman, - createDiffieHellmanGroup, - getDiffieHellman, - // Random - randomBytes, - randomFillSync, - randomFill, - randomInt, - randomUUID, - // Primes - PrimeNum as primeNum, - GeneratePrimeOptions as generatePrimeOptions, - CheckPrimeOptions as checkPrimeOptions, - generatePrime, - generatePrimeSync, - checkPrime, - checkPrimeSync, - // Hash and Hmac - createHash, - createHmac, - Hash, - HashOptions, - Hmac, - // Hkdf - hkdf, - hkdfSync, - // Pbkdf2 - pbkdf2, - pbkdf2Sync, - ArrayLike as arrayLike, - // Keys - KeyObject, - PublicKeyObject, - PrivateKeyObject, - SecretKeyObject, - generateKey, - generateKeyPair, - generateKeyPairSync, - generateKeySync, - createPrivateKey, - createPublicKey, - createSecretKey, -}; + // DH + DiffieHellman, + DiffieHellmanGroup, + createDiffieHellman, + createDiffieHellmanGroup, + getDiffieHellman, + // Random + randomBytes, + randomFillSync, + randomFill, + randomInt, + randomUUID, + // Primes + PrimeNum as primeNum, + GeneratePrimeOptions as generatePrimeOptions, + CheckPrimeOptions as checkPrimeOptions, + generatePrime, + generatePrimeSync, + checkPrime, + checkPrimeSync, + // Hash and Hmac + createHash, + createHmac, + Hash, + HashOptions, + Hmac, + // Hkdf + hkdf, + hkdfSync, + // Pbkdf2 + pbkdf2, + pbkdf2Sync, + ArrayLike as arrayLike, + // Keys + KeyObject, + PublicKeyObject, + PrivateKeyObject, + SecretKeyObject, + generateKey, + generateKeyPair, + generateKeyPairSync, + generateKeySync, + createPrivateKey, + createPublicKey, + createSecretKey, +} export function getCiphers() { - return [ - "aes-128-cbc", - "aes-192-cbc", - "aes-256-cbc", - "aes-128-ctr", - "aes-192-ctr", - "aes-256-ctr", - "aes-128-ecb", - "aes-192-ecb", - "aes-256-ecb", - "aes-128-gcm", - "aes-192-gcm", - "aes-256-gcm", - "aes-128-ofb", - "aes-192-ofb", - "aes-256-ofb", - "des-ecb", - "des-ede", - "des-ede-cbc", - "rc2-cbc", - ]; + return ["aes-128-cbc", "aes-192-cbc", "aes-256-cbc", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", + "aes-128-ecb", "aes-192-ecb", "aes-256-ecb", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", + "aes-128-ofb", "aes-192-ofb", "aes-256-ofb", "des-ecb", "des-ede", "des-ede-cbc", "rc2-cbc"]; } export function getCurves() { - // Hardcoded list of supported curves. Note that prime256v1 is equivalent to secp256r1, we follow - // OpenSSL's and bssl's nomenclature here. - return ["secp224r1", "prime256v1", "secp384r1", "secp521r1"]; + // Hardcoded list of supported curves. Note that prime256v1 is equivalent to secp256r1, we follow + // OpenSSL's and bssl's nomenclature here. + return ['secp224r1', 'prime256v1', 'secp384r1', 'secp521r1']; } export function getHashes() { - // Hardcoded list of hashes supported in boringssl, node's approach looks pretty clunky. This is - // expected to change infrequently based of bssl's stability-focused approach. - return [ - "md4", - "md5", - "sha1", - "sha224", - "sha256", - "sha384", - "sha512", - "md5-sha1", - "RSA-MD5", - "RSA-SHA1", - "RSA-SHA224", - "RSA-SHA256", - "RSA-SHA384", - "RSA-SHA512", - "DSA-SHA", - "DSA-SHA1", - "ecdsa-with-SHA1", - ]; + // Hardcoded list of hashes supported in boringssl, node's approach looks pretty clunky. This is + // expected to change infrequently based of bssl's stability-focused approach. + return ['md4', 'md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5-sha1', 'RSA-MD5', + 'RSA-SHA1', 'RSA-SHA224', 'RSA-SHA256', 'RSA-SHA384', 'RSA-SHA512', 'DSA-SHA', + 'DSA-SHA1', 'ecdsa-with-SHA1']; } // We do not implement the openssl secure heap. export function secureHeapUsed() { - return { - total: 0, - used: 0, - utilization: 0, - min: 0, - }; + return { + total: 0, + used: 0, + utilization: 0, + min: 0, + } } // We do not allow users to set the engine used. -export function setEngine(_1: string, _2?: number) { - throw new ERR_METHOD_NOT_IMPLEMENTED("setEngine"); +export function setEngine(_1 : string, _2?: number) { + throw new ERR_METHOD_NOT_IMPLEMENTED('setEngine'); } // We do not allow users to modify the FIPS enablement. export function setFips(_: boolean) { - throw new ERR_METHOD_NOT_IMPLEMENTED("setFips"); + throw new ERR_METHOD_NOT_IMPLEMENTED('setFips'); } // We always run in FIPS mode. export const fips = true; -export function getFips() { - return fips; -} +export function getFips() { return fips; } export default { - // DH - DiffieHellman, - DiffieHellmanGroup, - createDiffieHellman, - createDiffieHellmanGroup, - getDiffieHellman, - // Keys, - KeyObject, - PublicKeyObject, - PrivateKeyObject, - SecretKeyObject, - generateKey, - generateKeyPair, - generateKeyPairSync, - generateKeySync, - createPrivateKey, - createPublicKey, - createSecretKey, - // Random - // getRandomValues, - randomBytes, - randomFillSync, - randomFill, - randomInt, - randomUUID, - generatePrime, - generatePrimeSync, - checkPrime, - checkPrimeSync, - // Hash and Hmac - Hash, - Hmac, - createHash, - createHmac, - getHashes, - // Hkdf - hkdf, - hkdfSync, - // Pbkdf2 - pbkdf2, - pbkdf2Sync, - // Misc - getCiphers, - getCurves, - secureHeapUsed, - setEngine, - // timingSafeEqual, - // Fips - getFips, - setFips, - get fips() { - return getFips(); - }, - set fips(_: boolean) { - setFips(_); - }, - // WebCrypto - // subtle, - // webcrypto, + // DH + DiffieHellman, + DiffieHellmanGroup, + createDiffieHellman, + createDiffieHellmanGroup, + getDiffieHellman, + // Keys, + KeyObject, + PublicKeyObject, + PrivateKeyObject, + SecretKeyObject, + generateKey, + generateKeyPair, + generateKeyPairSync, + generateKeySync, + createPrivateKey, + createPublicKey, + createSecretKey, + // Random + // getRandomValues, + randomBytes, + randomFillSync, + randomFill, + randomInt, + randomUUID, + generatePrime, + generatePrimeSync, + checkPrime, + checkPrimeSync, + // Hash and Hmac + Hash, + Hmac, + createHash, + createHmac, + getHashes, + // Hkdf + hkdf, + hkdfSync, + // Pbkdf2 + pbkdf2, + pbkdf2Sync, + // Misc + getCiphers, + getCurves, + secureHeapUsed, + setEngine, + // timingSafeEqual, + // Fips + getFips, + setFips, + get fips() { return getFips(); }, + set fips(_: boolean) { setFips(_); }, + // WebCrypto + // subtle, + // webcrypto, }; // Classes @@ -319,3 +294,4 @@ export default { // * WebCrypto // * [x] crypto.subtle // * [x] crypto.webcrypto + diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/events.ts b/JS/wasm/crates/wasmjs-engine/shims/src/events.ts index 1772e3e84..938ed3c44 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/events.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/events.ts @@ -3,5 +3,5 @@ // https://opensource.org/licenses/Apache-2.0 // -export * from "./internal/events"; -export { default } from "./internal/events"; +export * from './internal/events'; +export { default } from './internal/events'; diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/index.js b/JS/wasm/crates/wasmjs-engine/shims/src/index.js index 2fa1129e0..9c29c339f 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/index.js +++ b/JS/wasm/crates/wasmjs-engine/shims/src/index.js @@ -1,110 +1,112 @@ // import { URLSearchParams } from "@ungap/url-search-params"; import { TextEncoder, TextDecoder } from "@sinonjs/text-encoding"; import httpStatus from "http-status"; -import Url from "url-parse"; -import _queryString from "query-string"; +import Url from 'url-parse' +import _queryString from 'query-string'; class URL { + constructor(urlStr, base = undefined) { - let url = Url(urlStr, base); - this.url = url; - this.protocol = url.protocol; - this.slashes = url.slashes; - this.auth = url.auth; - this.username = url.username; - this.password = url.password; - this.host = url.host; - this.port = url.port; - this.pathname = url.pathname; - this.search = url.query; - this.searchParams = new URLSearchParams(this.search); - this.hash = url.hash; - this.href = url.origin; - this.origin = url.origin; + let url = Url(urlStr, base) + this.url = url + this.protocol = url.protocol + this.slashes = url.slashes + this.auth = url.auth + this.username = url.username + this.password = url.password + this.host = url.host + this.port = url.port + this.pathname = url.pathname + this.search = url.query + this.searchParams = new URLSearchParams(this.search) + this.hash = url.hash + this.href = url.origin + this.origin = url.origin } set(key, value) { - this.url.set(key, value); + this.url.set(key, value) } toString() { - return this.url.toString(); + return this.url.toString() } toJson() { - return this.url.toString(); + return this.url.toString() } + } class URLSearchParams { - queryParams = {}; + queryParams = {} constructor(val) { this.queryParams = { - ..._queryString.parse(val), - }; + ..._queryString.parse(val) + } } append(key, val) { - this.queryParams[key] = val; + this.queryParams[key] = val } delete(key) { - delete this.queryParams[key]; + delete this.queryParams[key] } entries() { - let arr = []; - Object.entries(this.queryParams).map((o) => { + let arr = [] + Object.entries(this.queryParams).map(o => { if (Array.isArray(o[1])) { - o[1].map((k) => { - arr.push([o[0], k]); - }); + o[1].map(k => { + arr.push([o[0], k]) + }) } else { - arr.push([o[0], o[1]]); + arr.push([o[0], o[1]]) } - }); - let iterLength = arr.length; - let iterIndex = 0; + }) + let iterLength = arr.length + let iterIndex = 0 return { next: function () { - return iterIndex < iterLength - ? { value: arr[iterIndex++], done: false } - : { done: true }; - }, - }; + return iterIndex < iterLength ? + { value: arr[iterIndex++], done: false } : + { done: true }; + } + } } get(key) { - let val = this.queryParams[key]; + let val = this.queryParams[key] if (val) { - if (typeof val == "object") { - return val[0]; + if (typeof (val) == "object") { + return val[0] } - return val; + return val } - return null; + return null } getAll(key) { - let val = this.queryParams[key]; + let val = this.queryParams[key] if (val) { - return val; + return val } - return null; + return null } has(key) { - return this.queryParams[key] != undefined ? true : false; + return this.queryParams[key] != undefined ? true : false } keys() { - return Object.keys(this.queryParams); + return Object.keys(this.queryParams) } set(key, val) { - this.queryParams[key] = val; + this.queryParams[key] = val } toString() { - return _queryString.stringify(this.queryParams); + return _queryString.stringify(this.queryParams) } values() { - return Object.keys(this.queryParams).map((k) => this.queryParams[k]); + return Object.keys(this.queryParams).map(k => this.queryParams[k]) } [Symbol.iterator]() { - return this.entries(); + return this.entries() } } @@ -112,11 +114,11 @@ globalThis.URL = URL; globalThis.URLSearchParams = URLSearchParams; function atob(b64) { - return Buffer.from(b64, "base64").toString(); + return Buffer.from(b64, "base64").toString() } function btoa(data) { - return Buffer.from(data).toString("base64"); + return Buffer.from(data).toString('base64') } globalThis.btoa = btoa; @@ -205,9 +207,9 @@ class Response { return new Response(`Redirecting to ${url}`, { status, headers: { - Location: url, - }, - }); + Location: url + } + }) } get ok() { @@ -278,14 +280,14 @@ class Response { method: "GET", headers: {}, body: null, - ...opts, + ...opts }; if (optsWithDefault.body !== null && typeof optsWithDefault.body !== "string") { try { optsWithDefault.body = new TextEncoder().encode(optsWithDefault.body); } catch (e) { - return Promise.reject(`err: ${e}`); + return Promise.reject(`err: ${e}`) } } @@ -297,11 +299,12 @@ class Response { let response = new Response(result.body, { headers: result.headers, status: result.status, - }); + }) return Promise.resolve(response); } - }; + } + globalThis.console = { error(msg) { @@ -321,8 +324,8 @@ class Response { }, trace(msg) { this.log(msg); - }, - }; + } + } Reflect.deleteProperty(globalThis, "__send_http_request"); Reflect.deleteProperty(globalThis, "__console_log"); @@ -337,27 +340,28 @@ globalThis.addEventListener = (_eventName, handler) => { handlerFunction = handler; }; -const requestToHandler = (input) => { +const requestToHandler = input => { const request = new Request(input); const event = { request, response: {}, respondWith(res) { this.response = res; - }, + } }; try { handlerFunction(event); - Promise.resolve(event.response) - .then((res) => { - result = { - data: res.body, - headers: res.headers.headers, - status: res.status, - }; - }) + Promise.resolve( + event.response + ).then(res => { + result = { + data: res.body, + headers: res.headers.headers, + status: res.status, + }; + }) .catch((err) => { error = `err: \n${err}`; }); @@ -368,4 +372,4 @@ const requestToHandler = (input) => { globalThis.entrypoint = requestToHandler; globalThis.result = {}; -globalThis.error = null; +globalThis.error = null diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/async_hooks.d.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/async_hooks.d.ts index 6f02fb827..4e97d10a0 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/async_hooks.d.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/async_hooks.d.ts @@ -1,26 +1,22 @@ // Type definitions for c++ implementation. export interface AsyncResourceOptions { - triggerAsyncId?: number; + triggerAsyncId?: number; } export class AsyncResource { - public constructor(type: string, options?: AsyncResourceOptions); - public runInAsyncScope(fn: (...args: unknown[]) => R, ...args: unknown[]): R; + public constructor(type: string, options?: AsyncResourceOptions); + public runInAsyncScope(fn: (...args: unknown[]) => R, ...args: unknown[]): R; - public bind unknown>( - fn: Func - ): Func & { asyncResource: AsyncResource }; + public bind unknown>( + fn: Func): Func & { asyncResource: AsyncResource; }; - public static bind unknown, ThisArg>( - fn: Func, - type?: string, - thisArg?: ThisArg - ): Func & { asyncResource: AsyncResource }; + public static bind unknown, ThisArg>( + fn: Func, type?: string, thisArg?: ThisArg): Func & { asyncResource: AsyncResource; }; } export class AsyncLocalStorage { - public run(store: T, fn: (...args: unknown[]) => R, ...args: unknown[]): R; - public exit(fn: (...args: unknown[]) => R, ...args: unknown[]): R; - public getStore(): T; + public run(store: T, fn: (...args: unknown[]) => R, ...args: unknown[]): R; + public exit(fn: (...args: unknown[]) => R, ...args: unknown[]): R; + public getStore(): T; } diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/async_hooks.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/async_hooks.ts index 968aa2fc3..a78e2a726 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/async_hooks.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/async_hooks.ts @@ -9,15 +9,11 @@ export class AsyncResource { public runInAsyncScope(fn: (...args: unknown[]) => R, ...args: unknown[]): R; public bind unknown>( - fn: Func - ): Func & { asyncResource: AsyncResource }; + fn: Func): Func & { asyncResource: AsyncResource; }; // @ts-ignore public static bind unknown, ThisArg>( - fn: Func, - type?: string, - thisArg?: ThisArg - ): Func & { asyncResource: AsyncResource }; + fn: Func, type?: string, thisArg?: ThisArg): Func & { asyncResource: AsyncResource; }; } export class AsyncLocalStorage { diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/buffer.d.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/buffer.d.ts index 6ba318865..d387b6aa6 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/buffer.d.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/buffer.d.ts @@ -1,8 +1,9 @@ + export interface CompareOptions { aStart?: number; aEnd?: number; bStart?: number; - bEnd?: number; + bEnd?: number } type BufferSource = ArrayBufferView | ArrayBuffer; @@ -11,28 +12,25 @@ export function byteLength(value: string): number; export function compare(a: Uint8Array, b: Uint8Array, options?: CompareOptions): number; export function concat(list: Uint8Array[], length: number): ArrayBuffer; export function decodeString(value: string, encoding: string): ArrayBuffer; -export function fillImpl( - buffer: Uint8Array, - value: string | BufferSource, - start: number, - end: number, - encoding?: string -): void; -export function indexOf( - buffer: Uint8Array, - value: string | Uint8Array, - byteOffset?: number, - encoding?: string, - findLast?: boolean -): number | undefined; -export function swap(buffer: Uint8Array, size: 16 | 32 | 64): void; -export function toString(buffer: Uint8Array, start: number, end: number, encoding: string): string; -export function write( - buffer: Uint8Array, - value: string, - offset: number, - length: number, - encoding: string -): void; +export function fillImpl(buffer: Uint8Array, + value: string | BufferSource, + start: number, + end: number, + encoding?: string): void; +export function indexOf(buffer: Uint8Array, + value: string | Uint8Array, + byteOffset?: number, + encoding?: string, + findLast?: boolean): number | undefined; +export function swap(buffer: Uint8Array, size: 16|32|64): void; +export function toString(buffer: Uint8Array, + start: number, + end: number, + encoding: string): string; +export function write(buffer: Uint8Array, + value: string, + offset: number, + length: number, + encoding: string): void; export function decode(buffer: Uint8Array, state: Uint8Array): string; -export function flush(state: Uint8Array): string; +export function flush(state: Uint8Array): string; \ No newline at end of file diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/buffer.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/buffer.ts index 21fde0761..8ea27b939 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/buffer.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/buffer.ts @@ -1,521 +1,539 @@ -import { isInstance } from "./internal_buffer"; +import {isInstance} from "./internal_buffer"; import * as base64 from "base64-js"; import { TextEncoder, TextDecoder } from "@sinonjs/text-encoding"; const hexCharValueTable = { - "0": 0, - "1": 1, - "2": 2, - "3": 3, - "4": 4, - "5": 5, - "6": 6, - "7": 7, - "8": 8, - "9": 9, - a: 10, - b: 11, - c: 12, - d: 13, - e: 14, - f: 15, - A: 10, - B: 11, - C: 12, - D: 13, - E: 14, - F: 15, + "0": 0, + "1": 1, + "2": 2, + "3": 3, + "4": 4, + "5": 5, + "6": 6, + "7": 7, + "8": 8, + "9": 9, + a: 10, + b: 11, + c: 12, + d: 13, + e: 14, + f: 15, + A: 10, + B: 11, + C: 12, + D: 13, + E: 14, + F: 15, }; export function byteLength(string, encoding) { - if (Buffer.isBuffer(string)) { - return string.length; - } - if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { - return string.byteLength; - } - if (typeof string !== "string") { - throw new TypeError( - 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + - "Received type " + - typeof string - ); - } - - const len = string.length; - const mustMatch = arguments.length > 2 && arguments[2] === true; - if (!mustMatch && len === 0) return 0; - - // Use a for loop to avoid recursion - let loweredCase = false; - for (;;) { - switch (encoding) { - case "ascii": - case "latin1": - case "binary": - return len; - case "utf8": - case "utf-8": - return utf8ToBytes(string).length; - case "ucs2": - case "ucs-2": - case "utf16le": - case "utf-16le": - return len * 2; - case "hex": - return len >>> 1; - case "base64": - return base64ToBytes(string).length; - default: - if (loweredCase) { - return mustMatch ? -1 : utf8ToBytes(string).length; // assume utf8 - } - encoding = ("" + encoding).toLowerCase(); - loweredCase = true; + if (Buffer.isBuffer(string)) { + return string.length; + } + if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { + return string.byteLength; + } + if (typeof string !== "string") { + throw new TypeError( + 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + + "Received type " + + typeof string + ); + } + + const len = string.length; + const mustMatch = arguments.length > 2 && arguments[2] === true; + if (!mustMatch && len === 0) return 0; + + // Use a for loop to avoid recursion + let loweredCase = false; + for (;;) { + switch (encoding) { + case "ascii": + case "latin1": + case "binary": + return len; + case "utf8": + case "utf-8": + return utf8ToBytes(string).length; + case "ucs2": + case "ucs-2": + case "utf16le": + case "utf-16le": + return len * 2; + case "hex": + return len >>> 1; + case "base64": + return base64ToBytes(string).length; + default: + if (loweredCase) { + return mustMatch ? -1 : utf8ToBytes(string).length; // assume utf8 } + encoding = ("" + encoding).toLowerCase(); + loweredCase = true; } + } } // @ts-ignore export function compare(a: Uint8Array, b: Uint8Array, options?): number { - const aStart = options?.aStart ?? 0; - const aEnd = options?.aEnd ?? a.length; - const bStart = options?.bStart ?? 0; - const bEnd = options?.bEnd ?? b.length; - - const sliceA = a.slice(aStart, aEnd); - const sliceB = b.slice(bStart, bEnd); - - let x = sliceA.length; - let y = sliceB.length; - - for (let i = 0, len = Math.min(x, y); i < len; ++i) { - if (sliceA[i] !== sliceB[i]) { - x = sliceA[i]; - y = sliceB[i]; - break; - } + const aStart = options?.aStart ?? 0; + const aEnd = options?.aEnd ?? a.length; + const bStart = options?.bStart ?? 0; + const bEnd = options?.bEnd ?? b.length; + + const sliceA = a.slice(aStart, aEnd); + const sliceB = b.slice(bStart, bEnd); + + let x = sliceA.length; + let y = sliceB.length; + + for (let i = 0, len = Math.min(x, y); i < len; ++i) { + if (sliceA[i] !== sliceB[i]) { + x = sliceA[i]; + y = sliceB[i]; + break; } + } - if (x < y) return -1; - if (y < x) return 1; - return 0; + if (x < y) return -1; + if (y < x) return 1; + return 0; } export function concat(list: Uint8Array[], length: number): ArrayBuffer { - const result = new Uint8Array(length); - let offset = 0; - for (let i = 0; i < list.length; i++) { - result.set(list[i], offset); - offset += list[i].length; - } - return result.buffer; + const result = new Uint8Array(length); + let offset = 0; + for (let i = 0; i < list.length; i++) { + result.set(list[i], offset); + offset += list[i].length; + } + return result.buffer; } -export function toString(buffer: Uint8Array, start: number, end: number, encoding: string): string { - const slice = buffer.slice(start, end); - const decoder = new TextDecoder(encoding); - return decoder.decode(slice); +export function toString( + buffer: Uint8Array, + start: number, + end: number, + encoding: string +): string { + const slice = buffer.slice(start, end); + const decoder = new TextDecoder(encoding); + return decoder.decode(slice); } export function swap(buffer: Uint8Array, size: 16 | 32 | 64): void { - const length = buffer.length; - if (length % size !== 0) { - throw new RangeError("Buffer size must be a multiple of " + size); - } - - for (let i = 0; i < length; i += size) { - let left = i; - let right = i + size - 1; - while (left < right) { - const temp = buffer[left]; - buffer[left] = buffer[right]; - buffer[right] = temp; - left++; - right--; - } + const length = buffer.length; + if (length % size !== 0) { + throw new RangeError("Buffer size must be a multiple of " + size); + } + + for (let i = 0; i < length; i += size) { + let left = i; + let right = i + size - 1; + while (left < right) { + const temp = buffer[left]; + buffer[left] = buffer[right]; + buffer[right] = temp; + left++; + right--; } + } } export function decodeString(value: string, encoding: string): ArrayBuffer { - const encoder = new TextEncoder(); - return encoder.encode(value).buffer; + const encoder = new TextEncoder(); + return encoder.encode(value).buffer; } export function write( - buffer: Uint8Array, - value: string, - offset: number, - length: number, - encoding: string + buffer: Uint8Array, + value: string, + offset: number, + length: number, + encoding: string ): void { - let loweredCase = false; - for (;;) { - switch (encoding) { - case "hex": - return hexWrite(buffer, value, offset, length); - - case "utf8": - case "utf-8": - return utf8Write(buffer, value, offset, length); - - case "ascii": - case "latin1": - case "binary": - return asciiWrite(buffer, value, offset, length); - - case "base64": - // Warning: maxLength not taken into account in base64Write - return base64Write(buffer, value, offset, length); - - case "ucs2": - case "ucs-2": - case "utf16le": - case "utf-16le": - return ucs2Write(buffer, value, offset, length); - - default: - if (loweredCase) throw new TypeError("Unknown encoding: " + encoding); - encoding = ("" + encoding).toLowerCase(); - loweredCase = true; - } + let loweredCase = false; + for (;;) { + switch (encoding) { + case "hex": + return hexWrite(buffer, value, offset, length); + + case "utf8": + case "utf-8": + return utf8Write(buffer, value, offset, length); + + case "ascii": + case "latin1": + case "binary": + return asciiWrite(buffer, value, offset, length); + + case "base64": + // Warning: maxLength not taken into account in base64Write + return base64Write(buffer, value, offset, length); + + case "ucs2": + case "ucs-2": + case "utf16le": + case "utf-16le": + return ucs2Write(buffer, value, offset, length); + + default: + if (loweredCase) throw new TypeError("Unknown encoding: " + encoding); + encoding = ("" + encoding).toLowerCase(); + loweredCase = true; } + } } export function fillImpl( - buffer: Uint8Array, - val: string | BufferSource | number | boolean, - start: number, - end: number, - encoding?: string + buffer: Uint8Array, + val: string | BufferSource | number | boolean, + start: number, + end: number, + encoding?: string ): void { - let i; - if (typeof val === "number") { - for (i = start; i < end; ++i) { - buffer[i] = val; - } - } else { - const bytes = Buffer.isBuffer(val) ? val : Buffer.from(val as string, encoding); - const len = bytes.length; - for (i = 0; i < end - start; ++i) { - buffer[i + start] = bytes[i % len]; - } + let i; + if (typeof val === "number") { + for (i = start; i < end; ++i) { + buffer[i] = val; + } + } else { + const bytes = Buffer.isBuffer(val) + ? val + : Buffer.from(val as string, encoding); + const len = bytes.length; + for (i = 0; i < end - start; ++i) { + buffer[i + start] = bytes[i % len]; } + } } export function indexOf(buffer, val, byteOffset, encoding, dir) { - // Empty buffer means no match - if (buffer.length === 0) return -1; - - // Normalize byteOffset - if (typeof byteOffset === "string") { - encoding = byteOffset; - byteOffset = 0; - } else if (byteOffset > 0x7fffffff) { - byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; - } - byteOffset = +byteOffset; // Coerce to Number. - if (numberIsNaN(byteOffset)) { - // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer - byteOffset = dir ? 0 : buffer.length - 1; - } - - // Normalize byteOffset: negative offsets start from the end of the buffer - if (byteOffset < 0) byteOffset = buffer.length + byteOffset; - if (byteOffset >= buffer.length) { - if (dir) return -1; - else byteOffset = buffer.length - 1; - } else if (byteOffset < 0) { - if (dir) byteOffset = 0; - else return -1; +// Empty buffer means no match + if (buffer.length === 0) return -1; + + // Normalize byteOffset + if (typeof byteOffset === "string") { + encoding = byteOffset; + byteOffset = 0; + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff; + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000; + } + byteOffset = +byteOffset; // Coerce to Number. + if (numberIsNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : buffer.length - 1; + } + + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset; + if (byteOffset >= buffer.length) { + if (dir) return -1; + else byteOffset = buffer.length - 1; + } else if (byteOffset < 0) { + if (dir) byteOffset = 0; + else return -1; + } + + // Normalize val + if (typeof val === "string") { + val = Buffer.from(val, encoding); + } + + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1; } - - // Normalize val - if (typeof val === "string") { - val = Buffer.from(val, encoding); - } - - // Finally, search either indexOf (if dir is true) or lastIndexOf - if (Buffer.isBuffer(val)) { - // Special case: looking for empty string/buffer always fails - if (val.length === 0) { - return -1; - } - return arrayIndexOf(buffer, val, byteOffset, encoding, dir); - } else if (typeof val === "number") { - val = val & 0xff; // Search for a byte value [0-255] - if (typeof Uint8Array.prototype.indexOf === "function") { - if (dir) { - return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset); - } else { - return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset); - } - } - return arrayIndexOf(buffer, [val], byteOffset, encoding, dir); + return arrayIndexOf(buffer, val, byteOffset, encoding, dir); + } else if (typeof val === "number") { + val = val & 0xff; // Search for a byte value [0-255] + if (typeof Uint8Array.prototype.indexOf === "function") { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset); + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset); + } } + return arrayIndexOf(buffer, [val], byteOffset, encoding, dir); + } - throw new TypeError("val must be string, number or Buffer"); + throw new TypeError("val must be string, number or Buffer"); } function arrayIndexOf(arr, val, byteOffset, encoding, dir) { - let indexSize = 1; - let arrLength = arr.length; - let valLength = val.length; - - if (encoding !== undefined) { - encoding = String(encoding).toLowerCase(); - if ( - encoding === "ucs2" || - encoding === "ucs-2" || - encoding === "utf16le" || - encoding === "utf-16le" - ) { - if (arr.length < 2 || val.length < 2) { - return -1; - } - indexSize = 2; - arrLength /= 2; - valLength /= 2; - byteOffset /= 2; - } - } - - function read(buf, i) { - if (indexSize === 1) { - return buf[i]; - } else { - return buf.readUInt16BE(i * indexSize); - } + let indexSize = 1; + let arrLength = arr.length; + let valLength = val.length; + + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase(); + if ( + encoding === "ucs2" || + encoding === "ucs-2" || + encoding === "utf16le" || + encoding === "utf-16le" + ) { + if (arr.length < 2 || val.length < 2) { + return -1; + } + indexSize = 2; + arrLength /= 2; + valLength /= 2; + byteOffset /= 2; } + } - let i; - if (dir) { - let foundIndex = -1; - for (i = byteOffset; i < arrLength; i++) { - if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { - if (foundIndex === -1) foundIndex = i; - if (i - foundIndex + 1 === valLength) return foundIndex * indexSize; - } else { - if (foundIndex !== -1) i -= i - foundIndex; - foundIndex = -1; - } - } + function read(buf, i) { + if (indexSize === 1) { + return buf[i]; } else { - if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength; - for (i = byteOffset; i >= 0; i--) { - let found = true; - for (let j = 0; j < valLength; j++) { - if (read(arr, i + j) !== read(val, j)) { - found = false; - break; - } - } - if (found) return i; + return buf.readUInt16BE(i * indexSize); + } + } + + let i; + if (dir) { + let foundIndex = -1; + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i; + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize; + } else { + if (foundIndex !== -1) i -= i - foundIndex; + foundIndex = -1; + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength; + for (i = byteOffset; i >= 0; i--) { + let found = true; + for (let j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false; + break; } + } + if (found) return i; } + } - return -1; + return -1; } function utf8ToBytes(string, units?) { - units = units || Infinity; - let codePoint; - const length = string.length; - let leadSurrogate = null; - const bytes = []; - - for (let i = 0; i < length; ++i) { - codePoint = string.charCodeAt(i); - - // is surrogate component - if (codePoint > 0xd7ff && codePoint < 0xe000) { - // last char was a lead - if (!leadSurrogate) { - // no lead yet - if (codePoint > 0xdbff) { - // unexpected trail - if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); - continue; - } else if (i + 1 === length) { - // unpaired lead - if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); - continue; - } - - // valid lead - leadSurrogate = codePoint; - - continue; - } - - // 2 leads in a row - if (codePoint < 0xdc00) { - if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); - leadSurrogate = codePoint; - continue; - } - - // valid surrogate pair - codePoint = (((leadSurrogate - 0xd800) << 10) | (codePoint - 0xdc00)) + 0x10000; - } else if (leadSurrogate) { - // valid bmp char, but last char was a lead - if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); + units = units || Infinity; + let codePoint; + const length = string.length; + let leadSurrogate = null; + const bytes = []; + + for (let i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i); + + // is surrogate component + if (codePoint > 0xd7ff && codePoint < 0xe000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xdbff) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); + continue; + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); + continue; } - leadSurrogate = null; - - // encode utf8 - if (codePoint < 0x80) { - if ((units -= 1) < 0) break; - bytes.push(codePoint); - } else if (codePoint < 0x800) { - if ((units -= 2) < 0) break; - bytes.push((codePoint >> 0x6) | 0xc0, (codePoint & 0x3f) | 0x80); - } else if (codePoint < 0x10000) { - if ((units -= 3) < 0) break; - bytes.push( - (codePoint >> 0xc) | 0xe0, - ((codePoint >> 0x6) & 0x3f) | 0x80, - (codePoint & 0x3f) | 0x80 - ); - } else if (codePoint < 0x110000) { - if ((units -= 4) < 0) break; - bytes.push( - (codePoint >> 0x12) | 0xf0, - ((codePoint >> 0xc) & 0x3f) | 0x80, - ((codePoint >> 0x6) & 0x3f) | 0x80, - (codePoint & 0x3f) | 0x80 - ); - } else { - throw new Error("Invalid code point"); - } + // valid lead + leadSurrogate = codePoint; + + continue; + } + + // 2 leads in a row + if (codePoint < 0xdc00) { + if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); + leadSurrogate = codePoint; + continue; + } + + // valid surrogate pair + codePoint = + (((leadSurrogate - 0xd800) << 10) | (codePoint - 0xdc00)) + 0x10000; + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); } - return bytes; -} - -function hexWrite(buf, string, offset, length) { - offset = Number(offset) || 0; - const remaining = buf.length - offset; - if (!length) { - length = remaining; + leadSurrogate = null; + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break; + bytes.push(codePoint); + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break; + bytes.push((codePoint >> 0x6) | 0xc0, (codePoint & 0x3f) | 0x80); + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break; + bytes.push( + (codePoint >> 0xc) | 0xe0, + ((codePoint >> 0x6) & 0x3f) | 0x80, + (codePoint & 0x3f) | 0x80 + ); + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break; + bytes.push( + (codePoint >> 0x12) | 0xf0, + ((codePoint >> 0xc) & 0x3f) | 0x80, + ((codePoint >> 0x6) & 0x3f) | 0x80, + (codePoint & 0x3f) | 0x80 + ); } else { - length = Number(length); - if (length > remaining) { - length = remaining; - } + throw new Error("Invalid code point"); } + } - const strLen = string.length; + return bytes; +} - if (length > strLen / 2) { - length = strLen / 2; +function hexWrite(buf, string, offset, length) { + offset = Number(offset) || 0; + const remaining = buf.length - offset; + if (!length) { + length = remaining; + } else { + length = Number(length); + if (length > remaining) { + length = remaining; } - let i; - for (i = 0; i < length; ++i) { - const a = hexCharValueTable[string[i * 2]]; - const b = hexCharValueTable[string[i * 2 + 1]]; - if (a === undefined || b === undefined) { - return i; - } - buf[offset + i] = (a << 4) | b; + } + + const strLen = string.length; + + if (length > strLen / 2) { + length = strLen / 2; + } + let i; + for (i = 0; i < length; ++i) { + const a = hexCharValueTable[string[i * 2]]; + const b = hexCharValueTable[string[i * 2 + 1]]; + if (a === undefined || b === undefined) { + return i; } - return i; + buf[offset + i] = (a << 4) | b; + } + return i; } function base64ToBytes(str) { - return base64.toByteArray(base64clean(str)); + return base64.toByteArray(base64clean(str)); } function utf8Write(buf, string, offset, length) { - return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length); + return blitBuffer( + utf8ToBytes(string, buf.length - offset), + buf, + offset, + length + ); } function asciiWrite(buf, string, offset, length) { - return blitBuffer(asciiToBytes(string), buf, offset, length); + return blitBuffer(asciiToBytes(string), buf, offset, length); } function base64Write(buf, string, offset, length) { - return blitBuffer(base64ToBytes(string), buf, offset, length); + return blitBuffer(base64ToBytes(string), buf, offset, length); } function ucs2Write(buf, string, offset, length) { - return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length); + return blitBuffer( + utf16leToBytes(string, buf.length - offset), + buf, + offset, + length + ); } function asciiToBytes(str) { - const byteArray = []; - for (let i = 0; i < str.length; ++i) { - // Node's code seems to be doing this and not & 0x7F.. - byteArray.push(str.charCodeAt(i) & 0xff); - } - return byteArray; + const byteArray = []; + for (let i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xff); + } + return byteArray; } function utf16leToBytes(str, units) { - let c, hi, lo; - const byteArray = []; - for (let i = 0; i < str.length; ++i) { - if ((units -= 2) < 0) break; - - c = str.charCodeAt(i); - hi = c >> 8; - lo = c % 256; - byteArray.push(lo); - byteArray.push(hi); - } - - return byteArray; + let c, hi, lo; + const byteArray = []; + for (let i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break; + + c = str.charCodeAt(i); + hi = c >> 8; + lo = c % 256; + byteArray.push(lo); + byteArray.push(hi); + } + + return byteArray; } const INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g; function base64clean(str) { - // Node takes equal signs as end of the Base64 encoding - str = str.split("=")[0]; - // Node strips out invalid characters like \n and \t from the string, base64-js does not - str = str.trim().replace(INVALID_BASE64_RE, ""); - // Node converts strings with length < 2 to '' - if (str.length < 2) return ""; - // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not - while (str.length % 4 !== 0) { - str = str + "="; - } - return str; + // Node takes equal signs as end of the Base64 encoding + str = str.split("=")[0]; + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = str.trim().replace(INVALID_BASE64_RE, ""); + // Node converts strings with length < 2 to '' + if (str.length < 2) return ""; + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + "="; + } + return str; } function blitBuffer(src, dst, offset, length) { - let i; - for (i = 0; i < length; ++i) { - if (i + offset >= dst.length || i >= src.length) break; - dst[i + offset] = src[i]; - } - return i; + let i; + for (i = 0; i < length; ++i) { + if (i + offset >= dst.length || i >= src.length) break; + dst[i + offset] = src[i]; + } + return i; } function numberIsNaN(obj) { - // For IE11 support - return obj !== obj; // eslint-disable-line no-self-compare + // For IE11 support + return obj !== obj; // eslint-disable-line no-self-compare } export function flush(state: Uint8Array): string { - // Create a new Uint8Array object from the state. - const buffer = new Uint8Array(state); - return String.fromCharCode.apply(null, buffer); + // Create a new Uint8Array object from the state. + const buffer = new Uint8Array(state); + return String.fromCharCode.apply(null, buffer); } export function decode(buffer: Uint8Array, state: Uint8Array): string { - let result = ""; - for (let i = 0; i < buffer.length; i++) { - const byte = buffer[i]; - const char = state[byte]; - if (char === undefined) { - throw new Error("Invalid byte"); - } - result += char; + let result = ""; + for (let i = 0; i < buffer.length; i++) { + const byte = buffer[i]; + const char = state[byte]; + if (char === undefined) { + throw new Error("Invalid byte"); } - return result; -} + result += char; + } + return result; +} \ No newline at end of file diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/constants.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/constants.ts index 2013d207f..88ec50573 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/constants.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/constants.ts @@ -1,3 +1,4 @@ + export const CHAR_UPPERCASE_A = 65; /* A */ export const CHAR_LOWERCASE_A = 97; /* a */ export const CHAR_UPPERCASE_Z = 90; /* Z */ @@ -41,4 +42,4 @@ export const CHAR_AMPERSAND = 38; /* & */ export const CHAR_EQUAL = 61; /* = */ export const CHAR_0 = 48; /* 0 */ export const CHAR_9 = 57; /* 9 */ -export const EOL = ";"; +export const EOL = '\;'; \ No newline at end of file diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto.d.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto.d.ts index afab20186..6fb967959 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto.d.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto.d.ts @@ -1,47 +1,35 @@ -import { Buffer } from "./internal_buffer"; +import { + Buffer, +} from './internal_buffer'; // random export function checkPrimeSync(candidate: ArrayBufferView, num_checks: number): boolean; -export function randomPrime( - size: number, - safe: boolean, - add?: ArrayBufferView | undefined, - rem?: ArrayBufferView | undefined -): ArrayBuffer; +export function randomPrime(size: number, safe: boolean, add?: ArrayBufferView|undefined, + rem?: ArrayBufferView|undefined): ArrayBuffer; // Hash and Hmac export class HashHandle { - public constructor(algorithm: string, xofLen: number); - public update(data: Buffer | ArrayBufferView): number; - public digest(): ArrayBuffer; - public copy(xofLen: number): HashHandle; + public constructor(algorithm: string, xofLen: number); + public update(data: Buffer | ArrayBufferView): number; + public digest(): ArrayBuffer; + public copy(xofLen: number): HashHandle; } -export type ArrayLike = ArrayBuffer | string | Buffer | ArrayBufferView; +export type ArrayLike = ArrayBuffer|string|Buffer|ArrayBufferView; export class HmacHandle { - public constructor(algorithm: string, key: ArrayLike | CryptoKey); - public update(data: Buffer | ArrayBufferView): number; - public digest(): ArrayBuffer; + public constructor(algorithm: string, key: ArrayLike | CryptoKey); + public update(data: Buffer | ArrayBufferView): number; + public digest(): ArrayBuffer; } // hkdf -export function getHkdf( - hash: string, - key: ArrayLike, - salt: ArrayLike, - info: ArrayLike, - length: number -): ArrayBuffer; +export function getHkdf(hash: string, key: ArrayLike, salt: ArrayLike, info: ArrayLike, + length: number): ArrayBuffer; // pbkdf2 -export function getPbkdf( - password: ArrayLike, - salt: ArrayLike, - iterations: number, - keylen: number, - digest: string -): ArrayBuffer; +export function getPbkdf(password: ArrayLike, salt: ArrayLike, iterations: number, keylen: number, + digest: string): ArrayBuffer; // Keys export function exportKey(key: CryptoKey, options?: InnerExportOptions): KeyExportResult; @@ -226,21 +214,19 @@ export type KeyData = string | ArrayBuffer | ArrayBufferView; // DiffieHellman export class DiffieHellmanHandle { - public constructor( - sizeOrKey: number | ArrayBuffer | ArrayBufferView, - generator: number | ArrayBuffer | ArrayBufferView - ); - public setPublicKey(data: ArrayBuffer | ArrayBufferView | Buffer): void; - public setPrivateKey(data: ArrayBuffer | ArrayBufferView | Buffer): void; - public getPublicKey(): ArrayBuffer; - public getPrivateKey(): ArrayBuffer; - public getGenerator(): ArrayBuffer; - public getPrime(): ArrayBuffer; + public constructor(sizeOrKey: number | ArrayBuffer | ArrayBufferView, + generator: number | ArrayBuffer | ArrayBufferView); + public setPublicKey(data: ArrayBuffer | ArrayBufferView | Buffer): void; + public setPrivateKey(data: ArrayBuffer | ArrayBufferView | Buffer): void; + public getPublicKey(): ArrayBuffer; + public getPrivateKey(): ArrayBuffer; + public getGenerator(): ArrayBuffer; + public getPrime(): ArrayBuffer; - public computeSecret(key: ArrayBuffer | ArrayBufferView): ArrayBuffer; - public generateKeys(): ArrayBuffer; + public computeSecret(key: ArrayBuffer|ArrayBufferView): ArrayBuffer; + public generateKeys(): ArrayBuffer; - public getVerifyError(): number; + public getVerifyError(): number; } export function DiffieHellmanGroupHandle(name: string): DiffieHellmanHandle; diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto.ts index 12248fd6e..088a1d7db 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto.ts @@ -1,9 +1,10 @@ -import * as sjcl from "sjcl"; -import { Buffer } from "./internal_buffer"; +import * as sjcl from 'sjcl'; +import {Buffer} from "./internal_buffer"; -export type ArrayLike = ArrayBuffer | string | Buffer | ArrayBufferView; +export type ArrayLike = ArrayBuffer|string|Buffer|ArrayBufferView; export type KeyData = string | ArrayBuffer | ArrayBufferView; + /** * Checks if a number represented by an ArrayBufferView is prime. * @@ -36,16 +37,11 @@ export function checkPrimeSync(candidate: ArrayBufferView, num_checks: number): * @param {ArrayBufferView} [rem] - An ArrayBufferView representing a number to take the remainder of the generated prime number. * @returns {ArrayBuffer} - Returns an ArrayBuffer representing the generated prime number. */ -export function randomPrime( - size: number, - safe: boolean, - add?: ArrayBufferView, - rem?: ArrayBufferView -): ArrayBuffer { +export function randomPrime(size: number, safe: boolean, add?: ArrayBufferView, rem?: ArrayBufferView): ArrayBuffer { let prime: number; do { prime = sjcl.random.randomWords(1, 0)[0]; - prime = Math.abs(prime) % 2 ** size; + prime = Math.abs(prime) % (2 ** size); if (safe) { prime = 2 * prime + 1; } @@ -61,13 +57,7 @@ export function randomPrime( } // hkdf -export function getHkdf( - hash: string, - key: ArrayLike, - salt: ArrayLike, - info: ArrayLike, - length: number -): ArrayBuffer { +export function getHkdf(hash: string, key: ArrayLike, salt: ArrayLike, info: ArrayLike, length: number): ArrayBuffer { // Convert key, salt, and info to bitArrays let keyBits = sjcl.codec.utf8String.toBits(key.toString()); let saltBits = sjcl.codec.utf8String.toBits(salt.toString()); @@ -82,13 +72,7 @@ export function getHkdf( } // pbkdf2 -export function getPbkdf( - password: ArrayLike, - salt: ArrayLike, - iterations: number, - keylen: number, - digest: string -): ArrayBuffer { +export function getPbkdf(password: ArrayLike, salt: ArrayLike, iterations: number, keylen: number, digest: string): ArrayBuffer { // Convert password and salt to bitArrays let passwordBits = sjcl.codec.utf8String.toBits(password.toString()); let saltBits = sjcl.codec.utf8String.toBits(salt.toString()); @@ -101,18 +85,19 @@ export function getPbkdf( return sjcl.codec.arrayBuffer.fromBits(derivedKeyBits); } + export class HashHandle { private hash: sjcl.SjclHash; public constructor(algorithm: string, xofLen: number) { switch (algorithm) { - case "sha1": + case 'sha1': this.hash = new sjcl.hash.sha1(); break; - case "sha256": + case 'sha256': this.hash = new sjcl.hash.sha256(); break; - case "sha512": + case 'sha512': this.hash = new sjcl.hash.sha512(); break; default: @@ -136,23 +121,23 @@ export class HashHandle { } public copy(xofLen: number): HashHandle { - let algo = ""; + let algo =""; let hash = this.hash; switch (true) { case hash instanceof sjcl.hash.sha1: - algo = "sha1"; + algo = 'sha1'; break; case hash instanceof sjcl.hash.sha256: - algo = "sha256"; + algo = 'sha256'; break; case hash instanceof sjcl.hash.sha512: - algo = "sha512"; + algo = 'sha512'; break; default: throw new Error(`Unsupported hash algorithm: ${algo}`); } - let copy = new HashHandle(algo, xofLen); // Replace 'sha256' with the actual algorithm - copy.hash = this.hash; + let copy = new HashHandle( algo , xofLen); // Replace 'sha256' with the actual algorithm + copy.hash = this.hash return copy; } } @@ -163,13 +148,13 @@ export class HmacHandle { public constructor(algorithm: string, key: ArrayLike | CryptoKey) { let keyBits = sjcl.codec.utf8String.toBits(key.toString()); switch (algorithm) { - case "sha1": + case 'sha1': this.hmac = new sjcl.misc.hmac(keyBits, sjcl.hash.sha1); break; - case "sha256": + case 'sha256': this.hmac = new sjcl.misc.hmac(keyBits, sjcl.hash.sha256); break; - case "sha512": + case 'sha512': this.hmac = new sjcl.misc.hmac(keyBits, sjcl.hash.sha512); break; default: @@ -190,46 +175,45 @@ export class HmacHandle { } export interface RsaKeyAlgorithm { - name: "rsa" | "rsa-pss"; + name: 'rsa' | 'rsa-pss'; modulusLength: number; publicExponent: Uint8Array; hash?: string; } export interface EcKeyAlgorithm { - name: "ec"; + name: 'ec'; namedCurve: string; } export interface DhKeyAlgorithm { - name: "dh"; + name: 'dh'; prime: Uint8Array; generator: Uint8Array; } export interface DsaKeyAlgorithm { - name: "dsa"; + name: 'dsa'; prime: Uint8Array; divisorLength: number; } export interface HmacKeyAlgorithm { - name: "hmac"; + name: 'hmac'; hash: string; } export interface AesKeyAlgorithm { - name: "aes"; + name: 'aes'; length: number; } -export type KeyAlgorithm = - | RsaKeyAlgorithm - | EcKeyAlgorithm - | DhKeyAlgorithm - | DsaKeyAlgorithm - | HmacKeyAlgorithm - | AesKeyAlgorithm; +export type KeyAlgorithm = RsaKeyAlgorithm | + EcKeyAlgorithm | + DhKeyAlgorithm | + DsaKeyAlgorithm | + HmacKeyAlgorithm | + AesKeyAlgorithm; export interface CryptoKey { algorithm: KeyAlgorithm; @@ -270,17 +254,17 @@ export interface CryptoKeyPair { publicKey: CryptoKey; } -export type KeyObjectType = "secret" | "public" | "private"; +export type KeyObjectType = 'secret' | 'public' | 'private'; export type KeyExportResult = string | Buffer | JsonWebKey; -export type SecretKeyFormat = "buffer" | "jwk"; -export type AsymmetricKeyFormat = "pem" | "der" | "jwk"; -export type PublicKeyEncoding = "pkcs1" | "spki"; -export type PrivateKeyEncoding = "pkcs1" | "pkcs8" | "sec1"; -export type AsymmetricKeyType = "rsa" | "rsa-pss" | "dsa" | "ec" | "x25519" | "ed25519" | "dh"; -export type SecretKeyType = "hmac" | "aes"; -export type ParamEncoding = "named" | "explicit"; +export type SecretKeyFormat = 'buffer' | 'jwk'; +export type AsymmetricKeyFormat = 'pem' | 'der' | 'jwk'; +export type PublicKeyEncoding = 'pkcs1' | 'spki'; +export type PrivateKeyEncoding = 'pkcs1' | 'pkcs8' | 'sec1'; +export type AsymmetricKeyType = 'rsa' | 'rsa-pss' | 'dsa' | 'ec' | 'x25519' | 'ed25519' | 'dh'; +export type SecretKeyType = 'hmac' | 'aes'; +export type ParamEncoding = 'named' | 'explicit'; export interface SecretKeyExportOptions { format?: SecretKeyFormat; @@ -306,15 +290,13 @@ export interface InnerPrivateKeyExportOptions { passphrase?: Uint8Array; } -export type ExportOptions = - | SecretKeyExportOptions - | PublicKeyExportOptions - | PrivateKeyExportOptions; +export type ExportOptions = SecretKeyExportOptions | + PublicKeyExportOptions | + PrivateKeyExportOptions; -export type InnerExportOptions = - | SecretKeyExportOptions - | PublicKeyExportOptions - | InnerPrivateKeyExportOptions; +export type InnerExportOptions = SecretKeyExportOptions | + PublicKeyExportOptions | + InnerPrivateKeyExportOptions; export interface AsymmetricKeyDetails { modulusLength?: number; @@ -347,7 +329,7 @@ export interface GenerateKeyOptions { export interface GenerateKeyPairOptions { modulusLength?: number; - publicExponent?: number | bigint; + publicExponent?: number|bigint; hashAlgorithm?: string; mgf1HashAlgorithm?: string; saltLength?: number; @@ -396,12 +378,12 @@ export function createSecretKey(key: ArrayBuffer | ArrayBufferView): CryptoKey { return { algorithm: { - name: "aes", - length: key.byteLength * 8, + name: 'aes', + length: key.byteLength * 8 }, extractable: true, - type: "secret", - usages: ["encrypt", "decrypt"], + type: 'secret', + usages: ['encrypt', 'decrypt'] }; } @@ -415,16 +397,15 @@ export function createPublicKey(key: InnerCreateAsymmetricKeyOptions): CryptoKey throw new Error("Function createPublicKey is not implemented yet"); } + export class DiffieHellmanHandle { private prime: sjcl.BigNumber; private generator: sjcl.BigNumber; private privateKey: sjcl.BigNumber; private publicKey: sjcl.BigNumber; - public constructor( - sizeOrKey: number | ArrayBuffer | ArrayBufferView, - generator: number | ArrayBuffer | ArrayBufferView - ) { + public constructor(sizeOrKey: number | ArrayBuffer | ArrayBufferView, + generator: number | ArrayBuffer | ArrayBufferView) { // Convert sizeOrKey and generator to sjcl.bn this.prime = new sjcl.bn(sizeOrKey.toString()); this.generator = new sjcl.bn(generator.toString()); @@ -460,7 +441,7 @@ export class DiffieHellmanHandle { return sjcl.codec.arrayBuffer.fromBits(this.prime.toBits()); } - public computeSecret(key: ArrayBuffer | ArrayBufferView): ArrayBuffer { + public computeSecret(key: ArrayBuffer|ArrayBufferView): ArrayBuffer { let otherPublicKey = new sjcl.bn(key.toString()); let secret = otherPublicKey.powermod(this.privateKey, this.prime); return sjcl.codec.arrayBuffer.fromBits(secret.toBits()); @@ -468,7 +449,7 @@ export class DiffieHellmanHandle { public generateKeys(): ArrayBuffer { // Generate a new private key - this.privateKey = sjcl.bn.random(this.prime.sub(2), 10).add(1); + this.privateKey = sjcl.bn.random(this.prime.sub(2),10).add(1); // Calculate the new public key this.publicKey = this.generator.powermod(this.privateKey, this.prime); @@ -482,12 +463,13 @@ export class DiffieHellmanHandle { } } + export function DiffieHellmanGroupHandle(name: string): DiffieHellmanHandle { // Define some named groups with their prime and generator values - const groups: { [name: string]: { prime: number; generator: number } } = { - modp1: { prime: 2, generator: 2 }, - modp2: { prime: 3, generator: 2 }, - modp5: { prime: 5, generator: 2 }, + const groups: { [name: string]: { prime: number, generator: number } } = { + 'modp1': { prime: 2, generator: 2 }, + 'modp2': { prime: 3, generator: 2 }, + 'modp5': { prime: 5, generator: 2 }, // Add more named groups here }; diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_dh.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_dh.ts index 762f512f9..1ce519c6d 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_dh.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_dh.ts @@ -1,198 +1,202 @@ + /* eslint-disable */ -"use strict"; +'use strict'; -import { Buffer } from "./internal_buffer"; +import { + Buffer, +} from './internal_buffer'; -import * as cryptoImpl from "./crypto"; +import * as cryptoImpl from './crypto'; type ArrayLike = cryptoImpl.ArrayLike; -import { ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY, ERR_INVALID_ARG_TYPE } from "./internal_errors"; +import { + ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY, + ERR_INVALID_ARG_TYPE, +} from './internal_errors'; -import { validateInt32 } from "./validators"; +import { + validateInt32, +} from './validators'; -import { isArrayBufferView, isAnyArrayBuffer } from "./internal_types"; +import { + isArrayBufferView, + isAnyArrayBuffer +} from './internal_types'; -import { getArrayBufferOrView, toBuf, kHandle } from "./crypto_util"; +import { + getArrayBufferOrView, + toBuf, + kHandle, +} from './crypto_util'; const DH_GENERATOR = 2; interface DiffieHellman { - [kHandle]: cryptoImpl.DiffieHellmanHandle; + [kHandle]: cryptoImpl.DiffieHellmanHandle; } -let DiffieHellman = function ( - this: DiffieHellman, - sizeOrKey: number | ArrayLike, - keyEncoding?: number | string, - generator?: number | ArrayLike, - genEncoding?: string -): DiffieHellman { - if (!(this instanceof DiffieHellman)) - return new DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding); - if ( - typeof sizeOrKey !== "number" && - typeof sizeOrKey !== "string" && +let DiffieHellman = function (this: DiffieHellman, sizeOrKey: number|ArrayLike, + keyEncoding?: number|string, generator?: number|ArrayLike, + genEncoding?: string): DiffieHellman { + if (!(this instanceof DiffieHellman)) + return new DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding); + if (typeof sizeOrKey !== 'number' && + typeof sizeOrKey !== 'string' && !isArrayBufferView(sizeOrKey) && - !isAnyArrayBuffer(sizeOrKey) - ) { - throw new ERR_INVALID_ARG_TYPE( - "sizeOrKey", - ["number", "string", "ArrayBuffer", "Buffer", "TypedArray", "DataView"], - sizeOrKey - ); - } - - // Sizes < 0 don't make sense but they _are_ accepted (and subsequently - // rejected with ERR_OSSL_BN_BITS_TOO_SMALL) by OpenSSL. The glue code - // in node_crypto.cc accepts values that are IsInt32() for that reason - // and that's why we do that here too. - if (typeof sizeOrKey === "number") validateInt32(sizeOrKey, "sizeOrKey"); - - if (keyEncoding && !Buffer.isEncoding(keyEncoding) && keyEncoding !== "buffer") { - genEncoding = generator as any; - generator = keyEncoding; - keyEncoding = "utf-8"; // default encoding - } - - keyEncoding ??= "utf-8"; - genEncoding ??= "utf-8"; - - if (typeof sizeOrKey !== "number") sizeOrKey = toBuf(sizeOrKey, keyEncoding as string); - - if (!generator) { - generator = DH_GENERATOR; - } else if (typeof generator === "number") { - validateInt32(generator, "generator"); - } else if (typeof generator === "string") { - generator = toBuf(generator, genEncoding); - } else if (!isArrayBufferView(generator) && !isAnyArrayBuffer(generator)) { - throw new ERR_INVALID_ARG_TYPE( - "generator", - ["number", "string", "ArrayBuffer", "Buffer", "TypedArray", "DataView"], - generator - ); - } - - this[kHandle] = new cryptoImpl.DiffieHellmanHandle(sizeOrKey as any, generator as any); - Object.defineProperty(DiffieHellman.prototype, "verifyError", { - get: function () { - return this[kHandle].getVerifyError(); - }, - configurable: true, - enumerable: true, - }); - return this; -} as any as { - new ( - sizeOrKey: number | ArrayLike, - keyEncoding?: number | string, - generator?: number | ArrayLike, - genEncoding?: string - ): DiffieHellman; -}; + !isAnyArrayBuffer(sizeOrKey)) { + throw new ERR_INVALID_ARG_TYPE( + 'sizeOrKey', + ['number', 'string', 'ArrayBuffer', 'Buffer', 'TypedArray', 'DataView'], + sizeOrKey, + ); + } + + // Sizes < 0 don't make sense but they _are_ accepted (and subsequently + // rejected with ERR_OSSL_BN_BITS_TOO_SMALL) by OpenSSL. The glue code + // in node_crypto.cc accepts values that are IsInt32() for that reason + // and that's why we do that here too. + if (typeof sizeOrKey === 'number') + validateInt32(sizeOrKey, 'sizeOrKey'); + + if (keyEncoding && !Buffer.isEncoding(keyEncoding) && keyEncoding !== 'buffer') { + genEncoding = generator as any; + generator = keyEncoding; + keyEncoding = "utf-8"; // default encoding + } + + keyEncoding ??= 'utf-8'; + genEncoding ??= 'utf-8'; + + if (typeof sizeOrKey !== 'number') + sizeOrKey = toBuf(sizeOrKey, keyEncoding as string); + + if (!generator) { + generator = DH_GENERATOR; + } else if (typeof generator === 'number') { + validateInt32(generator, 'generator'); + } else if (typeof generator === 'string') { + generator = toBuf(generator, genEncoding); + } else if (!isArrayBufferView(generator) && !isAnyArrayBuffer(generator)) { + throw new ERR_INVALID_ARG_TYPE( + 'generator', + ['number', 'string', 'ArrayBuffer', 'Buffer', 'TypedArray', 'DataView'], + generator, + ); + } + + this[kHandle] = new cryptoImpl.DiffieHellmanHandle(sizeOrKey as any, generator as any); + Object.defineProperty(DiffieHellman.prototype, "verifyError", { + get: function () { + return this[kHandle].getVerifyError(); + }, + configurable: true, + enumerable: true, + }); + return this; +} as any as { new (sizeOrKey: number|ArrayLike, keyEncoding?: number|string, + generator?: number|ArrayLike, genEncoding?: string): DiffieHellman; }; interface DiffieHellmanGroup { - [kHandle]: cryptoImpl.DiffieHellmanHandle; + [kHandle]: cryptoImpl.DiffieHellmanHandle; } -let DiffieHellmanGroup = function (this: DiffieHellmanGroup, name: string): DiffieHellmanGroup { - if (!(this instanceof DiffieHellmanGroup)) return new DiffieHellmanGroup(name); - - // The C++-based handle is shared between both classes, so DiffieHellmanGroupHandle() is merely - // a different constructor for a DiffieHellmanHandle. - this[kHandle] = cryptoImpl.DiffieHellmanGroupHandle(name); - Object.defineProperty(DiffieHellmanGroup.prototype, "verifyError", { - get: function () { - return this[kHandle].getVerifyError(); - }, - configurable: true, - enumerable: true, - }); - return this; -} as any as { new (name: string): DiffieHellmanGroup }; - -DiffieHellmanGroup.prototype.generateKeys = DiffieHellman.prototype.generateKeys = dhGenerateKeys; +let DiffieHellmanGroup = function(this: DiffieHellmanGroup, name: string): DiffieHellmanGroup { + if (!(this instanceof DiffieHellmanGroup)) + return new DiffieHellmanGroup(name); + + // The C++-based handle is shared between both classes, so DiffieHellmanGroupHandle() is merely + // a different constructor for a DiffieHellmanHandle. + this[kHandle] = cryptoImpl.DiffieHellmanGroupHandle(name); + Object.defineProperty(DiffieHellmanGroup.prototype, "verifyError", { + get: function () { + return this[kHandle].getVerifyError(); + }, + configurable: true, + enumerable: true, + }); + return this; +} as any as { new (name: string): DiffieHellmanGroup; }; + +DiffieHellmanGroup.prototype.generateKeys = DiffieHellman.prototype.generateKeys = + dhGenerateKeys; DiffieHellmanGroup.prototype.computeSecret = DiffieHellman.prototype.computeSecret = - dhComputeSecret; + dhComputeSecret; DiffieHellmanGroup.prototype.getPrime = DiffieHellman.prototype.getPrime = dhGetPrime; -DiffieHellmanGroup.prototype.getGenerator = DiffieHellman.prototype.getGenerator = dhGetGenerator; -DiffieHellmanGroup.prototype.getPublicKey = DiffieHellman.prototype.getPublicKey = dhGetPublicKey; +DiffieHellmanGroup.prototype.getGenerator = DiffieHellman.prototype.getGenerator = + dhGetGenerator; +DiffieHellmanGroup.prototype.getPublicKey = DiffieHellman.prototype.getPublicKey = + dhGetPublicKey; DiffieHellmanGroup.prototype.getPrivateKey = DiffieHellman.prototype.getPrivateKey = - dhGetPrivateKey; + dhGetPrivateKey; DiffieHellman.prototype.setPublicKey = dhSetPublicKey; DiffieHellman.prototype.setPrivateKey = dhSetPrivateKey; -export { DiffieHellman, DiffieHellmanGroup }; +export {DiffieHellman, DiffieHellmanGroup}; -type DHLike = DiffieHellman | DiffieHellmanGroup; -function dhGenerateKeys(this: DHLike, encoding?: string): Buffer | string { - const keys = this[kHandle].generateKeys(); - return encode(keys, encoding); +type DHLike = DiffieHellman|DiffieHellmanGroup; +function dhGenerateKeys(this: DHLike, encoding?: string): Buffer|string { + const keys = this[kHandle].generateKeys(); + return encode(keys, encoding); } -function dhComputeSecret( - this: DHLike, - key: ArrayLike, - inEnc?: string, - outEnc?: string -): Buffer | string { - key = getArrayBufferOrView(key, "key", inEnc); - const ret = this[kHandle].computeSecret(key); - if (typeof ret === "string") throw new ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY(); - return encode(ret, outEnc); +function dhComputeSecret(this: DHLike, key: ArrayLike, inEnc?: string, + outEnc?: string): Buffer|string { + key = getArrayBufferOrView(key, 'key', inEnc); + const ret = this[kHandle].computeSecret(key); + if (typeof ret === 'string') + throw new ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY(); + return encode(ret, outEnc); } -function dhGetPrime(this: DHLike, encoding?: string): Buffer | string { - const prime = this[kHandle].getPrime(); - return encode(prime, encoding); +function dhGetPrime(this: DHLike, encoding?: string): Buffer|string { + const prime = this[kHandle].getPrime(); + return encode(prime, encoding); } -function dhGetGenerator(this: DHLike, encoding?: string): Buffer | string { - const generator = this[kHandle].getGenerator(); - return encode(generator, encoding); +function dhGetGenerator(this: DHLike, encoding?: string): Buffer|string { + const generator = this[kHandle].getGenerator(); + return encode(generator, encoding); } -function dhGetPublicKey(this: DHLike, encoding?: string): Buffer | string { - const key = this[kHandle].getPublicKey(); - return encode(key, encoding); +function dhGetPublicKey(this: DHLike, encoding?: string): Buffer|string { + const key = this[kHandle].getPublicKey(); + return encode(key, encoding); } -function dhGetPrivateKey(this: DHLike, encoding?: string): Buffer | string { - const key = this[kHandle].getPrivateKey(); - return encode(key, encoding); +function dhGetPrivateKey(this: DHLike, encoding?: string): Buffer|string { + const key = this[kHandle].getPrivateKey(); + return encode(key, encoding); } function dhSetPublicKey(this: DiffieHellman, key: ArrayLike, encoding?: string): DiffieHellman { - key = getArrayBufferOrView(key, "key", encoding); - this[kHandle].setPublicKey(key); - return this; + key = getArrayBufferOrView(key, 'key', encoding); + this[kHandle].setPublicKey(key); + return this; } function dhSetPrivateKey(this: DiffieHellman, key: ArrayLike, encoding?: string): DiffieHellman { - key = getArrayBufferOrView(key, "key", encoding); - this[kHandle].setPrivateKey(key); - return this; + key = getArrayBufferOrView(key, 'key', encoding); + this[kHandle].setPrivateKey(key); + return this; } -function encode(buffer: ArrayBuffer, encoding?: string): Buffer | string { - if (encoding && encoding !== "buffer") return Buffer.from(buffer).toString(encoding); - return Buffer.from(buffer); +function encode(buffer: ArrayBuffer, encoding?: string): Buffer|string { + if (encoding && encoding !== 'buffer') + return Buffer.from(buffer).toString(encoding); + return Buffer.from(buffer); } -export function createDiffieHellman( - sizeOrKey: number | ArrayLike, - keyEncoding?: number | string, - generator?: number | ArrayLike, - genEncoding?: string -): DiffieHellman { - return new DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding); +export function createDiffieHellman(sizeOrKey: number|ArrayLike, + keyEncoding?: number|string, generator?: number|ArrayLike, + genEncoding?: string): DiffieHellman { + return new DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding); } export function createDiffieHellmanGroup(name: string): DiffieHellmanGroup { - return new DiffieHellmanGroup(name); + return new DiffieHellmanGroup(name); } export function getDiffieHellman(name: string): DiffieHellmanGroup { - return createDiffieHellmanGroup(name); + return createDiffieHellmanGroup(name); } diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_hash.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_hash.ts index 296bd2013..160fd63a6 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_hash.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_hash.ts @@ -1,230 +1,235 @@ /* eslint-disable */ -import * as cryptoImpl from "./crypto"; +import * as cryptoImpl from './crypto'; type ArrayLike = cryptoImpl.ArrayLike; -import { kFinalized, kHandle, kState, getArrayBufferOrView, getStringOption } from "./crypto_util"; +import { + kFinalized, + kHandle, + kState, + getArrayBufferOrView, + getStringOption, +} from './crypto_util'; -import { Buffer } from "./internal_buffer"; +import { + Buffer +} from './internal_buffer'; import { - ERR_CRYPTO_HASH_FINALIZED, - ERR_CRYPTO_HASH_UPDATE_FAILED, - ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE, - ERR_INVALID_ARG_TYPE, -} from "./internal_errors"; + ERR_CRYPTO_HASH_FINALIZED, + ERR_CRYPTO_HASH_UPDATE_FAILED, + ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE, + ERR_INVALID_ARG_TYPE, +} from './internal_errors'; -import { validateEncoding, validateString, validateUint32 } from "./validators"; +import { + validateEncoding, + validateString, + validateUint32, +} from './validators'; -import { normalizeEncoding } from "./internal_utils"; +import { + normalizeEncoding +} from './internal_utils'; -import { isArrayBufferView, isCryptoKey, isAnyArrayBuffer } from "./internal_types"; +import { + isArrayBufferView, + isCryptoKey, + isAnyArrayBuffer, +} from './internal_types'; -import { Transform, TransformOptions, TransformCallback } from "./streams_transform"; +import { + Transform, + TransformOptions, + TransformCallback, +} from './streams_transform'; -import { KeyObject } from "./crypto_keys"; +import { + KeyObject, +} from './crypto_keys'; export interface HashOptions extends TransformOptions { - outputLength?: number; + outputLength?: number; } interface _kState { - [kFinalized]: boolean; + [kFinalized]: boolean; } interface Hash extends Transform { - [kHandle]: cryptoImpl.HashHandle; - [kState]: _kState; + [kHandle]: cryptoImpl.HashHandle; + [kState]: _kState; } // These helper functions are needed because the constructors can // use new, in which case V8 cannot inline the recursive constructor call export function createHash(algorithm: string, options?: HashOptions): Hash { - return new Hash(algorithm, options); + return new Hash(algorithm, options); } -let Hash = function ( - this: Hash, - algorithm: string | cryptoImpl.HashHandle, - options?: HashOptions -): Hash { - if (!(this instanceof Hash)) return new Hash(algorithm, options); - - const xofLen = typeof options === "object" ? options.outputLength : undefined; - if (xofLen !== undefined) validateUint32(xofLen, "options.outputLength"); - if (algorithm instanceof cryptoImpl.HashHandle) { - this[kHandle] = algorithm.copy(xofLen as number); - } else { - validateString(algorithm, "algorithm"); - this[kHandle] = new cryptoImpl.HashHandle(algorithm, xofLen as number); - } - this[kState] = { - [kFinalized]: false, - }; +let Hash = function(this: Hash, algorithm: string | cryptoImpl.HashHandle, + options?: HashOptions): Hash { + if (!(this instanceof Hash)) + return new Hash(algorithm, options); - Transform.call(this, options); - return this; -} as any as { new (algorithm: string | cryptoImpl.HashHandle, options?: HashOptions): Hash }; + const xofLen = typeof options === 'object' ? options.outputLength : undefined; + if (xofLen !== undefined) + validateUint32(xofLen, 'options.outputLength'); + if (algorithm instanceof cryptoImpl.HashHandle) { + this[kHandle] = algorithm.copy(xofLen as number); + } else { + validateString(algorithm, 'algorithm'); + this[kHandle] = new cryptoImpl.HashHandle(algorithm, xofLen as number); + } + this[kState] = { + [kFinalized]: false, + }; + + Transform.call(this, options); + return this; +} as any as { new (algorithm: string | cryptoImpl.HashHandle, options?: HashOptions): Hash; }; Object.setPrototypeOf(Hash.prototype, Transform.prototype); Object.setPrototypeOf(Hash, Transform); -Hash.prototype.copy = function (this: Hash, options?: HashOptions): Hash { - const state = this[kState]; - if (state[kFinalized]) throw new ERR_CRYPTO_HASH_FINALIZED(); - - return new Hash(this[kHandle], options); -}; - -Hash.prototype._transform = function ( - this: Hash | Hmac, - chunk: string | Buffer | ArrayBufferView, - encoding: string, - callback: TransformCallback -): void { - if (typeof chunk === "string") { - encoding ??= "utf-8"; - validateEncoding(chunk, encoding); - encoding = normalizeEncoding(encoding)!; - chunk = Buffer.from(chunk, encoding); - } - this[kHandle].update(chunk); - callback(); -}; +Hash.prototype.copy = function(this: Hash, options?: HashOptions): Hash { + const state = this[kState]; + if (state[kFinalized]) + throw new ERR_CRYPTO_HASH_FINALIZED(); -Hash.prototype._flush = function (this: Hash | Hmac, callback: TransformCallback): void { - this.push(Buffer.from(this[kHandle].digest())); - callback(); -}; + return new Hash(this[kHandle], options); +} -Hash.prototype.update = function ( - this: Hash | Hmac, - data: string | Buffer | ArrayBufferView, - encoding?: string -): Hash | Hmac { - encoding ??= "utf8"; - if (encoding === "buffer") { - encoding = undefined; - } +Hash.prototype._transform = function(this: Hash | Hmac, chunk: string | Buffer | ArrayBufferView, + encoding: string, callback: TransformCallback): void { + if (typeof chunk === 'string') { + encoding ??= 'utf-8'; + validateEncoding(chunk, encoding); + encoding = normalizeEncoding(encoding)!; + chunk = Buffer.from(chunk, encoding); + } + this[kHandle].update(chunk); + callback(); +} - const state = this[kState]; - if (state[kFinalized]) throw new ERR_CRYPTO_HASH_FINALIZED(); - - if (typeof data === "string") { - validateEncoding(data, encoding!); - encoding = normalizeEncoding(encoding); - data = Buffer.from(data, encoding); - } else if (!isArrayBufferView(data)) { - throw new ERR_INVALID_ARG_TYPE( - "data", - ["string", "Buffer", "TypedArray", "DataView"], - data - ); - } +Hash.prototype._flush = function(this: Hash | Hmac, callback: TransformCallback): void { + this.push(Buffer.from(this[kHandle].digest())); + callback(); +} - if (!this[kHandle].update(data)) throw new ERR_CRYPTO_HASH_UPDATE_FAILED(); - return this; -}; +Hash.prototype.update = function(this: Hash | Hmac, data: string | Buffer | ArrayBufferView, + encoding?: string): Hash | Hmac { + encoding ??= 'utf8'; + if (encoding === 'buffer') { + encoding = undefined; + } + + const state = this[kState]; + if (state[kFinalized]) + throw new ERR_CRYPTO_HASH_FINALIZED(); + + if (typeof data === 'string') { + validateEncoding(data, encoding!); + encoding = normalizeEncoding(encoding); + data = Buffer.from(data, encoding); + } else if (!isArrayBufferView(data)) { + throw new ERR_INVALID_ARG_TYPE( + 'data', ['string', 'Buffer', 'TypedArray', 'DataView'], data); + } + + if (!this[kHandle].update(data)) + throw new ERR_CRYPTO_HASH_UPDATE_FAILED(); + return this; +} -Hash.prototype.digest = function (this: Hash, outputEncoding?: string): Buffer | string { - const state = this[kState]; - if (state[kFinalized]) throw new ERR_CRYPTO_HASH_FINALIZED(); - - // Explicit conversion for backward compatibility. - const ret = Buffer.from(this[kHandle].digest()); - state[kFinalized] = true; - if (outputEncoding !== undefined && outputEncoding !== "buffer") { - return ret.toString(outputEncoding); - } else { - return ret; - } -}; +Hash.prototype.digest = function(this: Hash, outputEncoding?: string): Buffer | string { + const state = this[kState]; + if (state[kFinalized]) + throw new ERR_CRYPTO_HASH_FINALIZED(); + + // Explicit conversion for backward compatibility. + const ret = Buffer.from(this[kHandle].digest()); + state[kFinalized] = true; + if (outputEncoding !== undefined && outputEncoding !== 'buffer') { + return ret.toString(outputEncoding); + } else { + return ret; + } +} /////////////////////////// interface Hmac extends Transform { - [kHandle]: cryptoImpl.HmacHandle; - [kState]: _kState; + [kHandle]: cryptoImpl.HmacHandle; + [kState]: _kState; } -export function createHmac( - hmac: string, - key: ArrayLike | KeyObject | CryptoKey, - options?: TransformOptions -): Hmac { - return new Hmac(hmac, key, options); +export function createHmac(hmac: string, key: ArrayLike | KeyObject | CryptoKey, + options?: TransformOptions): Hmac { + return new Hmac(hmac, key, options); } -let Hmac = function ( - this: Hmac, - hmac: string, - key: ArrayLike | KeyObject | cryptoImpl.CryptoKey, - options?: TransformOptions -): Hmac { - if (!(this instanceof Hmac)) { - return new Hmac(hmac, key, options); +let Hmac = function(this: Hmac, hmac: string, key: ArrayLike | KeyObject | cryptoImpl.CryptoKey, + options?: TransformOptions): Hmac { + if (!(this instanceof Hmac)) { + return new Hmac(hmac, key, options); + } + validateString(hmac, 'hmac'); + const encoding = getStringOption(options, 'encoding'); + + if (key instanceof KeyObject) { + if (key.type !== 'secret') { + throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(key.type, 'secret'); } - validateString(hmac, "hmac"); - const encoding = getStringOption(options, "encoding"); - - if (key instanceof KeyObject) { - if (key.type !== "secret") { - throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(key.type, "secret"); - } - this[kHandle] = new cryptoImpl.HmacHandle(hmac, key[kHandle]); - } else if (isCryptoKey(key)) { - if ((key as cryptoImpl.CryptoKey).type !== "secret") { - throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE( - (key as cryptoImpl.CryptoKey).type, - "secret" - ); - } - this[kHandle] = new cryptoImpl.HmacHandle(hmac, key); - } else if (typeof key !== "string" && !isArrayBufferView(key) && !isAnyArrayBuffer(key)) { - throw new ERR_INVALID_ARG_TYPE( - "key", - ["ArrayBuffer", "Buffer", "ArrayBufferView", "string", "KeyObject", "CryptoKey"], - key - ); - } else { - this[kHandle] = new cryptoImpl.HmacHandle( - hmac, - getArrayBufferOrView(key as ArrayLike, "key", encoding) - ); + this[kHandle] = new cryptoImpl.HmacHandle(hmac, key[kHandle]); + } else if (isCryptoKey(key)) { + if ((key as cryptoImpl.CryptoKey).type !== 'secret') { + throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE((key as cryptoImpl.CryptoKey).type, 'secret'); } - - this[kState] = { - [kFinalized]: false, - }; - Transform.call(this, options); - return this; -} as any as { - new (hmac: string, key: ArrayLike | KeyObject | CryptoKey, options?: TransformOptions): Hmac; -}; + this[kHandle] = new cryptoImpl.HmacHandle(hmac, key); + } else if (typeof key !== 'string' && + !isArrayBufferView(key) && + !isAnyArrayBuffer(key)) { + throw new ERR_INVALID_ARG_TYPE( + 'key', + [ 'ArrayBuffer', 'Buffer', 'ArrayBufferView', 'string', 'KeyObject', 'CryptoKey'], + key); + } else { + this[kHandle] = new cryptoImpl.HmacHandle(hmac, getArrayBufferOrView(key as ArrayLike, + 'key', encoding)); + } + + this[kState] = { + [kFinalized]: false, + }; + Transform.call(this, options); + return this; +} as any as { new (hmac: string, key: ArrayLike | KeyObject | CryptoKey, + options?: TransformOptions): Hmac; }; Object.setPrototypeOf(Hmac.prototype, Transform.prototype); Object.setPrototypeOf(Hmac, Transform); Hmac.prototype.update = Hash.prototype.update; -Hmac.prototype.digest = function (this: Hmac, outputEncoding?: string): Buffer | string { - const state = this[kState]; - if (state[kFinalized]) { - const buf = Buffer.from(""); - return outputEncoding === "buffer" ? buf : buf.toString(outputEncoding); - } - - // Explicit conversion for backward compatibility. - const ret = Buffer.from(this[kHandle].digest()); - state[kFinalized] = true; - if (outputEncoding !== undefined && outputEncoding !== "buffer") { - return ret.toString(outputEncoding); - } else { - return ret; - } +Hmac.prototype.digest = function(this: Hmac, outputEncoding?: string): Buffer | string { + const state = this[kState]; + if (state[kFinalized]) { + const buf = Buffer.from(''); + return outputEncoding === 'buffer' ? buf : buf.toString(outputEncoding); + } + + // Explicit conversion for backward compatibility. + const ret = Buffer.from(this[kHandle].digest()); + state[kFinalized] = true; + if (outputEncoding !== undefined && outputEncoding !== 'buffer') { + return ret.toString(outputEncoding); + } else { + return ret; + } }; Hmac.prototype._flush = Hash.prototype._flush; Hmac.prototype._transform = Hash.prototype._transform; -export { Hash, Hmac }; +export {Hash, Hmac}; diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_hkdf.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_hkdf.ts index 7196bea89..3c48a2849 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_hkdf.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_hkdf.ts @@ -1,110 +1,124 @@ /* eslint-disable */ -"use strict"; +'use strict'; -import * as cryptoImpl from "./crypto"; +import * as cryptoImpl from './crypto'; -import { validateFunction, validateInteger, validateString } from "./validators"; +import { + validateFunction, + validateInteger, + validateString, +} from './validators'; -import { KeyObject } from "./crypto_keys"; +import { + KeyObject, +} from './crypto_keys'; type ArrayLike = cryptoImpl.ArrayLike; -import { kMaxLength } from "./internal_buffer"; - -import { toBuf, validateByteSource } from "./crypto_util"; - -import { isAnyArrayBuffer, isArrayBufferView } from "./internal_types"; - -import { NodeError, ERR_INVALID_ARG_TYPE, ERR_OUT_OF_RANGE } from "./internal_errors"; - -function validateParameters( - hash: string, - key: ArrayLike | KeyObject, - salt: ArrayLike, - info: ArrayLike, - length: number -) { - // TODO(soon): Add support for KeyObject input. - if (key instanceof KeyObject) { - throw new NodeError( - "ERR_METHOD_NOT_IMPLEMENTED", - "KeyObject support for hkdf() and " + - "hkdfSync() is not yet implemented. Use ArrayBuffer, TypedArray, " + - "DataView, or Buffer instead." - ); - } - - validateString(hash, "digest"); - key = prepareKey(key as unknown as ArrayLike); - salt = validateByteSource(salt, "salt"); - info = validateByteSource(info, "info"); - - validateInteger(length, "length", 0, kMaxLength); - - if (info.byteLength > 1024) { - throw new ERR_OUT_OF_RANGE( - "info", - "must not contain more than 1024 bytes", - info.byteLength - ); - } - - return { - hash, - key, - salt, - info, - length, - }; +import { + kMaxLength, +} from './internal_buffer'; + +import { + toBuf, + validateByteSource, +} from './crypto_util'; + +import { + isAnyArrayBuffer, + isArrayBufferView, +} from './internal_types'; + +import { + NodeError, + ERR_INVALID_ARG_TYPE, + ERR_OUT_OF_RANGE, +} from './internal_errors'; + +function validateParameters(hash: string, key: ArrayLike | KeyObject, salt: ArrayLike, + info: ArrayLike, length: number) { + // TODO(soon): Add support for KeyObject input. + if (key instanceof KeyObject) { + throw new NodeError("ERR_METHOD_NOT_IMPLEMENTED", "KeyObject support for hkdf() and " + + "hkdfSync() is not yet implemented. Use ArrayBuffer, TypedArray, " + + "DataView, or Buffer instead."); + } + + validateString(hash, 'digest'); + key = prepareKey(key as unknown as ArrayLike); + salt = validateByteSource(salt, 'salt'); + info = validateByteSource(info, 'info'); + + validateInteger(length, 'length', 0, kMaxLength); + + if (info.byteLength > 1024) { + throw new ERR_OUT_OF_RANGE( + 'info', + 'must not contain more than 1024 bytes', + info.byteLength); + } + + return { + hash, + key, + salt, + info, + length, + }; } function prepareKey(key: ArrayLike): ArrayLike { - key = toBuf(key); - - if (!isAnyArrayBuffer(key) && !isArrayBufferView(key)) { - throw new ERR_INVALID_ARG_TYPE( - "ikm", - ["string", "SecretKeyObject", "ArrayBuffer", "TypedArray", "DataView", "Buffer"], - key - ); - } - - return key; + key = toBuf(key); + + if (!isAnyArrayBuffer(key) && !isArrayBufferView(key)) { + throw new ERR_INVALID_ARG_TYPE( + 'ikm', + [ + 'string', + 'SecretKeyObject', + 'ArrayBuffer', + 'TypedArray', + 'DataView', + 'Buffer', + ], + key); + } + + return key; } -export function hkdf( - hash: string, - key: ArrayLike | KeyObject, - salt: ArrayLike, - info: ArrayLike, - length: number, - callback: (err: Error | null, derivedKey?: ArrayBuffer) => void -): void { - ({ hash, key, salt, info, length } = validateParameters(hash, key, salt, info, length)); - - validateFunction(callback, "callback"); - - new Promise((res, rej) => { - try { - res(cryptoImpl.getHkdf(hash, key as ArrayLike, salt, info, length)); - } catch (err) { - rej(err); - } - }).then( - (val: ArrayBuffer) => callback(null, val), - (err) => callback(err) - ); +export function hkdf(hash: string, key: ArrayLike | KeyObject, salt: ArrayLike, info: ArrayLike, + length: number, + callback: (err: Error|null, derivedKey?: ArrayBuffer) => void): void { + ({ + hash, + key, + salt, + info, + length, + } = validateParameters(hash, key, salt, info, length)); + + validateFunction(callback, 'callback'); + + new Promise((res, rej) => { + try { + res(cryptoImpl.getHkdf(hash, key as ArrayLike, salt, info, length)); + } catch(err) { + rej(err); + } + }).then((val: ArrayBuffer) => callback(null, val), (err) => callback(err)); } -export function hkdfSync( - hash: string, - key: ArrayLike | KeyObject, - salt: ArrayLike, - info: ArrayLike, - length: number -): ArrayBuffer { - ({ hash, key, salt, info, length } = validateParameters(hash, key, salt, info, length)); - - return cryptoImpl.getHkdf(hash, key, salt, info, length); +export function hkdfSync(hash: string, key: ArrayLike | KeyObject, salt: ArrayLike, + info: ArrayLike, length: number): ArrayBuffer { + ({ + hash, + key, + salt, + info, + length, + } = validateParameters(hash, key, salt, info, length)); + + return cryptoImpl.getHkdf(hash, key, salt, info, length); } diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_keys.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_keys.ts index 488d7b8d6..aa549f57d 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_keys.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_keys.ts @@ -1,220 +1,205 @@ /* eslint-disable */ -import { Buffer } from "./internal_buffer"; - -import * as cryptoImpl from "./crypto"; - -const { - CryptoKey, - KeyData, - KeyObjectType, - KeyExportResult, - SecretKeyType, - SecretKeyExportOptions, - PublicKeyExportOptions, - PrivateKeyExportOptions, - ExportOptions, - AsymmetricKeyDetails, - AsymmetricKeyType, - CreateAsymmetricKeyOptions, - GenerateKeyOptions, - GenerateKeyPairOptions, - InnerExportOptions, - // TODO(soon): Uncomment these once createPrivateKey/createPublicKey are implemented. - // JsonWebKey, - // InnerCreateAsymmetricKeyOptions, -} = cryptoImpl; - -import { arrayBufferToUnsignedBigInt, kHandle } from "./crypto_util"; +import { Buffer } from './internal_buffer'; + +import * as cryptoImpl from './crypto'; + +const +{ + CryptoKey, + KeyData, + KeyObjectType, + KeyExportResult, + SecretKeyType, + SecretKeyExportOptions, + PublicKeyExportOptions, + PrivateKeyExportOptions, + ExportOptions, + AsymmetricKeyDetails, + AsymmetricKeyType, + CreateAsymmetricKeyOptions, + GenerateKeyOptions, + GenerateKeyPairOptions, + InnerExportOptions, + // TODO(soon): Uncomment these once createPrivateKey/createPublicKey are implemented. + // JsonWebKey, + // InnerCreateAsymmetricKeyOptions, +} + = cryptoImpl; + + import { - isAnyArrayBuffer, - isArrayBuffer, - isArrayBufferView, - isUint8Array, - // TODO(soon): Uncomment these once createPrivateKey/createPublicKey are implemented. - // isSharedArrayBuffer, -} from "./internal_types"; + arrayBufferToUnsignedBigInt, + kHandle, +} from './crypto_util'; import { - ERR_INVALID_ARG_TYPE, - ERR_METHOD_NOT_IMPLEMENTED, - // TODO(soon): Uncomment these once createPrivateKey/createPublicKey are implemented. - // ERR_INVALID_ARG_VALUE, -} from "./internal_errors"; + isAnyArrayBuffer, + isArrayBuffer, + isArrayBufferView, + isUint8Array, + // TODO(soon): Uncomment these once createPrivateKey/createPublicKey are implemented. + // isSharedArrayBuffer, +} from './internal_types'; -import { validateObject, validateString } from "./validators"; +import { + ERR_INVALID_ARG_TYPE, + ERR_METHOD_NOT_IMPLEMENTED, + // TODO(soon): Uncomment these once createPrivateKey/createPublicKey are implemented. + // ERR_INVALID_ARG_VALUE, +} from './internal_errors'; -export abstract class KeyObject { - [kHandle]: CryptoKey; +import { + validateObject, + validateString, +} from './validators'; - constructor() { - // KeyObjects cannot be created with new ... use one of the - // create or generate methods, or use from to get from a - // CryptoKey. - throw new Error("Illegal constructor"); +export abstract class KeyObject { + [kHandle]: CryptoKey; + + constructor() { + // KeyObjects cannot be created with new ... use one of the + // create or generate methods, or use from to get from a + // CryptoKey. + throw new Error('Illegal constructor'); + } + + static from(key: CryptoKey) : KeyObject { + if (!(key instanceof CryptoKey)) { + throw new ERR_INVALID_ARG_TYPE('key', 'CryptoKey', key); } - - static from(key: CryptoKey): KeyObject { - if (!(key instanceof CryptoKey)) { - throw new ERR_INVALID_ARG_TYPE("key", "CryptoKey", key); - } - switch (key.type) { - case "secret": - return Reflect.construct( - function (this: SecretKeyObject) { - this[kHandle] = key; - }, - [], - SecretKeyObject - ); - case "private": - return Reflect.construct( - function (this: PrivateKeyObject) { - this[kHandle] = key; - }, - [], - PrivateKeyObject - ); - case "public": - return Reflect.construct( - function (this: PublicKeyObject) { - this[kHandle] = key; - }, - [], - PublicKeyObject - ); - } + switch (key.type) { + case 'secret': + return Reflect.construct(function(this: SecretKeyObject) { + this[kHandle] = key; + }, [], SecretKeyObject); + case 'private': + return Reflect.construct(function(this: PrivateKeyObject) { + this[kHandle] = key; + }, [], PrivateKeyObject); + case 'public': + return Reflect.construct(function(this: PublicKeyObject) { + this[kHandle] = key; + }, [], PublicKeyObject); } - - export(options: ExportOptions = {}): KeyExportResult { - validateObject(options, "options", {}); - - // Yes, converting to any is a bit of a cheat, but it allows us to check - // each option individually without having to do a bunch of type guards. - const opts = options as any; - if (opts.format !== undefined) validateString(opts.format, "options.format"); - if (opts.type !== undefined) validateString(opts.type, "options.type"); - if (this.type === "private") { - if (opts.cipher !== undefined) { - validateString(opts.cipher, "options.cipher"); - if (typeof opts.passphrase === "string") { - opts.passphrase = Buffer.from(opts.passphrase, opts.encoding); - } - if (!isUint8Array(opts.passphrase)) { - throw new ERR_INVALID_ARG_TYPE( - "options.passphrase", - ["string", "Uint8Array"], - opts.passphrase - ); - } - } + } + + export(options: ExportOptions = {}) : KeyExportResult { + validateObject(options, 'options', {}); + + // Yes, converting to any is a bit of a cheat, but it allows us to check + // each option individually without having to do a bunch of type guards. + const opts = options as any; + if (opts.format !== undefined) validateString(opts.format, 'options.format'); + if (opts.type !== undefined) validateString(opts.type, 'options.type'); + if (this.type === 'private') { + if (opts.cipher !== undefined) { + validateString(opts.cipher, 'options.cipher'); + if (typeof opts.passphrase === 'string') { + opts.passphrase = Buffer.from(opts.passphrase, opts.encoding); } - - const ret = cryptoImpl.exportKey(this[kHandle], options as InnerExportOptions); - if (typeof ret === "string") return ret; - if (isUint8Array(ret)) { - return Buffer.from( - (ret as Uint8Array).buffer, - ret.byteOffset, - ret.byteLength - ) as KeyExportResult; - } else if (isArrayBuffer(ret)) { - return Buffer.from(ret as ArrayBuffer, 0, (ret as ArrayBuffer).byteLength); + if (!isUint8Array(opts.passphrase)) { + throw new ERR_INVALID_ARG_TYPE('options.passphrase', [ + 'string', 'Uint8Array' + ], opts.passphrase); } - return ret; + } } - equals(otherKeyObject: KeyObject): boolean { - if (this === otherKeyObject || this[kHandle] === otherKeyObject[kHandle]) return true; - if (this.type !== otherKeyObject.type) return false; - if (!(otherKeyObject[kHandle] instanceof CryptoKey)) { - throw new ERR_INVALID_ARG_TYPE("otherKeyObject", "KeyObject", otherKeyObject); - } - return cryptoImpl.equals(this[kHandle], otherKeyObject[kHandle]); + const ret = cryptoImpl.exportKey(this[kHandle], options as InnerExportOptions); + if (typeof ret === 'string') return ret; + if (isUint8Array(ret)) { + return Buffer.from((ret as Uint8Array).buffer, ret.byteOffset, ret.byteLength) as KeyExportResult; + } else if (isArrayBuffer(ret)) { + return Buffer.from(ret as ArrayBuffer, 0, (ret as ArrayBuffer).byteLength); } + return ret; + } + + equals(otherKeyObject: KeyObject) : boolean { + if (this === otherKeyObject || + this[kHandle] === otherKeyObject[kHandle]) return true; + if (this.type !== otherKeyObject.type) return false; + if (!(otherKeyObject[kHandle] instanceof CryptoKey)) { + throw new ERR_INVALID_ARG_TYPE('otherKeyObject', 'KeyObject', otherKeyObject); + } + return cryptoImpl.equals(this[kHandle], otherKeyObject[kHandle]); + } - abstract get type(): KeyObjectType; + abstract get type() : KeyObjectType; } abstract class AsymmetricKeyObject extends KeyObject { - get asymmetricKeyDetails(): AsymmetricKeyDetails { - let detail = cryptoImpl.getAsymmetricKeyDetail(this[kHandle]); - if (isArrayBuffer(detail.publicExponent)) { - detail.publicExponent = arrayBufferToUnsignedBigInt(detail.publicExponent as any); - } - return detail; + get asymmetricKeyDetails() : AsymmetricKeyDetails { + let detail = cryptoImpl.getAsymmetricKeyDetail(this[kHandle]); + if (isArrayBuffer(detail.publicExponent)) { + detail.publicExponent = arrayBufferToUnsignedBigInt(detail.publicExponent as any); } + return detail; + } - get asymmetricKeyType(): AsymmetricKeyType { - return cryptoImpl.getAsymmetricKeyType(this[kHandle]); - } + get asymmetricKeyType() : AsymmetricKeyType { + return cryptoImpl.getAsymmetricKeyType(this[kHandle]); + } } export class PublicKeyObject extends AsymmetricKeyObject { - override export(options?: PublicKeyExportOptions): KeyExportResult { - return super.export(options); - } + override export(options?: PublicKeyExportOptions) : KeyExportResult { + return super.export(options); + } - get type(): KeyObjectType { - return "public"; - } + get type() : KeyObjectType { return 'public'; } } export class PrivateKeyObject extends AsymmetricKeyObject { - override export(options?: PrivateKeyExportOptions): KeyExportResult { - return super.export(options); - } + override export(options?: PrivateKeyExportOptions) : KeyExportResult { + return super.export(options); + } - get type(): KeyObjectType { - return "private"; - } + get type() : KeyObjectType { return 'private'; } } export class SecretKeyObject extends KeyObject { - get symmetricKeySize(): number { - return (this[kHandle].algorithm as any).length | 0; - } + get symmetricKeySize() : number { + return (this[kHandle].algorithm as any).length | 0 + } - override export(options?: SecretKeyExportOptions): KeyExportResult { - return super.export(options); - } + override export(options?: SecretKeyExportOptions) : KeyExportResult { + return super.export(options); + } - get type(): KeyObjectType { - return "secret"; - } + get type() : KeyObjectType { return 'secret'; } } type ValidateKeyDataOptions = { - allowObject?: boolean; + allowObject?: boolean; }; -function validateKeyData( - key: unknown, - name: string, - options: ValidateKeyDataOptions = { - allowObject: false, - } -) { - if ( - key == null || - (typeof key !== "string" && - options.allowObject && - typeof key !== "object" && - !isArrayBufferView(key) && - !isAnyArrayBuffer(key)) - ) { - const expected = ["string", "ArrayBuffer", "TypedArray", "DataView"]; - if (options.allowObject) expected.push("object"); - throw new ERR_INVALID_ARG_TYPE(name, expected, key); - } +function validateKeyData(key: unknown, name: string, options : ValidateKeyDataOptions = { + allowObject: false, +}) { + if (key == null || + (typeof key !== 'string' && + (options.allowObject && typeof key !== 'object') && + !isArrayBufferView(key) && + !isAnyArrayBuffer(key))) { + const expected = [ + 'string', + 'ArrayBuffer', + 'TypedArray', + 'DataView' + ]; + if (options.allowObject) expected.push('object'); + throw new ERR_INVALID_ARG_TYPE(name, expected, key); + } } -export function createSecretKey(key: string, encoding?: string): SecretKeyObject; -export function createSecretKey(key: ArrayBuffer | ArrayBufferView): SecretKeyObject; -export function createSecretKey(key: KeyData, encoding?: string): SecretKeyObject { - validateKeyData(key, "key"); - if (typeof key === "string") key = Buffer.from(key as string, encoding); - return KeyObject.from(cryptoImpl.createSecretKey(key)) as SecretKeyObject; +export function createSecretKey(key: string, encoding?: string) : SecretKeyObject; +export function createSecretKey(key: ArrayBuffer | ArrayBufferView) : SecretKeyObject; +export function createSecretKey(key: KeyData, encoding?: string) : SecretKeyObject { + validateKeyData(key, 'key'); + if (typeof key === 'string') key = Buffer.from(key as string, encoding); + return KeyObject.from(cryptoImpl.createSecretKey(key)) as SecretKeyObject; } // TODO(soon): Fully implement createPrivateKey/createPublicKey. These are the @@ -309,41 +294,40 @@ export function createSecretKey(key: KeyData, encoding?: string): SecretKeyObjec // return inner; // } -export function createPrivateKey(key: string): PrivateKeyObject; -export function createPrivateKey(key: ArrayBuffer | ArrayBufferView): PrivateKeyObject; -export function createPrivateKey(key: CreateAsymmetricKeyOptions): PrivateKeyObject; -export function createPrivateKey(_key: CreateAsymmetricKeyOptions | KeyData): PrivateKeyObject { - // The options here are fairly complex. The key data can be a string, - // ArrayBuffer, or ArrayBufferView. The first argument can be one of - // these or an object with a key property that is one of these. If the - // key data is a string, then it will be decoded using an encoding - // (defaults to UTF8). - throw new ERR_METHOD_NOT_IMPLEMENTED("crypto.createPrivateKey"); - // return KeyObject.from(cryptoImpl.createPrivateKey( - // validateAsymmetricKeyOptions(key, kPrivateKey))) as PrivateKeyObject; +export function createPrivateKey(key: string) : PrivateKeyObject; +export function createPrivateKey(key: ArrayBuffer | ArrayBufferView) : PrivateKeyObject; +export function createPrivateKey(key: CreateAsymmetricKeyOptions) : PrivateKeyObject; +export function createPrivateKey(_key: CreateAsymmetricKeyOptions | KeyData) : PrivateKeyObject { + // The options here are fairly complex. The key data can be a string, + // ArrayBuffer, or ArrayBufferView. The first argument can be one of + // these or an object with a key property that is one of these. If the + // key data is a string, then it will be decoded using an encoding + // (defaults to UTF8). + throw new ERR_METHOD_NOT_IMPLEMENTED('crypto.createPrivateKey'); + // return KeyObject.from(cryptoImpl.createPrivateKey( + // validateAsymmetricKeyOptions(key, kPrivateKey))) as PrivateKeyObject; } -export function createPublicKey(key: string): PublicKeyObject; -export function createPublicKey(key: ArrayBuffer): PublicKeyObject; -export function createPublicKey(key: ArrayBufferView): PublicKeyObject; - -export function createPublicKey(key: KeyObject): PublicKeyObject; -export function createPublicKey(key: CryptoKey): PublicKeyObject; -export function createPublicKey(key: CreateAsymmetricKeyOptions): PublicKeyObject; -export function createPublicKey( - _key: CreateAsymmetricKeyOptions | KeyData | CryptoKey | KeyObject -): PublicKeyObject { - // The options here are a bit complicated. The key material itself can - // either be a string, ArrayBuffer, or ArrayBufferView. It is also - // possible to pass a private key in the form of either a CryptoKey - // or KeyObject. The first argument can be one of these, or an object - // whose key value is one of these. If the key data is a string, then - // it will be decoded using an encoding (defaults to UTF8). If a - // CryptoKey or KeyObject is passed, it will be used to derived the - // public key. - throw new ERR_METHOD_NOT_IMPLEMENTED("crypto.createPublicKey"); - // return KeyObject.from(cryptoImpl.createPublicKey( - // validateAsymmetricKeyOptions(key, kPublicKey))) as PublicKeyObject; +export function createPublicKey(key: string) : PublicKeyObject; +export function createPublicKey(key: ArrayBuffer) : PublicKeyObject; +export function createPublicKey(key: ArrayBufferView) : PublicKeyObject; + +export function createPublicKey(key: KeyObject) : PublicKeyObject; +export function createPublicKey(key: CryptoKey) : PublicKeyObject; +export function createPublicKey(key: CreateAsymmetricKeyOptions) : PublicKeyObject; +export function createPublicKey(_key: CreateAsymmetricKeyOptions | KeyData | CryptoKey | KeyObject) + : PublicKeyObject { + // The options here are a bit complicated. The key material itself can + // either be a string, ArrayBuffer, or ArrayBufferView. It is also + // possible to pass a private key in the form of either a CryptoKey + // or KeyObject. The first argument can be one of these, or an object + // whose key value is one of these. If the key data is a string, then + // it will be decoded using an encoding (defaults to UTF8). If a + // CryptoKey or KeyObject is passed, it will be used to derived the + // public key. + throw new ERR_METHOD_NOT_IMPLEMENTED('crypto.createPublicKey'); + // return KeyObject.from(cryptoImpl.createPublicKey( + // validateAsymmetricKeyOptions(key, kPublicKey))) as PublicKeyObject; } // ====================================================================================== @@ -351,56 +335,50 @@ export function createPublicKey( export type PublicKeyResult = KeyExportResult | PublicKeyObject; export type PrivateKeyResult = KeyExportResult | PrivateKeyObject; export type GenerateKeyCallback = (err?: any, key?: KeyObject) => void; -export type GenerateKeyPairCallback = ( - err?: any, - publicKey?: PublicKeyResult, - privateKey?: PrivateKeyResult -) => void; +export type GenerateKeyPairCallback = + (err?: any, publicKey?: PublicKeyResult, privateKey?: PrivateKeyResult) => void; export interface KeyObjectPair { - publicKey: PublicKeyResult; - privateKey: PrivateKeyResult; + publicKey: PublicKeyResult; + privateKey: PrivateKeyResult; } -export function generateKey( - _type: SecretKeyType, - _options: GenerateKeyOptions, - callback: GenerateKeyCallback -) { - // We intentionally have not implemented key generation up to this point. - // The reason is that generation of cryptographically safe keys is a CPU - // intensive operation that can often exceed limits on the amount of CPU - // time a worker is allowed. - callback(new ERR_METHOD_NOT_IMPLEMENTED("crypto.generateKeySync")); +export function generateKey(_type: SecretKeyType, + _options: GenerateKeyOptions, + callback: GenerateKeyCallback) { +// We intentionally have not implemented key generation up to this point. +// The reason is that generation of cryptographically safe keys is a CPU +// intensive operation that can often exceed limits on the amount of CPU +// time a worker is allowed. +callback(new ERR_METHOD_NOT_IMPLEMENTED('crypto.generateKeySync')); } -export function generateKeySync(_type: SecretKeyType, _options: GenerateKeyOptions) { - // We intentionally have not implemented key generation up to this point. - // The reason is that generation of cryptographically safe keys is a CPU - // intensive operation that can often exceed limits on the amount of CPU - // time a worker is allowed. - throw new ERR_METHOD_NOT_IMPLEMENTED("crypto.generateKeySync"); +export function generateKeySync(_type: SecretKeyType, + _options: GenerateKeyOptions) { +// We intentionally have not implemented key generation up to this point. +// The reason is that generation of cryptographically safe keys is a CPU +// intensive operation that can often exceed limits on the amount of CPU +// time a worker is allowed. +throw new ERR_METHOD_NOT_IMPLEMENTED('crypto.generateKeySync'); } export function generateKeyPair( - _type: AsymmetricKeyType, + _type : AsymmetricKeyType, _options: GenerateKeyPairOptions, - callback: GenerateKeyPairCallback -) { - // We intentionally have not implemented key generation up to this point. - // The reason is that generation of cryptographically safe keys is a CPU - // intensive operation that can often exceed limits on the amount of CPU - // time a worker is allowed. - callback(new ERR_METHOD_NOT_IMPLEMENTED("crypto.generateKeyPair")); + callback: GenerateKeyPairCallback) { + // We intentionally have not implemented key generation up to this point. + // The reason is that generation of cryptographically safe keys is a CPU + // intensive operation that can often exceed limits on the amount of CPU + // time a worker is allowed. + callback(new ERR_METHOD_NOT_IMPLEMENTED('crypto.generateKeyPair')); } export function generateKeyPairSync( - _type: AsymmetricKeyType, - _options: GenerateKeyPairOptions -): KeyObjectPair { - // We intentionally have not implemented key generation up to this point. - // The reason is that generation of cryptographically safe keys is a CPU - // intensive operation that can often exceed limits on the amount of CPU - // time a worker is allowed. - throw new ERR_METHOD_NOT_IMPLEMENTED("crypto.generateKeyPairSync"); + _type : AsymmetricKeyType, + _options: GenerateKeyPairOptions) : KeyObjectPair { + // We intentionally have not implemented key generation up to this point. + // The reason is that generation of cryptographically safe keys is a CPU + // intensive operation that can often exceed limits on the amount of CPU + // time a worker is allowed. + throw new ERR_METHOD_NOT_IMPLEMENTED('crypto.generateKeyPairSync'); } diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_pbkdf2.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_pbkdf2.ts index 3d575b53a..40772a90c 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_pbkdf2.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_pbkdf2.ts @@ -1,85 +1,64 @@ /* eslint-disable */ -"use strict"; +'use strict'; -import * as cryptoImpl from "./crypto"; +import * as cryptoImpl from './crypto'; type ArrayLike = cryptoImpl.ArrayLike; -export { ArrayLike }; +export {ArrayLike}; -import { Buffer } from "./internal_buffer"; +import { + Buffer, +} from './internal_buffer'; -import { validateInt32, validateFunction, validateString } from "./validators"; +import { + validateInt32, + validateFunction, + validateString, +} from './validators'; -import { getArrayBufferOrView } from "./crypto_util"; +import { + getArrayBufferOrView, +} from './crypto_util'; -export function pbkdf2Sync( - password: ArrayLike, - salt: ArrayLike, - iterations: number, - keylen: number, - digest: string -): Buffer { - ({ password, salt, iterations, keylen, digest } = check( - password, - salt, - iterations, - keylen, - digest - )); +export function pbkdf2Sync(password: ArrayLike, salt: ArrayLike, iterations: number, + keylen: number, digest: string): Buffer { + ({ password, salt, iterations, keylen, digest } = + check(password, salt, iterations, keylen, digest)); - const result = cryptoImpl.getPbkdf(password, salt, iterations, keylen, digest); - return Buffer.from(result); + const result = cryptoImpl.getPbkdf(password, salt, iterations, keylen, digest); + return Buffer.from(result); } -export type Pbkdf2Callback = (err?: Error | null, result?: Buffer) => void; -export function pbkdf2( - password: ArrayLike, - salt: ArrayLike, - iterations: number, - keylen: number, - digest: string, - callback: Pbkdf2Callback -): void { - if (typeof digest === "function") { - // Appease node test cases - validateString(undefined, "digest"); - } - validateFunction(callback, "callback"); - ({ password, salt, iterations, keylen, digest } = check( - password, - salt, - iterations, - keylen, - digest - )); +export type Pbkdf2Callback = (err?: Error|null, result?: Buffer) => void; +export function pbkdf2(password: ArrayLike, salt: ArrayLike, iterations: number, keylen: number, + digest: string, callback: Pbkdf2Callback): void { + if (typeof digest === 'function') { + // Appease node test cases + validateString(undefined, 'digest'); + } + validateFunction(callback, 'callback'); + ({ password, salt, iterations, keylen, digest } = + check(password, salt, iterations, keylen, digest)); - new Promise((res, rej) => { - try { - res(cryptoImpl.getPbkdf(password, salt, iterations, keylen, digest)); - } catch (err) { - rej(err); - } - }).then( - (val) => callback(null, Buffer.from(val)), - (err) => callback(err) - ); + new Promise((res, rej) => { + try { + res(cryptoImpl.getPbkdf(password, salt, iterations, keylen, digest)); + } catch(err) { + rej(err); + } + }).then((val) => callback(null, Buffer.from(val)), (err) => callback(err)); } -function check( - password: ArrayLike | ArrayBufferView, - salt: ArrayLike | ArrayBufferView, - iterations: number, - keylen: number, - digest: string -): any { - validateString(digest, "digest"); +function check(password: ArrayLike|ArrayBufferView, salt: ArrayLike|ArrayBufferView, iterations: number, keylen: number, + digest: string): any { + validateString(digest, 'digest'); - password = getArrayBufferOrView(password, "password"); - salt = getArrayBufferOrView(salt, "salt"); - // OpenSSL uses a signed int to represent these values, so we are restricted - // to the 31-bit range here (which is plenty). - validateInt32(iterations, "iterations", 1); - validateInt32(keylen, "keylen", 0); + password = getArrayBufferOrView(password, 'password'); + salt = getArrayBufferOrView(salt, 'salt'); + // OpenSSL uses a signed int to represent these values, so we are restricted + // to the 31-bit range here (which is plenty). + validateInt32(iterations, 'iterations', 1); + validateInt32(keylen, 'keylen', 0); - return { password, salt, iterations, keylen, digest }; + return { password, salt, iterations, keylen, digest }; } diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_random.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_random.ts index ac49474c8..64c0a58a1 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_random.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_random.ts @@ -1,126 +1,127 @@ /* eslint-disable */ -import * as cryptoImpl from "./crypto"; +import * as cryptoImpl from './crypto'; import { - validateObject, - validateBoolean, - validateFunction, - validateInt32, - validateInteger, -} from "./validators"; + validateObject, + validateBoolean, + validateFunction, + validateInt32, + validateInteger, +} from './validators'; -import { isAnyArrayBuffer, isArrayBufferView } from "./internal_types"; +import { + isAnyArrayBuffer, + isArrayBufferView +} from './internal_types'; -import { ERR_INVALID_ARG_TYPE, ERR_OUT_OF_RANGE } from "./internal_errors"; +import { + ERR_INVALID_ARG_TYPE, + ERR_OUT_OF_RANGE, +} from './internal_errors'; -import { Buffer, kMaxLength } from "./internal_buffer"; +import { + Buffer, + kMaxLength +} from './internal_buffer'; -import { arrayBufferToUnsignedBigInt } from "./crypto_util"; +import { + arrayBufferToUnsignedBigInt, +} from './crypto_util'; -export type RandomBytesCallback = (err: any | null, buffer: Uint8Array) => void; +export type RandomBytesCallback = (err: any|null, buffer: Uint8Array) => void; export function randomBytes(size: number, callback: RandomBytesCallback): void; export function randomBytes(size: number): Uint8Array; -export function randomBytes(size: number, callback?: RandomBytesCallback): Uint8Array | void { - validateInteger(size, "size", 0, kMaxLength); - const buf = Buffer.alloc(size); - if (callback !== undefined) { - randomFill(buf, callback as RandomFillCallback); - } else { - randomFillSync(buf); - return buf; - } +export function randomBytes(size: number, callback?: RandomBytesCallback) : Uint8Array|void{ + validateInteger(size, 'size', 0, kMaxLength); + const buf = Buffer.alloc(size); + if (callback !== undefined) { + randomFill(buf, callback as RandomFillCallback); + } else { + randomFillSync(buf); + return buf; + } } export function randomFillSync( - buffer: ArrayBufferView | ArrayBuffer, + buffer: ArrayBufferView|ArrayBuffer, offset?: number, - size?: number -) { - if (!isAnyArrayBuffer(buffer) && !isArrayBufferView(buffer)) { - throw new ERR_INVALID_ARG_TYPE( - "buffer", - ["TypedArray", "DataView", "ArrayBuffer", "SharedArrayBuffer"], - buffer - ); - } - const maxLength = (buffer as Uint8Array).length; - if (offset !== undefined) { - validateInteger(offset!, "offset", 0, kMaxLength); - } else offset = 0; - if (size !== undefined) { - validateInteger(size!, "size", 0, maxLength - offset); - } else size = maxLength; - if (isAnyArrayBuffer(buffer)) { - buffer = Buffer.from(buffer as ArrayBuffer); - } - buffer = (buffer as Buffer).subarray(offset, offset + size); - return crypto.getRandomValues(buffer as ArrayBufferView); + size?: number) { + if (!isAnyArrayBuffer(buffer) && !isArrayBufferView(buffer)) { + throw new ERR_INVALID_ARG_TYPE('buffer', [ + 'TypedArray', + 'DataView', + 'ArrayBuffer', + 'SharedArrayBuffer' + ],buffer); + } + const maxLength = (buffer as Uint8Array).length; + if (offset !== undefined) { + validateInteger(offset!, 'offset', 0, kMaxLength); + } else offset = 0; + if (size !== undefined) { + validateInteger(size!, 'size', 0, maxLength - offset); + } else size = maxLength; + if (isAnyArrayBuffer(buffer)) { + buffer = Buffer.from(buffer as ArrayBuffer); + } + buffer = (buffer as Buffer).subarray(offset, offset + size); + return crypto.getRandomValues(buffer as ArrayBufferView); } -export type RandomFillCallback = (err: any | null, buf?: ArrayBufferView | ArrayBuffer) => void; -export function randomFill( - buffer: ArrayBufferView | ArrayBuffer, - callback?: RandomFillCallback -): void; -export function randomFill( - buffer: ArrayBufferView | ArrayBuffer, - offset: number, - callback?: RandomFillCallback -): void; -export function randomFill( - buffer: ArrayBufferView | ArrayBuffer, - offset: number, - size: number, - callback?: RandomFillCallback -): void; -export function randomFill( - buffer: ArrayBufferView | ArrayBuffer, - offsetOrCallback?: number | RandomFillCallback, - sizeOrCallback?: number | RandomFillCallback, - callback?: RandomFillCallback -) { - if (!isAnyArrayBuffer(buffer) && !isArrayBufferView(buffer)) { - throw new ERR_INVALID_ARG_TYPE( - "buffer", - ["TypedArray", "DataView", "ArrayBuffer", "SharedArrayBuffer"], - buffer - ); - } - - let offset = 0; - let size = 0; - const maxLength = (buffer as Uint8Array).length; - if (typeof callback === "function") { - validateInteger(offsetOrCallback, "offset", 0, maxLength); - offset = offsetOrCallback as number; - - validateInteger(sizeOrCallback, "size", 0, maxLength - offset); - size = sizeOrCallback as number; - } else if (typeof sizeOrCallback === "function") { - validateInteger(offsetOrCallback, "offset", 0, maxLength); - offset = offsetOrCallback as number; - size = maxLength - offset; - callback = sizeOrCallback as RandomFillCallback; - } else if (typeof offsetOrCallback === "function") { - offset = 0; - size = maxLength; - callback = offsetOrCallback as RandomFillCallback; - } - validateFunction(callback, "callback"); - - // We're currently not actually implementing the fill itself asynchronously, - // so we defer to randomFillSync here, but we invoke the callback asynchronously. - new Promise((res) => { - randomFillSync(buffer, offset, size); - res(); - }).then( - () => callback!(null, buffer), - (err: any) => callback!(err) - ); +export type RandomFillCallback = (err: any|null, buf?: ArrayBufferView|ArrayBuffer) => void; +export function randomFill(buffer: ArrayBufferView|ArrayBuffer, + callback?: RandomFillCallback) : void; +export function randomFill(buffer: ArrayBufferView|ArrayBuffer, + offset: number, + callback?: RandomFillCallback) : void; + export function randomFill(buffer: ArrayBufferView|ArrayBuffer, + offset: number, + size: number, + callback?: RandomFillCallback) : void; +export function randomFill(buffer: ArrayBufferView|ArrayBuffer, + offsetOrCallback?: number|RandomFillCallback, + sizeOrCallback?: number|RandomFillCallback, + callback?: RandomFillCallback) { + if (!isAnyArrayBuffer(buffer) && !isArrayBufferView(buffer)) { + throw new ERR_INVALID_ARG_TYPE('buffer', [ + 'TypedArray', + 'DataView', + 'ArrayBuffer', + 'SharedArrayBuffer' + ],buffer); + } + + let offset = 0; + let size = 0; + const maxLength = (buffer as Uint8Array).length; + if (typeof callback === 'function') { + validateInteger(offsetOrCallback, 'offset', 0, maxLength); + offset = offsetOrCallback as number; + + validateInteger(sizeOrCallback, 'size', 0, maxLength - offset); + size = sizeOrCallback as number; + } else if (typeof sizeOrCallback === 'function') { + validateInteger(offsetOrCallback, 'offset', 0, maxLength); + offset = offsetOrCallback as number; + size = maxLength - offset; + callback = sizeOrCallback as RandomFillCallback; + } else if (typeof offsetOrCallback === 'function') { + offset = 0; + size = maxLength; + callback = offsetOrCallback as RandomFillCallback; + } + validateFunction(callback, 'callback'); + + // We're currently not actually implementing the fill itself asynchronously, + // so we defer to randomFillSync here, but we invoke the callback asynchronously. + new Promise((res) => { + randomFillSync(buffer, offset, size); + res(); + }).then(() => callback!(null, buffer), (err: any) => callback!(err)); } -const RAND_MAX = 0xffff_ffff_ffff; +const RAND_MAX = 0xFFFF_FFFF_FFFF; // Cache random data to use in randomInt. The cache size must be evenly // divisible by 6 because each attempt to obtain a random int uses 6 bytes. const randomCache = Buffer.alloc(6 * 1024); @@ -128,266 +129,282 @@ let randomCacheOffset = 0; let initialized = false; function getRandomInt(min: number, max: number) { - if (!initialized) { - randomFillSync(randomCache); - initialized = true; - } - // First we generate a random int between [0..range) - const range = max - min; - - if (!(range <= RAND_MAX)) { - throw new ERR_OUT_OF_RANGE(`max${max ? "" : " - min"}`, `<= ${RAND_MAX}`, range); + if (!initialized) { + randomFillSync(randomCache); + initialized = true; + } + // First we generate a random int between [0..range) + const range = max - min; + + if (!(range <= RAND_MAX)) { + throw new ERR_OUT_OF_RANGE(`max${max ? '' : ' - min'}`, `<= ${RAND_MAX}`, range); + } + + // For (x % range) to produce an unbiased value greater than or equal to 0 and + // less than range, x must be drawn randomly from the set of integers greater + // than or equal to 0 and less than randLimit. + const randLimit = RAND_MAX - (RAND_MAX % range); + + // If we don't have a callback, or if there is still data in the cache, we can + // do this synchronously, which is super fast. + while (randomCacheOffset <= randomCache.length) { + if (randomCacheOffset === randomCache.length) { + // This might block the thread for a bit, but we are in sync mode. + randomFillSync(randomCache); + randomCacheOffset = 0; } - // For (x % range) to produce an unbiased value greater than or equal to 0 and - // less than range, x must be drawn randomly from the set of integers greater - // than or equal to 0 and less than randLimit. - const randLimit = RAND_MAX - (RAND_MAX % range); - - // If we don't have a callback, or if there is still data in the cache, we can - // do this synchronously, which is super fast. - while (randomCacheOffset <= randomCache.length) { - if (randomCacheOffset === randomCache.length) { - // This might block the thread for a bit, but we are in sync mode. - randomFillSync(randomCache); - randomCacheOffset = 0; - } - - const x = randomCache.readUIntBE(randomCacheOffset, 6); - randomCacheOffset += 6; - if (x < randLimit) { - const n = (x % range) + min; - return n; - } + const x = randomCache.readUIntBE(randomCacheOffset, 6); + randomCacheOffset += 6; + if (x < randLimit) { + const n = (x % range) + min; + return n; } - return 0; // Should be unreachable. + } + return 0; // Should be unreachable. } -export type RandomIntCallback = (err: any | null, n?: number) => void; -export function randomInt(max: number): number; -export function randomInt(min: number, max: number): number; -export function randomInt(max: number, callback: RandomIntCallback): void; -export function randomInt(min: number, max: number, callback: RandomIntCallback): void; -export function randomInt( - minOrMax: number, - maxOrCallback?: number | RandomIntCallback, - callback?: RandomIntCallback -) { - let min = 0; - let max = 0; - if (typeof callback === "function") { - validateInteger(minOrMax, "min"); - validateInteger(maxOrCallback, "max"); - min = minOrMax as number; - max = maxOrCallback as number; - } else if (typeof maxOrCallback === "function") { - min = 0; - validateInteger(minOrMax, "max"); - max = minOrMax as number; - callback = maxOrCallback as RandomIntCallback; - } else if (arguments.length === 2) { - validateInteger(minOrMax, "min"); - validateInteger(maxOrCallback, "max"); - min = minOrMax as number; - max = maxOrCallback as number; - } else { - min = 0; - validateInteger(minOrMax, "max"); - max = minOrMax; - } - - if (min > max) { - throw new ERR_OUT_OF_RANGE("min", "min <= max", min); - } - - if (callback !== undefined) { - new Promise((res) => { - res(getRandomInt(min, max)); - }).then( - (n: number) => callback!(null, n), - (err: any) => callback!(err) - ); - return; - } else { - return getRandomInt(min, max); - } +export type RandomIntCallback = (err: any|null, n?: number) => void; +export function randomInt(max: number) : number; +export function randomInt(min: number, max: number) : number; +export function randomInt(max: number, callback: RandomIntCallback) : void; +export function randomInt(min: number, max: number, callback: RandomIntCallback) : void; +export function randomInt(minOrMax: number, + maxOrCallback?: number|RandomIntCallback, + callback?: RandomIntCallback) { + let min = 0; + let max = 0; + if (typeof callback === 'function') { + validateInteger(minOrMax, 'min'); + validateInteger(maxOrCallback, 'max'); + min = minOrMax as number; + max = maxOrCallback as number; + } else if (typeof maxOrCallback === 'function') { + min = 0; + validateInteger(minOrMax, 'max'); + max = minOrMax as number; + callback = maxOrCallback as RandomIntCallback; + } else if (arguments.length === 2) { + validateInteger(minOrMax, 'min'); + validateInteger(maxOrCallback, 'max'); + min = minOrMax as number; + max = maxOrCallback as number; + } else { + min = 0; + validateInteger(minOrMax, 'max'); + max = minOrMax; + } + + if (min > max) { + throw new ERR_OUT_OF_RANGE('min', 'min <= max', min); + } + + if (callback !== undefined) { + new Promise((res) => { + res(getRandomInt(min, max)); + }).then((n: number) => callback!(null, n), (err: any) => callback!(err)); + return; + } else { + return getRandomInt(min, max); + } } export function randomUUID(options?: any) { - // While we do not actually use the entropy cache, we go ahead and validate - // the input parameters as Node.js does. - if (options !== undefined) { - validateObject(options, "options", options); - if (options.disableEntropyCache !== undefined) { - validateBoolean(options.disableEntropyCache, "options.disableEntropyCache"); - } + // While we do not actually use the entropy cache, we go ahead and validate + // the input parameters as Node.js does. + if (options !== undefined) { + validateObject(options, 'options', options); + if (options.disableEntropyCache !== undefined) { + validateBoolean(options.disableEntropyCache, 'options.disableEntropyCache'); } - return crypto.randomUUID(); + } + return crypto.randomUUID(); } export type PrimeNum = ArrayBuffer | ArrayBufferView | Buffer | bigint; export interface GeneratePrimeOptions { - add?: PrimeNum; - rem?: PrimeNum; - safe?: boolean; - bigint?: boolean; + add?: PrimeNum; + rem?: PrimeNum; + safe?: boolean; + bigint?: boolean; } export interface CheckPrimeOptions { - checks?: number; + checks?: number; } -export type GeneratePrimeCallback = (err?: any, prime?: bigint | ArrayBuffer) => void; +export type GeneratePrimeCallback = (err?: any, prime?: bigint|ArrayBuffer) => void; export type CheckPrimeCallback = (err?: any, prime?: boolean) => void; -function processGeneratePrimeOptions(options: GeneratePrimeOptions): { - add: ArrayBufferView; - rem: ArrayBufferView; - safe: boolean; - bigint: boolean; -} { - validateObject(options, "options", {}); - const { safe = false, bigint = false } = options; - let { add, rem } = options; - validateBoolean(safe, "options.safe"); - validateBoolean(bigint, "options.bigint"); - - if (add !== undefined) { - if (typeof add === "bigint") { - add = unsignedBigIntToBuffer(add, "options.add"); - } else if (!isAnyArrayBuffer(add) && !isArrayBufferView(add)) { - throw new ERR_INVALID_ARG_TYPE( - "options.add", - ["ArrayBuffer", "TypedArray", "Buffer", "DataView", "bigint"], - add - ); - } +function processGeneratePrimeOptions(options: GeneratePrimeOptions) : { + add: ArrayBufferView, + rem: ArrayBufferView, + safe: boolean, + bigint: boolean } { + validateObject(options, 'options', {}); + const { + safe = false, + bigint = false, + } = options; + let { + add, + rem, + } = options; + validateBoolean(safe, 'options.safe'); + validateBoolean(bigint, 'options.bigint'); + + if (add !== undefined) { + if (typeof add === 'bigint') { + add = unsignedBigIntToBuffer(add, 'options.add'); + } else if (!isAnyArrayBuffer(add) && !isArrayBufferView(add)) { + throw new ERR_INVALID_ARG_TYPE( + 'options.add', + [ + 'ArrayBuffer', + 'TypedArray', + 'Buffer', + 'DataView', + 'bigint', + ], + add); } - - if (rem !== undefined) { - if (typeof rem === "bigint") { - rem = unsignedBigIntToBuffer(rem, "options.rem"); - } else if (!isAnyArrayBuffer(rem) && !isArrayBufferView(rem)) { - throw new ERR_INVALID_ARG_TYPE( - "options.rem", - ["ArrayBuffer", "TypedArray", "Buffer", "DataView", "bigint"], - rem - ); - } + } + + if (rem !== undefined) { + if (typeof rem === 'bigint') { + rem = unsignedBigIntToBuffer(rem, 'options.rem'); + } else if (!isAnyArrayBuffer(rem) && !isArrayBufferView(rem)) { + throw new ERR_INVALID_ARG_TYPE( + 'options.rem', + [ + 'ArrayBuffer', + 'TypedArray', + 'Buffer', + 'DataView', + 'bigint', + ], + rem); } - - return { - safe, - bigint, - add: add as ArrayBufferView, - rem: rem as ArrayBufferView, - }; + } + + return { + safe, + bigint, + add: add as ArrayBufferView, + rem: rem as ArrayBufferView, + } } export function generatePrimeSync(size: number, options: GeneratePrimeOptions = {}) { - validateInt32(size, "size", 1); - const { safe, bigint, add, rem } = processGeneratePrimeOptions(options); - - let primeBuf = cryptoImpl.randomPrime(size, safe, add, rem); - return bigint ? arrayBufferToUnsignedBigInt(primeBuf) : primeBuf; + validateInt32(size, 'size', 1); + const { + safe, + bigint, + add, + rem, + } = processGeneratePrimeOptions(options); + + let primeBuf = cryptoImpl.randomPrime(size, safe, add, rem); + return bigint ? arrayBufferToUnsignedBigInt(primeBuf) : primeBuf; } -export function generatePrime( - size: number, - options: GeneratePrimeOptions, - callback: GeneratePrimeCallback -): void; -export function generatePrime(size: number, callback: GeneratePrimeCallback): void; -export function generatePrime( - size: number, - options: GeneratePrimeOptions | GeneratePrimeCallback, - callback?: GeneratePrimeCallback -): void { - validateInt32(size, "size", 1); - if (typeof options === "function") { - callback = options; - options = {}; +export function generatePrime(size: number, + options: GeneratePrimeOptions, + callback: GeneratePrimeCallback) : void; +export function generatePrime(size: number, callback: GeneratePrimeCallback) : void; +export function generatePrime(size: number, + options: GeneratePrimeOptions|GeneratePrimeCallback, + callback?: GeneratePrimeCallback) : void { + validateInt32(size, 'size', 1); + if (typeof options === 'function') { + callback = options; + options = {}; + } + validateFunction(callback, 'callback'); + + const { + safe, + bigint, + add, + rem + } = processGeneratePrimeOptions(options as GeneratePrimeOptions); + + new Promise((res, rej) => { + try { + const primeBuf = cryptoImpl.randomPrime(size, safe, add, rem); + res(bigint ? arrayBufferToUnsignedBigInt(primeBuf) : primeBuf); + } catch(err) { + rej(err); } - validateFunction(callback, "callback"); - - const { safe, bigint, add, rem } = processGeneratePrimeOptions(options as GeneratePrimeOptions); - - new Promise((res, rej) => { - try { - const primeBuf = cryptoImpl.randomPrime(size, safe, add, rem); - res(bigint ? arrayBufferToUnsignedBigInt(primeBuf) : primeBuf); - } catch (err) { - rej(err); - } - }).then( - (val) => callback!(null, val), - (err) => callback!(err) - ); + }).then((val) => callback!(null, val), (err) => callback!(err)); } function unsignedBigIntToBuffer(bigint: bigint, name: string) { - if (bigint < 0) { - throw new ERR_OUT_OF_RANGE(name, ">= 0", bigint); - } + if (bigint < 0) { + throw new ERR_OUT_OF_RANGE(name, '>= 0', bigint); + } - const hex = bigint.toString(16); - const padded = hex.padStart(hex.length + (hex.length % 2), "0"); - return Buffer.from(padded, "hex"); + const hex = bigint.toString(16); + const padded = hex.padStart(hex.length + (hex.length % 2), '0'); + return Buffer.from(padded, 'hex'); } -function validateCandidate(candidate: PrimeNum): Buffer { - if (typeof candidate === "bigint") candidate = unsignedBigIntToBuffer(candidate, "candidate"); - if (!isAnyArrayBuffer(candidate) && !isArrayBufferView(candidate)) { - throw new ERR_INVALID_ARG_TYPE( - "candidate", - ["ArrayBuffer", "TypedArray", "Buffer", "DataView", "bigint"], - candidate - ); - } - return candidate as Buffer; +function validateCandidate(candidate: PrimeNum) : Buffer { + if (typeof candidate === 'bigint') + candidate = unsignedBigIntToBuffer(candidate, 'candidate'); + if (!isAnyArrayBuffer(candidate) && !isArrayBufferView(candidate)) { + throw new ERR_INVALID_ARG_TYPE( + 'candidate', + [ + 'ArrayBuffer', + 'TypedArray', + 'Buffer', + 'DataView', + 'bigint', + ], + candidate, + ); + } + return candidate as Buffer; } -function validateChecks(options: CheckPrimeOptions): number { - const { checks = 0 } = options; - // The checks option is unsigned but must fit into a signed 32-bit integer for OpenSSL. - validateInt32(checks, "options.checks", 0); - return checks; +function validateChecks(options : CheckPrimeOptions) : number { + const { + checks = 0, + } = options; + // The checks option is unsigned but must fit into a signed 32-bit integer for OpenSSL. + validateInt32(checks, 'options.checks', 0); + return checks; } export function checkPrimeSync(candidate: PrimeNum, options: CheckPrimeOptions = {}) { - candidate = validateCandidate(candidate); - validateObject(options, "options", {}); - const checks = validateChecks(options); - return cryptoImpl.checkPrimeSync(candidate as ArrayBufferView, checks); + candidate = validateCandidate(candidate); + validateObject(options, 'options', {}); + const checks = validateChecks(options); + return cryptoImpl.checkPrimeSync(candidate as ArrayBufferView, checks); } -export function checkPrime( - candidate: PrimeNum, - options: CheckPrimeOptions, - callback: CheckPrimeCallback -): void; -export function checkPrime(candidate: PrimeNum, callback: CheckPrimeCallback): void; -export function checkPrime( - candidate: PrimeNum, - options: CheckPrimeOptions | CheckPrimeCallback, - callback?: CheckPrimeCallback -): void { - candidate = validateCandidate(candidate); - if (typeof options === "function") { - callback = options; - options = {}; +export function checkPrime(candidate: PrimeNum, + options: CheckPrimeOptions, + callback: CheckPrimeCallback) : void; +export function checkPrime(candidate: PrimeNum, + callback: CheckPrimeCallback) : void; +export function checkPrime(candidate: PrimeNum, + options: CheckPrimeOptions|CheckPrimeCallback, + callback?: CheckPrimeCallback) : void { + candidate = validateCandidate(candidate); + if (typeof options === 'function') { + callback = options; + options = {}; + } + validateObject(options, 'options', {}); + validateFunction(callback, 'callback'); + const checks = validateChecks(options); + new Promise((res, rej) => { + try { + res(cryptoImpl.checkPrimeSync(candidate as ArrayBufferView, checks)); + } catch(err) { + rej(err); } - validateObject(options, "options", {}); - validateFunction(callback, "callback"); - const checks = validateChecks(options); - new Promise((res, rej) => { - try { - res(cryptoImpl.checkPrimeSync(candidate as ArrayBufferView, checks)); - } catch (err) { - rej(err); - } - }).then( - (val) => callback!(null, val), - (err) => callback!(err) - ); + }).then((val) => callback!(null, val), (err) => callback!(err)); } diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_util.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_util.ts index 9b268df0b..5f52cdedc 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_util.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/crypto_util.ts @@ -1,48 +1,61 @@ /* eslint-disable */ -"use strict"; +'use strict'; -import { Buffer } from "./internal_buffer"; +import { + Buffer, +} from './internal_buffer'; -import { isAnyArrayBuffer, isArrayBufferView } from "./internal_types"; +import { + isAnyArrayBuffer, + isArrayBufferView, +} from './internal_types'; -import { ERR_INVALID_ARG_TYPE } from "./internal_errors"; +import { + ERR_INVALID_ARG_TYPE, +} from './internal_errors'; -import { validateString } from "./validators"; +import { + validateString, +} from './validators'; -import * as cryptoImpl from "./crypto"; +import * as cryptoImpl from './crypto'; type ArrayLike = cryptoImpl.ArrayLike; -export const kHandle = Symbol("kHandle"); -export const kFinalized = Symbol("kFinalized"); -export const kState = Symbol("kFinalized"); +export const kHandle = Symbol('kHandle'); +export const kFinalized = Symbol('kFinalized'); +export const kState = Symbol('kFinalized'); export function getStringOption(options: any, key: string) { - let value; - if (options && (value = options[key]) != null) validateString(value, `options.${key}`); - return value; + let value; + if (options && (value = options[key]) != null) + validateString(value, `options.${key}`); + return value; } -export function getArrayBufferOrView( - buffer: Buffer | ArrayBuffer | ArrayBufferView | string, - name: string, - encoding?: string -): Buffer | ArrayBuffer | ArrayBufferView { - if (isAnyArrayBuffer(buffer)) return buffer as ArrayBuffer; - if (typeof buffer === "string") { - if (encoding === undefined || encoding === "buffer") { - encoding = "utf8"; - } - return Buffer.from(buffer, encoding); +export function getArrayBufferOrView(buffer: Buffer | ArrayBuffer | ArrayBufferView | string, name: string, encoding?: string): Buffer | ArrayBuffer | ArrayBufferView { + if (isAnyArrayBuffer(buffer)) + return buffer as ArrayBuffer; + if (typeof buffer === 'string') { + if (encoding === undefined || encoding === 'buffer') { + encoding = 'utf8'; } - if (!isArrayBufferView(buffer)) { - throw new ERR_INVALID_ARG_TYPE( - name, - ["string", "ArrayBuffer", "Buffer", "TypedArray", "DataView"], - buffer - ); - } - return buffer; + return Buffer.from(buffer, encoding); + } + if (!isArrayBufferView(buffer)) { + throw new ERR_INVALID_ARG_TYPE( + name, + [ + 'string', + 'ArrayBuffer', + 'Buffer', + 'TypedArray', + 'DataView', + ], + buffer, + ); + } + return buffer; } /** @@ -58,45 +71,48 @@ export const numberToHexCharCode = (number: number): number => (number < 10 ? 48 * @return {bigint} */ export function arrayBufferToUnsignedBigInt(buf: ArrayBuffer): bigint { - const length = buf.byteLength; - const chars = Array(length * 2); - const view = new DataView(buf); - - for (let i = 0; i < length; i++) { - const val = view.getUint8(i); - chars[2 * i] = numberToHexCharCode(val >> 4); - chars[2 * i + 1] = numberToHexCharCode(val & 0xf); - } + const length = buf.byteLength; + const chars = Array(length * 2); + const view = new DataView(buf); + + for (let i = 0; i < length; i++) { + const val = view.getUint8(i); + chars[2 * i] = numberToHexCharCode(val >> 4); + chars[2 * i + 1] = numberToHexCharCode(val & 0xf); + } - return BigInt(`0x${String.fromCharCode.apply(null, chars)}`); + return BigInt(`0x${String.fromCharCode.apply(null, chars)}`); } // This is here because many functions accepted binary strings without // any explicit encoding in older versions of node, and we don't want // to break them unnecessarily. -export function toBuf(val: ArrayLike, encoding?: string): Buffer | ArrayBuffer | ArrayBufferView { - if (typeof val === "string") { - if (encoding === "buffer") { - encoding = "utf8"; - } - return Buffer.from(val, encoding); +export function toBuf(val: ArrayLike, encoding?: string): Buffer|ArrayBuffer|ArrayBufferView { + if (typeof val === 'string') { + if (encoding === 'buffer') { + encoding = 'utf8'; } - return val; + return Buffer.from(val, encoding); + } + return val; } -export function validateByteSource( - val: ArrayLike, - name: string -): Buffer | ArrayBuffer | ArrayBufferView { - val = toBuf(val); +export function validateByteSource(val: ArrayLike, + name: string): Buffer|ArrayBuffer|ArrayBufferView { + val = toBuf(val); - if (isAnyArrayBuffer(val) || isArrayBufferView(val)) { - return val; - } - - throw new ERR_INVALID_ARG_TYPE( - name, - ["string", "ArrayBuffer", "TypedArray", "DataView", "Buffer"], - val - ); + if (isAnyArrayBuffer(val) || isArrayBufferView(val)) { + return val; + } + + throw new ERR_INVALID_ARG_TYPE( + name, + [ + 'string', + 'ArrayBuffer', + 'TypedArray', + 'DataView', + 'Buffer', + ], + val); } diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/events.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/events.ts index 83f86114d..f7b92a65d 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/events.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/events.ts @@ -1,12 +1,17 @@ import { - AbortError, - ERR_INVALID_ARG_TYPE, - ERR_INVALID_THIS, - ERR_OUT_OF_RANGE, - ERR_UNHANDLED_ERROR, + AbortError, + ERR_INVALID_ARG_TYPE, + ERR_INVALID_THIS, + ERR_OUT_OF_RANGE, + ERR_UNHANDLED_ERROR, } from "./internal_errors"; -import { validateAbortSignal, validateBoolean, validateFunction } from "./validators"; +import { + validateAbortSignal, + validateBoolean, + validateFunction, +} from "./validators"; + import * as process from "./process"; @@ -23,76 +28,78 @@ const kErrorMonitor = Symbol("events.errorMonitor"); const kMaxEventTargetListeners = Symbol("events.maxEventTargetListeners"); const kMaxEventTargetListenersWarned = Symbol("events.maxEventTargetListenersWarned"); + export interface EventEmitterOptions { - captureRejections?: boolean; -} + captureRejections? : boolean; +}; -export type EventName = string | symbol; +export type EventName = string|symbol; export type EventCallback = (...args: any[]) => unknown; export interface EventEmitter { - addListener(eventName: EventName, listener: EventCallback): EventEmitter; - emit(eventName: EventName, ...args: unknown[]): void; - eventNames(): EventName[]; - getMaxListeners(): number; - listenerCount(eventName: EventName): number; - listeners(eventName: EventName): EventCallback[]; - off(eventName: EventName, listener: EventCallback): EventEmitter; - on(eventName: EventName, listener: EventCallback): EventEmitter; - once(eventName: EventName, listener: EventCallback): EventEmitter; - prependListener(eventName: EventName, listener: EventCallback): EventEmitter; - prependOnceListener(eventName: EventName, listener: EventCallback): EventEmitter; - removeAllListeners(eventName?: EventName): EventEmitter; - removeListener(eventName: EventName, listener: EventCallback): EventEmitter; - setMaxListeners(n: number): EventEmitter; - rawListeners(eventName: EventName): EventCallback[]; - [kRejection](err: unknown, eventName: EventName, ...args: unknown[]): void; -} + addListener(eventName: EventName, listener: EventCallback): EventEmitter; + emit(eventName: EventName, ...args: unknown[]): void; + eventNames() : EventName[]; + getMaxListeners(): number; + listenerCount(eventName: EventName): number; + listeners(eventName: EventName): EventCallback[]; + off(eventName: EventName, listener: EventCallback): EventEmitter; + on(eventName: EventName, listener: EventCallback): EventEmitter; + once(eventName: EventName, listener: EventCallback): EventEmitter; + prependListener(eventName: EventName, listener: EventCallback): EventEmitter; + prependOnceListener(eventName: EventName, listener: EventCallback): EventEmitter; + removeAllListeners(eventName?: EventName): EventEmitter; + removeListener(eventName: EventName, listener: EventCallback): EventEmitter; + setMaxListeners(n: number): EventEmitter; + rawListeners(eventName: EventName): EventCallback[]; + [kRejection](err: unknown, eventName: EventName, ...args: unknown[]) : void; +}; type AsyncResource = typeof AsyncResource; -declare var EventTarget: Function; +declare var EventTarget : Function; -export function EventEmitter(this: EventEmitter, opts?: EventEmitterOptions) { - EventEmitter.init.call(this, opts); +export function EventEmitter(this : EventEmitter, opts? : EventEmitterOptions) { + EventEmitter.init.call(this, opts); } class EventEmitterReferencingAsyncResource extends AsyncResource { - #eventEmitter: EventEmitter; - constructor(emitter: EventEmitter) { - super(""); - this.#eventEmitter = emitter; - } - - get eventEmitter() { - if (this.#eventEmitter === undefined) - throw new ERR_INVALID_THIS("EventEmitterReferencingAsyncResource"); - return this.#eventEmitter; - } + #eventEmitter : EventEmitter; + constructor(emitter : EventEmitter) { + super(''); + this.#eventEmitter = emitter; + } + + get eventEmitter() { + if (this.#eventEmitter === undefined) + throw new ERR_INVALID_THIS('EventEmitterReferencingAsyncResource'); + return this.#eventEmitter; + } } // @ts-ignore -- TODO(soon) Properly handle the extends EventEmitter here export class EventEmitterAsyncResource extends EventEmitter { - #asyncResource: EventEmitterReferencingAsyncResource; - - constructor(options?: EventEmitterOptions) { - super(options); - // @ts-ignore - this.#asyncResource = new EventEmitterReferencingAsyncResource(this); - } - - get asyncResource(): AsyncResource { - if (this.#asyncResource === undefined) - throw new ERR_INVALID_THIS("EventEmitterAsyncResource"); - // @ts-ignore - return this.#asyncResource; - } - - emit(event: string | symbol, ...args: any[]): void { - if (this.#asyncResource === undefined) - throw new ERR_INVALID_THIS("EventEmitterAsyncResource"); - args.unshift(super.emit, this, event); - Reflect.apply(this.#asyncResource.runInAsyncScope, this.#asyncResource, args); - } + #asyncResource : EventEmitterReferencingAsyncResource; + + constructor(options? : EventEmitterOptions) { + super(options); + // @ts-ignore + this.#asyncResource = new EventEmitterReferencingAsyncResource(this); + } + + get asyncResource() : AsyncResource { + if (this.#asyncResource === undefined) + throw new ERR_INVALID_THIS('EventEmitterAsyncResource'); + // @ts-ignore + return this.#asyncResource; + } + + emit(event : string | symbol, ...args : any[]) : void { + if (this.#asyncResource === undefined) + throw new ERR_INVALID_THIS('EventEmitterAsyncResource'); + args.unshift(super.emit, this, event); + Reflect.apply(this.#asyncResource.runInAsyncScope, + this.#asyncResource, args); + } } export default EventEmitter; @@ -112,777 +119,786 @@ export const errorMonitor = EventEmitter.errorMonitor; export let defaultMaxListeners = 10; Object.defineProperties(EventEmitter, { - captureRejections: { - get() { - return EventEmitter.prototype[kCapture]; - }, - set(value) { - validateBoolean(value, "EventEmitter.captureRejections"); - - EventEmitter.prototype[kCapture] = value; - }, - enumerable: true, + captureRejections: { + get() { + return EventEmitter.prototype[kCapture]; }, - defaultMaxListeners: { - enumerable: true, - get: function () { - return defaultMaxListeners; - }, - set: function (arg) { - if (typeof arg !== "number" || arg < 0 || Number.isNaN(arg)) { - throw new ERR_OUT_OF_RANGE("defaultMaxListeners", "a non-negative number", arg); - } - defaultMaxListeners = arg; - }, + set(value) { + validateBoolean(value, "EventEmitter.captureRejections"); + + EventEmitter.prototype[kCapture] = value; }, - kMaxEventTargetListeners: { - value: kMaxEventTargetListeners, - enumerable: false, - configurable: false, - writable: false, + enumerable: true, + }, + defaultMaxListeners: { + enumerable: true, + get: function () { + return defaultMaxListeners; }, - kMaxEventTargetListenersWarned: { - value: kMaxEventTargetListenersWarned, - enumerable: false, - configurable: false, - writable: false, + set: function (arg) { + if (typeof arg !== "number" || arg < 0 || Number.isNaN(arg)) { + throw new ERR_OUT_OF_RANGE( + "defaultMaxListeners", + "a non-negative number", + arg, + ); + } + defaultMaxListeners = arg; }, + }, + kMaxEventTargetListeners: { + value: kMaxEventTargetListeners, + enumerable: false, + configurable: false, + writable: false, + }, + kMaxEventTargetListenersWarned: { + value: kMaxEventTargetListenersWarned, + enumerable: false, + configurable: false, + writable: false, + }, }); // The default for captureRejections is false Object.defineProperty(EventEmitter.prototype, kCapture, { - value: false, - writable: true, - enumerable: false, + value: false, + writable: true, + enumerable: false, }); -EventEmitter.init = function (this: any, opts?: EventEmitterOptions) { - if (this._events === undefined || this._events === Object.getPrototypeOf(this)._events) { - this._events = Object.create(null); - this._eventsCount = 0; - } - - (this as any)._maxListeners ??= undefined; - - if (opts?.captureRejections) { - validateBoolean(opts.captureRejections, "options.captureRejections"); - (this as any)[kCapture] = Boolean(opts.captureRejections); - } else { - // Assigning the kCapture property directly saves an expensive - // prototype lookup in a very sensitive hot path. - (this as any)[kCapture] = EventEmitter.prototype[kCapture]; - } +EventEmitter.init = function (this: any, opts? : EventEmitterOptions) { + if (this._events === undefined || this._events === Object.getPrototypeOf(this)._events) { + this._events = Object.create(null); + this._eventsCount = 0; + } + + (this as any)._maxListeners ??= undefined; + + if (opts?.captureRejections) { + validateBoolean(opts.captureRejections, "options.captureRejections"); + (this as any)[kCapture] = Boolean(opts.captureRejections); + } else { + // Assigning the kCapture property directly saves an expensive + // prototype lookup in a very sensitive hot path. + (this as any)[kCapture] = EventEmitter.prototype[kCapture]; + } }; -export function setMaxListeners(n = defaultMaxListeners, ...eventTargets: any[]) { - if (typeof n !== "number" || n < 0 || Number.isNaN(n)) { - throw new ERR_OUT_OF_RANGE("n", "a non-negative number", n); - } - if (eventTargets.length === 0) { - defaultMaxListeners = n; - } else { - for (let i = 0; i < eventTargets.length; i++) { - const target = eventTargets[i]; - if (target instanceof EventTarget) { - (target as any)[kMaxEventTargetListeners] = n; - (target as any)[kMaxEventTargetListenersWarned] = false; - } else if (typeof target.setMaxListeners === "function") { - target.setMaxListeners(n); - } else { - throw new ERR_INVALID_ARG_TYPE( - "eventTargets", - ["EventEmitter", "EventTarget"], - target - ); - } - } +export function setMaxListeners( + n = defaultMaxListeners, + ...eventTargets : any[]) { + if (typeof n !== "number" || n < 0 || Number.isNaN(n)) { + throw new ERR_OUT_OF_RANGE("n", "a non-negative number", n); + } + if (eventTargets.length === 0) { + defaultMaxListeners = n; + } else { + for (let i = 0; i < eventTargets.length; i++) { + const target = eventTargets[i]; + if (target instanceof EventTarget) { + (target as any)[kMaxEventTargetListeners] = n; + (target as any)[kMaxEventTargetListenersWarned] = false; + } else if (typeof target.setMaxListeners === "function") { + target.setMaxListeners(n); + } else { + throw new ERR_INVALID_ARG_TYPE( + "eventTargets", + ["EventEmitter", "EventTarget"], + target, + ); + } } + } } EventEmitter.prototype._events = undefined; EventEmitter.prototype._eventsCount = 0; EventEmitter.prototype._maxListeners = undefined; -function addCatch(that: any, promise: Promise, type: string | symbol, args: any[]) { - if (!that[kCapture]) { - return; - } - - // Handle Promises/A+ spec, then could be a getter - // that throws on second use. - try { - const then = promise.then; - - if (typeof then === "function") { - then.call(promise, undefined, function (err) { - // The callback is called with nextTick to avoid a follow-up - // rejection from this promise. - process.nextTick(emitUnhandledRejectionOrErr, that, err, type, args); - }); - } - } catch (err) { - that.emit("error", err); - } +function addCatch(that : any, promise : Promise, type : string | symbol, args : any[]) { + if (!that[kCapture]) { + return; + } + + // Handle Promises/A+ spec, then could be a getter + // that throws on second use. + try { + const then = promise.then; + + if (typeof then === "function") { + then.call(promise, undefined, function (err) { + // The callback is called with nextTick to avoid a follow-up + // rejection from this promise. + process.nextTick(emitUnhandledRejectionOrErr, that, err, type, args); + }); + } + } catch (err) { + that.emit("error", err); + } } -function emitUnhandledRejectionOrErr(ee: any, err: any, type: string | symbol, args: any[]) { - if (typeof ee[kRejection] === "function") { - ee[kRejection](err, type, ...args); - } else { - // We have to disable the capture rejections mechanism, otherwise - // we might end up in an infinite loop. - const prev = ee[kCapture]; - - // If the error handler throws, it is not catcheable and it - // will end up in 'uncaughtException'. We restore the previous - // value of kCapture in case the uncaughtException is present - // and the exception is handled. - try { - ee[kCapture] = false; - ee.emit("error", err); - } finally { - ee[kCapture] = prev; - } +function emitUnhandledRejectionOrErr(ee : any, err : any, type: string | symbol, args : any[]) { + if (typeof ee[kRejection] === "function") { + ee[kRejection](err, type, ...args); + } else { + // We have to disable the capture rejections mechanism, otherwise + // we might end up in an infinite loop. + const prev = ee[kCapture]; + + // If the error handler throws, it is not catcheable and it + // will end up in 'uncaughtException'. We restore the previous + // value of kCapture in case the uncaughtException is present + // and the exception is handled. + try { + ee[kCapture] = false; + ee.emit("error", err); + } finally { + ee[kCapture] = prev; } + } } -EventEmitter.prototype.setMaxListeners = function setMaxListeners(n: number) { - if (typeof n !== "number" || n < 0 || Number.isNaN(n)) { - throw new ERR_OUT_OF_RANGE("n", "a non-negative number", n); - } - this._maxListeners = n; - return this; +EventEmitter.prototype.setMaxListeners = function setMaxListeners(n : number) { + if (typeof n !== "number" || n < 0 || Number.isNaN(n)) { + throw new ERR_OUT_OF_RANGE("n", "a non-negative number", n); + } + this._maxListeners = n; + return this; }; -function _getMaxListeners(that: any) { - if (that._maxListeners === undefined) { - return (EventEmitter as any).defaultMaxListeners; - } - return that._maxListeners; +function _getMaxListeners(that : any) { + if (that._maxListeners === undefined) { + return (EventEmitter as any).defaultMaxListeners; + } + return that._maxListeners; } EventEmitter.prototype.getMaxListeners = function getMaxListeners() { - return _getMaxListeners(this); + return _getMaxListeners(this); }; -EventEmitter.prototype.emit = function emit(type: string | symbol, ...args: any[]) { - let doError = type === "error"; - - const events = this._events; - if (events !== undefined) { - if (doError && events[kErrorMonitor] !== undefined) { - this.emit(kErrorMonitor, ...args); - } - doError = doError && events.error === undefined; - } else if (!doError) { - return false; - } +EventEmitter.prototype.emit = function emit(type : string | symbol, ...args: any[]) { + let doError = type === "error"; - // If there is no 'error' event listener then throw. - if (doError) { - let er; - if (args.length > 0) { - er = args[0]; - } - if (er instanceof Error) { - try { - const capture = {}; - (Error as any).captureStackTrace(capture, EventEmitter.prototype.emit); - } catch { - // pass - } - - // Note: The comments on the `throw` lines are intentional, they show - // up in Node's output if this results in an unhandled exception. - throw er; // Unhandled 'error' event - } - - let stringifiedEr; - try { - stringifiedEr = inspect(er); - } catch { - stringifiedEr = er; - } - - // At least give some kind of context to the user - const err = new ERR_UNHANDLED_ERROR(stringifiedEr); - (err as any).context = er; - throw err; // Unhandled 'error' event + const events = this._events; + if (events !== undefined) { + if (doError && events[kErrorMonitor] !== undefined) { + this.emit(kErrorMonitor, ...args); } + doError = doError && events.error === undefined; + } else if (!doError) { + return false; + } - const handler = events[type]; - - if (handler === undefined) { - return false; + // If there is no 'error' event listener then throw. + if (doError) { + let er; + if (args.length > 0) { + er = args[0]; } + if (er instanceof Error) { + try { + const capture = {}; + (Error as any).captureStackTrace(capture, EventEmitter.prototype.emit); + } catch { + // pass + } - if (typeof handler === "function") { - const result = handler.apply(this, args); - - // We check if result is undefined first because that - // is the most common case so we do not pay any perf - // penalty - if (result !== undefined && result !== null) { - addCatch(this, result, type, args); - } - } else { - const len = handler.length; - const listeners = arrayClone(handler); - for (let i = 0; i < len; ++i) { - const result = listeners[i].apply(this, args); - - // We check if result is undefined first because that - // is the most common case so we do not pay any perf - // penalty. - // This code is duplicated because extracting it away - // would make it non-inlineable. - if (result !== undefined && result !== null) { - addCatch(this, result, type, args); - } - } + // Note: The comments on the `throw` lines are intentional, they show + // up in Node's output if this results in an unhandled exception. + throw er; // Unhandled 'error' event } - return true; + let stringifiedEr; + try { + stringifiedEr = inspect(er); + } catch { + stringifiedEr = er; + } + + // At least give some kind of context to the user + const err = new ERR_UNHANDLED_ERROR(stringifiedEr); + (err as any).context = er; + throw err; // Unhandled 'error' event + } + + const handler = events[type]; + + if (handler === undefined) { + return false; + } + + if (typeof handler === "function") { + const result = handler.apply(this, args); + + // We check if result is undefined first because that + // is the most common case so we do not pay any perf + // penalty + if (result !== undefined && result !== null) { + addCatch(this, result, type, args); + } + } else { + const len = handler.length; + const listeners = arrayClone(handler); + for (let i = 0; i < len; ++i) { + const result = listeners[i].apply(this, args); + + // We check if result is undefined first because that + // is the most common case so we do not pay any perf + // penalty. + // This code is duplicated because extracting it away + // would make it non-inlineable. + if (result !== undefined && result !== null) { + addCatch(this, result, type, args); + } + } + } + + return true; }; -function _addListener(target: any, type: string | symbol, listener: unknown, prepend: boolean) { - let m; - let events; - let existing; - - validateFunction(listener, "listener"); - - events = target._events; - if (events === undefined) { - events = target._events = Object.create(null); - target._eventsCount = 0; - } else { - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (events.newListener !== undefined) { - target.emit("newListener", type, (listener as any).listener ?? listener); - - // Re-assign `events` because a newListener handler could have caused the - // this._events to be assigned to a new object - events = target._events; - } - existing = events[type]; - } - - if (existing === undefined) { - // Optimize the case of one listener. Don't need the extra array object. - events[type] = listener; - ++target._eventsCount; +function _addListener(target : any, type : string | symbol, listener : unknown, prepend : boolean) { + let m; + let events; + let existing; + + validateFunction(listener, "listener"); + + events = target._events; + if (events === undefined) { + events = target._events = Object.create(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener !== undefined) { + target.emit("newListener", type, (listener as any).listener ?? listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (existing === undefined) { + // Optimize the case of one listener. Don't need the extra array object. + events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === "function") { + // Adding the second element, need to change to array. + existing = events[type] = prepend + ? [listener, existing] + : [existing, listener]; + // If we've already got an array, just append. + } else if (prepend) { + existing.unshift(listener); } else { - if (typeof existing === "function") { - // Adding the second element, need to change to array. - existing = events[type] = prepend ? [listener, existing] : [existing, listener]; - // If we've already got an array, just append. - } else if (prepend) { - existing.unshift(listener); - } else { - existing.push(listener); - } - - // Check for listener leak - m = _getMaxListeners(target); - if (m > 0 && existing.length > m && !existing.warned) { - existing.warned = true; - console.log( - "Possible EventEmitter memory leak detected. " + - `${existing.length} ${String(type)} listeners ` + - `added to an EventEmitter. Use ` + - "emitter.setMaxListeners() to increase limit" - ); - // TODO(soon): Implement process.emitWarning and inspect - // // No error code for this since it is a Warning - // // eslint-disable-next-line no-restricted-syntax - // const w = new Error( - // "Possible EventEmitter memory leak detected. " + - // `${existing.length} ${String(type)} listeners ` + - // `added to ${inspect(target, { depth: -1 })}. Use ` + - // "emitter.setMaxListeners() to increase limit", - // ); - // w.name = "MaxListenersExceededWarning"; - // w.emitter = target; - // w.type = type; - // w.count = existing.length; - // process.emitWarning(w); - } - } - - return target; + existing.push(listener); + } + + // Check for listener leak + m = _getMaxListeners(target); + if (m > 0 && existing.length > m && !existing.warned) { + existing.warned = true; + console.log( + "Possible EventEmitter memory leak detected. " + + `${existing.length} ${String(type)} listeners ` + + `added to an EventEmitter. Use ` + + "emitter.setMaxListeners() to increase limit", + ); + // TODO(soon): Implement process.emitWarning and inspect + // // No error code for this since it is a Warning + // // eslint-disable-next-line no-restricted-syntax + // const w = new Error( + // "Possible EventEmitter memory leak detected. " + + // `${existing.length} ${String(type)} listeners ` + + // `added to ${inspect(target, { depth: -1 })}. Use ` + + // "emitter.setMaxListeners() to increase limit", + // ); + // w.name = "MaxListenersExceededWarning"; + // w.emitter = target; + // w.type = type; + // w.count = existing.length; + // process.emitWarning(w); + } + } + + return target; } -EventEmitter.prototype.addListener = function addListener( - type: string | symbol, - listener: unknown -) { - return _addListener(this, type, listener, false); +EventEmitter.prototype.addListener = function addListener(type : string | symbol, listener : unknown) { + return _addListener(this, type, listener, false); }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.prependListener = function prependListener( - type: string | symbol, - listener: unknown + type : string | symbol, + listener : unknown, ) { - return _addListener(this, type, listener, true); + return _addListener(this, type, listener, true); }; function onceWrapper(this: any) { - if (!this.fired) { - this.target.removeListener(this.type, this.wrapFn); - this.fired = true; - if (arguments.length === 0) { - return this.listener.call(this.target); - } - return this.listener.apply(this.target, arguments); + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + if (arguments.length === 0) { + return this.listener.call(this.target); } + return this.listener.apply(this.target, arguments); + } } -function _onceWrap(target: any, type: string | symbol, listener: unknown) { - const state = { fired: false, wrapFn: undefined, target, type, listener }; - const wrapped = onceWrapper.bind(state); - (wrapped as any).listener = listener; - (state as any).wrapFn = wrapped; - return wrapped; +function _onceWrap(target : any, type : string | symbol, listener : unknown) { + const state = { fired: false, wrapFn: undefined, target, type, listener }; + const wrapped = onceWrapper.bind(state); + (wrapped as any).listener = listener; + (state as any).wrapFn = wrapped; + return wrapped; } -EventEmitter.prototype.once = function once(type: string | symbol, listener: unknown) { - validateFunction(listener, "listener"); +EventEmitter.prototype.once = function once(type : string | symbol, listener : unknown) { + validateFunction(listener, "listener"); - this.on(type, _onceWrap(this, type, listener)); - return this; + this.on(type, _onceWrap(this, type, listener)); + return this; }; EventEmitter.prototype.prependOnceListener = function prependOnceListener( - type: string | symbol, - listener: unknown + type : string | symbol, + listener : unknown, ) { - validateFunction(listener, "listener"); + validateFunction(listener, "listener"); - this.prependListener(type, _onceWrap(this, type, listener)); - return this; + this.prependListener(type, _onceWrap(this, type, listener)); + return this; }; EventEmitter.prototype.removeListener = function removeListener( - type: string | symbol, - listener: unknown + type : string | symbol, + listener : unknown, ) { - validateFunction(listener, "listener"); + validateFunction(listener, "listener"); - const events = this._events; - if (events === undefined) { - return this; - } + const events = this._events; + if (events === undefined) { + return this; + } + + const list = events[type]; + if (list === undefined) { + return this; + } - const list = events[type]; - if (list === undefined) { - return this; + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) { + this._events = Object.create(null); + } else { + delete events[type]; + if (events.removeListener) { + this.emit("removeListener", type, list.listener || listener); + } } + } else if (typeof list !== "function") { + let position = -1; - if (list === listener || list.listener === listener) { - if (--this._eventsCount === 0) { - this._events = Object.create(null); - } else { - delete events[type]; - if (events.removeListener) { - this.emit("removeListener", type, list.listener || listener); - } - } - } else if (typeof list !== "function") { - let position = -1; - - for (let i = list.length - 1; i >= 0; i--) { - if (list[i] === listener || list[i].listener === listener) { - position = i; - break; - } - } - - if (position < 0) { - return this; - } - - if (position === 0) { - list.shift(); - } else { - spliceOne(list, position); - } - - if (list.length === 1) { - events[type] = list[0]; - } - - if (events.removeListener !== undefined) { - this.emit("removeListener", type, listener); - } + for (let i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + position = i; + break; + } } - return this; -}; + if (position < 0) { + return this; + } -EventEmitter.prototype.off = EventEmitter.prototype.removeListener; + if (position === 0) { + list.shift(); + } else { + spliceOne(list, position); + } -EventEmitter.prototype.removeAllListeners = function removeAllListeners(type: string | symbol) { - const events = this._events; - if (events === undefined) { - return this; + if (list.length === 1) { + events[type] = list[0]; } - // Not listening for removeListener, no need to emit - if (events.removeListener === undefined) { - if (arguments.length === 0) { - this._events = Object.create(null); - this._eventsCount = 0; - } else if (events[type] !== undefined) { - if (--this._eventsCount === 0) { - this._events = Object.create(null); - } else { - delete events[type]; - } - } - return this; + if (events.removeListener !== undefined) { + this.emit("removeListener", type, listener); } + } - // Emit removeListener for all listeners on all events + return this; +}; + +EventEmitter.prototype.off = EventEmitter.prototype.removeListener; + +EventEmitter.prototype.removeAllListeners = function removeAllListeners(type : string | symbol) { + const events = this._events; + if (events === undefined) { + return this; + } + + // Not listening for removeListener, no need to emit + if (events.removeListener === undefined) { if (arguments.length === 0) { - for (const key of Reflect.ownKeys(events)) { - if (key === "removeListener") continue; - this.removeAllListeners(key); - } - this.removeAllListeners("removeListener"); + this._events = Object.create(null); + this._eventsCount = 0; + } else if (events[type] !== undefined) { + if (--this._eventsCount === 0) { this._events = Object.create(null); - this._eventsCount = 0; - return this; + } else { + delete events[type]; + } + } + return this; + } + + // Emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (const key of Reflect.ownKeys(events)) { + if (key === "removeListener") continue; + this.removeAllListeners(key); } + this.removeAllListeners("removeListener"); + this._events = Object.create(null); + this._eventsCount = 0; + return this; + } - const listeners = events[type]; + const listeners = events[type]; - if (typeof listeners === "function") { - this.removeListener(type, listeners); - } else if (listeners !== undefined) { - // LIFO order - for (let i = listeners.length - 1; i >= 0; i--) { - this.removeListener(type, listeners[i]); - } + if (typeof listeners === "function") { + this.removeListener(type, listeners); + } else if (listeners !== undefined) { + // LIFO order + for (let i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); } + } - return this; + return this; }; -function _listeners(target: any, type: string | symbol, unwrap: boolean) { - const events = target._events; +function _listeners(target : any, type : string | symbol, unwrap : boolean) { + const events = target._events; - if (events === undefined) { - return []; - } + if (events === undefined) { + return []; + } - const evlistener = events[type]; - if (evlistener === undefined) { - return []; - } + const evlistener = events[type]; + if (evlistener === undefined) { + return []; + } - if (typeof evlistener === "function") { - return unwrap ? [evlistener.listener || evlistener] : [evlistener]; - } + if (typeof evlistener === "function") { + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + } - return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener); + return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener); } -EventEmitter.prototype.listeners = function listeners(type: string | symbol) { - return _listeners(this, type, true); +EventEmitter.prototype.listeners = function listeners(type : string | symbol) { + return _listeners(this, type, true); }; -EventEmitter.prototype.rawListeners = function rawListeners(type: string | symbol) { - return _listeners(this, type, false); +EventEmitter.prototype.rawListeners = function rawListeners(type : string | symbol) { + return _listeners(this, type, false); }; -const _listenerCount = function listenerCount(this: any, type: string | symbol) { - const events = this._events; +const _listenerCount = function listenerCount(this : any, type : string | symbol) { + const events = this._events; - if (events !== undefined) { - const evlistener = events[type]; + if (events !== undefined) { + const evlistener = events[type]; - if (typeof evlistener === "function") { - return 1; - } else if (evlistener !== undefined) { - return evlistener.length; - } + if (typeof evlistener === "function") { + return 1; + } else if (evlistener !== undefined) { + return evlistener.length; } + } - return 0; + return 0; }; EventEmitter.prototype.listenerCount = _listenerCount; -export function listenerCount(emitter: any, type: string | symbol) { - if (typeof emitter.listenerCount === "function") { - return emitter.listenerCount(type); - } - return _listenerCount.call(emitter, type); +export function listenerCount(emitter : any, type : string | symbol) { + if (typeof emitter.listenerCount === "function") { + return emitter.listenerCount(type); + } + return _listenerCount.call(emitter, type); } EventEmitter.prototype.eventNames = function eventNames() { - return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; + return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; }; -function arrayClone(arr: any[]) { - // At least since V8 8.3, this implementation is faster than the previous - // which always used a simple for-loop - switch (arr.length) { - case 2: - return [arr[0], arr[1]]; - case 3: - return [arr[0], arr[1], arr[2]]; - case 4: - return [arr[0], arr[1], arr[2], arr[3]]; - case 5: - return [arr[0], arr[1], arr[2], arr[3], arr[4]]; - case 6: - return [arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]]; - } - return arr.slice(); +function arrayClone(arr : any[]) { + // At least since V8 8.3, this implementation is faster than the previous + // which always used a simple for-loop + switch (arr.length) { + case 2: + return [arr[0], arr[1]]; + case 3: + return [arr[0], arr[1], arr[2]]; + case 4: + return [arr[0], arr[1], arr[2], arr[3]]; + case 5: + return [arr[0], arr[1], arr[2], arr[3], arr[4]]; + case 6: + return [arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]]; + } + return arr.slice(); } -function unwrapListeners(arr: any[]) { - const ret = arrayClone(arr); - for (let i = 0; i < ret.length; ++i) { - const orig = ret[i].listener; - if (typeof orig === "function") { - ret[i] = orig; - } +function unwrapListeners(arr : any[]) { + const ret = arrayClone(arr); + for (let i = 0; i < ret.length; ++i) { + const orig = ret[i].listener; + if (typeof orig === "function") { + ret[i] = orig; } - return ret; + } + return ret; } -export function getEventListeners(emitterOrTarget: any, type: string | symbol) { - // First check if EventEmitter - if (typeof emitterOrTarget.listeners === "function") { - return emitterOrTarget.listeners(type); - } - if (emitterOrTarget instanceof EventTarget) { - // Workers does not implement the ability to get the event listeners on an - // EventTarget the way that Node.js does. We simply return empty here. - return []; - } - throw new ERR_INVALID_ARG_TYPE("emitter", ["EventEmitter", "EventTarget"], emitterOrTarget); +export function getEventListeners(emitterOrTarget : any, type : string | symbol) { + // First check if EventEmitter + if (typeof emitterOrTarget.listeners === "function") { + return emitterOrTarget.listeners(type); + } + if (emitterOrTarget instanceof EventTarget) { + // Workers does not implement the ability to get the event listeners on an + // EventTarget the way that Node.js does. We simply return empty here. + return []; + } + throw new ERR_INVALID_ARG_TYPE( + "emitter", + ["EventEmitter", "EventTarget"], + emitterOrTarget, + ); } export interface OnceOptions { - signal?: AbortSignal; -} + signal?: AbortSignal; +}; -export async function once(emitter: any, name: string | symbol, options: OnceOptions = {}) { - const signal = options?.signal; - validateAbortSignal(signal, "options.signal"); - if (signal?.aborted) { - throw new AbortError(); +export async function once(emitter : any, name : string | symbol, options : OnceOptions = {}) { + const signal = options?.signal; + validateAbortSignal(signal, "options.signal"); + if (signal?.aborted) { + throw new AbortError(); + } + return new Promise((resolve, reject) => { + const errorListener = (err : any) => { + emitter.removeListener(name, resolver); + if (signal != null) { + eventTargetAgnosticRemoveListener(signal, "abort", abortListener); + } + reject(err); + }; + const resolver = (...args : any[]) => { + if (typeof emitter.removeListener === "function") { + emitter.removeListener("error", errorListener); + } + if (signal != null) { + eventTargetAgnosticRemoveListener(signal, "abort", abortListener); + } + resolve(args); + }; + eventTargetAgnosticAddListener(emitter, name, resolver, { once: true }); + if (name !== "error" && typeof emitter.once === "function") { + emitter.once("error", errorListener); } - return new Promise((resolve, reject) => { - const errorListener = (err: any) => { - emitter.removeListener(name, resolver); - if (signal != null) { - eventTargetAgnosticRemoveListener(signal, "abort", abortListener); - } - reject(err); - }; - const resolver = (...args: any[]) => { - if (typeof emitter.removeListener === "function") { - emitter.removeListener("error", errorListener); - } - if (signal != null) { - eventTargetAgnosticRemoveListener(signal, "abort", abortListener); - } - resolve(args); - }; - eventTargetAgnosticAddListener(emitter, name, resolver, { once: true }); - if (name !== "error" && typeof emitter.once === "function") { - emitter.once("error", errorListener); - } - function abortListener() { - eventTargetAgnosticRemoveListener(emitter, name, resolver); - eventTargetAgnosticRemoveListener(emitter, "error", errorListener); - reject(new AbortError()); - } - if (signal != null) { - eventTargetAgnosticAddListener(signal, "abort", abortListener, { once: true }); - } - }); + function abortListener() { + eventTargetAgnosticRemoveListener(emitter, name, resolver); + eventTargetAgnosticRemoveListener(emitter, "error", errorListener); + reject(new AbortError()); + } + if (signal != null) { + eventTargetAgnosticAddListener( + signal, + "abort", + abortListener, + { once: true }, + ); + } + }); } const AsyncIteratorPrototype = Object.getPrototypeOf( - Object.getPrototypeOf(async function* () {}).prototype + Object.getPrototypeOf(async function* () {}).prototype, ); function createIterResult(value: any, done: boolean) { - return { value, done }; + return { value, done }; } -function eventTargetAgnosticRemoveListener( - emitter: any, - name: string | symbol, - listener: unknown, - flags: unknown = undefined -) { - if (typeof emitter.removeListener === "function") { - emitter.removeListener(name, listener); - } else if (typeof emitter.removeEventListener === "function") { - emitter.removeEventListener(name, listener, flags); - } else { - throw new ERR_INVALID_ARG_TYPE("emitter", "EventEmitter", emitter); - } +function eventTargetAgnosticRemoveListener(emitter : any, name : string | symbol, listener : unknown, flags : unknown = undefined) { + if (typeof emitter.removeListener === "function") { + emitter.removeListener(name, listener); + } else if (typeof emitter.removeEventListener === "function") { + emitter.removeEventListener(name, listener, flags); + } else { + throw new ERR_INVALID_ARG_TYPE("emitter", "EventEmitter", emitter); + } } interface AddListenerFlags { - once?: boolean; + once? : boolean; } -function eventTargetAgnosticAddListener( - emitter: any, - name: string | symbol, - listener: unknown, - flags: AddListenerFlags = {} -) { - if (typeof emitter.on === "function") { - if (flags?.once) { - emitter.once(name, listener); - } else { - emitter.on(name, listener); - } - } else if (typeof emitter.addEventListener === "function") { - // EventTarget does not have `error` event semantics like Node - // EventEmitters, we do not listen to `error` events here. - emitter.addEventListener( - name, - (arg: unknown) => { - (listener as any)(arg); - }, - flags - ); +function eventTargetAgnosticAddListener(emitter : any, name : string | symbol, listener : unknown, flags : AddListenerFlags = {}) { + if (typeof emitter.on === "function") { + if (flags?.once) { + emitter.once(name, listener); } else { - throw new ERR_INVALID_ARG_TYPE("emitter", "EventEmitter", emitter); - } + emitter.on(name, listener); + } + } else if (typeof emitter.addEventListener === "function") { + // EventTarget does not have `error` event semantics like Node + // EventEmitters, we do not listen to `error` events here. + emitter.addEventListener(name, (arg : unknown) => { + (listener as any)(arg); + }, flags); + } else { + throw new ERR_INVALID_ARG_TYPE("emitter", "EventEmitter", emitter); + } } interface OnOptions { - signal?: AbortSignal; + signal?: AbortSignal; } -export function on(emitter: any, event: string | symbol, options: OnOptions = {}) { - const signal = options?.signal; - validateAbortSignal(signal, "options.signal"); - if (signal?.aborted) { - throw new AbortError(); - } +export function on(emitter : any, event : string | symbol, options : OnOptions = {}) { + const signal = options?.signal; + validateAbortSignal(signal, "options.signal"); + if (signal?.aborted) { + throw new AbortError(); + } + + const unconsumedEvents : any[] = []; + const unconsumedPromises : any[] = []; + let error : any = null; + let finished = false; + + const iterator = Object.setPrototypeOf({ + next() { + // First, we consume all unread events + const value = unconsumedEvents.shift(); + if (value) { + return Promise.resolve(createIterResult(value, false)); + } + + // Then we error, if an error happened + // This happens one time if at all, because after 'error' + // we stop listening + if (error) { + const p = Promise.reject(error); + // Only the first element errors + error = null; + return p; + } + + // If the iterator is finished, resolve to done + if (finished) { + return Promise.resolve(createIterResult(undefined, true)); + } + + // Wait until an event happens + return new Promise(function (resolve, reject) { + unconsumedPromises.push({ resolve, reject }); + }); + }, - const unconsumedEvents: any[] = []; - const unconsumedPromises: any[] = []; - let error: any = null; - let finished = false; - - const iterator = Object.setPrototypeOf( - { - next() { - // First, we consume all unread events - const value = unconsumedEvents.shift(); - if (value) { - return Promise.resolve(createIterResult(value, false)); - } - - // Then we error, if an error happened - // This happens one time if at all, because after 'error' - // we stop listening - if (error) { - const p = Promise.reject(error); - // Only the first element errors - error = null; - return p; - } - - // If the iterator is finished, resolve to done - if (finished) { - return Promise.resolve(createIterResult(undefined, true)); - } - - // Wait until an event happens - return new Promise(function (resolve, reject) { - unconsumedPromises.push({ resolve, reject }); - }); - }, - - return() { - eventTargetAgnosticRemoveListener(emitter, event, eventHandler); - eventTargetAgnosticRemoveListener(emitter, "error", errorHandler); - - if (signal) { - eventTargetAgnosticRemoveListener(signal, "abort", abortListener, { - once: true, - }); - } - - finished = true; - - for (const promise of unconsumedPromises) { - promise.resolve(createIterResult(undefined, true)); - } - - return Promise.resolve(createIterResult(undefined, true)); - }, - - throw(err: any) { - if (!err || !(err instanceof Error)) { - throw new ERR_INVALID_ARG_TYPE("EventEmitter.AsyncIterator", "Error", err); - } - error = err; - eventTargetAgnosticRemoveListener(emitter, event, eventHandler); - eventTargetAgnosticRemoveListener(emitter, "error", errorHandler); - }, - - [Symbol.asyncIterator]() { - return this; - }, - }, - AsyncIteratorPrototype - ); + return() { + eventTargetAgnosticRemoveListener(emitter, event, eventHandler); + eventTargetAgnosticRemoveListener(emitter, "error", errorHandler); - eventTargetAgnosticAddListener(emitter, event, eventHandler); - if (event !== "error" && typeof emitter.on === "function") { - emitter.on("error", errorHandler); - } + if (signal) { + eventTargetAgnosticRemoveListener( + signal, + "abort", + abortListener, + { once: true }, + ); + } - if (signal) { - eventTargetAgnosticAddListener(signal, "abort", abortListener, { once: true }); - } + finished = true; - return iterator; + for (const promise of unconsumedPromises) { + promise.resolve(createIterResult(undefined, true)); + } - function abortListener() { - errorHandler(new AbortError()); - } + return Promise.resolve(createIterResult(undefined, true)); + }, - function eventHandler(...args: any[]) { - const promise = unconsumedPromises.shift(); - if (promise) { - promise.resolve(createIterResult(args, false)); - } else { - unconsumedEvents.push(args); - } - } + throw(err : any) { + if (!err || !(err instanceof Error)) { + throw new ERR_INVALID_ARG_TYPE( + "EventEmitter.AsyncIterator", + "Error", + err, + ); + } + error = err; + eventTargetAgnosticRemoveListener(emitter, event, eventHandler); + eventTargetAgnosticRemoveListener(emitter, "error", errorHandler); + }, + + [Symbol.asyncIterator]() { + return this; + }, + }, AsyncIteratorPrototype); + + eventTargetAgnosticAddListener(emitter, event, eventHandler); + if (event !== "error" && typeof emitter.on === "function") { + emitter.on("error", errorHandler); + } + + if (signal) { + eventTargetAgnosticAddListener( + signal, + "abort", + abortListener, + { once: true }, + ); + } + + return iterator; - function errorHandler(err: any) { - finished = true; + function abortListener() { + errorHandler(new AbortError()); + } - const toError = unconsumedPromises.shift(); + function eventHandler(...args : any[]) { + const promise = unconsumedPromises.shift(); + if (promise) { + promise.resolve(createIterResult(args, false)); + } else { + unconsumedEvents.push(args); + } + } - if (toError) { - toError.reject(err); - } else { - // The next time we call next() - error = err; - } + function errorHandler(err : any) { + finished = true; - iterator.return(); + const toError = unconsumedPromises.shift(); + + if (toError) { + toError.reject(err); + } else { + // The next time we call next() + error = err; } + + iterator.return(); + } } diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_buffer.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_buffer.ts index e2487edc5..1b3d68e8f 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_buffer.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_buffer.ts @@ -1,3 +1,4 @@ + import { ERR_BUFFER_OUT_OF_BOUNDS, ERR_OUT_OF_RANGE, @@ -5,18 +6,29 @@ import { ERR_INVALID_ARG_VALUE, ERR_INVALID_BUFFER_SIZE, ERR_UNKNOWN_ENCODING, -} from "./internal_errors"; +} from './internal_errors'; -import * as bufferUtil from "./buffer"; +import * as bufferUtil from './buffer'; -import { isAnyArrayBuffer, isArrayBufferView, isUint8Array } from "./internal_types"; +import { + isAnyArrayBuffer, + isArrayBufferView, + isUint8Array, +} from './internal_types'; -import { normalizeEncoding } from "./internal_utils"; +import { + normalizeEncoding, +} from './internal_utils'; -import { validateString } from "./validators"; +import { + validateString, +} from './validators'; -import * as internalUtil from "./util"; -import { InspectOptionsStylized, inspect as utilInspect } from "./internal_inspect"; +import * as internalUtil from './util'; +import { + InspectOptionsStylized, + inspect as utilInspect, +} from './internal_inspect'; // Temporary buffers to convert numbers. const float32Array = new Float32Array(1); @@ -35,7 +47,7 @@ export const bigEndian = uInt8Float32Array[3] === 0; export const kMaxLength = 2147483647; export const kStringMaxLength = 536870888; const MAX_UINT32 = 2 ** 32; -const kIsBuffer = Symbol("kIsBuffer"); +const kIsBuffer = Symbol('kIsBuffer'); const customInspectSymbol = typeof Symbol === "function" && typeof Symbol["for"] === "function" @@ -49,38 +61,34 @@ export const constants = { MAX_STRING_LENGTH: kStringMaxLength, }; -function createBuffer(length: number): Buffer { +function createBuffer(length: number) : Buffer { if (length > kMaxLength) { - throw new ERR_OUT_OF_RANGE("The given length is invalid", `0 to ${kMaxLength}`, length); + throw new ERR_OUT_OF_RANGE('The given length is invalid', `0 to ${kMaxLength}`, length); } const buf = new Uint8Array(length); Object.setPrototypeOf(buf, Buffer.prototype); return buf as Buffer; } -type WithImplicitCoercion = T | { valueOf(): T }; -type StringLike = WithImplicitCoercion | { [Symbol.toPrimitive](hint: "string"): string }; -type ArrayBufferLike = WithImplicitCoercion; -type BufferSource = StringLike | ArrayBufferLike | Uint8Array | ReadonlyArray; +type WithImplicitCoercion = | T | { valueOf(): T; }; +type StringLike = WithImplicitCoercion | { [Symbol.toPrimitive](hint: "string"): string; }; +type ArrayBufferLike = WithImplicitCoercion; +type BufferSource = StringLike|ArrayBufferLike|Uint8Array|ReadonlyArray; export interface Buffer extends Uint8Array { readonly buffer: ArrayBuffer; readonly parent: ArrayBuffer; readonly byteOffset: number; readonly length: number; - compare( - target: Uint8Array, - targetStart?: number, - targetEnd?: number, - sourceStart?: number, - sourceEnd?: number - ): number; - copy( - target: Uint8Array, - targetStart?: number, - sourceStart?: number, - sourceEnd?: number - ): number; + compare(target: Uint8Array, + targetStart?: number, + targetEnd?: number, + sourceStart?: number, + sourceEnd?: number): number; + copy(target: Uint8Array, + targetStart?: number, + sourceStart?: number, + sourceEnd?: number): number; equals(other: Uint8Array): boolean; fill(value: number, offset?: number, end?: number): this; fill(value: string, encoding?: string): this; @@ -98,32 +106,32 @@ export interface Buffer extends Uint8Array { lastIndexOf(value: string, encoding?: string): number; lastIndexOf(value: string, byteOffset?: number, encoding?: string): number; lastIndexOf(value: Uint8Array, byteOffset?: number): number; - readBigInt64BE(offset?: number): bigint; - readBigInt64LE(offset?: number): bigint; - readBigUInt64BE(offset?: number): bigint; - readBigUInt64LE(offset?: number): bigint; - readDoubleBE(offset?: number): number; - readDoubleLE(offset?: number): number; - readFloatBE(offset?: number): number; - readFloatLE(offset?: number): number; - readInt8(offset?: number): number; - readInt16BE(offset?: number): number; - readInt16LE(offset?: number): number; - readInt32BE(offset?: number): number; - readInt32LE(offset?: number): number; - readIntBE(offset?: number, byteLength?: number): number; - readIntLE(offset?: number, byteLength?: number): number; - readUInt8(offset?: number): number; - readUInt16BE(offset?: number): number; - readUInt16LE(offset?: number): number; - readUInt32BE(offset?: number): number; - readUInt32LE(offset?: number): number; - readUIntBE(offset?: number, byteLength?: number): number; - readUIntLE(offset?: number, byteLength?: number): number; + readBigInt64BE(offset?: number) : bigint; + readBigInt64LE(offset?: number) : bigint; + readBigUInt64BE(offset?: number) : bigint; + readBigUInt64LE(offset?: number) : bigint; + readDoubleBE(offset?: number) : number; + readDoubleLE(offset?: number) : number; + readFloatBE(offset?: number) : number; + readFloatLE(offset?: number) : number; + readInt8(offset?: number) : number; + readInt16BE(offset?: number) : number; + readInt16LE(offset?: number) : number; + readInt32BE(offset?: number) : number; + readInt32LE(offset?: number) : number; + readIntBE(offset?: number, byteLength?: number) : number; + readIntLE(offset?: number, byteLength?: number) : number; + readUInt8(offset?: number) : number; + readUInt16BE(offset?: number) : number; + readUInt16LE(offset?: number) : number; + readUInt32BE(offset?: number) : number; + readUInt32LE(offset?: number) : number; + readUIntBE(offset?: number, byteLength?: number) : number; + readUIntLE(offset?: number, byteLength?: number) : number; swap16(): this; swap32(): this; swap64(): this; - toJSON(): { type: "Buffer"; data: number[] }; + toJSON(): {type: 'Buffer', data: number[]}; toString(encoding?: string, start?: number, end?: number): string; write(string: string, encoding?: string): number; write(string: string, offset?: number, encoding?: string): number; @@ -150,29 +158,26 @@ export interface Buffer extends Uint8Array { writeUInt32LE(value: number, offset?: number): number; writeUIntBE(value: number, offset?: number, byteLength?: number): number; writeUIntLE(value: number, offset?: number, byteLength?: number): number; - new (array: Iterable): Buffer; + new (array:Iterable): Buffer; new (arrayBuffer: ArrayBufferLike, byteOffset?: number, length?: number): Buffer; new (buffer: ArrayBufferView): Buffer; new (size: number): Buffer; new (string: string, encoding?: string): Buffer; -} +}; -type FillValue = string | number | ArrayBufferView; +type FillValue = string|number|ArrayBufferView; -export function Buffer(value: number): Buffer; -export function Buffer(value: StringLike, encoding?: string): Buffer; -export function Buffer(value: ArrayBufferLike, byteOffset?: number, length?: number): Buffer; -export function Buffer( - value: Uint8Array | ReadonlyArray, - byteOffset?: number, - length?: number -): Buffer; -export function Buffer(value: StringLike, encoding?: string): Buffer; -export function Buffer( - value: number | BufferSource, - encodingOrOffset?: string | number, - length?: number -): Buffer { +export function Buffer(value: number) : Buffer; +export function Buffer(value: StringLike, encoding?: string) : Buffer; +export function Buffer(value: ArrayBufferLike, byteOffset?: number, length?: number) : Buffer; +export function Buffer(value: Uint8Array|ReadonlyArray, + byteOffset?: number, + length?: number) : Buffer; +export function Buffer(value: StringLike, + encoding?: string) : Buffer; +export function Buffer(value: number|BufferSource, + encodingOrOffset? : string|number, + length?: number) : Buffer { if (typeof value === "number") { if (typeof encodingOrOffset === "string") { throw new ERR_INVALID_ARG_TYPE("string", "string", value); @@ -197,7 +202,7 @@ Object.defineProperties(Buffer, { enumerable: true, value: 0, writable: false, - }, + } }); Object.defineProperties(Buffer.prototype, { @@ -226,26 +231,21 @@ Object.defineProperties(Buffer.prototype, { }, }); -function _from(value: BufferSource, encodingOrOffset?: string | number, length?: number): Buffer { +function _from(value: BufferSource, + encodingOrOffset? : string|number, + length?: number) : Buffer { if (typeof value === "string") { return fromString(value, encodingOrOffset as string | undefined) as Buffer; } if (typeof value === "object" && value != null) { if (isAnyArrayBuffer(value)) { - return fromArrayBuffer( - value as ArrayBufferLike, - encodingOrOffset as number, - length - ) as Buffer; + return fromArrayBuffer(value as ArrayBufferLike, encodingOrOffset as number, length) as Buffer; } const valueOf = value?.valueOf(); - if ( - valueOf != null && - valueOf !== value && - (typeof valueOf === "string" || typeof valueOf === "object") - ) { + if (valueOf != null && valueOf !== value && + (typeof valueOf === "string" || typeof valueOf === "object")) { return _from(valueOf as BufferSource, encodingOrOffset, length); } @@ -279,22 +279,23 @@ function _from(value: BufferSource, encodingOrOffset?: string | number, length?: "ArrayBuffer", "SharedArrayBuffer", "Array", - "Array-like Object", + "Array-like Object" ], - value + value, ); } -function from(value: StringLike, encoding?: string): Buffer; -function from(value: ArrayBufferLike, byteOffset?: number, length?: number): Buffer; -function from( - value: Uint8Array | ReadonlyArray, - byteOffset?: number, - length?: number -): Buffer; -function from(value: BufferSource, encodingOrOffset?: string | number, length?: number) { +function from(value: StringLike, + encoding?: string) : Buffer; +function from(value: ArrayBufferLike, + byteOffset?: number, + length?: number) : Buffer; +function from(value: Uint8Array|ReadonlyArray, + byteOffset?: number, + length?: number) : Buffer; +function from(value: BufferSource, encodingOrOffset?: string|number, length?: number) { return _from(value, encodingOrOffset, length); -} +}; function fromString(string: StringLike, encoding?: string) { if (typeof encoding !== "string" || encoding === "") { @@ -307,21 +308,20 @@ function fromString(string: StringLike, encoding?: string) { const ab = bufferUtil.decodeString(`${string}`, normalizedEncoding as string); if (ab === undefined) { - throw new ERR_INVALID_ARG_VALUE( - "string", - string, - `Unable to decode string using encoding ${encoding}` - ); + throw new ERR_INVALID_ARG_VALUE('string', string, + `Unable to decode string using encoding ${encoding}`); } return fromArrayBuffer(ab, 0, ab.byteLength); } -function fromArrayLike(array: Uint8Array | ReadonlyArray) { +function fromArrayLike(array: Uint8Array|ReadonlyArray) { const u8 = Uint8Array.from(array); return fromArrayBuffer(u8.buffer, u8.byteOffset, u8.byteLength); } -function fromArrayBuffer(obj: ArrayBufferLike, byteOffset: number, length?: number) { +function fromArrayBuffer(obj: ArrayBufferLike, + byteOffset: number, + length?: number) { // Convert byteOffset to integer if (byteOffset === undefined) { byteOffset = 0; @@ -361,16 +361,17 @@ Buffer.from = from; function of(...args: number[]) { const buf = Buffer.alloc(args.length); - for (let k = 0; k < args.length; k++) buf[k] = args[k]!; + for (let k = 0; k < args.length; k++) + buf[k] = args[k]!; return buf; } Buffer.of = of; -function alloc(size: number, fill?: FillValue, encoding?: string): Buffer { +function alloc(size: number, fill?: FillValue, encoding?: string) : Buffer { validateNumber(size, "size"); if (Number.isNaN(size)) { - throw new ERR_INVALID_ARG_VALUE.RangeError("size", size); + throw new ERR_INVALID_ARG_VALUE.RangeError('size', size); } if (size >= kMaxLength) { throw new ERR_OUT_OF_RANGE("size", `0 to ${kMaxLength}`, size); @@ -379,7 +380,7 @@ function alloc(size: number, fill?: FillValue, encoding?: string): Buffer { const buffer = createBuffer(size); if (fill !== undefined) { if (encoding !== undefined) { - validateString(encoding, "encoding"); + validateString(encoding, 'encoding'); } return buffer.fill(fill as any, encoding); } @@ -388,7 +389,7 @@ function alloc(size: number, fill?: FillValue, encoding?: string): Buffer { Buffer.alloc = alloc; -function allocUnsafe(size: number): Buffer { +function allocUnsafe(size: number) : Buffer { return alloc(size); } @@ -406,7 +407,7 @@ Buffer.isBuffer = function isBuffer(b: unknown) { return b != null && (b as any)[kIsBuffer] && b !== Buffer.prototype; }; -export function compare(a: Buffer | Uint8Array, b: Buffer | Uint8Array) { +export function compare(a: Buffer|Uint8Array, b: Buffer|Uint8Array) { if (isInstance(a, Uint8Array)) { const buf = a as Uint8Array; a = fromArrayBuffer(buf.buffer, buf.byteOffset, buf.byteLength); @@ -416,10 +417,10 @@ export function compare(a: Buffer | Uint8Array, b: Buffer | Uint8Array) { b = fromArrayBuffer(buf.buffer, buf.byteOffset, buf.byteLength); } if (!Buffer.isBuffer(a)) { - throw new ERR_INVALID_ARG_TYPE("a", ["Buffer", "Uint8Array"], typeof a); + throw new ERR_INVALID_ARG_TYPE('a', ['Buffer', 'Uint8Array'], typeof a); } if (!Buffer.isBuffer(b)) { - throw new ERR_INVALID_ARG_TYPE("b", ["Buffer", "Uint8Array"], typeof b); + throw new ERR_INVALID_ARG_TYPE('b', ['Buffer', 'Uint8Array'], typeof b); } if (a === b) return 0; @@ -429,16 +430,14 @@ export function compare(a: Buffer | Uint8Array, b: Buffer | Uint8Array) { Buffer.compare = compare; export function isEncoding(encoding: unknown) { - return ( - typeof encoding === "string" && + return typeof encoding === "string" && encoding.length !== 0 && - normalizeEncoding(encoding) !== undefined - ); + normalizeEncoding(encoding) !== undefined; } Buffer.isEncoding = isEncoding; -Buffer.concat = function concat(list: (Buffer | Uint8Array)[], length?: number) { +Buffer.concat = function concat(list: (Buffer|Uint8Array)[], length?: number) { if (!Array.isArray(list)) { throw new ERR_INVALID_ARG_TYPE("list", "(Buffer|Uint8Array)[]", list); } @@ -451,7 +450,7 @@ Buffer.concat = function concat(list: (Buffer | Uint8Array)[], length?: number) if (list[i]!.length !== undefined) { length += list[i]!.length; } else { - throw new ERR_INVALID_ARG_TYPE("list", "(Buffer|Uint8Array)[]", list[i]); + throw new ERR_INVALID_ARG_TYPE('list', '(Buffer|Uint8Array)[]', list[i]); } } } @@ -465,17 +464,15 @@ function base64ByteLength(str: string) { let len = str.length; if (str.charCodeAt(len - 1) === 0x3d) { len--; - } - if (len > 1 && str.charCodeAt(len - 1) === 0x3d) len--; + } if (len > 1 && str.charCodeAt(len - 1) === 0x3d) + len--; // Base64 ratio: 3/4 return (len * 3) >>> 2; } -function byteLength( - string: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, - encoding?: string -) { +function byteLength(string: string|ArrayBufferView|ArrayBuffer|SharedArrayBuffer, + encoding?: string) { if (typeof string !== "string") { if (isArrayBufferView(string) || isAnyArrayBuffer(string)) { return string.byteLength; @@ -491,19 +488,19 @@ function byteLength( } switch (normalizedEncoding) { - case "ascii": + case 'ascii': // Fall through - case "latin1": + case 'latin1': return (string as string).length; - case "utf16le": + case 'utf16le': return (string as string).length * 2; - case "base64": + case 'base64': // Fall through - case "base64url": + case 'base64url': return base64ByteLength(string as string); - case "hex": + case 'hex': return (string as string).length >>> 1; - case "utf8": + case 'utf8': // Fall-through default: return bufferUtil.byteLength(string as string, normalizedEncoding as string); @@ -539,7 +536,10 @@ Buffer.prototype.swap64 = function swap64() { return this; }; -Buffer.prototype.toString = function toString(encoding?: string, start?: number, end?: number) { +Buffer.prototype.toString = function toString( + encoding?: string, + start?: number, + end?: number) { if (arguments.length === 0) { return bufferUtil.toString(this, 0, this.length, "utf8"); } @@ -574,31 +574,31 @@ Buffer.prototype.toString = function toString(encoding?: string, start?: number, Buffer.prototype.toLocaleString = Buffer.prototype.toString; -Buffer.prototype.equals = function equals(b: Buffer | Uint8Array) { +Buffer.prototype.equals = function equals(b: Buffer|Uint8Array) { return compare(this, b) === 0; }; Buffer.prototype.inspect = function inspect(_recurseTimes: number, ctx: InspectOptionsStylized) { let str = ""; const max = INSPECT_MAX_BYTES; - str = this.toString("hex", 0, max) - .replace(/(.{2})/g, "$1 ") - .trim(); + str = this.toString("hex", 0, max).replace(/(.{2})/g, "$1 ").trim(); const remaining = this.length - max; if (remaining > 0) { - str += ` ... ${remaining} more byte${remaining > 1 ? "s" : ""}`; + str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`; } // Inspect special properties as well, if possible. if (ctx) { let extras = false; const filter = ctx.showHidden ? internalUtil.ALL_PROPERTIES : internalUtil.ONLY_ENUMERABLE; const obj: Record = { __proto__: null }; - internalUtil.getOwnNonIndexProperties(this, filter).forEach((key) => { - extras = true; - obj[key] = this[key]; - }); + internalUtil.getOwnNonIndexProperties(this, filter).forEach( + (key) => { + extras = true; + obj[key] = this[key]; + }); if (extras) { - if (this.length !== 0) str += ", "; + if (this.length !== 0) + str += ', '; // '[Object: null prototype] {'.length === 26 // This is guarded with a test. str += utilInspect(obj, { @@ -616,11 +616,11 @@ if (customInspectSymbol) { } Buffer.prototype.compare = function compare( - target: Buffer | Uint8Array, + target: Buffer|Uint8Array, start?: number, end?: number, thisStart?: number, - thisEnd?: number + thisEnd?: number, ) { if (isInstance(target, Uint8Array)) { target = fromArrayBuffer(target.buffer, target.byteOffset, target.byteLength); @@ -663,15 +663,15 @@ Buffer.prototype.compare = function compare( function includes( this: Buffer, - val: string | number | Buffer | Uint8Array, + val: string|number|Buffer|Uint8Array, byteOffset?: number, - encoding?: string -) { + encoding?: string) { return this.indexOf(val as any, byteOffset, encoding) !== -1; } Buffer.prototype.includes = includes; + // Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, // OR the last index of `val` in `buffer` at offset <= `byteOffset`. // @@ -683,32 +683,32 @@ Buffer.prototype.includes = includes; // - dir - true for indexOf, false for lastIndexOf function bidirectionalIndexOf( buffer: Uint8Array, - val: string | number | Buffer | Uint8Array, - byteOffset: number | string | undefined, - encoding: string | undefined, - dir: boolean | undefined -) { + val: string|number|Buffer|Uint8Array, + byteOffset: number|string|undefined, + encoding: string|undefined, + dir: boolean|undefined) { + if (Buffer.isBuffer(val) && !isUint8Array(val)) { - throw new ERR_INVALID_ARG_TYPE("val", ["string", "number", "Buffer", "Uint8Array"], val); + throw new ERR_INVALID_ARG_TYPE('val', ['string', 'number', 'Buffer', 'Uint8Array'], val); } - if (typeof byteOffset === "string") { + if (typeof byteOffset === 'string') { encoding = byteOffset; byteOffset = undefined; - } else if ((byteOffset as number) > 0x7fffffff) { + } else if (byteOffset as number > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if ((byteOffset as number) < -0x80000000) { + } else if (byteOffset as number < -0x80000000) { byteOffset = -0x80000000; } // Coerce to Number. Values like null and [] become 0. byteOffset = +(byteOffset as number); // If the offset is undefined, "foo", {}, coerces to NaN, search whole buffer. if (Number.isNaN(byteOffset)) { - byteOffset = dir ? 0 : buffer.length || buffer.byteLength; + byteOffset = dir ? 0 : (buffer.length || buffer.byteLength); } - dir = !!dir; // Cast to bool. + dir = !!dir; // Cast to bool. - if (typeof val === "number") { + if (typeof val === 'number') { val = (val >>> 0) & 0xff; if (dir) { return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset); @@ -717,8 +717,8 @@ function bidirectionalIndexOf( } } - if (typeof val !== "string" && !isUint8Array(val) && !Buffer.isBuffer(val)) { - throw new ERR_INVALID_ARG_TYPE("value", ["number", "string", "Buffer", "Uint8Array"], val); + if (typeof val !== 'string' && !isUint8Array(val) && !Buffer.isBuffer(val)) { + throw new ERR_INVALID_ARG_TYPE('value', ['number', 'string', 'Buffer', 'Uint8Array'], val); } let normalizedEncoding = normalizeEncoding(encoding); @@ -731,173 +731,160 @@ function bidirectionalIndexOf( } Buffer.prototype.indexOf = function indexOf( - val: string | number | Buffer | Uint8Array, - byteOffset?: number | string, - encoding?: string -) { + val: string|number|Buffer|Uint8Array, + byteOffset?: number|string, + encoding?: string) { return bidirectionalIndexOf(this, val, byteOffset, encoding, true); }; Buffer.prototype.lastIndexOf = function lastIndexOf( - val: string | number | Buffer | Uint8Array, - byteOffset?: number | string, - encoding?: string -) { + val: string|number|Buffer|Uint8Array, + byteOffset?: number|string, + encoding?: string) { return bidirectionalIndexOf(this, val, byteOffset, encoding, false); }; Buffer.prototype.asciiSlice = function asciiSlice(offset: number, length: number) { validateOffset(offset, "offset", 0, this.length); validateOffset(length, "length", 0, this.length - offset); - return bufferUtil.toString(this, offset, offset + length, "ascii"); + return bufferUtil.toString(this, offset, offset + length, 'ascii'); }; Buffer.prototype.base64Slice = function base64Slice(offset: number, length: number) { validateOffset(offset, "offset", 0, this.length); validateOffset(length, "length", 0, this.length - offset); - return bufferUtil.toString(this, offset, offset + length, "base64"); + return bufferUtil.toString(this, offset, offset + length, 'base64'); }; Buffer.prototype.base64urlSlice = function base64urlSlice(offset: number, length: number) { validateOffset(offset, "offset", 0, this.length); validateOffset(length, "length", 0, this.length - offset); - return bufferUtil.toString(this, offset, offset + length, "base64url"); + return bufferUtil.toString(this, offset, offset + length, 'base64url'); }; Buffer.prototype.hexSlice = function hexSlice(offset: number, length: number) { validateOffset(offset, "offset", 0, this.length); validateOffset(length, "length", 0, this.length - offset); - return bufferUtil.toString(this, offset, offset + length, "hex"); + return bufferUtil.toString(this, offset, offset + length, 'hex'); }; -Buffer.prototype.latin1Slice = function latin1Slice(offset: number, length: number) { +Buffer.prototype.latin1Slice = function latin1Slice(offset: number, + length: number) { validateOffset(offset, "offset", 0, this.length); validateOffset(length, "length", 0, this.length - offset); - return bufferUtil.toString(this, offset, offset + length, "latin1"); + return bufferUtil.toString(this, offset, offset + length, 'latin1'); }; Buffer.prototype.ucs2Slice = function ucs2Slice(offset: number, length: number) { validateOffset(offset, "offset", 0, this.length); validateOffset(length, "length", 0, this.length - offset); - return bufferUtil.toString(this, offset, offset + length, "utf16le"); + return bufferUtil.toString(this, offset, offset + length, 'utf16le'); }; Buffer.prototype.utf8Slice = function utf8Slice(offset: number, length: number) { validateOffset(offset, "offset", 0, this.length); validateOffset(length, "length", 0, this.length - offset); - return bufferUtil.toString(this, offset, offset + length, "utf8"); + return bufferUtil.toString(this, offset, offset + length, 'utf8'); }; -Buffer.prototype.asciiWrite = function asciiWrite( - string: StringLike, - offset?: number, - length?: number -) { +Buffer.prototype.asciiWrite = function asciiWrite(string: StringLike, + offset?: number, + length?: number) { offset ??= 0; length ??= this.length; validateOffset(offset as number, "offset", 0, this.length); validateOffset(length as number, "length", 0, this.length - offset); - return bufferUtil.write(this, `${string}`, offset as number, length as number, "ascii"); + return bufferUtil.write(this, `${string}`, offset as number, length as number, 'ascii'); }; -Buffer.prototype.base64Write = function base64Write( - string: StringLike, - offset?: number, - length?: number -) { +Buffer.prototype.base64Write = function base64Write(string: StringLike, + offset?: number, + length?: number) { offset ??= 0; length ??= this.length; validateOffset(offset as number, "offset", 0, this.length); validateOffset(length as number, "length", 0, this.length - offset); - return bufferUtil.write(this, `${string}`, offset as number, length as number, "base64"); + return bufferUtil.write(this, `${string}`, offset as number, length as number, 'base64'); }; -Buffer.prototype.base64urlWrite = function base64urlWrite( - string: StringLike, - offset?: number, - length?: number -) { +Buffer.prototype.base64urlWrite = function base64urlWrite(string: StringLike, + offset?: number, + length?: number) { offset ??= 0; length ??= this.length; validateOffset(offset as number, "offset", 0, this.length); validateOffset(length as number, "length", 0, this.length - offset); - return bufferUtil.write(this, `${string}`, offset as number, length as number, "base64url"); + return bufferUtil.write(this, `${string}`, offset as number, length as number, 'base64url'); }; -Buffer.prototype.hexWrite = function hexWrite(string: StringLike, offset: number, length: number) { +Buffer.prototype.hexWrite = function hexWrite(string: StringLike, + offset: number, + length: number) { offset ??= 0; length ??= this.length; validateOffset(offset as number, "offset", 0, this.length); validateOffset(length as number, "length", 0, this.length - offset); - return bufferUtil.write(this, `${string}`, offset as number, length as number, "hex"); + return bufferUtil.write(this, `${string}`, offset as number, length as number, 'hex'); }; -Buffer.prototype.latin1Write = function latin1Write( - string: StringLike, - offset: number, - length: number -) { +Buffer.prototype.latin1Write = function latin1Write(string: StringLike, + offset: number, + length: number) { offset ??= 0; length ??= this.length; validateOffset(offset as number, "offset", 0, this.length); validateOffset(length as number, "length", 0, this.length - offset); - return bufferUtil.write(this, `${string}`, offset as number, length as number, "latin1"); + return bufferUtil.write(this, `${string}`, offset as number, length as number, 'latin1'); }; -Buffer.prototype.ucs2Write = function ucs2Write( - string: StringLike, - offset: number, - length: number -) { +Buffer.prototype.ucs2Write = function ucs2Write(string: StringLike, + offset: number, + length: number) { offset ??= 0; length ??= this.length; validateOffset(offset as number, "offset", 0, this.length); validateOffset(length as number, "length", 0, this.length - offset); - return bufferUtil.write(this, `${string}`, offset as number, length as number, "utf16le"); + return bufferUtil.write(this, `${string}`, offset as number, length as number, 'utf16le'); }; -Buffer.prototype.utf8Write = function utf8Write( - string: StringLike, - offset: number, - length: number -) { +Buffer.prototype.utf8Write = function utf8Write(string: StringLike, + offset: number, + length: number) { offset ??= 0; length ??= this.length; validateOffset(offset as number, "offset", 0, this.length); validateOffset(length as number, "length", 0, this.length - offset); - return bufferUtil.write(this, `${string}`, offset as number, length as number, "utf8"); + return bufferUtil.write(this, `${string}`, offset as number, length as number, 'utf8'); }; -Buffer.prototype.write = function write( - string: StringLike, - offset?: number | string, - length?: number | string, - encoding?: string -) { +Buffer.prototype.write = function write(string: StringLike, + offset?: number | string, + length?: number | string, + encoding?: string) { string = `${string}`; if (offset === undefined) { // Buffer#write(string) return bufferUtil.write(this, string as string, 0, this.length, "utf8"); } - if (length === undefined && typeof offset === "string") { + if (length === undefined && typeof offset === 'string') { // Buffer#write(string, encoding) encoding = offset; length = this.length; offset = 0; } else { // Buffer#write(string, offset[, length][, encoding]) - validateOffset(offset as number, "offset", 0, this.length); + validateOffset(offset as number, 'offset', 0, this.length); const remaining = this.length - (offset as number); if (length === undefined) { length = remaining; - } else if (typeof length === "string") { + } else if (typeof length === 'string') { encoding = length; length = remaining; } else { - validateOffset(length, "length", 0, this.length); + validateOffset(length, 'length', 0, this.length); if (length > remaining) { length = remaining; } @@ -913,13 +900,8 @@ Buffer.prototype.write = function write( throw new ERR_UNKNOWN_ENCODING(encoding as string); } - return bufferUtil.write( - this, - string as string, - offset as number, - length as number, - normalizedEncoding as string - ); + return bufferUtil.write(this, string as string, offset as number, length as number, + normalizedEncoding as string); }; Buffer.prototype.toJSON = function toJSON() { @@ -961,24 +943,17 @@ Buffer.prototype.slice = function slice(start: number, end?: number) { Buffer.prototype.readUintLE = Buffer.prototype.readUIntLE = function readUIntLE( offset: number, - byteLength: number -) { + byteLength: number) { if (offset === undefined) { throw new ERR_INVALID_ARG_TYPE("offset", "number", offset); } switch (byteLength) { - case 1: - return this.readUInt8(offset); - case 2: - return this.readUInt16LE(offset); - case 3: - return readUInt24LE(this, offset); - case 4: - return this.readUInt32LE(offset); - case 5: - return readUInt40LE(this, offset); - case 6: - return readUInt48LE(this, offset); + case 1: return this.readUInt8(offset); + case 2: return this.readUInt16LE(offset); + case 3: return readUInt24LE(this, offset); + case 4: return this.readUInt32LE(offset); + case 5: return readUInt40LE(this, offset); + case 6: return readUInt48LE(this, offset); default: boundsError(byteLength, 6, "byteLength"); } @@ -986,30 +961,24 @@ Buffer.prototype.readUintLE = Buffer.prototype.readUIntLE = function readUIntLE( Buffer.prototype.readUintBE = Buffer.prototype.readUIntBE = function readUIntBE( offset: number, - byteLength: number -) { + byteLength: number) { if (offset === undefined) { throw new ERR_INVALID_ARG_TYPE("offset", "number", offset); } switch (byteLength) { - case 1: - return this.readUInt8(offset); - case 2: - return this.readUInt16BE(offset); - case 3: - return readUInt24BE(this, offset); - case 4: - return this.readUInt32BE(offset); - case 5: - return readUInt40BE(this, offset); - case 6: - return readUInt48BE(this, offset); + case 1: return this.readUInt8(offset); + case 2: return this.readUInt16BE(offset); + case 3: return readUInt24BE(this, offset); + case 4: return this.readUInt32BE(offset); + case 5: return readUInt40BE(this, offset); + case 6: return readUInt48BE(this, offset); default: boundsError(byteLength, 6, "byteLength"); } }; -Buffer.prototype.readUint8 = Buffer.prototype.readUInt8 = function readUInt8(offset: number = 0) { +Buffer.prototype.readUint8 = Buffer.prototype.readUInt8 = function readUInt8( + offset: number = 0) { validateOffset(offset, "offset", 0, this.length); const val = this[offset]; if (val === undefined) { @@ -1021,110 +990,104 @@ Buffer.prototype.readUint8 = Buffer.prototype.readUInt8 = function readUInt8(off Buffer.prototype.readUint16BE = Buffer.prototype.readUInt16BE = readUInt16BE; -Buffer.prototype.readUint16LE = Buffer.prototype.readUInt16LE = function readUInt16LE( - offset: number = 0 -) { - validateOffset(offset, "offset", 0, this.length); - const first = this[offset]; - const last = this[offset + 1]; - if (first === undefined || last === undefined) { - boundsError(offset, this.length - 2); - } +Buffer.prototype.readUint16LE = + Buffer.prototype.readUInt16LE = + function readUInt16LE(offset: number = 0) { + validateOffset(offset, "offset", 0, this.length); + const first = this[offset]; + const last = this[offset + 1]; + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 2); + } - return first + last * 2 ** 8; -}; + return first + last * 2 ** 8; + }; + +Buffer.prototype.readUint32LE = + Buffer.prototype.readUInt32LE = + function readUInt32LE(this: Buffer, offset: number = 0) { + validateOffset(offset, "offset", 0, this.length); + const first = this[offset]; + const last = this[offset + 3]; + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 4); + } -Buffer.prototype.readUint32LE = Buffer.prototype.readUInt32LE = function readUInt32LE( - this: Buffer, - offset: number = 0 -) { - validateOffset(offset, "offset", 0, this.length); - const first = this[offset]; - const last = this[offset + 3]; - if (first === undefined || last === undefined) { - boundsError(offset, this.length - 4); - } - - return first + this[++offset]! * 2 ** 8 + this[++offset]! * 2 ** 16 + last * 2 ** 24; -}; + return first + + this[++offset]! * 2 ** 8 + + this[++offset]! * 2 ** 16 + + last * 2 ** 24; + }; Buffer.prototype.readUint32BE = Buffer.prototype.readUInt32BE = readUInt32BE; -Buffer.prototype.readBigUint64LE = Buffer.prototype.readBigUInt64LE = function readBigUInt64LE( - this: Buffer, - offset: number = 0 -) { - offset = offset >>> 0; - validateOffset(offset, "offset", 0, this.length); - const first = this[offset]; - const last = this[offset + 7]; - if (first === undefined || last === undefined) { - boundsError(offset, this.length - 8); - } - const lo = - first + this[++offset]! * 2 ** 8 + this[++offset]! * 2 ** 16 + this[++offset]! * 2 ** 24; - const hi = - this[++offset]! + this[++offset]! * 2 ** 8 + this[++offset]! * 2 ** 16 + last * 2 ** 24; - return BigInt(lo) + (BigInt(hi) << BigInt(32)); -}; - -Buffer.prototype.readBigUint64BE = Buffer.prototype.readBigUInt64BE = function readBigUInt64BE( - this: Buffer, - offset: number = 0 +Buffer.prototype.readBigUint64LE = + Buffer.prototype.readBigUInt64LE = + function readBigUInt64LE(this: Buffer, offset: number = 0) { + offset = offset >>> 0; + validateOffset(offset, "offset", 0, this.length); + const first = this[offset]; + const last = this[offset + 7]; + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 8); + } + const lo = first + this[++offset]! * 2 ** 8 + + this[++offset]! * 2 ** 16 + + this[++offset]! * 2 ** 24; + const hi = this[++offset]! + this[++offset]! * 2 ** 8 + + this[++offset]! * 2 ** 16 + last * 2 ** 24; + return BigInt(lo) + (BigInt(hi) << BigInt(32)); + }; + +Buffer.prototype.readBigUint64BE = + Buffer.prototype.readBigUInt64BE = + function readBigUInt64BE(this: Buffer, offset: number = 0) { + offset = offset >>> 0; + validateOffset(offset, "offset", 0, this.length); + const first = this[offset]; + const last = this[offset + 7]; + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 8); + } + const hi = first * 2 ** 24 + this[++offset]! * 2 ** 16 + + this[++offset]! * 2 ** 8 + this[++offset]!; + const lo = this[++offset]! * 2 ** 24 + this[++offset]! * 2 ** 16 + + this[++offset]! * 2 ** 8 + last; + return (BigInt(hi) << BigInt(32)) + BigInt(lo); + }; + +Buffer.prototype.readIntLE = function readIntLE( + offset: number, + byteLength: number, ) { - offset = offset >>> 0; - validateOffset(offset, "offset", 0, this.length); - const first = this[offset]; - const last = this[offset + 7]; - if (first === undefined || last === undefined) { - boundsError(offset, this.length - 8); - } - const hi = - first * 2 ** 24 + this[++offset]! * 2 ** 16 + this[++offset]! * 2 ** 8 + this[++offset]!; - const lo = - this[++offset]! * 2 ** 24 + this[++offset]! * 2 ** 16 + this[++offset]! * 2 ** 8 + last; - return (BigInt(hi) << BigInt(32)) + BigInt(lo); -}; - -Buffer.prototype.readIntLE = function readIntLE(offset: number, byteLength: number) { if (offset === undefined) { throw new ERR_INVALID_ARG_TYPE("offset", "number", offset); } switch (byteLength) { - case 1: - return this.readInt8(offset); - case 2: - return this.readInt16LE(offset); - case 3: - return readInt24LE(this, offset); - case 4: - return this.readInt32LE(offset); - case 5: - return readInt40LE(this, offset); - case 6: - return readInt48LE(this, offset); + case 1: return this.readInt8(offset); + case 2: return this.readInt16LE(offset); + case 3: return readInt24LE(this, offset); + case 4: return this.readInt32LE(offset); + case 5: return readInt40LE(this, offset); + case 6: return readInt48LE(this, offset); default: boundsError(byteLength, 6, "byteLength"); } }; -Buffer.prototype.readIntBE = function readIntBE(offset: number, byteLength: number) { +Buffer.prototype.readIntBE = function readIntBE( + offset: number, + byteLength: number) { if (offset === undefined) { throw new ERR_INVALID_ARG_TYPE("offset", "number", offset); } switch (byteLength) { - case 1: - return this.readInt8(offset); - case 2: - return this.readInt16BE(offset); - case 3: - return readInt24BE(this, offset); - case 4: - return this.readInt32BE(offset); - case 5: - return readInt40BE(this, offset); - case 6: - return readInt48BE(this, offset); + case 1: return this.readInt8(offset); + case 2: return this.readInt16BE(offset); + case 3: return readInt24BE(this, offset); + case 4: return this.readInt32BE(offset); + case 5: return readInt40BE(this, offset); + case 6: return readInt48BE(this, offset); default: boundsError(byteLength, 6, "byteLength"); } @@ -1137,7 +1100,7 @@ Buffer.prototype.readInt8 = function readInt8(offset: number = 0) { boundsError(offset, this.length - 1); } - return val | ((val & (2 ** 7)) * 0x1fffffe); + return val | (val & 2 ** 7) * 0x1fffffe; }; Buffer.prototype.readInt16LE = function readInt16LE(offset: number = 0) { @@ -1149,7 +1112,7 @@ Buffer.prototype.readInt16LE = function readInt16LE(offset: number = 0) { } const val = first + last * 2 ** 8; - return val | ((val & (2 ** 15)) * 0x1fffe); + return val | (val & 2 ** 15) * 0x1fffe; }; Buffer.prototype.readInt16BE = function readInt16BE(offset: number = 0) { @@ -1161,7 +1124,7 @@ Buffer.prototype.readInt16BE = function readInt16BE(offset: number = 0) { } const val = first * 2 ** 8 + last; - return val | ((val & (2 ** 15)) * 0x1fffe); + return val | (val & 2 ** 15) * 0x1fffe; }; Buffer.prototype.readInt32LE = function readInt32LE(offset: number = 0) { @@ -1172,7 +1135,10 @@ Buffer.prototype.readInt32LE = function readInt32LE(offset: number = 0) { boundsError(offset, this.length - 4); } - return first + this[++offset] * 2 ** 8 + this[++offset] * 2 ** 16 + (last << 24); // Overflow + return first + + this[++offset] * 2 ** 8 + + this[++offset] * 2 ** 16 + + (last << 24); // Overflow }; Buffer.prototype.readInt32BE = function readInt32BE(offset: number = 0) { @@ -1183,12 +1149,10 @@ Buffer.prototype.readInt32BE = function readInt32BE(offset: number = 0) { boundsError(offset, this.length - 4); } - return ( - (first << 24) + // Overflow + return (first << 24) + // Overflow this[++offset] * 2 ** 16 + this[++offset] * 2 ** 8 + - last - ); + last; }; Buffer.prototype.readBigInt64LE = function readBigInt64LE(this: Buffer, offset: number = 0) { @@ -1199,14 +1163,13 @@ Buffer.prototype.readBigInt64LE = function readBigInt64LE(this: Buffer, offset: if (first === undefined || last === undefined) { boundsError(offset, this.length - 8); } - const val = - this[offset + 4]! + this[offset + 5]! * 2 ** 8 + this[offset + 6]! * 2 ** 16 + (last << 24); - return ( - (BigInt(val) << BigInt(32)) + + const val = this[offset + 4]! + this[offset + 5]! * 2 ** 8 + + this[offset + 6]! * 2 ** 16 + (last << 24); + return (BigInt(val) << BigInt(32)) + BigInt( - first + this[++offset]! * 2 ** 8 + this[++offset]! * 2 ** 16 + this[++offset]! * 2 ** 24 - ) - ); + first + this[++offset]! * 2 ** 8 + this[++offset]! * 2 ** 16 + + this[++offset]! * 2 ** 24, + ); }; Buffer.prototype.readBigInt64BE = function readBigInt64BE(this: Buffer, offset: number = 0) { @@ -1217,114 +1180,106 @@ Buffer.prototype.readBigInt64BE = function readBigInt64BE(this: Buffer, offset: if (first === undefined || last === undefined) { boundsError(offset, this.length - 8); } - const val = - (first << 24) + this[++offset]! * 2 ** 16 + this[++offset]! * 2 ** 8 + this[++offset]!; - return ( - (BigInt(val) << BigInt(32)) + + const val = (first << 24) + this[++offset]! * 2 ** 16 + + this[++offset]! * 2 ** 8 + this[++offset]!; + return (BigInt(val) << BigInt(32)) + BigInt( - this[++offset]! * 2 ** 24 + this[++offset]! * 2 ** 16 + this[++offset]! * 2 ** 8 + last - ) - ); + this[++offset]! * 2 ** 24 + this[++offset]! * 2 ** 16 + + this[++offset]! * 2 ** 8 + last, + ); }; Buffer.prototype.readFloatLE = function readFloatLE(offset: number = 0) { - return bigEndian ? readFloatBackwards(this, offset) : readFloatForwards(this, offset); + return bigEndian + ? readFloatBackwards(this, offset) + : readFloatForwards(this, offset); }; Buffer.prototype.readFloatBE = function readFloatBE(offset: number = 0) { - return bigEndian ? readFloatForwards(this, offset) : readFloatBackwards(this, offset); + return bigEndian + ? readFloatForwards(this, offset) + : readFloatBackwards(this, offset); }; Buffer.prototype.readDoubleLE = function readDoubleLE(offset: number = 0) { - return bigEndian ? readDoubleBackwards(this, offset) : readDoubleForwards(this, offset); + return bigEndian + ? readDoubleBackwards(this, offset) + : readDoubleForwards(this, offset); }; Buffer.prototype.readDoubleBE = function readDoubleBE(offset: number = 0) { - return bigEndian ? readDoubleForwards(this, offset) : readDoubleBackwards(this, offset); -}; - -Buffer.prototype.writeUintLE = Buffer.prototype.writeUIntLE = function writeUIntLE( - value: number, - offset: number, - byteLength: number -) { - switch (byteLength) { - case 1: - return writeU_Int8(this, value, offset, 0, 0xff); - case 2: - return writeU_Int16LE(this, value, offset, 0, 0xffff); - case 3: - return writeU_Int24LE(this, value, offset, 0, 0xffffff); - case 4: - return writeU_Int32LE(this, value, offset, 0, 0xffffffff); - case 5: - return writeU_Int40LE(this, value, offset, 0, 0xffffffffff); - case 6: - return writeU_Int48LE(this, value, offset, 0, 0xffffffffffff); - default: - boundsError(byteLength, 6, "byteLength"); - } -}; - -Buffer.prototype.writeUintBE = Buffer.prototype.writeUIntBE = function writeUIntBE( - value: number, - offset: number, - byteLength: number -) { - switch (byteLength) { - case 1: - return writeU_Int8(this, value, offset, 0, 0xff); - case 2: - return writeU_Int16BE(this, value, offset, 0, 0xffff); - case 3: - return writeU_Int24BE(this, value, offset, 0, 0xffffff); - case 4: - return writeU_Int32BE(this, value, offset, 0, 0xffffffff); - case 5: - return writeU_Int40BE(this, value, offset, 0, 0xffffffffff); - case 6: - return writeU_Int48BE(this, value, offset, 0, 0xffffffffffff); - default: - boundsError(byteLength, 6, "byteLength"); - } -}; + return bigEndian + ? readDoubleForwards(this, offset) + : readDoubleBackwards(this, offset); +}; + +Buffer.prototype.writeUintLE = + Buffer.prototype.writeUIntLE = + function writeUIntLE(value: number, offset: number, byteLength: number) { + switch (byteLength) { + case 1: return writeU_Int8(this, value, offset, 0, 0xff); + case 2: return writeU_Int16LE(this, value, offset, 0, 0xffff); + case 3: return writeU_Int24LE(this, value, offset, 0, 0xffffff); + case 4: return writeU_Int32LE(this, value, offset, 0, 0xffffffff); + case 5: return writeU_Int40LE(this, value, offset, 0, 0xffffffffff); + case 6: return writeU_Int48LE(this, value, offset, 0, 0xffffffffffff); + default: + boundsError(byteLength, 6, "byteLength"); + } + }; + +Buffer.prototype.writeUintBE = + Buffer.prototype.writeUIntBE = + function writeUIntBE(value: number, offset: number, byteLength: number) { + switch (byteLength) { + case 1: return writeU_Int8(this, value, offset, 0, 0xff); + case 2: return writeU_Int16BE(this, value, offset, 0, 0xffff); + case 3: return writeU_Int24BE(this, value, offset, 0, 0xffffff); + case 4: return writeU_Int32BE(this, value, offset, 0, 0xffffffff); + case 5: return writeU_Int40BE(this, value, offset, 0, 0xffffffffff); + case 6: return writeU_Int48BE(this, value, offset, 0, 0xffffffffffff); + default: + boundsError(byteLength, 6, "byteLength"); + } + }; Buffer.prototype.writeUint8 = Buffer.prototype.writeUInt8 = function writeUInt8( value: number, - offset: number = 0 + offset: number = 0, ) { return writeU_Int8(this, value, offset, 0, 0xff); }; -Buffer.prototype.writeUint16LE = Buffer.prototype.writeUInt16LE = function writeUInt16LE( - value: number, - offset: number = 0 -) { - return writeU_Int16LE(this, value, offset, 0, 0xffff); -}; +Buffer.prototype.writeUint16LE = + Buffer.prototype.writeUInt16LE = + function writeUInt16LE(value: number, offset: number = 0) { + return writeU_Int16LE(this, value, offset, 0, 0xffff); + }; -Buffer.prototype.writeUint16BE = Buffer.prototype.writeUInt16BE = function writeUInt16BE( - value: number, - offset: number = 0 -) { - return writeU_Int16BE(this, value, offset, 0, 0xffff); -}; +Buffer.prototype.writeUint16BE = + Buffer.prototype.writeUInt16BE = + function writeUInt16BE(value: number, offset: number = 0) { + return writeU_Int16BE(this, value, offset, 0, 0xffff); + }; -Buffer.prototype.writeUint32LE = Buffer.prototype.writeUInt32LE = function writeUInt32LE( - value: number, - offset: number = 0 -) { - return _writeUInt32LE(this, value, offset, 0, 0xffffffff); -}; +Buffer.prototype.writeUint32LE = + Buffer.prototype.writeUInt32LE = + function writeUInt32LE(value: number, offset: number = 0) { + return _writeUInt32LE(this, value, offset, 0, 0xffffffff); + }; -Buffer.prototype.writeUint32BE = Buffer.prototype.writeUInt32BE = function writeUInt32BE( - value: number, - offset: number = 0 -) { - return _writeUInt32BE(this, value, offset, 0, 0xffffffff); -}; +Buffer.prototype.writeUint32BE = + Buffer.prototype.writeUInt32BE = + function writeUInt32BE(value: number, offset: number = 0) { + return _writeUInt32BE(this, value, offset, 0, 0xffffffff); + }; -function wrtBigUInt64LE(buf: Buffer, value: bigint, offset: number, min: bigint, max: bigint) { +function wrtBigUInt64LE( + buf: Buffer, + value: bigint, + offset: number, + min: bigint, + max: bigint) { checkIntBI(value, min, max, buf, offset, 7); let lo = Number(value & BigInt(4294967295)); buf[offset++] = lo; @@ -1334,7 +1289,7 @@ function wrtBigUInt64LE(buf: Buffer, value: bigint, offset: number, min: bigint, buf[offset++] = lo; lo = lo >> 8; buf[offset++] = lo; - let hi = Number((value >> BigInt(32)) & BigInt(4294967295)); + let hi = Number(value >> BigInt(32) & BigInt(4294967295)); buf[offset++] = hi; hi = hi >> 8; buf[offset++] = hi; @@ -1345,7 +1300,12 @@ function wrtBigUInt64LE(buf: Buffer, value: bigint, offset: number, min: bigint, return offset; } -function wrtBigUInt64BE(buf: Buffer, value: bigint, offset: number, min: bigint, max: bigint) { +function wrtBigUInt64BE( + buf: Buffer, + value: bigint, + offset: number, + min: bigint, + max: bigint) { checkIntBI(value, min, max, buf, offset, 7); let lo = Number(value & BigInt(4294967295)); buf[offset + 7] = lo; @@ -1355,7 +1315,7 @@ function wrtBigUInt64BE(buf: Buffer, value: bigint, offset: number, min: bigint, buf[offset + 5] = lo; lo = lo >> 8; buf[offset + 4] = lo; - let hi = Number((value >> BigInt(32)) & BigInt(4294967295)); + let hi = Number(value >> BigInt(32) & BigInt(4294967295)); buf[offset + 3] = hi; hi = hi >> 8; buf[offset + 2] = hi; @@ -1366,40 +1326,29 @@ function wrtBigUInt64BE(buf: Buffer, value: bigint, offset: number, min: bigint, return offset + 8; } -Buffer.prototype.writeBigUint64LE = Buffer.prototype.writeBigUInt64LE = function writeBigUInt64LE( - this: Buffer, - value: bigint, - offset: number = 0 -) { - return wrtBigUInt64LE(this, value, offset, 0n, 0xffffffffffffffffn); -}; +Buffer.prototype.writeBigUint64LE = + Buffer.prototype.writeBigUInt64LE = + function writeBigUInt64LE(this: Buffer, value: bigint, offset: number = 0) { + return wrtBigUInt64LE(this, value, offset, 0n, 0xffffffffffffffffn); + }; -Buffer.prototype.writeBigUint64BE = Buffer.prototype.writeBigUInt64BE = function writeBigUInt64BE( - this: Buffer, - value: bigint, - offset: number = 0 -) { - return wrtBigUInt64BE(this, value, offset, 0n, 0xffffffffffffffffn); -}; +Buffer.prototype.writeBigUint64BE = + Buffer.prototype.writeBigUInt64BE = + function writeBigUInt64BE(this: Buffer, value: bigint, offset: number = 0) { + return wrtBigUInt64BE(this, value, offset, 0n, 0xffffffffffffffffn); + }; Buffer.prototype.writeIntLE = function writeIntLE( value: number, offset: number, - byteLength: number -) { - switch (byteLength) { - case 1: - return writeU_Int8(this, value, offset, -0x80, 0x7f); - case 2: - return writeU_Int16LE(this, value, offset, -0x8000, 0x7fff); - case 3: - return writeU_Int24LE(this, value, offset, -0x800000, 0x7fffff); - case 4: - return writeU_Int32LE(this, value, offset, -0x80000000, 0x7fffffff); - case 5: - return writeU_Int40LE(this, value, offset, -0x8000000000, 0x7fffffffff); - case 6: - return writeU_Int48LE(this, value, offset, -0x800000000000, 0x7fffffffffff); + byteLength: number) { + switch(byteLength) { + case 1: return writeU_Int8(this, value, offset, -0x80, 0x7f); + case 2: return writeU_Int16LE(this, value, offset, -0x8000, 0x7fff); + case 3: return writeU_Int24LE(this, value, offset, -0x800000, 0x7fffff); + case 4: return writeU_Int32LE(this, value, offset, -0x80000000, 0x7fffffff); + case 5: return writeU_Int40LE(this, value, offset, -0x8000000000, 0x7fffffffff); + case 6: return writeU_Int48LE(this, value, offset, -0x800000000000, 0x7fffffffffff); default: boundsError(byteLength, 6, "byteLength"); } @@ -1408,21 +1357,14 @@ Buffer.prototype.writeIntLE = function writeIntLE( Buffer.prototype.writeIntBE = function writeIntBE( value: number, offset: number, - byteLength: number -) { - switch (byteLength) { - case 1: - return writeU_Int8(this, value, offset, -0x80, 0x7f); - case 2: - return writeU_Int16BE(this, value, offset, -0x8000, 0x7fff); - case 3: - return writeU_Int24BE(this, value, offset, -0x800000, 0x7fffff); - case 4: - return writeU_Int32BE(this, value, offset, -0x80000000, 0x7fffffff); - case 5: - return writeU_Int40BE(this, value, offset, -0x8000000000, 0x7fffffffff); - case 6: - return writeU_Int48BE(this, value, offset, -0x800000000000, 0x7fffffffffff); + byteLength: number) { + switch(byteLength) { + case 1: return writeU_Int8(this, value, offset, -0x80, 0x7f); + case 2: return writeU_Int16BE(this, value, offset, -0x8000, 0x7fff); + case 3: return writeU_Int24BE(this, value, offset, -0x800000, 0x7fffff); + case 4: return writeU_Int32BE(this, value, offset, -0x80000000, 0x7fffffff); + case 5: return writeU_Int40BE(this, value, offset, -0x8000000000, 0x7fffffffff); + case 6: return writeU_Int48BE(this, value, offset, -0x800000000000, 0x7fffffffffff); default: boundsError(byteLength, 6, "byteLength"); } @@ -1436,7 +1378,10 @@ Buffer.prototype.writeInt16LE = function writeInt16LE(value: number, offset: num return writeU_Int16LE(this, value, offset, -0x8000, 0x7fff); }; -Buffer.prototype.writeInt16BE = function writeInt16BE(value: number, offset: number = 0) { +Buffer.prototype.writeInt16BE = function writeInt16BE( + value: number, + offset: number = 0, +) { return writeU_Int16BE(this, value, offset, -0x8000, 0x7fff); }; @@ -1448,51 +1393,57 @@ Buffer.prototype.writeInt32BE = function writeInt32BE(value: number, offset: num return writeU_Int32BE(this, value, offset, -0x80000000, 0x7fffffff); }; -Buffer.prototype.writeBigInt64LE = function writeBigInt64LE( - this: Buffer, - value: bigint, - offset: number = 0 -) { - return wrtBigUInt64LE(this, value, offset, -0x8000000000000000n, 0x7fffffffffffffffn); -}; +Buffer.prototype.writeBigInt64LE = + function writeBigInt64LE(this: Buffer, value: bigint, offset: number = 0) { + return wrtBigUInt64LE(this, value, offset, -0x8000000000000000n, 0x7fffffffffffffffn); + }; -Buffer.prototype.writeBigInt64BE = function writeBigInt64BE( - this: Buffer, - value: bigint, - offset: number = 0 -) { - return wrtBigUInt64BE(this, value, offset, -0x8000000000000000n, 0x7fffffffffffffffn); -}; +Buffer.prototype.writeBigInt64BE = + function writeBigInt64BE(this: Buffer, value: bigint, offset: number = 0) { + return wrtBigUInt64BE(this, value, offset, -0x8000000000000000n, 0x7fffffffffffffffn); + }; -Buffer.prototype.writeFloatLE = function writeFloatLE(value: number, offset: number) { +Buffer.prototype.writeFloatLE = function writeFloatLE( + value: number, + offset: number, +) { return bigEndian ? writeFloatBackwards(this, value, offset) : writeFloatForwards(this, value, offset); }; -Buffer.prototype.writeFloatBE = function writeFloatBE(value: number, offset: number) { +Buffer.prototype.writeFloatBE = function writeFloatBE( + value: number, + offset: number, +) { return bigEndian ? writeFloatForwards(this, value, offset) : writeFloatBackwards(this, value, offset); }; -Buffer.prototype.writeDoubleLE = function writeDoubleLE(value: number, offset: number) { +Buffer.prototype.writeDoubleLE = function writeDoubleLE( + value: number, + offset: number, +) { return bigEndian ? writeDoubleBackwards(this, value, offset) : writeDoubleForwards(this, value, offset); }; -Buffer.prototype.writeDoubleBE = function writeDoubleBE(value: number, offset: number) { +Buffer.prototype.writeDoubleBE = function writeDoubleBE( + value: number, + offset: number, +) { return bigEndian ? writeDoubleForwards(this, value, offset) : writeDoubleBackwards(this, value, offset); }; Buffer.prototype.copy = function copy( - target: Buffer | Uint8Array, + target: Buffer|Uint8Array, targetStart?: number, sourceStart?: number, - sourceEnd?: number + sourceEnd?: number, ) { if (!isUint8Array(target)) { throw new ERR_INVALID_ARG_TYPE("target", ["Buffer", "Uint8Array"], target); @@ -1554,12 +1505,11 @@ Buffer.prototype.copy = function copy( }; Buffer.prototype.fill = function fill( - val: string | number | Buffer | Uint8Array, - start?: number | string, + val: string|number|Buffer|Uint8Array, + start?: number|string, end?: number, - encoding?: string -) { - let normalizedEncoding: string | undefined; + encoding?: string) { + let normalizedEncoding : string | undefined; if (typeof val === "string") { if (typeof start === "string") { encoding = start; @@ -1575,24 +1525,24 @@ Buffer.prototype.fill = function fill( } if (val.length === 1) { const code = val.charCodeAt(0); - if ((encoding === "utf8" && code < 128) || encoding === "latin1") { + if (encoding === "utf8" && code < 128 || encoding === "latin1") { val = code; } } } if (start !== undefined) { - validateNumber(start, "start"); + validateNumber(start, 'start'); } if (end !== undefined) { - validateNumber(end, "end"); + validateNumber(end, 'end'); } if ((end as number) < 0 || (end as number) > this.length) { - throw new ERR_OUT_OF_RANGE("end", `0 to ${this.length}`, end); + throw new ERR_OUT_OF_RANGE('end', `0 to ${this.length}`, end); } if ((start as number) < 0 || this.length < (start as number) || this.length < (end as number)) { - throw new ERR_OUT_OF_RANGE("start", "0 to end", start); + throw new ERR_OUT_OF_RANGE('start', '0 to end', start); } if ((end as number) <= (start as number)) { return this; @@ -1601,19 +1551,17 @@ Buffer.prototype.fill = function fill( end = end === void 0 ? this.length : end >>> 0; if (typeof val === "string") { - bufferUtil.fillImpl( - this, + bufferUtil.fillImpl(this, val as string, start as number, end as number, - normalizedEncoding - ); + normalizedEncoding); return this; } if (isArrayBufferView(val)) { if ((val as ArrayBufferView).byteLength === 0) { - throw new ERR_INVALID_ARG_VALUE("value", "zero-length"); + throw new ERR_INVALID_ARG_VALUE('value', 'zero-length'); } bufferUtil.fillImpl(this, val as ArrayBufferView, start as number, end as number); return this; @@ -1631,7 +1579,10 @@ Buffer.prototype.fill = function fill( return this; }; -function checkBounds(buf: Buffer, offset: number, byteLength2: number) { +function checkBounds( + buf: Buffer, + offset: number, + byteLength2: number) { validateOffset(offset, "offset", 0, buf.length); if (buf[offset] === undefined || buf[offset + byteLength2] === undefined) { boundsError(offset, buf.length - (byteLength2 + 1)); @@ -1639,13 +1590,12 @@ function checkBounds(buf: Buffer, offset: number, byteLength2: number) { } function checkIntBI( - value: bigint | number, - min: bigint | number, - max: bigint | number, + value: bigint|number, + min: bigint|number, + max: bigint|number, buf: Buffer, offset: number, - byteLength2: number -) { + byteLength2: number) { if (value > max || value < min) { const n = typeof min === "bigint" ? "n" : ""; let range; @@ -1666,16 +1616,13 @@ function checkIntBI( } export function isInstance(obj: unknown, type: Function) { - return ( - obj instanceof type || - (obj != null && - obj.constructor != null && - obj.constructor.name != null && - obj.constructor.name === type.name) - ); + return obj instanceof type || + obj != null && obj.constructor != null && + obj.constructor.name != null && obj.constructor.name === type.name; } -function readUInt48LE(buf: Buffer | Uint8Array, offset: number = 0) { + +function readUInt48LE(buf: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buf.length); const first = buf[offset]; const last = buf[offset + 5]; @@ -1683,16 +1630,14 @@ function readUInt48LE(buf: Buffer | Uint8Array, offset: number = 0) { boundsError(offset, buf.length - 6); } - return ( - first + + return first + buf[++offset]! * 2 ** 8 + buf[++offset]! * 2 ** 16 + buf[++offset]! * 2 ** 24 + - (buf[++offset]! + last * 2 ** 8) * 2 ** 32 - ); + (buf[++offset]! + last * 2 ** 8) * 2 ** 32; } -function readUInt40LE(buf: Buffer | Uint8Array, offset: number = 0) { +function readUInt40LE(buf: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buf.length); const first = buf[offset]; const last = buf[offset + 4]; @@ -1700,16 +1645,14 @@ function readUInt40LE(buf: Buffer | Uint8Array, offset: number = 0) { boundsError(offset, buf.length - 5); } - return ( - first + + return first + buf[++offset]! * 2 ** 8 + buf[++offset]! * 2 ** 16 + buf[++offset]! * 2 ** 24 + - last * 2 ** 32 - ); + last * 2 ** 32; } -function readUInt24LE(buf: Buffer | Uint8Array, offset: number = 0) { +function readUInt24LE(buf: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buf.length); const first = buf[offset]; const last = buf[offset + 2]; @@ -1720,7 +1663,7 @@ function readUInt24LE(buf: Buffer | Uint8Array, offset: number = 0) { return first + buf[++offset]! * 2 ** 8 + last * 2 ** 16; } -function readUInt48BE(buf: Buffer | Uint8Array, offset: number = 0) { +function readUInt48BE(buf: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buf.length); const first = buf[offset]; const last = buf[offset + 5]; @@ -1728,16 +1671,14 @@ function readUInt48BE(buf: Buffer | Uint8Array, offset: number = 0) { boundsError(offset, buf.length - 6); } - return ( - (first * 2 ** 8 + buf[++offset]!) * 2 ** 32 + + return (first * 2 ** 8 + buf[++offset]!) * 2 ** 32 + buf[++offset]! * 2 ** 24 + buf[++offset]! * 2 ** 16 + buf[++offset]! * 2 ** 8 + - last - ); + last; } -function readUInt40BE(buf: Buffer | Uint8Array, offset: number = 0) { +function readUInt40BE(buf: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buf.length); const first = buf[offset]; const last = buf[offset + 4]; @@ -1745,16 +1686,14 @@ function readUInt40BE(buf: Buffer | Uint8Array, offset: number = 0) { boundsError(offset, buf.length - 5); } - return ( - first * 2 ** 32 + + return first * 2 ** 32 + buf[++offset]! * 2 ** 24 + buf[++offset]! * 2 ** 16 + buf[++offset]! * 2 ** 8 + - last - ); + last; } -function readUInt24BE(buf: Buffer | Uint8Array, offset: number = 0) { +function readUInt24BE(buf: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buf.length); const first = buf[offset]; const last = buf[offset + 2]; @@ -1784,10 +1723,13 @@ function readUInt32BE(this: Buffer, offset: number = 0) { boundsError(offset, this.length - 4); } - return first * 2 ** 24 + this[++offset]! * 2 ** 16 + this[++offset]! * 2 ** 8 + last; + return first * 2 ** 24 + + this[++offset]! * 2 ** 16 + + this[++offset]! * 2 ** 8 + + last; } -function readDoubleBackwards(buffer: Buffer | Uint8Array, offset: number = 0) { +function readDoubleBackwards(buffer: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buffer.length); const first = buffer[offset]; const last = buffer[offset + 7]; @@ -1806,7 +1748,7 @@ function readDoubleBackwards(buffer: Buffer | Uint8Array, offset: number = 0) { return float64Array[0]; } -function readDoubleForwards(buffer: Buffer | Uint8Array, offset: number = 0) { +function readDoubleForwards(buffer: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buffer.length); const first = buffer[offset]; const last = buffer[offset + 7]; @@ -1825,7 +1767,7 @@ function readDoubleForwards(buffer: Buffer | Uint8Array, offset: number = 0) { return float64Array[0]; } -function writeDoubleForwards(buffer: Buffer | Uint8Array, val: number, offset: number = 0) { +function writeDoubleForwards(buffer: Buffer|Uint8Array, val: number, offset: number = 0) { val = +val; checkBounds(buffer as any, offset, 7); @@ -1841,7 +1783,7 @@ function writeDoubleForwards(buffer: Buffer | Uint8Array, val: number, offset: n return offset; } -function writeDoubleBackwards(buffer: Buffer | Uint8Array, val: number, offset: number = 0) { +function writeDoubleBackwards(buffer: Buffer|Uint8Array, val: number, offset: number = 0) { val = +val; checkBounds(buffer as any, offset, 7); @@ -1857,7 +1799,7 @@ function writeDoubleBackwards(buffer: Buffer | Uint8Array, val: number, offset: return offset; } -function readFloatBackwards(buffer: Buffer | Uint8Array, offset: number = 0) { +function readFloatBackwards(buffer: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buffer.length); const first = buffer[offset]; const last = buffer[offset + 3]; @@ -1872,7 +1814,7 @@ function readFloatBackwards(buffer: Buffer | Uint8Array, offset: number = 0) { return float32Array[0]; } -function readFloatForwards(buffer: Buffer | Uint8Array, offset: number = 0) { +function readFloatForwards(buffer: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buffer.length); const first = buffer[offset]; const last = buffer[offset + 3]; @@ -1887,7 +1829,7 @@ function readFloatForwards(buffer: Buffer | Uint8Array, offset: number = 0) { return float32Array[0]; } -function writeFloatForwards(buffer: Buffer | Uint8Array, val: number, offset: number = 0) { +function writeFloatForwards(buffer: Buffer|Uint8Array, val: number, offset: number = 0) { val = +val; checkBounds(buffer as any, offset, 3); @@ -1899,7 +1841,7 @@ function writeFloatForwards(buffer: Buffer | Uint8Array, val: number, offset: nu return offset; } -function writeFloatBackwards(buffer: Buffer | Uint8Array, val: number, offset: number = 0) { +function writeFloatBackwards(buffer: Buffer|Uint8Array, val: number, offset: number = 0) { val = +val; checkBounds(buffer as any, offset, 3); @@ -1911,7 +1853,7 @@ function writeFloatBackwards(buffer: Buffer | Uint8Array, val: number, offset: n return offset; } -function readInt24LE(buf: Buffer | Uint8Array, offset: number = 0) { +function readInt24LE(buf: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buf.length); const first = buf[offset]; const last = buf[offset + 2]; @@ -1920,10 +1862,10 @@ function readInt24LE(buf: Buffer | Uint8Array, offset: number = 0) { } const val = first + buf[++offset]! * 2 ** 8 + last * 2 ** 16; - return val | ((val & (2 ** 23)) * 0x1fe); + return val | (val & 2 ** 23) * 0x1fe; } -function readInt40LE(buf: Buffer | Uint8Array, offset: number = 0) { +function readInt40LE(buf: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buf.length); const first = buf[offset]; const last = buf[offset + 4]; @@ -1931,16 +1873,14 @@ function readInt40LE(buf: Buffer | Uint8Array, offset: number = 0) { boundsError(offset, buf.length - 5); } - return ( - (last | ((last & (2 ** 7)) * 0x1fffffe)) * 2 ** 32 + + return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 + first + buf[++offset]! * 2 ** 8 + buf[++offset]! * 2 ** 16 + - buf[++offset]! * 2 ** 24 - ); + buf[++offset]! * 2 ** 24; } -function readInt48LE(buf: Buffer | Uint8Array, offset: number = 0) { +function readInt48LE(buf: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buf.length); const first = buf[offset]; const last = buf[offset + 5]; @@ -1949,16 +1889,14 @@ function readInt48LE(buf: Buffer | Uint8Array, offset: number = 0) { } const val = buf[offset + 4]! + last * 2 ** 8; - return ( - (val | ((val & (2 ** 15)) * 0x1fffe)) * 2 ** 32 + + return (val | (val & 2 ** 15) * 0x1fffe) * 2 ** 32 + first + buf[++offset]! * 2 ** 8 + buf[++offset]! * 2 ** 16 + - buf[++offset]! * 2 ** 24 - ); + buf[++offset]! * 2 ** 24; } -function readInt24BE(buf: Buffer | Uint8Array, offset: number = 0) { +function readInt24BE(buf: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buf.length); const first = buf[offset]; const last = buf[offset + 2]; @@ -1967,10 +1905,10 @@ function readInt24BE(buf: Buffer | Uint8Array, offset: number = 0) { } const val = first * 2 ** 16 + buf[++offset]! * 2 ** 8 + last; - return val | ((val & (2 ** 23)) * 0x1fe); + return val | (val & 2 ** 23) * 0x1fe; } -function readInt48BE(buf: Buffer | Uint8Array, offset: number = 0) { +function readInt48BE(buf: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buf.length); const first = buf[offset]; const last = buf[offset + 5]; @@ -1979,16 +1917,14 @@ function readInt48BE(buf: Buffer | Uint8Array, offset: number = 0) { } const val = buf[++offset]! + first * 2 ** 8; - return ( - (val | ((val & (2 ** 15)) * 0x1fffe)) * 2 ** 32 + + return (val | (val & 2 ** 15) * 0x1fffe) * 2 ** 32 + buf[++offset]! * 2 ** 24 + buf[++offset]! * 2 ** 16 + buf[++offset]! * 2 ** 8 + - last - ); + last; } -function readInt40BE(buf: Buffer | Uint8Array, offset: number = 0) { +function readInt40BE(buf: Buffer|Uint8Array, offset: number = 0) { validateOffset(offset, "offset", 0, buf.length); const first = buf[offset]; const last = buf[offset + 4]; @@ -1996,16 +1932,14 @@ function readInt40BE(buf: Buffer | Uint8Array, offset: number = 0) { boundsError(offset, buf.length - 5); } - return ( - (first | ((first & (2 ** 7)) * 0x1fffffe)) * 2 ** 32 + + return (first | (first & 2 ** 7) * 0x1fffffe) * 2 ** 32 + buf[++offset]! * 2 ** 24 + buf[++offset]! * 2 ** 16 + buf[++offset]! * 2 ** 8 + - last - ); + last; } -function boundsError(value: number, length: number, type?: string): never { +function boundsError(value: number, length: number, type?: string) : never { if (Math.floor(value) !== value) { throw new ERR_OUT_OF_RANGE(type || "offset", "an integer", value); } @@ -2014,7 +1948,11 @@ function boundsError(value: number, length: number, type?: string): never { throw new ERR_BUFFER_OUT_OF_BOUNDS(); } - throw new ERR_OUT_OF_RANGE(type || "offset", `>= ${type ? 1 : 0} and <= ${length}`, value); + throw new ERR_OUT_OF_RANGE( + type || "offset", + `>= ${type ? 1 : 0} and <= ${length}`, + value, + ); } function validateNumber(value: unknown, name: string) { @@ -2024,13 +1962,12 @@ function validateNumber(value: unknown, name: string) { } function checkInt( - value: number | bigint, - min: number | bigint, - max: number | bigint, + value: number|bigint, + min: number|bigint, + max: number|bigint, buf: Buffer, offset: number, - byteLength: number -) { + byteLength: number) { if (value > max || value < min) { const n = typeof min === "bigint" ? "n" : ""; let range; @@ -2038,8 +1975,7 @@ function checkInt( if (min === 0 || min === 0n) { range = `>= 0${n} and < 2${n} ** ${(byteLength + 1) * 8}${n}`; } else { - range = - `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and ` + + range = `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and ` + `< 2${n} ** ${(byteLength + 1) * 8 - 1}${n}`; } } else { @@ -2050,16 +1986,25 @@ function checkInt( checkBounds(buf, offset, byteLength); } -function toInteger(n: number | undefined, defaultVal: number) { +function toInteger(n: number|undefined, defaultVal: number) { if (n === undefined) n = 0; n = +(n as number); - if (!Number.isNaN(n) && n >= Number.MIN_SAFE_INTEGER && n <= Number.MAX_SAFE_INTEGER) { - return n % 1 === 0 ? n : Math.floor(n); + if ( + !Number.isNaN(n) && + n >= Number.MIN_SAFE_INTEGER && + n <= Number.MAX_SAFE_INTEGER + ) { + return ((n % 1) === 0 ? n : Math.floor(n)); } return defaultVal; } -function writeU_Int8(buf: Buffer, value: number, offset: number, min: number, max: number) { +function writeU_Int8( + buf: Buffer, + value: number, + offset: number, + min: number, + max: number) { value = +value; validateOffset(offset, "offset", 0, buf.length); if (value > max || value < min) { @@ -2073,7 +2018,12 @@ function writeU_Int8(buf: Buffer, value: number, offset: number, min: number, ma return offset + 1; } -function writeU_Int16BE(buf: Buffer, value: number, offset: number, min: number, max: number) { +function writeU_Int16BE( + buf: Buffer, + value: number, + offset: number, + min: number, + max: number) { value = +value; validateOffset(offset, "offset", 0, buf.length); checkInt(value, min, max, buf, offset, 1); @@ -2083,7 +2033,12 @@ function writeU_Int16BE(buf: Buffer, value: number, offset: number, min: number, return offset; } -function _writeUInt32LE(buf: Buffer, value: number, offset: number, min: number, max: number) { +function _writeUInt32LE( + buf: Buffer, + value: number, + offset: number, + min: number, + max: number) { value = +value; validateOffset(offset, "offset", 0, buf.length); checkInt(value, min, max, buf, offset, 3); @@ -2098,7 +2053,12 @@ function _writeUInt32LE(buf: Buffer, value: number, offset: number, min: number, return offset; } -function writeU_Int16LE(buf: Buffer, value: number, offset: number, min: number, max: number) { +function writeU_Int16LE( + buf: Buffer, + value: number, + offset: number, + min: number, + max: number) { value = +value; validateOffset(offset, "offset", 0, buf.length); checkInt(value, min, max, buf, offset, 1); @@ -2108,7 +2068,12 @@ function writeU_Int16LE(buf: Buffer, value: number, offset: number, min: number, return offset; } -function _writeUInt32BE(buf: Buffer, value: number, offset: number, min: number, max: number) { +function _writeUInt32BE( + buf: Buffer, + value: number, + offset: number, + min: number, + max: number) { value = +value; validateOffset(offset, "offset", 0, buf.length); checkInt(value, min, max, buf, offset, 3); @@ -2123,7 +2088,12 @@ function _writeUInt32BE(buf: Buffer, value: number, offset: number, min: number, return offset + 4; } -function writeU_Int48BE(buf: Buffer, value: number, offset: number, min: number, max: number) { +function writeU_Int48BE( + buf: Buffer, + value: number, + offset: number, + min: number, + max: number) { value = +value; validateOffset(offset, "offset", 0, buf.length); checkInt(value, min, max, buf, offset, 5); @@ -2141,7 +2111,12 @@ function writeU_Int48BE(buf: Buffer, value: number, offset: number, min: number, return offset + 4; } -function writeU_Int40BE(buf: Buffer, value: number, offset: number, min: number, max: number) { +function writeU_Int40BE( + buf: Buffer, + value: number, + offset: number, + min: number, + max: number) { value = +value; validateOffset(offset, "offset", 0, buf.length); checkInt(value, min, max, buf, offset, 4); @@ -2157,7 +2132,12 @@ function writeU_Int40BE(buf: Buffer, value: number, offset: number, min: number, return offset + 4; } -function writeU_Int32BE(buf: Buffer, value: number, offset: number, min: number, max: number) { +function writeU_Int32BE( + buf: Buffer, + value: number, + offset: number, + min: number, + max: number) { value = +value; validateOffset(offset, "offset", 0, buf.length); checkInt(value, min, max, buf, offset, 3); @@ -2172,7 +2152,12 @@ function writeU_Int32BE(buf: Buffer, value: number, offset: number, min: number, return offset + 4; } -function writeU_Int24BE(buf: Buffer, value: number, offset: number, min: number, max: number) { +function writeU_Int24BE( + buf: Buffer, + value: number, + offset: number, + min: number, + max: number) { value = +value; validateOffset(offset, "offset", 0, buf.length); checkInt(value, min, max, buf, offset, 2); @@ -2189,7 +2174,7 @@ function validateOffset( value: number, name: string, min: number = 0, - max: number = Number.MAX_SAFE_INTEGER + max: number = Number.MAX_SAFE_INTEGER, ) { if (typeof value !== "number") { throw new ERR_INVALID_ARG_TYPE(name, "number", value); @@ -2202,7 +2187,12 @@ function validateOffset( } } -function writeU_Int48LE(buf: Buffer, value: number, offset: number, min: number, max: number) { +function writeU_Int48LE( + buf: Buffer, + value: number, + offset: number, + min: number, + max: number) { value = +value; validateOffset(offset, "offset", 0, buf.length); checkInt(value, min, max, buf, offset, 5); @@ -2220,7 +2210,12 @@ function writeU_Int48LE(buf: Buffer, value: number, offset: number, min: number, return offset; } -function writeU_Int40LE(buf: Buffer, value: number, offset: number, min: number, max: number) { +function writeU_Int40LE( + buf: Buffer, + value: number, + offset: number, + min: number, + max: number) { value = +value; validateOffset(offset, "offset", 0, buf.length); checkInt(value, min, max, buf, offset, 4); @@ -2237,7 +2232,12 @@ function writeU_Int40LE(buf: Buffer, value: number, offset: number, min: number, return offset; } -function writeU_Int32LE(buf: Buffer, value: number, offset: number, min: number, max: number) { +function writeU_Int32LE( + buf: Buffer, + value: number, + offset: number, + min: number, + max: number) { value = +value; validateOffset(offset, "offset", 0, buf.length); checkInt(value, min, max, buf, offset, 3); @@ -2252,7 +2252,12 @@ function writeU_Int32LE(buf: Buffer, value: number, offset: number, min: number, return offset; } -function writeU_Int24LE(buf: Buffer, value: number, offset: number, min: number, max: number) { +function writeU_Int24LE( + buf: Buffer, + value: number, + offset: number, + min: number, + max: number) { value = +value; validateOffset(offset, "offset", 0, buf.length); checkInt(value, min, max, buf, offset, 2); diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_errors.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_errors.ts index ab8e66830..5a6b40f0c 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_errors.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_errors.ts @@ -57,7 +57,10 @@ export class NodeTypeError extends NodeErrorAbstraction implements TypeError { } } -function createInvalidArgType(name: string, expected: string | string[]): string { +function createInvalidArgType( + name: string, + expected: string | string[], +): string { // https://github.com/nodejs/node/blob/f3eb224/lib/internal/errors.js#L1037-L1087 expected = Array.isArray(expected) ? expected : [expected]; let msg = "The "; @@ -196,10 +199,7 @@ export class ERR_CRYPTO_INCOMPATIBLE_KEY extends NodeError { export class ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE extends NodeError { constructor(actual: string, expected: string) { - super( - "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE", - `Invalid key object type ${actual}, expected ${expected}.` - ); + super("ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE", `Invalid key object type ${actual}, expected ${expected}.`); } } @@ -226,7 +226,10 @@ export class ERR_INVALID_ARG_VALUE_RANGE extends NodeRangeError { const type = name.includes(".") ? "property" : "argument"; const inspected = inspect(value); - super("ERR_INVALID_ARG_VALUE", `The ${type} '${name}' ${reason}. Received ${inspected}`); + super( + "ERR_INVALID_ARG_VALUE", + `The ${type} '${name}' ${reason}. Received ${inspected}`, + ); } } @@ -235,7 +238,10 @@ export class ERR_INVALID_ARG_VALUE extends NodeTypeError { const type = name.includes(".") ? "property" : "argument"; const inspected = inspect(value); - super("ERR_INVALID_ARG_VALUE", `The ${type} '${name}' ${reason}. Received ${inspected}`); + super( + "ERR_INVALID_ARG_VALUE", + `The ${type} '${name}' ${reason}. Received ${inspected}`, + ); } static RangeError = ERR_INVALID_ARG_VALUE_RANGE; @@ -244,10 +250,16 @@ export class ERR_INVALID_ARG_VALUE extends NodeTypeError { export class ERR_OUT_OF_RANGE extends RangeError { code = "ERR_OUT_OF_RANGE"; - constructor(str: string, range: string, input: unknown, replaceDefaultBoolean = false) { + constructor( + str: string, + range: string, + input: unknown, + replaceDefaultBoolean = false) { // TODO(later): Implement internal assert? // assert(range, 'Missing "range" argument'); - let msg = replaceDefaultBoolean ? str : `The value of "${str}" is out of range.`; + let msg = replaceDefaultBoolean + ? str + : `The value of "${str}" is out of range.`; let received; if (Number.isInteger(input) && Math.abs(input as number) > 2 ** 32) { received = addNumericalSeparator(String(input)); @@ -292,14 +304,17 @@ export class ERR_BUFFER_OUT_OF_BOUNDS extends NodeRangeError { "ERR_BUFFER_OUT_OF_BOUNDS", name ? `"${name}" is outside of buffer bounds` - : "Attempt to access memory outside buffer bounds" + : "Attempt to access memory outside buffer bounds", ); } } export class ERR_INVALID_BUFFER_SIZE extends NodeRangeError { constructor(size: number) { - super("ERR_INVALID_BUFFER_SIZE", `Buffer size must be a multiple of ${size}-bits`); + super( + "ERR_INVALID_BUFFER_SIZE", + `Buffer size must be a multiple of ${size}-bits`, + ); } } @@ -357,9 +372,11 @@ export class ERR_INVALID_RETURN_VALUE extends NodeTypeError { constructor(input: string, name: string, value: unknown) { super( "ERR_INVALID_RETURN_VALUE", - `Expected ${input} to be returned from the "${name}" function but got ${determineSpecificType( - value - )}.` + `Expected ${input} to be returned from the "${name}" function but got ${ + determineSpecificType( + value, + ) + }.`, ); } } @@ -378,7 +395,9 @@ export class ERR_MISSING_ARGS extends NodeTypeError { const wrap = (a: unknown) => `"${a}"`; - args = args.map((a) => (Array.isArray(a) ? a.map(wrap).join(" or ") : wrap(a))); + args = args.map((a) => + Array.isArray(a) ? a.map(wrap).join(" or ") : wrap(a) + ); switch (len) { case 1: @@ -406,8 +425,8 @@ export class ERR_FALSY_VALUE_REJECTION extends NodeError { } export class ERR_METHOD_NOT_IMPLEMENTED extends NodeError { - constructor(name: string | symbol) { - if (typeof name === "symbol") { + constructor(name: string|symbol) { + if (typeof name === 'symbol') { name = (name as symbol).description!; } super("ERR_METHOD_NOT_IMPLEMENTED", `The ${name} method is not implemented`); @@ -420,16 +439,16 @@ export class ERR_STREAM_CANNOT_PIPE extends NodeError { } } export class ERR_STREAM_DESTROYED extends NodeError { - constructor(name: string | symbol) { - if (typeof name === "symbol") { + constructor(name: string|symbol) { + if (typeof name === 'symbol') { name = (name as symbol).description!; } super("ERR_STREAM_DESTROYED", `Cannot call ${name} after a stream was destroyed`); } } export class ERR_STREAM_ALREADY_FINISHED extends NodeError { - constructor(name: string | symbol) { - if (typeof name === "symbol") { + constructor(name: string|symbol) { + if (typeof name === 'symbol') { name = (name as symbol).description!; } super("ERR_STREAM_ALREADY_FINISHED", `Cannot call ${name} after a stream was finished`); @@ -469,5 +488,5 @@ export function aggregateTwoErrors(innerError: any, outerError: any) { (err as any).code = outerError.code; return err; } - return innerError || outerError; + return innerError || outerError } diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_inspect.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_inspect.ts index 4e5c8c797..99ac8ecbd 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_inspect.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_inspect.ts @@ -1,3 +1,4 @@ + import * as internal from "./util"; import { Buffer } from "./internal_buffer"; @@ -34,9 +35,9 @@ import { validateObject, validateString } from "./validators"; function assert(value: boolean, message = "Assertion failed"): asserts value { if (!value) throw new Error(message); } -assert.fail = function (message = "Assertion failed"): never { +assert.fail = function(message = "Assertion failed"): never { throw new Error(message); -}; +} function isError(e: unknown): e is Error { // An error could be an instance of Error while not being a native error @@ -46,28 +47,18 @@ function isError(e: unknown): e is Error { } const typedArrayPrototype = Object.getPrototypeOf(Uint8Array).prototype; -const typedArrayPrototypeLength: (this: internal.TypedArray) => number = - Object.getOwnPropertyDescriptor(typedArrayPrototype, "length")!.get!; -const typedArrayPrototypeToStringTag: (this: internal.TypedArray) => string = - Object.getOwnPropertyDescriptor(typedArrayPrototype, Symbol.toStringTag)!.get!; - -const setPrototypeSize: (this: Set) => number = Object.getOwnPropertyDescriptor( - Set.prototype, - "size" -)!.get!; -const mapPrototypeSize: (this: Map) => number = Object.getOwnPropertyDescriptor( - Map.prototype, - "size" -)!.get!; +const typedArrayPrototypeLength: (this: internal.TypedArray) => number = Object.getOwnPropertyDescriptor(typedArrayPrototype, "length")!.get!; +const typedArrayPrototypeToStringTag: (this: internal.TypedArray) => string = Object.getOwnPropertyDescriptor(typedArrayPrototype, Symbol.toStringTag)!.get!; + +const setPrototypeSize: (this: Set) => number = Object.getOwnPropertyDescriptor(Set.prototype, "size")!.get!; +const mapPrototypeSize: (this: Map) => number = Object.getOwnPropertyDescriptor(Map.prototype, "size")!.get!; let maxStack_ErrorName: string; let maxStack_ErrorMessage: string; function isStackOverflowError(err: Error): boolean { if (maxStack_ErrorMessage === undefined) { try { - function overflowStack() { - overflowStack(); - } + function overflowStack() { overflowStack(); } overflowStack(); } catch (err) { assert(isError(err)); @@ -76,15 +67,16 @@ function isStackOverflowError(err: Error): boolean { } } - return err && err.name === maxStack_ErrorName && err.message === maxStack_ErrorMessage; + return err && err.name === maxStack_ErrorName && + err.message === maxStack_ErrorMessage; } -export const customInspectSymbol = Symbol.for("nodejs.util.inspect.custom"); +export const customInspectSymbol = Symbol.for('nodejs.util.inspect.custom'); const colorRegExp = /\u001b\[\d\d?m/g; function removeColors(str: string): string { - return str.replace(colorRegExp, ""); + return str.replace(colorRegExp, ''); } export interface InspectOptions { @@ -188,11 +180,12 @@ export interface InspectOptionsStylized extends InspectOptions { } const builtInObjects = new Set( - Object.getOwnPropertyNames(globalThis).filter((e) => /^[A-Z][a-zA-Z0-9]+$/.exec(e) !== null) + Object.getOwnPropertyNames(globalThis).filter( + (e) => /^[A-Z][a-zA-Z0-9]+$/.exec(e) !== null) ); // https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot -const isUndetectableObject = (v: unknown): boolean => typeof v === "undefined" && v !== undefined; +const isUndetectableObject = (v: unknown): boolean => typeof v === 'undefined' && v !== undefined; // These options must stay in sync with `getUserOptions`. So if any option will // be added or removed, `getUserOptions` must also be updated accordingly. @@ -215,14 +208,10 @@ const kObjectType = 0; const kArrayType = 1; const kArrayExtrasType = 2; -const strEscapeSequencesRegExp = - /[\x00-\x1f\x27\x5c\x7f-\x9f]|[\ud800-\udbff](?![\udc00-\udfff])|(?<~]))"; -const ansi = new RegExp(ansiPattern, "g"); +const ansiPattern = '[\\u001B\\u009B][[\\]()#;?]*' + + '(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*' + + '|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)' + + '|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'; +const ansi = new RegExp(ansiPattern, 'g'); interface Context extends Required { maxArrayLength: number; @@ -452,11 +294,9 @@ function getUserOptions(ctx: Context, isCrossContext: boolean): InspectOptionsSt // and remove all other non-primitives, including non-primitive user options. if (isCrossContext) { Object.setPrototypeOf(ret, null); - for (const key of Object.keys(ret) as (keyof InspectOptionsStylized)[]) { - if ( - (typeof ret[key] === "object" || typeof ret[key] === "function") && - ret[key] !== null - ) { + for (const key of (Object.keys(ret) as (keyof InspectOptionsStylized)[])) { + if ((typeof ret[key] === 'object' || typeof ret[key] === 'function') && + ret[key] !== null) { delete ret[key]; } } @@ -468,7 +308,7 @@ function getUserOptions(ctx: Context, isCrossContext: boolean): InspectOptionsSt // Continue regardless of error. } - if (typeof stylized !== "string") return value; + if (typeof stylized !== 'string') return value; // `stylized` is a string as it should be, which is safe to pass along. return stylized; }, null); @@ -484,12 +324,7 @@ function getUserOptions(ctx: Context, isCrossContext: boolean): InspectOptionsSt * @param {object} opts Optional options object that alters the output. */ /* Legacy: value, showHidden, depth, colors */ -export function inspect( - value: unknown, - showHidden?: boolean, - depth?: number | null, - color?: boolean -): string; +export function inspect(value: unknown, showHidden?: boolean, depth?: number | null, color?: boolean): string; export function inspect(value: unknown, opts?: InspectOptions): string; export function inspect(value: unknown, opts?: Partial | boolean): string { // Default options @@ -523,7 +358,7 @@ export function inspect(value: unknown, opts?: Partial | } } // Set user-specified options - if (typeof opts === "boolean") { + if (typeof opts === 'boolean') { ctx.showHidden = opts; } else if (opts) { const optKeys = Object.keys(opts) as (keyof InspectOptionsStylized)[]; @@ -534,8 +369,7 @@ export function inspect(value: unknown, opts?: Partial | // functionality. if ( Object.prototype.hasOwnProperty.call(inspectDefaultOptions, key) || - key === "stylize" - ) { + key === 'stylize') { (ctx as Record)[key] = opts[key]; } else if (ctx.userOptions === undefined) { // This is required to pass through the actual user input. @@ -551,12 +385,12 @@ export function inspect(value: unknown, opts?: Partial | } inspect.custom = customInspectSymbol; -Object.defineProperty(inspect, "defaultOptions", { +Object.defineProperty(inspect, 'defaultOptions', { get() { return inspectDefaultOptions; }, set(options) { - validateObject(options, "options"); + validateObject(options, 'options'); return Object.assign(inspectDefaultOptions, options); }, }); @@ -628,36 +462,36 @@ function defineColorAlias(target: string, alias: string) { }); } -defineColorAlias("gray", "grey"); -defineColorAlias("gray", "blackBright"); -defineColorAlias("bgGray", "bgGrey"); -defineColorAlias("bgGray", "bgBlackBright"); -defineColorAlias("dim", "faint"); -defineColorAlias("strikethrough", "crossedout"); -defineColorAlias("strikethrough", "strikeThrough"); -defineColorAlias("strikethrough", "crossedOut"); -defineColorAlias("hidden", "conceal"); -defineColorAlias("inverse", "swapColors"); -defineColorAlias("inverse", "swapcolors"); -defineColorAlias("doubleunderline", "doubleUnderline"); +defineColorAlias('gray', 'grey'); +defineColorAlias('gray', 'blackBright'); +defineColorAlias('bgGray', 'bgGrey'); +defineColorAlias('bgGray', 'bgBlackBright'); +defineColorAlias('dim', 'faint'); +defineColorAlias('strikethrough', 'crossedout'); +defineColorAlias('strikethrough', 'strikeThrough'); +defineColorAlias('strikethrough', 'crossedOut'); +defineColorAlias('hidden', 'conceal'); +defineColorAlias('inverse', 'swapColors'); +defineColorAlias('inverse', 'swapcolors'); +defineColorAlias('doubleunderline', 'doubleUnderline'); // TODO(BridgeAR): Add function style support for more complex styles. // Don't use 'blue' not visible on cmd.exe inspect.styles = { __proto__: null, - special: "cyan", - number: "yellow", - bigint: "yellow", - boolean: "yellow", - undefined: "grey", - null: "bold", - string: "green", - symbol: "green", - date: "magenta", + special: 'cyan', + number: 'yellow', + bigint: 'yellow', + boolean: 'yellow', + undefined: 'grey', + null: 'bold', + string: 'green', + symbol: 'green', + date: 'magenta', name: undefined, // TODO(BridgeAR): Highlight regular expressions properly. - regexp: "red", - module: "underline", + regexp: 'red', + module: 'underline', }; function addQuotes(str: string, quotes: number): string { @@ -689,9 +523,10 @@ function strEscape(str: string): string { if (str.includes("'")) { // This invalidates the charCode and therefore can not be matched for // anymore. - if (!str.includes('"')) { + if (!(str.includes('"'))) { singleQuote = -1; - } else if (!str.includes("`") && !str.includes("${")) { + } else if (!str.includes('`') && + !str.includes('${')) { singleQuote = -2; } if (singleQuote !== 39) { @@ -701,17 +536,21 @@ function strEscape(str: string): string { } // Some magic numbers that worked out fine while benchmarking with v8 6.0 - if (str.length < 5000 && escapeTest.exec(str) === null) return addQuotes(str, singleQuote); + if (str.length < 5000 && escapeTest.exec(str) === null) + return addQuotes(str, singleQuote); if (str.length > 100) { str = str.replace(escapeReplace, escapeFn); return addQuotes(str, singleQuote); } - let result = ""; + let result = ''; let last = 0; for (let i = 0; i < str.length; i++) { const point = str.charCodeAt(i); - if (point === singleQuote || point === 92 || point < 32 || (point > 126 && point < 160)) { + if (point === singleQuote || + point === 92 || + point < 32 || + (point > 126 && point < 160)) { if (last === i) { result += meta[point]; } else { @@ -741,7 +580,8 @@ function stylizeWithColor(str: string, styleType: Style): string { const style = inspect.styles[styleType]; if (style !== undefined) { const color = (inspect.colors as unknown as Record)[style]; - if (color !== undefined) return `\u001b[${color[0]}m${str}\u001b[${color[1]}m`; + if (color !== undefined) + return `\u001b[${color[0]}m${str}\u001b[${color[1]}m`; } return str; } @@ -763,27 +603,20 @@ function isInstanceof(object: unknown, proto: Function): boolean { } } -function getConstructorName( - obj: object, - ctx: Context, - recurseTimes: number, - protoProps?: string[] -): string | null { +function getConstructorName(obj: object, ctx: Context, recurseTimes: number, protoProps?: string[]): string | null { let firstProto: unknown; const tmp = obj; while (obj || isUndetectableObject(obj)) { - const descriptor = Object.getOwnPropertyDescriptor(obj, "constructor"); - if ( - descriptor !== undefined && - typeof descriptor.value === "function" && - descriptor.value.name !== "" && - isInstanceof(tmp, descriptor.value) - ) { - if ( - protoProps !== undefined && - (firstProto !== obj || !builtInObjects.has(descriptor.value.name)) - ) { - addPrototypeProperties(ctx, tmp, firstProto || tmp, recurseTimes, protoProps); + const descriptor = Object.getOwnPropertyDescriptor(obj, 'constructor'); + if (descriptor !== undefined && + typeof descriptor.value === 'function' && + descriptor.value.name !== '' && + isInstanceof(tmp, descriptor.value)) { + if (protoProps !== undefined && + (firstProto !== obj || + !builtInObjects.has(descriptor.value.name))) { + addPrototypeProperties( + ctx, tmp, firstProto || tmp, recurseTimes, protoProps); } return String(descriptor.value.name); } @@ -804,7 +637,8 @@ function getConstructorName( return `${res} `; } - const protoConstr = getConstructorName(firstProto!, ctx, recurseTimes + 1, protoProps); + const protoConstr = getConstructorName( + firstProto!, ctx, recurseTimes + 1, protoProps); if (protoConstr === null) { return `${res} <${inspect(firstProto, { @@ -820,13 +654,7 @@ function getConstructorName( // This function has the side effect of adding prototype properties to the // `output` argument (which is an array). This is intended to highlight user // defined prototype properties. -function addPrototypeProperties( - ctx: Context, - main: object, - obj: Object, - recurseTimes: number, - output: string[] -): void { +function addPrototypeProperties(ctx: Context, main: object, obj: Object, recurseTimes: number, output: string[]): void { let depth = 0; let keys: PropertyKey[] | undefined; let keySet: Set | undefined; @@ -838,12 +666,10 @@ function addPrototypeProperties( return; } // Stop as soon as a built-in object type is detected. - const descriptor = Object.getOwnPropertyDescriptor(obj, "constructor"); - if ( - descriptor !== undefined && - typeof descriptor.value === "function" && - builtInObjects.has(descriptor.value.name) - ) { + const descriptor = Object.getOwnPropertyDescriptor(obj, 'constructor'); + if (descriptor !== undefined && + typeof descriptor.value === 'function' && + builtInObjects.has(descriptor.value.name)) { return; } } @@ -858,18 +684,17 @@ function addPrototypeProperties( ctx.seen.push(main); for (const key of keys) { // Ignore the `constructor` property and keys that exist on layers above. - if ( - key === "constructor" || + if (key === 'constructor' || Object.prototype.hasOwnProperty.call(main, key) || - (depth !== 0 && keySet!.has(key)) - ) { + (depth !== 0 && keySet!.has(key))) { continue; } const desc = Object.getOwnPropertyDescriptor(obj, key); - if (typeof desc?.value === "function") { + if (typeof desc?.value === 'function') { continue; } - const value = formatProperty(ctx, obj, recurseTimes, key, kObjectType, desc, main); + const value = formatProperty( + ctx, obj, recurseTimes, key, kObjectType, desc, main); if (ctx.colors) { // Faint! output.push(`\u001b[2m${value}\u001b[22m`); @@ -884,15 +709,15 @@ function addPrototypeProperties( } while (++depth !== 3); } -function getPrefix(constructor: string | null, tag: string, fallback: string, size = ""): string { +function getPrefix(constructor: string | null, tag: string, fallback: string, size = ''): string { if (constructor === null) { - if (tag !== "" && fallback !== tag) { + if (tag !== '' && fallback !== tag) { return `[${fallback}${size}: null prototype] [${tag}] `; } return `[${fallback}${size}: null prototype] `; } - if (tag !== "" && constructor !== tag) { + if (tag !== '' && constructor !== tag) { return `${constructor}${size} [${tag}] `; } return `${constructor}${size} `; @@ -904,7 +729,8 @@ function getKeys(value: object, showHidden: boolean): PropertyKey[] { const symbols = Object.getOwnPropertySymbols(value); if (showHidden) { keys = Object.getOwnPropertyNames(value); - if (symbols.length !== 0) keys.push(...symbols); + if (symbols.length !== 0) + keys.push(...symbols); } else { // This might throw if `value` is a Module Namespace Object from an // unevaluated module, but we don't want to perform the actual type @@ -914,16 +740,12 @@ function getKeys(value: object, showHidden: boolean): PropertyKey[] { try { keys = Object.keys(value); } catch (err: any) { - assert( - isNativeError(err) && - err.name === "ReferenceError" && - isModuleNamespaceObject(value) - ); + assert(isNativeError(err) && err.name === 'ReferenceError' && + isModuleNamespaceObject(value)); keys = Object.getOwnPropertyNames(value); } if (symbols.length !== 0) { - const filter = (key: PropertyKey) => - Object.prototype.propertyIsEnumerable.call(value, key); + const filter = (key: PropertyKey) => Object.prototype.propertyIsEnumerable.call(value, key); keys.push(...symbols.filter(filter)); } } @@ -931,11 +753,11 @@ function getKeys(value: object, showHidden: boolean): PropertyKey[] { } function getCtxStyle(value: unknown, constructor: string | null, tag: string): string { - let fallback = ""; + let fallback = ''; if (constructor === null) { fallback = internal.getConstructorName(value); if (fallback === tag) { - fallback = "Object"; + fallback = 'Object'; } } return getPrefix(constructor, tag, fallback); @@ -943,7 +765,7 @@ function getCtxStyle(value: unknown, constructor: string | null, tag: string): s function formatProxy(ctx: Context, proxy: internal.ProxyDetails, recurseTimes: number): string { if (ctx.depth !== null && recurseTimes > ctx.depth) { - return ctx.stylize("Proxy [Array]", "special"); + return ctx.stylize('Proxy [Array]', 'special'); } recurseTimes += 1; ctx.indentationLvl += 2; @@ -952,24 +774,22 @@ function formatProxy(ctx: Context, proxy: internal.ProxyDetails, recurseTimes: n formatValue(ctx, proxy.handler, recurseTimes), ]; ctx.indentationLvl -= 2; - return reduceToSingleString(ctx, res, "", ["Proxy [", "]"], kArrayExtrasType, recurseTimes); + return reduceToSingleString( + ctx, res, '', ['Proxy [', ']'], kArrayExtrasType, recurseTimes); } // Note: using `formatValue` directly requires the indentation level to be // corrected by setting `ctx.indentationLvL += diff` and then to decrease the // value afterwards again. -function formatValue( - ctx: Context, - value: unknown, - recurseTimes: number, - typedArray?: unknown -): string { +function formatValue(ctx: Context, value: unknown, recurseTimes: number, typedArray?: unknown): string { // Primitive types cannot have properties. - if (typeof value !== "object" && typeof value !== "function" && !isUndetectableObject(value)) { + if (typeof value !== 'object' && + typeof value !== 'function' && + !isUndetectableObject(value)) { return formatPrimitive(ctx.stylize, value as Primitive, ctx); } if (value === null) { - return ctx.stylize("null", "null"); + return ctx.stylize('null', 'null'); } // Memorize the context for custom inspection on proxies. @@ -979,7 +799,7 @@ function formatValue( const proxy = internal.getProxyDetails(value); if (proxy !== undefined) { if (proxy === null || proxy.target === null) { - return ctx.stylize("", "special"); + return ctx.stylize('', 'special'); } if (ctx.showProxy) { return formatProxy(ctx, proxy, recurseTimes); @@ -993,9 +813,7 @@ function formatValue( let maybeCustom = (value as Record)[customInspectSymbol]; // WORKERD SPECIFIC PATCH: if `value` is a JSG resource type, use a well-known custom inspect - const maybeResourceTypeInspect = (value as Record)[ - internal.kResourceTypeInspect - ]; + const maybeResourceTypeInspect = (value as Record)[internal.kResourceTypeInspect]; if (typeof maybeResourceTypeInspect === "object") { maybeCustom = formatJsgResourceType.bind( context as Record, @@ -1003,31 +821,30 @@ function formatValue( ); } - if ( - typeof maybeCustom === "function" && + if (typeof maybeCustom === 'function' && // Filter out the util module, its inspect function is special. maybeCustom !== inspect && // Also filter out any prototype objects using the circular check. - !((value as object).constructor && (value as object).constructor.prototype === value) - ) { + !((value as object).constructor && (value as object).constructor.prototype === value)) { // This makes sure the recurseTimes are reported as before while using // a counter internally. const depth = ctx.depth === null ? null : ctx.depth - recurseTimes; - const isCrossContext = proxy !== undefined || !(context instanceof Object); + const isCrossContext = + proxy !== undefined || !(context instanceof Object); const ret = Function.prototype.call.call( maybeCustom, context, depth, getUserOptions(ctx, isCrossContext), - inspect + inspect, ); // If the custom inspection method returned `this`, don't go into // infinite recursion. if (ret !== context) { - if (typeof ret !== "string") { + if (typeof ret !== 'string') { return formatValue(ctx, ret, recurseTimes); } - return ret.replaceAll("\n", `\n${" ".repeat(ctx.indentationLvl)}`); + return ret.replaceAll('\n', `\n${' '.repeat(ctx.indentationLvl)}`); } } } @@ -1046,18 +863,13 @@ function formatValue( ctx.circular.set(value, index); } } - return ctx.stylize(`[Circular *${index}]`, "special"); + return ctx.stylize(`[Circular *${index}]`, 'special'); } return formatRaw(ctx, value, recurseTimes, typedArray); } -function formatRaw( - ctx: Context, - value: unknown, - recurseTimes: number, - typedArray: unknown -): string { +function formatRaw(ctx: Context, value: unknown, recurseTimes: number, typedArray: unknown): string { let keys: PropertyKey[] | undefined; let protoProps: string[] | undefined; if (ctx.showHidden && (ctx.depth === null || recurseTimes <= ctx.depth)) { @@ -1073,19 +885,16 @@ function formatRaw( let tag = (value as { [Symbol.toStringTag]?: string })[Symbol.toStringTag]; // Only list the tag in case it's non-enumerable / not an own property. // Otherwise we'd print this twice. - if ( - typeof tag !== "string" || - (tag !== "" && - (ctx.showHidden - ? Object.prototype.hasOwnProperty - : Object.prototype.propertyIsEnumerable - ).call(value, Symbol.toStringTag)) - ) { - tag = ""; - } - let base = ""; - let formatter: (ctx: Context, value: any, recurseTimes: number) => string[] = - getEmptyFormatArray; + if (typeof tag !== 'string' || + (tag !== '' && + (ctx.showHidden ? + Object.prototype.hasOwnProperty : + Object.prototype.propertyIsEnumerable) + .call(value, Symbol.toStringTag))) { + tag = ''; + } + let base = ''; + let formatter: (ctx: Context, value: any, recurseTimes: number) => string[] = getEmptyFormatArray; let braces: [string, string] | undefined; let noIterator = true; let i = 0; @@ -1103,7 +912,7 @@ function formatRaw( if (isEntriesObject) { // WORKERD SPECIFIC PATCH: if `value` is an object with entries, format them like a map const size = value[kEntries].length; - const prefix = getPrefix(constructor, tag, "Object", `(${size})`); + const prefix = getPrefix(constructor, tag, 'Object', `(${size})`); keys = getKeys(value, ctx.showHidden); // Remove `kEntries` and `size` from keys @@ -1112,70 +921,66 @@ function formatRaw( if (sizeIndex !== -1) keys.splice(sizeIndex, 1); formatter = formatMap.bind(null, value[kEntries][Symbol.iterator]()); - if (size === 0 && keys.length === 0 && protoProps === undefined) return `${prefix}{}`; - braces = [`${prefix}{`, "}"]; + if (size === 0 && keys.length === 0 && protoProps === undefined) + return `${prefix}{}`; + braces = [`${prefix}{`, '}']; } else if (Array.isArray(value)) { // Only set the constructor for non ordinary ("Array [...]") arrays. - const prefix = - constructor !== "Array" || tag !== "" - ? getPrefix(constructor, tag, "Array", `(${value.length})`) - : ""; + const prefix = (constructor !== 'Array' || tag !== '') ? + getPrefix(constructor, tag, 'Array', `(${value.length})`) : + ''; keys = internal.getOwnNonIndexProperties(value, filter); - braces = [`${prefix}[`, "]"]; + braces = [`${prefix}[`, ']']; if (value.length === 0 && keys.length === 0 && protoProps === undefined) return `${braces[0]}]`; extrasType = kArrayExtrasType; formatter = formatArray; } else if (isSet(value)) { const size = setPrototypeSize.call(value); - const prefix = getPrefix(constructor, tag, "Set", `(${size})`); + const prefix = getPrefix(constructor, tag, 'Set', `(${size})`); keys = getKeys(value, ctx.showHidden); - formatter = - constructor !== null - ? formatSet.bind(null, value) - : formatSet.bind(null, Set.prototype.values.call(value)); - if (size === 0 && keys.length === 0 && protoProps === undefined) return `${prefix}{}`; - braces = [`${prefix}{`, "}"]; + formatter = constructor !== null ? + formatSet.bind(null, value) : + formatSet.bind(null, Set.prototype.values.call(value)); + if (size === 0 && keys.length === 0 && protoProps === undefined) + return `${prefix}{}`; + braces = [`${prefix}{`, '}']; } else if (isMap(value)) { const size = mapPrototypeSize.call(value); - const prefix = getPrefix(constructor, tag, "Map", `(${size})`); + const prefix = getPrefix(constructor, tag, 'Map', `(${size})`); keys = getKeys(value, ctx.showHidden); - formatter = - constructor !== null - ? formatMap.bind(null, value) - : formatMap.bind(null, Map.prototype.entries.call(value)); - if (size === 0 && keys.length === 0 && protoProps === undefined) return `${prefix}{}`; - braces = [`${prefix}{`, "}"]; + formatter = constructor !== null ? + formatMap.bind(null, value) : + formatMap.bind(null, Map.prototype.entries.call(value)); + if (size === 0 && keys.length === 0 && protoProps === undefined) + return `${prefix}{}`; + braces = [`${prefix}{`, '}']; } else if (isTypedArray(value)) { keys = internal.getOwnNonIndexProperties(value, filter); let bound = value; - let fallback = ""; + let fallback = ''; if (constructor === null) { fallback = typedArrayPrototypeToStringTag.call(value); // Reconstruct the array information. - bound = new ( - globalThis as unknown as Record< - string, - { new (value: NodeJS.TypedArray): NodeJS.TypedArray } - > - )[fallback]!(value); + bound = new (globalThis as unknown as Record)[fallback]!(value); } const size = typedArrayPrototypeLength.call(value); const prefix = getPrefix(constructor, tag, fallback, `(${size})`); - braces = [`${prefix}[`, "]"]; - if (value.length === 0 && keys.length === 0 && !ctx.showHidden) return `${braces[0]}]`; + braces = [`${prefix}[`, ']']; + if (value.length === 0 && keys.length === 0 && !ctx.showHidden) + return `${braces[0]}]`; // Special handle the value. The original value is required below. The // bound function is required to reconstruct missing information. formatter = formatTypedArray.bind(null, bound, size); extrasType = kArrayExtrasType; } else if (isMapIterator(value)) { keys = getKeys(value, ctx.showHidden); - braces = getIteratorBraces("Map", tag); + braces = getIteratorBraces('Map', tag); // Add braces to the formatter parameters. formatter = formatIterator.bind(null, braces); } else if (isSetIterator(value)) { keys = getKeys(value, ctx.showHidden); - braces = getIteratorBraces("Set", tag); + braces = getIteratorBraces('Set', tag); // Add braces to the formatter parameters. formatter = formatIterator.bind(null, braces); } else { @@ -1184,73 +989,77 @@ function formatRaw( } if (noIterator) { keys = getKeys(value as object, ctx.showHidden); - braces = ["{", "}"]; - if (constructor === "Object") { + braces = ['{', '}']; + if (constructor === 'Object') { if (isArgumentsObject(value)) { - braces[0] = "[Arguments] {"; - } else if (tag !== "") { - braces[0] = `${getPrefix(constructor, tag, "Object")}{`; + braces[0] = '[Arguments] {'; + } else if (tag !== '') { + braces[0] = `${getPrefix(constructor, tag, 'Object')}{`; } if (keys.length === 0 && protoProps === undefined) { return `${braces[0]}}`; } - } else if (typeof value === "function") { + } else if (typeof value === 'function') { base = getFunctionBase(value, constructor, tag); - if (keys.length === 0 && protoProps === undefined) return ctx.stylize(base, "special"); + if (keys.length === 0 && protoProps === undefined) + return ctx.stylize(base, 'special'); } else if (isRegExp(value)) { // Make RegExps say that they are RegExps - base = RegExp.prototype.toString.call(constructor !== null ? value : new RegExp(value)); - const prefix = getPrefix(constructor, tag, "RegExp"); - if (prefix !== "RegExp ") base = `${prefix}${base}`; - if ( - (keys.length === 0 && protoProps === undefined) || - (ctx.depth !== null && recurseTimes > ctx.depth) - ) { - return ctx.stylize(base, "regexp"); + base = RegExp.prototype.toString.call( + constructor !== null ? value : new RegExp(value) + ); + const prefix = getPrefix(constructor, tag, 'RegExp'); + if (prefix !== 'RegExp ') + base = `${prefix}${base}`; + if ((keys.length === 0 && protoProps === undefined) || + (ctx.depth !== null && recurseTimes > ctx.depth)) { + return ctx.stylize(base, 'regexp'); } } else if (isDate(value)) { // Make dates with properties first say the date - base = Number.isNaN(Date.prototype.getTime.call(value)) - ? Date.prototype.toString.call(value) - : Date.prototype.toISOString.call(value); - const prefix = getPrefix(constructor, tag, "Date"); - if (prefix !== "Date ") base = `${prefix}${base}`; + base = Number.isNaN(Date.prototype.getTime.call(value)) ? + Date.prototype.toString.call(value) : + Date.prototype.toISOString.call(value); + const prefix = getPrefix(constructor, tag, 'Date'); + if (prefix !== 'Date ') + base = `${prefix}${base}`; if (keys.length === 0 && protoProps === undefined) { - return ctx.stylize(base, "date"); + return ctx.stylize(base, 'date'); } } else if (isError(value)) { base = formatError(value, constructor, tag, ctx, keys); - if (keys.length === 0 && protoProps === undefined) return base; + if (keys.length === 0 && protoProps === undefined) + return base; } else if (isAnyArrayBuffer(value)) { // Fast path for ArrayBuffer and SharedArrayBuffer. // Can't do the same for DataView because it has a non-primitive // .buffer property that we need to recurse for. - const arrayType = isArrayBuffer(value) ? "ArrayBuffer" : "SharedArrayBuffer"; + const arrayType = isArrayBuffer(value) ? 'ArrayBuffer' : + 'SharedArrayBuffer'; const prefix = getPrefix(constructor, tag, arrayType); if (typedArray === undefined) { formatter = formatArrayBuffer; } else if (keys.length === 0 && protoProps === undefined) { - return ( - prefix + `{ byteLength: ${formatNumber(ctx.stylize, value.byteLength, false)} }` - ); + return prefix + + `{ byteLength: ${formatNumber(ctx.stylize, value.byteLength, false)} }`; } braces[0] = `${prefix}{`; - keys.unshift("byteLength"); + keys.unshift('byteLength'); } else if (isDataView(value)) { - braces[0] = `${getPrefix(constructor, tag, "DataView")}{`; + braces[0] = `${getPrefix(constructor, tag, 'DataView')}{`; // .buffer goes last, it's not a primitive like the others. - keys.unshift("byteLength", "byteOffset", "buffer"); + keys.unshift('byteLength', 'byteOffset', 'buffer'); } else if (isPromise(value)) { - braces[0] = `${getPrefix(constructor, tag, "Promise")}{`; + braces[0] = `${getPrefix(constructor, tag, 'Promise')}{`; formatter = formatPromise; } else if (isWeakSet(value)) { - braces[0] = `${getPrefix(constructor, tag, "WeakSet")}{`; + braces[0] = `${getPrefix(constructor, tag, 'WeakSet')}{`; formatter = ctx.showHidden ? formatWeakSet : formatWeakCollection; } else if (isWeakMap(value)) { - braces[0] = `${getPrefix(constructor, tag, "WeakMap")}{`; + braces[0] = `${getPrefix(constructor, tag, 'WeakMap')}{`; formatter = ctx.showHidden ? formatWeakMap : formatWeakCollection; } else if (isModuleNamespaceObject(value)) { - braces[0] = `${getPrefix(constructor, tag, "Module")}{`; + braces[0] = `${getPrefix(constructor, tag, 'Module')}{`; // Special handle keys for namespace objects. formatter = formatNamespaceObject.bind(null, keys); } else if (isBoxedPrimitive(value)) { @@ -1268,8 +1077,9 @@ function formatRaw( if (ctx.depth !== null && recurseTimes > ctx.depth) { let constructorName = getCtxStyle(value, constructor, tag).slice(0, -1); - if (constructor !== null) constructorName = `[${constructorName}]`; - return ctx.stylize(constructorName, "special"); + if (constructor !== null) + constructorName = `[${constructorName}]`; + return ctx.stylize(constructorName, 'special'); } recurseTimes += 1; @@ -1280,7 +1090,9 @@ function formatRaw( try { output = formatter(ctx, value, recurseTimes); for (i = 0; i < keys!.length; i++) { - output.push(formatProperty(ctx, value as object, recurseTimes, keys![i]!, extrasType)); + output.push( + formatProperty(ctx, value as object, recurseTimes, keys![i]!, extrasType), + ); } if (protoProps !== undefined) { output.push(...protoProps); @@ -1292,10 +1104,10 @@ function formatRaw( if (ctx.circular !== undefined) { const index = ctx.circular.get(value); if (index !== undefined) { - const reference = ctx.stylize(``, "special"); + const reference = ctx.stylize(``, 'special'); // Add reference always to the very beginning of the output. if (ctx.compact !== true) { - base = base === "" ? reference : `${reference} ${base}`; + base = base === '' ? reference : `${reference} ${base}`; } else { braces![0] = `${reference} ${braces![0]}`; } @@ -1313,7 +1125,8 @@ function formatRaw( } } - const res = reduceToSingleString(ctx, output, base, braces!, extrasType, recurseTimes, value); + const res = reduceToSingleString( + ctx, output, base, braces!, extrasType, recurseTimes, value); const budget = ctx.budget[ctx.indentationLvl] || 0; const newLength = budget + res.length; ctx.budget[ctx.indentationLvl] = newLength; @@ -1332,65 +1145,61 @@ function formatRaw( function getIteratorBraces(type: string, tag: string): [string, string] { if (tag !== `${type} Iterator`) { - if (tag !== "") tag += "] ["; + if (tag !== '') + tag += '] ['; tag += `${type} Iterator`; } - return [`[${tag}] {`, "}"]; + return [`[${tag}] {`, '}']; } -function getBoxedBase( - value: unknown, - ctx: Context, - keys: PropertyKey[], - constructor: string | null, - tag: string -): string { +function getBoxedBase(value: unknown, ctx: Context, keys: PropertyKey[], constructor: string | null, tag: string): string { let fn: (this: unknown) => Primitive; let type: Capitalize> | "BigInt"; if (isNumberObject(value)) { fn = Number.prototype.valueOf; - type = "Number"; + type = 'Number'; } else if (isStringObject(value)) { fn = String.prototype.valueOf; - type = "String"; + type = 'String'; // For boxed Strings, we have to remove the 0-n indexed entries, // since they just noisy up the output and are redundant // Make boxed primitive Strings look like such keys.splice(0, value.length); } else if (isBooleanObject(value)) { fn = Boolean.prototype.valueOf; - type = "Boolean"; + type = 'Boolean'; } else if (isBigIntObject(value)) { fn = BigInt.prototype.valueOf; - type = "BigInt"; + type = 'BigInt'; } else { fn = Symbol.prototype.valueOf; - type = "Symbol"; + type = 'Symbol'; } let base = `[${type}`; if (type !== constructor) { if (constructor === null) { - base += " (null prototype)"; + base += ' (null prototype)'; } else { base += ` (${constructor})`; } } base += `: ${formatPrimitive(stylizeNoColor, fn.call(value), ctx)}]`; - if (tag !== "" && tag !== constructor) { + if (tag !== '' && tag !== constructor) { base += ` [${tag}]`; } - if (keys.length !== 0 || ctx.stylize === stylizeNoColor) return base; + if (keys.length !== 0 || ctx.stylize === stylizeNoColor) + return base; return ctx.stylize(base, type.toLowerCase() as Style); } function getClassBase(value: any, constructor: string | null, tag: string): string { - const hasName = Object.prototype.hasOwnProperty.call(value, "name"); - const name = (hasName && value.name) || "(anonymous)"; + const hasName = Object.prototype.hasOwnProperty.call(value, 'name'); + const name = (hasName && value.name) || '(anonymous)'; let base = `class ${name}`; - if (constructor !== "Function" && constructor !== null) { + if (constructor !== 'Function' && constructor !== null) { base += ` [${constructor}]`; } - if (tag !== "" && constructor !== tag) { + if (tag !== '' && constructor !== tag) { base += ` [${tag}]`; } if (constructor !== null) { @@ -1399,26 +1208,25 @@ function getClassBase(value: any, constructor: string | null, tag: string): stri base += ` extends ${superName}`; } } else { - base += " extends [null prototype]"; + base += ' extends [null prototype]'; } return `[${base}]`; } function getFunctionBase(value: Function, constructor: string | null, tag: string): string { const stringified = Function.prototype.toString.call(value); - if (stringified.startsWith("class") && stringified.endsWith("}")) { + if (stringified.startsWith('class') && stringified.endsWith('}')) { const slice = stringified.slice(5, -1); - const bracketIndex = slice.indexOf("{"); - if ( - bracketIndex !== -1 && - (!slice.slice(0, bracketIndex).includes("(") || + const bracketIndex = slice.indexOf('{'); + if (bracketIndex !== -1 && + (!slice.slice(0, bracketIndex).includes('(') || // Slow path to guarantee that it's indeed a class. classRegExp.exec(slice.replace(stripCommentsRegExp, "")) !== null) ) { return getClassBase(value, constructor, tag); } } - let type = "Function"; + let type = 'Function'; if (isGeneratorFunction(value)) { type = `Generator${type}`; } @@ -1427,27 +1235,24 @@ function getFunctionBase(value: Function, constructor: string | null, tag: strin } let base = `[${type}`; if (constructor === null) { - base += " (null prototype)"; + base += ' (null prototype)'; } - if (value.name === "") { - base += " (anonymous)"; + if (value.name === '') { + base += ' (anonymous)'; } else { base += `: ${value.name}`; } - base += "]"; + base += ']'; if (constructor !== type && constructor !== null) { base += ` ${constructor}`; } - if (tag !== "" && constructor !== tag) { + if (tag !== '' && constructor !== tag) { base += ` [${tag}]`; } return base; } -export function identicalSequenceRange( - a: unknown[], - b: unknown[] -): { len: number; offset: number } { +export function identicalSequenceRange(a: unknown[], b: unknown[]): { len: number, offset: number } { for (let i = 0; i < a.length - 3; i++) { // Find the first entry of b that matches the current entry of a. const pos = b.indexOf(a[i]); @@ -1475,7 +1280,7 @@ function getStackString(error: Error): string { } function getStackFrames(ctx: Context, err: Error, stack: string): string[] { - const frames = stack.split("\n"); + const frames = stack.split('\n'); let cause; try { @@ -1487,44 +1292,36 @@ function getStackFrames(ctx: Context, err: Error, stack: string): string[] { // Remove stack frames identical to frames in cause. if (cause != null && isError(cause)) { const causeStack = getStackString(cause); - const causeStackStart = causeStack.indexOf("\n at"); + const causeStackStart = causeStack.indexOf('\n at'); if (causeStackStart !== -1) { - const causeFrames = causeStack.slice(causeStackStart + 1).split("\n"); + const causeFrames = causeStack.slice(causeStackStart + 1).split('\n'); const { len, offset } = identicalSequenceRange(frames, causeFrames); if (len > 0) { const skipped = len - 2; const msg = ` ... ${skipped} lines matching cause stack trace ...`; - frames.splice(offset + 1, skipped, ctx.stylize(msg, "undefined")); + frames.splice(offset + 1, skipped, ctx.stylize(msg, 'undefined')); } } } return frames; } -function improveStack( - stack: string, - constructor: string | null, - name: string, - tag: string -): string { +function improveStack(stack: string, constructor: string | null, name: string, tag: string): string { // A stack trace may contain arbitrary data. Only manipulate the output // for "regular errors" (errors that "look normal") for now. let len = name.length; - if ( - constructor === null || - (name.endsWith("Error") && + if (constructor === null || + (name.endsWith('Error') && stack.startsWith(name) && - (stack.length === len || stack[len] === ":" || stack[len] === "\n")) - ) { - let fallback = "Error"; + (stack.length === len || stack[len] === ':' || stack[len] === '\n'))) { + let fallback = 'Error'; if (constructor === null) { - const start = - /^([A-Z][a-z_ A-Z0-9[\]()-]+)(?::|\n {4}at)/.exec(stack) || + const start = /^([A-Z][a-z_ A-Z0-9[\]()-]+)(?::|\n {4}at)/.exec(stack) || /^([a-z_A-Z0-9-]*Error)$/.exec(stack); - fallback = (start && start[1]) || ""; + fallback = (start && start[1]) || ''; len = fallback.length; - fallback = fallback || "Error"; + fallback = fallback || 'Error'; } const prefix = getPrefix(constructor, tag, fallback).slice(0, -1); if (name !== prefix) { @@ -1542,14 +1339,9 @@ function improveStack( return stack; } -function removeDuplicateErrorKeys( - ctx: Context, - keys: PropertyKey[], - err: Error, - stack: string -): void { +function removeDuplicateErrorKeys(ctx: Context, keys: PropertyKey[], err: Error, stack: string): void { if (!ctx.showHidden && keys.length !== 0) { - for (const name of ["name", "message", "stack"] as const) { + for (const name of ['name', 'message', 'stack'] as const) { const index = keys.indexOf(name); // Only hide the property in case it's part of the original stack if (index !== -1 && stack.includes(err[name]!)) { @@ -1560,13 +1352,13 @@ function removeDuplicateErrorKeys( } function markNodeModules(ctx: Context, line: string): string { - let tempLine = ""; + let tempLine = ''; let nodeModule; let pos = 0; while ((nodeModule = nodeModulesRegExp.exec(line)) !== null) { // '/node_modules/'.length === 14 tempLine += line.slice(pos, nodeModule.index + 14); - tempLine += ctx.stylize(nodeModule[1]!, "module"); + tempLine += ctx.stylize(nodeModule[1]!, 'module'); pos = nodeModule.index + nodeModule[0].length; } if (pos !== 0) { @@ -1575,37 +1367,31 @@ function markNodeModules(ctx: Context, line: string): string { return line; } -function formatError( - err: Error, - constructor: string | null, - tag: string, - ctx: Context, - keys: PropertyKey[] -): string { - const name = err.name != null ? String(err.name) : "Error"; +function formatError(err: Error, constructor: string | null, tag: string, ctx: Context, keys: PropertyKey[]): string { + const name = err.name != null ? String(err.name) : 'Error'; let stack = getStackString(err); removeDuplicateErrorKeys(ctx, keys, err, stack); - if ("cause" in err && (keys.length === 0 || !keys.includes("cause"))) { - keys.push("cause"); + if ('cause' in err && + (keys.length === 0 || !keys.includes('cause'))) { + keys.push('cause'); } // Print errors aggregated into AggregateError - if ( - Array.isArray((err as { errors?: unknown }).errors) && - (keys.length === 0 || !keys.includes("errors")) - ) { - keys.push("errors"); + if (Array.isArray((err as { errors?: unknown }).errors) && + (keys.length === 0 || !keys.includes('errors'))) { + keys.push('errors'); } stack = improveStack(stack, constructor, name, tag); // Ignore the error message if it's contained in the stack. let pos = (err.message && stack.indexOf(err.message)) || -1; - if (pos !== -1) pos += err.message.length; + if (pos !== -1) + pos += err.message.length; // Wrap the error in brackets in case it has no stack trace. - const stackStart = stack.indexOf("\n at", pos); + const stackStart = stack.indexOf('\n at', pos); if (stackStart === -1) { stack = `[${stack}]`; } else { @@ -1615,30 +1401,26 @@ function formatError( if (ctx.colors) { // Highlight userland code and node modules. for (let line of lines) { - newStack += "\n"; + newStack += '\n'; line = markNodeModules(ctx, line); newStack += line; } } else { - newStack += `\n${lines.join("\n")}`; + newStack += `\n${lines.join('\n')}`; } stack = newStack; } // The message and the stack have to be indented as well! if (ctx.indentationLvl !== 0) { - const indentation = " ".repeat(ctx.indentationLvl); - stack = stack.replaceAll("\n", `\n${indentation}`); + const indentation = ' '.repeat(ctx.indentationLvl); + stack = stack.replaceAll('\n', `\n${indentation}`); } return stack; } -function groupArrayElements( - ctx: Context, - output: string[], - value: unknown[] | undefined -): string[] { +function groupArrayElements(ctx: Context, output: string[], value: unknown[] | undefined): string[] { let totalLength = 0; let maxLength = 0; let i = 0; @@ -1656,7 +1438,8 @@ function groupArrayElements( const len = getStringWidth(output[i]!, ctx.colors); dataLen[i] = len; totalLength += len + separatorSpace; - if (maxLength < len) maxLength = len; + if (maxLength < len) + maxLength = len; } // Add two to `maxLength` as we add a single whitespace character plus a comma // in-between two entries. @@ -1665,10 +1448,9 @@ function groupArrayElements( // of arrays that contains entries of very different length (i.e., if a single // entry is longer than 1/5 of all other entries combined). Otherwise the // space in-between small entries would be enormous. - if ( - actualMax * 3 + ctx.indentationLvl < ctx.breakLength && - (totalLength / actualMax > 5 || maxLength <= 6) - ) { + if (actualMax * 3 + ctx.indentationLvl < ctx.breakLength && + (totalLength / actualMax > 5 || maxLength <= 6)) { + const approxCharHeights = 2.5; const averageBias = Math.sqrt(actualMax - totalLength / output.length); const biasedMax = Math.max(actualMax - 3 - averageBias, 1); @@ -1679,18 +1461,18 @@ function groupArrayElements( // which contains n rectangles of size `actualMax * approxCharHeights`. // Divide that by `actualMax` to receive the correct number of columns. // The added bias increases the columns for short entries. - Math.round(Math.sqrt(approxCharHeights * biasedMax * outputLength) / biasedMax), + Math.round( + Math.sqrt( + approxCharHeights * biasedMax * outputLength, + ) / biasedMax, + ), // Do not exceed the breakLength. Math.floor((ctx.breakLength - ctx.indentationLvl) / actualMax), // Limit array grouping for small `compact` modes as the user requested // minimal grouping. - (ctx.compact === false - ? 0 - : ctx.compact === true - ? inspectDefaultOptions.compact - : ctx.compact) * 4, + (ctx.compact === false ? 0 : ctx.compact === true ? inspectDefaultOptions.compact : ctx.compact) * 4, // Limit the columns to a maximum of fifteen. - 15 + 15, ); // Return with the original output if no grouping should happen. if (columns <= 1) { @@ -1701,7 +1483,8 @@ function groupArrayElements( for (let i = 0; i < columns; i++) { let lineMaxLength = 0; for (let j = i; j < output.length; j += columns) { - if (dataLen[j] > lineMaxLength) lineMaxLength = dataLen[j]; + if (dataLen[j] > lineMaxLength) + lineMaxLength = dataLen[j]; } lineMaxLength += separatorSpace; maxLineLength[i] = lineMaxLength; @@ -1709,7 +1492,7 @@ function groupArrayElements( let order = String.prototype.padStart; if (value !== undefined) { for (let i = 0; i < output.length; i++) { - if (typeof value[i] !== "number" && typeof value[i] !== "bigint") { + if (typeof value[i] !== 'number' && typeof value[i] !== 'bigint') { order = String.prototype.padEnd; break; } @@ -1719,19 +1502,21 @@ function groupArrayElements( for (let i = 0; i < outputLength; i += columns) { // The last lines may contain less entries than columns. const max = Math.min(i + columns, outputLength); - let str = ""; + let str = ''; let j = i; for (; j < max - 1; j++) { // Calculate extra color padding in case it's active. This has to be // done line by line as some lines might contain more colors than // others. const padding = maxLineLength[j - i]! + output[j]!.length - dataLen[j]; - str += order.call(`${output[j]}, `, padding, " "); + str += order.call(`${output[j]}, `, padding, ' '); } if (order === String.prototype.padStart) { - const padding = - maxLineLength[j - i]! + output[j]!.length - dataLen[j] - separatorSpace; - str += output[j]!.padStart(padding, " "); + const padding = maxLineLength[j - i]! + + output[j]!.length - + dataLen[j] - + separatorSpace; + str += output[j]!.padStart(padding, ' '); } else { str += output[j]; } @@ -1745,19 +1530,14 @@ function groupArrayElements( return output; } -function handleMaxCallStackSize( - ctx: Context, - err: Error, - constructorName: string, - indentationLvl: number -): string { +function handleMaxCallStackSize(ctx: Context, err: Error, constructorName: string, indentationLvl: number): string { if (isStackOverflowError(err)) { ctx.seen.pop(); ctx.indentationLvl = indentationLvl; return ctx.stylize( `[${constructorName}: Inspection interrupted ` + - "prematurely. Maximum call stack size exceeded.]", - "special" + 'prematurely. Maximum call stack size exceeded.]', + 'special', ); } /* c8 ignore next */ @@ -1765,129 +1545,119 @@ function handleMaxCallStackSize( } function addNumericSeparator(integerString: string): string { - let result = ""; + let result = ''; let i = integerString.length; - const start = integerString.startsWith("-") ? 1 : 0; + const start = integerString.startsWith('-') ? 1 : 0; for (; i >= start + 4; i -= 3) { result = `_${integerString.slice(i - 3, i)}${result}`; } - return i === integerString.length ? integerString : `${integerString.slice(0, i)}${result}`; + return i === integerString.length ? + integerString : + `${integerString.slice(0, i)}${result}`; } function addNumericSeparatorEnd(integerString: string): string { - let result = ""; + let result = ''; let i = 0; for (; i < integerString.length - 3; i += 3) { result += `${integerString.slice(i, i + 3)}_`; } - return i === 0 ? integerString : `${result}${integerString.slice(i)}`; + return i === 0 ? + integerString : + `${result}${integerString.slice(i)}`; } -const remainingText = (remaining: number) => - `... ${remaining} more item${remaining > 1 ? "s" : ""}`; +const remainingText = (remaining: number) => `... ${remaining} more item${remaining > 1 ? 's' : ''}`; -function formatNumber( - fn: InspectOptionsStylized["stylize"], - number: number, - numericSeparator?: boolean -): string { +function formatNumber(fn: InspectOptionsStylized["stylize"], number: number, numericSeparator?: boolean): string { if (!numericSeparator) { // Format -0 as '-0'. Checking `number === -0` won't distinguish 0 from -0. if (Object.is(number, -0)) { - return fn("-0", "number"); + return fn('-0', 'number'); } - return fn(`${number}`, "number"); + return fn(`${number}`, 'number'); } const integer = Math.trunc(number); const string = String(integer); if (integer === number) { - if (!Number.isFinite(number) || string.includes("e")) { - return fn(string, "number"); + if (!Number.isFinite(number) || string.includes('e')) { + return fn(string, 'number'); } - return fn(`${addNumericSeparator(string)}`, "number"); + return fn(`${addNumericSeparator(string)}`, 'number'); } if (Number.isNaN(number)) { - return fn(string, "number"); + return fn(string, 'number'); } - return fn( - `${addNumericSeparator(string)}.${addNumericSeparatorEnd( - String(number).slice(string.length + 1) - )}`, - "number" - ); + return fn(`${ + addNumericSeparator(string) + }.${ + addNumericSeparatorEnd( + String(number).slice(string.length + 1), + ) + }`, 'number'); } -function formatBigInt( - fn: InspectOptionsStylized["stylize"], - bigint: bigint, - numericSeparator?: boolean -): string { +function formatBigInt(fn: InspectOptionsStylized["stylize"], bigint: bigint, numericSeparator?: boolean): string { const string = String(bigint); if (!numericSeparator) { - return fn(`${string}n`, "bigint"); + return fn(`${string}n`, 'bigint'); } - return fn(`${addNumericSeparator(string)}n`, "bigint"); + return fn(`${addNumericSeparator(string)}n`, 'bigint'); } type Primitive = string | number | bigint | boolean | undefined | symbol; -function formatPrimitive( - fn: InspectOptionsStylized["stylize"], - value: Primitive, - ctx: Context -): string { - if (typeof value === "string") { - let trailer = ""; +function formatPrimitive(fn: InspectOptionsStylized["stylize"], value: Primitive, ctx: Context): string { + if (typeof value === 'string') { + let trailer = ''; if (ctx.maxStringLength !== null && value.length > ctx.maxStringLength) { const remaining = value.length - ctx.maxStringLength; value = value.slice(0, ctx.maxStringLength); - trailer = `... ${remaining} more character${remaining > 1 ? "s" : ""}`; + trailer = `... ${remaining} more character${remaining > 1 ? 's' : ''}`; } - if ( - ctx.compact !== true && + if (ctx.compact !== true && // We do not support handling unicode characters width with // the readline getStringWidth function as there are // performance implications. value.length > kMinLineLength && - value.length > ctx.breakLength - ctx.indentationLvl - 4 - ) { - return ( - value + value.length > ctx.breakLength - ctx.indentationLvl - 4) { + return value .split(/(?<=\n)/) - .map((line) => fn(strEscape(line), "string")) - .join(` +\n${" ".repeat(ctx.indentationLvl + 2)}`) + trailer - ); - } - return fn(strEscape(value), "string") + trailer; - } - if (typeof value === "number") return formatNumber(fn, value, ctx.numericSeparator); - if (typeof value === "bigint") return formatBigInt(fn, value, ctx.numericSeparator); - if (typeof value === "boolean") return fn(`${value}`, "boolean"); - if (typeof value === "undefined") return fn("undefined", "undefined"); + .map((line) => fn(strEscape(line), 'string')) + .join(` +\n${' '.repeat(ctx.indentationLvl + 2)}`) + + trailer; + } + return fn(strEscape(value), 'string') + trailer; + } + if (typeof value === 'number') + return formatNumber(fn, value, ctx.numericSeparator); + if (typeof value === 'bigint') + return formatBigInt(fn, value, ctx.numericSeparator); + if (typeof value === 'boolean') + return fn(`${value}`, 'boolean'); + if (typeof value === 'undefined') + return fn('undefined', 'undefined'); // es6 symbol primitive - return fn(Symbol.prototype.toString.call(value), "symbol"); + return fn(Symbol.prototype.toString.call(value), 'symbol'); } -function formatNamespaceObject( - keys: PropertyKey[], - ctx: Context, - value: object, - recurseTimes: number -): string[] { +function formatNamespaceObject(keys: PropertyKey[], ctx: Context, value: object, recurseTimes: number): string[] { const output = new Array(keys.length); for (let i = 0; i < keys.length; i++) { try { - output[i] = formatProperty(ctx, value, recurseTimes, keys[i]!, kObjectType); + output[i] = formatProperty(ctx, value, recurseTimes, keys[i]!, + kObjectType); } catch (err) { - assert(isNativeError(err) && err.name === "ReferenceError"); + assert(isNativeError(err) && err.name === 'ReferenceError'); // Use the existing functionality. This makes sure the indentation and // line breaks are always correct. Otherwise it is very difficult to keep // this aligned, even though this is a hacky way of dealing with this. - const tmp = { [keys[i]!]: "" }; + const tmp = { [keys[i]!]: '' }; output[i] = formatProperty(ctx, tmp, recurseTimes, keys[i]!, kObjectType); - const pos = output[i]!.lastIndexOf(" "); + const pos = output[i]!.lastIndexOf(' '); // We have to find the last whitespace and have to replace that value as // it will be visualized as a regular string. - output[i] = output[i]!.slice(0, pos + 1) + ctx.stylize("", "special"); + output[i] = output[i]!.slice(0, pos + 1) + + ctx.stylize('', 'special'); } } // Reset the keys to an empty array. This prevents duplicated inspection. @@ -1896,14 +1666,7 @@ function formatNamespaceObject( } // The array is sparse and/or has extra keys -function formatSpecialArray( - ctx: Context, - value: unknown[], - recurseTimes: number, - maxLength: number, - output: string[], - i: number -): string[] { +function formatSpecialArray(ctx: Context, value: unknown[], recurseTimes: number, maxLength: number, output: string[], i: number): string[] { const keys = Object.keys(value); let index = i; for (; i < keys.length && output.length < maxLength; i++) { @@ -1918,9 +1681,9 @@ function formatSpecialArray( break; } const emptyItems = tmp - index; - const ending = emptyItems > 1 ? "s" : ""; + const ending = emptyItems > 1 ? 's' : ''; const message = `<${emptyItems} empty item${ending}>`; - output.push(ctx.stylize(message, "undefined")); + output.push(ctx.stylize(message, 'undefined')); index = tmp; if (output.length === maxLength) { break; @@ -1932,9 +1695,9 @@ function formatSpecialArray( const remaining = value.length - index; if (output.length !== maxLength) { if (remaining > 0) { - const ending = remaining > 1 ? "s" : ""; + const ending = remaining > 1 ? 's' : ''; const message = `<${remaining} empty item${ending}>`; - output.push(ctx.stylize(message, "undefined")); + output.push(ctx.stylize(message, 'undefined')); } } else if (remaining > 0) { output.push(remainingText(remaining)); @@ -1947,16 +1710,16 @@ function formatArrayBuffer(ctx: Context, value: ArrayBuffer): string[] { try { buffer = new Uint8Array(value); } catch { - return [ctx.stylize("(detached)", "special")]; + return [ctx.stylize('(detached)', 'special')]; } const maxArrayLength = ctx.maxArrayLength; - let str = Buffer.prototype.hexSlice - .call(buffer, 0, Math.min(maxArrayLength, buffer.length)) - .replace(/(.{2})/g, "$1 ") + let str = Buffer.prototype.hexSlice.call(buffer, 0, Math.min(maxArrayLength, buffer.length)) + .replace(/(.{2})/g, '$1 ') .trim(); const remaining = buffer.length - maxArrayLength; - if (remaining > 0) str += ` ... ${remaining} more byte${remaining > 1 ? "s" : ""}`; - return [`${ctx.stylize("[Uint8Contents]", "special")}: <${str}>`]; + if (remaining > 0) + str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`; + return [`${ctx.stylize('[Uint8Contents]', 'special')}: <${str}>`]; } function formatArray(ctx: Context, value: unknown[], recurseTimes: number): string[] { @@ -1978,18 +1741,13 @@ function formatArray(ctx: Context, value: unknown[], recurseTimes: number): stri return output; } -function formatTypedArray( - value: internal.TypedArray, - length: number, - ctx: Context, - _ignored: unknown, - recurseTimes: number -): string[] { +function formatTypedArray(value: internal.TypedArray, length: number, ctx: Context, _ignored: unknown, recurseTimes: number): string[] { const maxLength = Math.min(Math.max(0, ctx.maxArrayLength), length); const remaining = value.length - maxLength; const output = new Array(maxLength); - const elementFormatter = - value.length > 0 && typeof value[0] === "number" ? formatNumber : formatBigInt; + const elementFormatter = value.length > 0 && typeof value[0] === 'number' ? + formatNumber : + formatBigInt; for (let i = 0; i < maxLength; ++i) { // @ts-expect-error `value[i]` assumed to be of correct numeric type output[i] = elementFormatter(ctx.stylize, value[i], ctx.numericSeparator); @@ -2002,11 +1760,11 @@ function formatTypedArray( // All besides `BYTES_PER_ELEMENT` are actually getters. ctx.indentationLvl += 2; for (const key of [ - "BYTES_PER_ELEMENT", - "length", - "byteLength", - "byteOffset", - "buffer", + 'BYTES_PER_ELEMENT', + 'length', + 'byteLength', + 'byteOffset', + 'buffer', ] as const) { const str = formatValue(ctx, value[key], recurseTimes, true); output.push(`[${key}]: ${str}`); @@ -2016,12 +1774,7 @@ function formatTypedArray( return output; } -function formatSet( - value: Set | IterableIterator, - ctx: Context, - _ignored: unknown, - recurseTimes: number -): string[] { +function formatSet(value: Set | IterableIterator, ctx: Context, _ignored: unknown, recurseTimes: number): string[] { const length = isSet(value) ? value.size : NaN; const maxLength = Math.min(Math.max(0, ctx.maxArrayLength), length); const remaining = length - maxLength; @@ -2040,12 +1793,7 @@ function formatSet( return output; } -function formatMap( - value: Map | IterableIterator<[unknown, unknown]>, - ctx: Context, - _ignored: unknown, - recurseTimes: number -): string[] { +function formatMap(value: Map | IterableIterator<[unknown, unknown]>, ctx: Context, _ignored: unknown, recurseTimes: number): string[] { const length = isMap(value) ? value.size : NaN; const maxLength = Math.min(Math.max(0, ctx.maxArrayLength), length); const remaining = length - maxLength; @@ -2054,7 +1802,9 @@ function formatMap( let i = 0; for (const { 0: k, 1: v } of value) { if (i >= maxLength) break; - output.push(`${formatValue(ctx, k, recurseTimes)} => ${formatValue(ctx, v, recurseTimes)}`); + output.push( + `${formatValue(ctx, k, recurseTimes)} => ${formatValue(ctx, v, recurseTimes)}` + ); i++; } if (remaining > 0) { @@ -2064,12 +1814,7 @@ function formatMap( return output; } -function formatSetIterInner( - ctx: Context, - recurseTimes: number, - entries: unknown[], - state: number -): string[] { +function formatSetIterInner(ctx: Context, recurseTimes: number, entries: unknown[], state: number): string[] { const maxArrayLength = Math.max(ctx.maxArrayLength, 0); const maxLength = Math.min(maxArrayLength, entries.length); const output = new Array(maxLength); @@ -2091,12 +1836,7 @@ function formatSetIterInner( return output; } -function formatMapIterInner( - ctx: Context, - recurseTimes: number, - entries: unknown[], - state: number -): string[] { +function formatMapIterInner(ctx: Context, recurseTimes: number, entries: unknown[], state: number): string[] { const maxArrayLength = Math.max(ctx.maxArrayLength, 0); // Entries exist as [key1, val1, key2, val2, ...] const len = entries.length / 2; @@ -2108,16 +1848,14 @@ function formatMapIterInner( if (state === kWeak) { for (; i < maxLength; i++) { const pos = i * 2; - output[i] = `${formatValue(ctx, entries[pos], recurseTimes)} => ${formatValue( - ctx, - entries[pos + 1], - recurseTimes - )}`; + output[i] = + `${formatValue(ctx, entries[pos], recurseTimes)} => ${formatValue(ctx, entries[pos + 1], recurseTimes)}`; } // Sort all entries to have a halfway reliable output (if more entries than // retrieved ones exist, we can not reliably return the same output) if the // output is not sorted anyway. - if (!ctx.sorted) output.sort(); + if (!ctx.sorted) + output.sort(); } else { for (; i < maxLength; i++) { const pos = i * 2; @@ -2126,13 +1864,7 @@ function formatMapIterInner( formatValue(ctx, entries[pos + 1], recurseTimes), ]; output[i] = reduceToSingleString( - ctx, - res, - "", - ["[", "]"], - kArrayExtrasType, - recurseTimes - ); + ctx, res, '', ['[', ']'], kArrayExtrasType, recurseTimes); } } ctx.indentationLvl -= 2; @@ -2143,7 +1875,7 @@ function formatMapIterInner( } function formatWeakCollection(ctx: Context): string[] { - return [ctx.stylize("", "special")]; + return [ctx.stylize('', 'special')]; } function formatWeakSet(ctx: Context, value: WeakSet, recurseTimes: number): string[] { @@ -2156,16 +1888,11 @@ function formatWeakMap(ctx: Context, value: WeakMap, recurseTimes: return formatMapIterInner(ctx, recurseTimes, entries, kWeak); } -function formatIterator( - braces: [string, string], - ctx: Context, - value: Iterator, - recurseTimes: number -): string[] { +function formatIterator(braces: [string, string], ctx: Context, value: Iterator, recurseTimes: number): string[] { const { entries, isKeyValue } = internal.previewEntries(value)!; if (isKeyValue) { // Mark entry iterators as such. - braces[0] = braces[0].replace(/ Iterator] {$/, " Entries] {"); + braces[0] = braces[0].replace(/ Iterator] {$/, ' Entries] {'); return formatMapIterInner(ctx, recurseTimes, entries, kMapEntries); } @@ -2176,93 +1903,80 @@ function formatPromise(ctx: Context, value: Promise, recurseTimes: numb let output: string[]; const { state, result } = internal.getPromiseDetails(value)!; if (state === internal.kPending) { - output = [ctx.stylize("", "special")]; + output = [ctx.stylize('', 'special')]; } else { ctx.indentationLvl += 2; const str = formatValue(ctx, result, recurseTimes); ctx.indentationLvl -= 2; output = [ - state === internal.kRejected ? `${ctx.stylize("", "special")} ${str}` : str, + state === internal.kRejected ? + `${ctx.stylize('', 'special')} ${str}` : + str, ]; } return output; } -function formatProperty( - ctx: Context, - value: object, - recurseTimes: number, - key: PropertyKey, - type: number, - desc?: PropertyDescriptor, - original = value -): string { +function formatProperty(ctx: Context, value: object, recurseTimes: number, key: PropertyKey, type: number, desc?: PropertyDescriptor, + original = value): string { let name: string, str: string; - let extra = " "; - desc = desc || - Object.getOwnPropertyDescriptor(value, key) || { - value: (value as Record)[key], - enumerable: true, - }; + let extra = ' '; + desc = desc || Object.getOwnPropertyDescriptor(value, key) || + { value: (value as Record)[key], enumerable: true }; if (desc.value !== undefined) { - const diff = ctx.compact !== true || type !== kObjectType ? 2 : 3; + const diff = (ctx.compact !== true || type !== kObjectType) ? 2 : 3; ctx.indentationLvl += diff; str = formatValue(ctx, desc.value, recurseTimes); if (diff === 3 && ctx.breakLength < getStringWidth(str, ctx.colors)) { - extra = `\n${" ".repeat(ctx.indentationLvl)}`; + extra = `\n${' '.repeat(ctx.indentationLvl)}`; } ctx.indentationLvl -= diff; } else if (desc.get !== undefined) { - const label = desc.set !== undefined ? "Getter/Setter" : "Getter"; + const label = desc.set !== undefined ? 'Getter/Setter' : 'Getter'; const s = ctx.stylize; - const sp = "special"; - if ( - ctx.getters && - (ctx.getters === true || - (ctx.getters === "get" && desc.set === undefined) || - (ctx.getters === "set" && desc.set !== undefined)) - ) { + const sp = 'special'; + if (ctx.getters && (ctx.getters === true || + (ctx.getters === 'get' && desc.set === undefined) || + (ctx.getters === 'set' && desc.set !== undefined))) { try { const tmp = desc.get.call(original); ctx.indentationLvl += 2; if (tmp === null) { - str = `${s(`[${label}:`, sp)} ${s("null", "null")}${s("]", sp)}`; - } else if (typeof tmp === "object") { + str = `${s(`[${label}:`, sp)} ${s('null', 'null')}${s(']', sp)}`; + } else if (typeof tmp === 'object') { str = `${s(`[${label}]`, sp)} ${formatValue(ctx, tmp, recurseTimes)}`; } else { const primitive = formatPrimitive(s, tmp, ctx); - str = `${s(`[${label}:`, sp)} ${primitive}${s("]", sp)}`; + str = `${s(`[${label}:`, sp)} ${primitive}${s(']', sp)}`; } ctx.indentationLvl -= 2; } catch (err) { const message = ``; - str = `${s(`[${label}:`, sp)} ${message}${s("]", sp)}`; + str = `${s(`[${label}:`, sp)} ${message}${s(']', sp)}`; } } else { str = ctx.stylize(`[${label}]`, sp); } } else if (desc.set !== undefined) { - str = ctx.stylize("[Setter]", "special"); + str = ctx.stylize('[Setter]', 'special'); } else { - str = ctx.stylize("undefined", "undefined"); + str = ctx.stylize('undefined', 'undefined'); } if (type === kArrayType) { return str; } - if (typeof key === "symbol") { - const tmp = Symbol.prototype.toString - .call(key) - .replace(strEscapeSequencesReplacer, escapeFn); - name = `[${ctx.stylize(tmp, "symbol")}]`; - } else if (key === "__proto__") { + if (typeof key === 'symbol') { + const tmp = Symbol.prototype.toString.call(key).replace(strEscapeSequencesReplacer, escapeFn); + name = `[${ctx.stylize(tmp, 'symbol')}]`; + } else if (key === '__proto__') { name = "['__proto__']"; } else if (desc.enumerable === false) { const tmp = String(key).replace(strEscapeSequencesReplacer, escapeFn); name = `[${tmp}]`; } else if (keyStrRegExp.exec(String(key)) !== null) { - name = ctx.stylize(String(key), "name"); + name = ctx.stylize(String(key), 'name'); } else { - name = ctx.stylize(strEscape(String(key)), "string"); + name = ctx.stylize(strEscape(String(key)), 'string'); } return `${name}:${extra}${str}`; } @@ -2275,7 +1989,8 @@ function isBelowBreakLength(ctx: Context, output: string[], start: number, base: // function. Check the performance overhead and make it an opt-in in case it's // significant. let totalLength = output.length + start; - if (totalLength + output.length > ctx.breakLength) return false; + if (totalLength + output.length > ctx.breakLength) + return false; for (let i = 0; i < output.length; i++) { if (ctx.colors) { totalLength += removeColors(output[i]!).length; @@ -2287,20 +2002,13 @@ function isBelowBreakLength(ctx: Context, output: string[], start: number, base: } } // Do not line up properties on the same line if `base` contains line breaks. - return base === "" || !base.includes("\n"); + return base === '' || !base.includes('\n'); } function reduceToSingleString( - ctx: Context, - output: string[], - base: string, - braces: [string, string], - extrasType: number, - recurseTimes: number, - value?: unknown -): string { + ctx: Context, output: string[], base: string, braces: [string, string], extrasType: number, recurseTimes: number, value?: unknown): string { if (ctx.compact !== true) { - if (typeof ctx.compact === "number" && ctx.compact >= 1) { + if (typeof ctx.compact === 'number' && ctx.compact >= 1) { // Memorize the original output length. In case the output is grouped, // prevent lining up the entries on a single line. const entries = output.length; @@ -2323,41 +2031,39 @@ function reduceToSingleString( // Consolidate all entries of the local most inner depth up to // `ctx.compact`, as long as the properties are smaller than // `ctx.breakLength`. - if (ctx.currentDepth - recurseTimes < ctx.compact && entries === output.length) { + if (ctx.currentDepth - recurseTimes < ctx.compact && + entries === output.length) { // Line up all entries on a single line in case the entries do not // exceed `breakLength`. Add 10 as constant to start next to all other // factors that may reduce `breakLength`. - const start = - output.length + ctx.indentationLvl + braces[0].length + base.length + 10; + const start = output.length + ctx.indentationLvl + + braces[0].length + base.length + 10; if (isBelowBreakLength(ctx, output, start, base)) { - const joinedOutput = output.join(", "); - if (!joinedOutput.includes("\n")) { - return ( - `${base ? `${base} ` : ""}${braces[0]} ${joinedOutput}` + - ` ${braces[1]}` - ); + const joinedOutput = output.join(', '); + if (!joinedOutput.includes('\n')) { + return `${base ? `${base} ` : ''}${braces[0]} ${joinedOutput}` + + ` ${braces[1]}`; } } } } // Line up each entry on an individual line. - const indentation = `\n${" ".repeat(ctx.indentationLvl)}`; - return ( - `${base ? `${base} ` : ""}${braces[0]}${indentation} ` + - `${output.join(`,${indentation} `)}${indentation}${braces[1]}` - ); + const indentation = `\n${' '.repeat(ctx.indentationLvl)}`; + return `${base ? `${base} ` : ''}${braces[0]}${indentation} ` + + `${output.join(`,${indentation} `)}${indentation}${braces[1]}`; } // Line up all entries on a single line in case the entries do not exceed // `breakLength`. if (isBelowBreakLength(ctx, output, 0, base)) { - return `${braces[0]}${base ? ` ${base}` : ""} ${output.join(", ")} ` + braces[1]; + return `${braces[0]}${base ? ` ${base}` : ''} ${output.join(', ')} ` + + braces[1]; } - const indentation = " ".repeat(ctx.indentationLvl); + const indentation = ' '.repeat(ctx.indentationLvl); // If the opening "brace" is too large, like in the case of "Set {", // we need to force the first item to be on the next line or the // items will not line up correctly. - const ln = - base === "" && braces[0].length === 1 ? " " : `${base ? ` ${base}` : ""}\n${indentation} `; + const ln = base === '' && braces[0].length === 1 ? + ' ' : `${base ? ` ${base}` : ''}\n${indentation} `; // Line up each entry on an individual line. return `${braces[0]}${ln}${output.join(`,\n${indentation} `)} ${braces[1]}`; } @@ -2373,12 +2079,12 @@ function hasBuiltInToString(value: object): boolean { } // Count objects that have no `toString` function as built-in. - if (typeof value?.toString !== "function") { + if (typeof value?.toString !== 'function') { return true; } // The object has a own `toString` property. Thus it's not not a built-in one. - if (Object.prototype.hasOwnProperty.call(value, "toString")) { + if (Object.prototype.hasOwnProperty.call(value, 'toString')) { return false; } @@ -2387,19 +2093,16 @@ function hasBuiltInToString(value: object): boolean { let pointer = value; do { pointer = Object.getPrototypeOf(pointer); - } while (!Object.prototype.hasOwnProperty.call(pointer, "toString")); + } while (!Object.prototype.hasOwnProperty.call(pointer, 'toString')); // Check closer if the object is a built-in. - const descriptor = Object.getOwnPropertyDescriptor(pointer, "constructor"); - return ( - descriptor !== undefined && - typeof descriptor.value === "function" && - builtInObjects.has(descriptor.value.name) - ); + const descriptor = Object.getOwnPropertyDescriptor(pointer, 'constructor'); + return descriptor !== undefined && + typeof descriptor.value === 'function' && + builtInObjects.has(descriptor.value.name); } -const firstErrorLine = (error: unknown) => - (isError(error) ? error.message : String(error)).split("\n", 1)[0]; +const firstErrorLine = (error: unknown) => (isError(error) ? error.message : String(error)).split('\n', 1)[0]; let CIRCULAR_ERROR_MESSAGE: string | undefined; function tryStringify(arg: unknown): string { try { @@ -2415,14 +2118,9 @@ function tryStringify(arg: unknown): string { CIRCULAR_ERROR_MESSAGE = firstErrorLine(circularError); } } - if ( - typeof err === "object" && - err !== null && - "name" in err && - err.name === "TypeError" && - firstErrorLine(err) === CIRCULAR_ERROR_MESSAGE - ) { - return "[Circular]"; + if (typeof err === "object" && err !== null && "name" in err && err.name === 'TypeError' && + firstErrorLine(err) === CIRCULAR_ERROR_MESSAGE) { + return '[Circular]'; } throw err; } @@ -2433,7 +2131,7 @@ export function format(...args: unknown[]): string { } export function formatWithOptions(inspectOptions: InspectOptions, ...args: unknown[]): string { - validateObject(inspectOptions, "inspectOptions", { allowArray: true }); + validateObject(inspectOptions, 'inspectOptions', { allowArray: true }); return formatWithOptionsInternal(inspectOptions, args); } @@ -2441,7 +2139,7 @@ function formatNumberNoColor(number: number, options?: InspectOptions): string { return formatNumber( stylizeNoColor, number, - options?.numericSeparator ?? inspectDefaultOptions.numericSeparator + options?.numericSeparator ?? inspectDefaultOptions.numericSeparator, ); } @@ -2449,20 +2147,17 @@ function formatBigIntNoColor(bigint: bigint, options?: InspectOptions): string { return formatBigInt( stylizeNoColor, bigint, - options?.numericSeparator ?? inspectDefaultOptions.numericSeparator + options?.numericSeparator ?? inspectDefaultOptions.numericSeparator, ); } -function formatWithOptionsInternal( - inspectOptions: InspectOptions | undefined, - args: unknown[] -): string { +function formatWithOptionsInternal(inspectOptions: InspectOptions | undefined, args: unknown[]): string { const first = args[0]; let a = 0; - let str = ""; - let join = ""; + let str = ''; + let join = ''; - if (typeof first === "string") { + if (typeof first === 'string') { if (args.length === 1) { return first; } @@ -2470,23 +2165,19 @@ function formatWithOptionsInternal( let lastPos = 0; for (let i = 0; i < first.length - 1; i++) { - if (first.charCodeAt(i) === 37) { - // '%' + if (first.charCodeAt(i) === 37) { // '%' const nextChar = first.charCodeAt(++i); if (a + 1 !== args.length) { switch (nextChar) { - case 115: { - // 's' + case 115: { // 's' const tempArg = args[++a]; - if (typeof tempArg === "number") { + if (typeof tempArg === 'number') { tempStr = formatNumberNoColor(tempArg, inspectOptions); - } else if (typeof tempArg === "bigint") { + } else if (typeof tempArg === 'bigint') { tempStr = formatBigIntNoColor(tempArg, inspectOptions); - } else if ( - typeof tempArg !== "object" || + } else if (typeof tempArg !== 'object' || tempArg === null || - !hasBuiltInToString(tempArg) - ) { + !hasBuiltInToString(tempArg)) { tempStr = String(tempArg); } else { tempStr = inspect(tempArg, { @@ -2501,13 +2192,12 @@ function formatWithOptionsInternal( case 106: // 'j' tempStr = tryStringify(args[++a]); break; - case 100: { - // 'd' + case 100: { // 'd' const tempNum = args[++a]; - if (typeof tempNum === "bigint") { + if (typeof tempNum === 'bigint') { tempStr = formatBigIntNoColor(tempNum, inspectOptions); - } else if (typeof tempNum === "symbol") { - tempStr = "NaN"; + } else if (typeof tempNum === 'symbol') { + tempStr = 'NaN'; } else { tempStr = formatNumberNoColor(Number(tempNum), inspectOptions); } @@ -2524,37 +2214,31 @@ function formatWithOptionsInternal( depth: 4, }); break; - case 105: { - // 'i' + case 105: { // 'i' const tempInteger = args[++a]; - if (typeof tempInteger === "bigint") { + if (typeof tempInteger === 'bigint') { tempStr = formatBigIntNoColor(tempInteger, inspectOptions); - } else if (typeof tempInteger === "symbol") { - tempStr = "NaN"; + } else if (typeof tempInteger === 'symbol') { + tempStr = 'NaN'; } else { tempStr = formatNumberNoColor( - Number.parseInt(tempInteger as unknown as string), - inspectOptions - ); + Number.parseInt(tempInteger as unknown as string), inspectOptions); } break; } - case 102: { - // 'f' + case 102: { // 'f' const tempFloat = args[++a]; - if (typeof tempFloat === "symbol") { - tempStr = "NaN"; + if (typeof tempFloat === 'symbol') { + tempStr = 'NaN'; } else { tempStr = formatNumberNoColor( - Number.parseFloat(tempFloat as unknown as string), - inspectOptions - ); + Number.parseFloat(tempFloat as unknown as string), inspectOptions); } break; } case 99: // 'c' a += 1; - tempStr = ""; + tempStr = ''; break; case 37: // '%' str += first.slice(lastPos, i); @@ -2576,7 +2260,7 @@ function formatWithOptionsInternal( } if (lastPos !== 0) { a++; - join = " "; + join = ' '; if (lastPos < first.length) { str += first.slice(lastPos); } @@ -2586,25 +2270,23 @@ function formatWithOptionsInternal( while (a < args.length) { const value = args[a]; str += join; - str += typeof value !== "string" ? inspect(value, inspectOptions) : value; - join = " "; + str += typeof value !== 'string' ? inspect(value, inspectOptions) : value; + join = ' '; a++; } return str; } export function isZeroWidthCodePoint(code: number): boolean { - return ( - code <= 0x1f || // C0 control codes - (code >= 0x7f && code <= 0x9f) || // C1 control codes - (code >= 0x300 && code <= 0x36f) || // Combining Diacritical Marks - (code >= 0x200b && code <= 0x200f) || // Modifying Invisible Characters + return code <= 0x1F || // C0 control codes + (code >= 0x7F && code <= 0x9F) || // C1 control codes + (code >= 0x300 && code <= 0x36F) || // Combining Diacritical Marks + (code >= 0x200B && code <= 0x200F) || // Modifying Invisible Characters // Combining Diacritical Marks for Symbols - (code >= 0x20d0 && code <= 0x20ff) || - (code >= 0xfe00 && code <= 0xfe0f) || // Variation Selectors - (code >= 0xfe20 && code <= 0xfe2f) || // Combining Half Marks - (code >= 0xe0100 && code <= 0xe01ef) - ); // Variation Selectors + (code >= 0x20D0 && code <= 0x20FF) || + (code >= 0xFE00 && code <= 0xFE0F) || // Variation Selectors + (code >= 0xFE20 && code <= 0xFE2F) || // Combining Half Marks + (code >= 0xE0100 && code <= 0xE01EF); // Variation Selectors } /** @@ -2613,8 +2295,9 @@ export function isZeroWidthCodePoint(code: number): boolean { export function getStringWidth(str: string, removeControlChars = true): number { let width = 0; - if (removeControlChars) str = stripVTControlCharacters(str); - str = str.normalize("NFC"); + if (removeControlChars) + str = stripVTControlCharacters(str); + str = str.normalize('NFC'); for (const char of str) { const code = char.codePointAt(0)!; if (isFullWidthCodePoint(code)) { @@ -2625,7 +2308,7 @@ export function getStringWidth(str: string, removeControlChars = true): number { } return width; -} +}; /** * Returns true if the character represented by a given @@ -2634,39 +2317,38 @@ export function getStringWidth(str: string, removeControlChars = true): number { const isFullWidthCodePoint = (code: number) => { // Code points are partially derived from: // https://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt - return ( - code >= 0x1100 && - (code <= 0x115f || // Hangul Jamo - code === 0x2329 || // LEFT-POINTING ANGLE BRACKET - code === 0x232a || // RIGHT-POINTING ANGLE BRACKET - // CJK Radicals Supplement .. Enclosed CJK Letters and Months - (code >= 0x2e80 && code <= 0x3247 && code !== 0x303f) || - // Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A - (code >= 0x3250 && code <= 0x4dbf) || - // CJK Unified Ideographs .. Yi Radicals - (code >= 0x4e00 && code <= 0xa4c6) || - // Hangul Jamo Extended-A - (code >= 0xa960 && code <= 0xa97c) || - // Hangul Syllables - (code >= 0xac00 && code <= 0xd7a3) || - // CJK Compatibility Ideographs - (code >= 0xf900 && code <= 0xfaff) || - // Vertical Forms - (code >= 0xfe10 && code <= 0xfe19) || - // CJK Compatibility Forms .. Small Form Variants - (code >= 0xfe30 && code <= 0xfe6b) || - // Halfwidth and Fullwidth Forms - (code >= 0xff01 && code <= 0xff60) || - (code >= 0xffe0 && code <= 0xffe6) || - // Kana Supplement - (code >= 0x1b000 && code <= 0x1b001) || - // Enclosed Ideographic Supplement - (code >= 0x1f200 && code <= 0x1f251) || - // Miscellaneous Symbols and Pictographs 0x1f300 - 0x1f5ff - // Emoticons 0x1f600 - 0x1f64f - (code >= 0x1f300 && code <= 0x1f64f) || - // CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane - (code >= 0x20000 && code <= 0x3fffd)) + return code >= 0x1100 && ( + code <= 0x115f || // Hangul Jamo + code === 0x2329 || // LEFT-POINTING ANGLE BRACKET + code === 0x232a || // RIGHT-POINTING ANGLE BRACKET + // CJK Radicals Supplement .. Enclosed CJK Letters and Months + (code >= 0x2e80 && code <= 0x3247 && code !== 0x303f) || + // Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A + (code >= 0x3250 && code <= 0x4dbf) || + // CJK Unified Ideographs .. Yi Radicals + (code >= 0x4e00 && code <= 0xa4c6) || + // Hangul Jamo Extended-A + (code >= 0xa960 && code <= 0xa97c) || + // Hangul Syllables + (code >= 0xac00 && code <= 0xd7a3) || + // CJK Compatibility Ideographs + (code >= 0xf900 && code <= 0xfaff) || + // Vertical Forms + (code >= 0xfe10 && code <= 0xfe19) || + // CJK Compatibility Forms .. Small Form Variants + (code >= 0xfe30 && code <= 0xfe6b) || + // Halfwidth and Fullwidth Forms + (code >= 0xff01 && code <= 0xff60) || + (code >= 0xffe0 && code <= 0xffe6) || + // Kana Supplement + (code >= 0x1b000 && code <= 0x1b001) || + // Enclosed Ideographic Supplement + (code >= 0x1f200 && code <= 0x1f251) || + // Miscellaneous Symbols and Pictographs 0x1f300 - 0x1f5ff + // Emoticons 0x1f600 - 0x1f64f + (code >= 0x1f300 && code <= 0x1f64f) || + // CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane + (code >= 0x20000 && code <= 0x3fffd) ); }; @@ -2674,9 +2356,9 @@ const isFullWidthCodePoint = (code: number) => { * Remove all VT control characters. Use to estimate displayed string width. */ export function stripVTControlCharacters(str: string): string { - validateString(str, "str"); + validateString(str, 'str'); - return str.replace(ansi, ""); + return str.replace(ansi, ''); } // ================================================================================================ @@ -2694,7 +2376,7 @@ export function formatLog(...args: [...values: unknown[], colors: boolean]): str function isBuiltinPrototype(proto: unknown) { if (proto === null) return true; - const descriptor = Object.getOwnPropertyDescriptor(proto, "constructor"); + const descriptor = Object.getOwnPropertyDescriptor(proto, 'constructor'); return ( descriptor !== undefined && typeof descriptor.value === "function" && @@ -2729,7 +2411,7 @@ function formatJsgResourceType( options: InspectOptionsStylized ): unknown { const name = this.constructor.name; - if (depth < 0) return options.stylize(`[${name}]`, "special"); + if (depth < 0) return options.stylize(`[${name}]`, 'special'); // Build a plain object for inspection. If this value has an `entries()` function, add those // entries for map-like `K => V` formatting. Note we can't use a `Map` here as a key may have @@ -2748,7 +2430,7 @@ function formatJsgResourceType( if (typeof value === "function" || this.constructor.propertyIsEnumerable(key)) continue; record[key] = value; } - } while (!isBuiltinPrototype((current = Object.getPrototypeOf(current)))); + } while (!isBuiltinPrototype(current = Object.getPrototypeOf(current))); // Add additional inspect-only properties as non-enumerable so they appear in square brackets for (const [key, symbol] of Object.entries(additionalProperties)) { @@ -2769,4 +2451,4 @@ function formatJsgResourceType( // something like `Headers(1) { 'a' => '1' }`. return `${name}${inspected.replace("Object", "")}`; } -} +} \ No newline at end of file diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_path.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_path.ts index 174193c23..88659773c 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_path.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_path.ts @@ -1,52 +1,54 @@ -import { CHAR_DOT, CHAR_FORWARD_SLASH } from "./constants"; +import { + CHAR_DOT, + CHAR_FORWARD_SLASH, +} from './constants'; -import { validateObject, validateString } from "./validators"; +import { + validateObject, + validateString, +} from './validators'; -function isPosixPathSeparator(code: number) { +function isPosixPathSeparator(code : number) { return code === CHAR_FORWARD_SLASH; } // Resolves . and .. elements in a path with directory names -function normalizeString( - path: string, - allowAboveRoot: boolean, - separator: string, - isPathSeparator: (code: number) => boolean -) { - let res = ""; +function normalizeString(path: string, allowAboveRoot: boolean, separator: string, isPathSeparator: (code:number) => boolean) { + let res = ''; let lastSegmentLength = 0; let lastSlash = -1; let dots = 0; let code = 0; for (let i = 0; i <= path.length; ++i) { - if (i < path.length) code = path.charCodeAt(i); - else if (isPathSeparator(code)) break; - else code = CHAR_FORWARD_SLASH; + if (i < path.length) + code = path.charCodeAt(i); + else if (isPathSeparator(code)) + break; + else + code = CHAR_FORWARD_SLASH; if (isPathSeparator(code)) { if (lastSlash === i - 1 || dots === 1) { // NOOP } else if (dots === 2) { - if ( - res.length < 2 || - lastSegmentLength !== 2 || + if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== CHAR_DOT || - res.charCodeAt(res.length - 2) !== CHAR_DOT - ) { + res.charCodeAt(res.length - 2) !== CHAR_DOT) { if (res.length > 2) { const lastSlashIndex = res.lastIndexOf(separator); if (lastSlashIndex === -1) { - res = ""; + res = ''; lastSegmentLength = 0; } else { res = res.slice(0, lastSlashIndex); - lastSegmentLength = res.length - 1 - res.lastIndexOf(separator); + lastSegmentLength = + res.length - 1 - res.lastIndexOf(separator); } lastSlash = i; dots = 0; continue; } else if (res.length !== 0) { - res = ""; + res = ''; lastSegmentLength = 0; lastSlash = i; dots = 0; @@ -54,12 +56,14 @@ function normalizeString( } } if (allowAboveRoot) { - res += res.length > 0 ? `${separator}..` : ".."; + res += res.length > 0 ? `${separator}..` : '..'; lastSegmentLength = 2; } } else { - if (res.length > 0) res += `${separator}${path.slice(lastSlash + 1, i)}`; - else res = path.slice(lastSlash + 1, i); + if (res.length > 0) + res += `${separator}${path.slice(lastSlash + 1, i)}`; + else + res = path.slice(lastSlash + 1, i); lastSegmentLength = i - lastSlash - 1; } lastSlash = i; @@ -73,8 +77,8 @@ function normalizeString( return res; } -function formatExt(ext: string) { - return ext ? `${ext[0] === "." ? "" : "."}${ext}` : ""; +function formatExt(ext : string) { + return ext ? `${ext[0] === '.' ? '' : '.'}${ext}` : ''; } /** @@ -97,10 +101,11 @@ type PathObject = { ext?: string; }; -function _format(sep: string, pathObject: PathObject) { - validateObject(pathObject, "pathObject", {}); +function _format(sep : string, pathObject : PathObject) { + validateObject(pathObject, 'pathObject', {}); const dir = pathObject.dir || pathObject.root; - const base = pathObject.base || `${pathObject.name || ""}${formatExt(pathObject.ext!)}`; + const base = pathObject.base || + `${pathObject.name || ''}${formatExt(pathObject.ext!)}`; if (!dir) { return base; } @@ -110,53 +115,53 @@ function _format(sep: string, pathObject: PathObject) { // We currently do not implement the path.win32 subset. const win32 = { resolve(..._: [string[], string]) { - throw new Error("path.win32.resolve() is not implemented."); + throw new Error('path.win32.resolve() is not implemented.'); }, - normalize(_: string) { - throw new Error("path.win32.normalize() is not implemented."); + normalize(_ : string) { + throw new Error('path.win32.normalize() is not implemented.'); }, - isAbsolute(_: string) { - throw new Error("path.win32.isAbsolute() is not implemented."); + isAbsolute(_ : string) { + throw new Error('path.win32.isAbsolute() is not implemented.'); }, - join(..._: string[]) { - throw new Error("path.win32.join() is not implemented."); + join(..._ : string[]) { + throw new Error('path.win32.join() is not implemented.'); }, - relative(_0: string, _1: string) { - throw new Error("path.win32.relative() is not implemented."); + relative(_0 : string, _1 : string) { + throw new Error('path.win32.relative() is not implemented.'); }, - toNamespacedPath(_: string) { - throw new Error("path.win32.toNamedspacedPath() is not implemented."); + toNamespacedPath(_ : string) { + throw new Error('path.win32.toNamedspacedPath() is not implemented.'); }, - dirname(_: string) { - throw new Error("path.win32.dirname() is not implemented."); + dirname(_ : string) { + throw new Error('path.win32.dirname() is not implemented.'); }, - basename(_0: string, _1?: string) { - throw new Error("path.win32.basename() is not implemented."); - }, + basename(_0 : string, _1? : string) { + throw new Error('path.win32.basename() is not implemented.'); +}, - extname(_: string) { - throw new Error("path.win32.extname() is not implemented."); - }, +extname(_ : string) { + throw new Error('path.win32.extname() is not implemented.'); +}, - format(_: PathObject) { - throw new Error("path.win32.format() is not implemented."); - }, +format(_ : PathObject) { + throw new Error('path.win32.format() is not implemented.'); +}, - parse(_: string) { - throw new Error("path.win32.parse() is not implemented."); - }, +parse(_: string) { + throw new Error('path.win32.parse() is not implemented.'); +}, - sep: "\\", - delimiter: ";", - win32: null as Object | null, - posix: null as Object | null, +sep: '\\', + delimiter: ';', + win32: null as Object|null, + posix: null as Object|null, }; const posix = { @@ -166,13 +171,13 @@ const posix = { * @returns {string} */ resolve(...args: string[]) { - let resolvedPath = ""; + let resolvedPath = ''; let resolvedAbsolute = false; for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) { - const path = i >= 0 ? args[i] : "/"; + const path = i >= 0 ? args[i] : '/'; - validateString(path, "path"); + validateString(path, 'path'); // Skip empty entries if (path!.length === 0) { @@ -187,34 +192,38 @@ const posix = { // handle relative paths to be safe (might happen when process.cwd() fails) // Normalize the path - resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, "/", isPosixPathSeparator); + resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, '/', + isPosixPathSeparator); if (resolvedAbsolute) { return `/${resolvedPath}`; } - return resolvedPath.length > 0 ? resolvedPath : "."; + return resolvedPath.length > 0 ? resolvedPath : '.'; }, /** * @param {string} path * @returns {string} */ - normalize(path: string) { - validateString(path, "path"); + normalize(path : string) { + validateString(path, 'path'); - if (path.length === 0) return "."; + if (path.length === 0) + return '.'; const isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH; const trailingSeparator = path.charCodeAt(path.length - 1) === CHAR_FORWARD_SLASH; // Normalize the path - path = normalizeString(path, !isAbsolute, "/", isPosixPathSeparator); + path = normalizeString(path, !isAbsolute, '/', isPosixPathSeparator); if (path.length === 0) { - if (isAbsolute) return "/"; - return trailingSeparator ? "./" : "."; + if (isAbsolute) + return '/'; + return trailingSeparator ? './' : '.'; } - if (trailingSeparator) path += "/"; + if (trailingSeparator) + path += '/'; return isAbsolute ? `/${path}` : path; }, @@ -223,8 +232,8 @@ const posix = { * @param {string} path * @returns {boolean} */ - isAbsolute(path: string) { - validateString(path, "path"); + isAbsolute(path : string) { + validateString(path, 'path'); return path.length > 0 && path.charCodeAt(0) === CHAR_FORWARD_SLASH; }, @@ -232,18 +241,22 @@ const posix = { * @param {...string} args * @returns {string} */ - join(...args: string[]) { - if (args.length === 0) return "."; + join(...args : string[]) { + if (args.length === 0) + return '.'; let joined; for (let i = 0; i < args.length; ++i) { const arg = args[i]; - validateString(arg, "path"); + validateString(arg, 'path'); if (arg!.length > 0) { - if (joined === undefined) joined = arg; - else joined += `/${arg}`; + if (joined === undefined) + joined = arg; + else + joined += `/${arg}`; } } - if (joined === undefined) return "."; + if (joined === undefined) + return '.'; return posix.normalize(joined); }, @@ -252,17 +265,19 @@ const posix = { * @param {string} to * @returns {string} */ - relative(from: string, to: string) { - validateString(from, "from"); - validateString(to, "to"); + relative(from: string, to : string) { + validateString(from, 'from'); + validateString(to, 'to'); - if (from === to) return ""; + if (from === to) + return ''; // Trim leading forward slashes. from = posix.resolve(from); to = posix.resolve(to); - if (from === to) return ""; + if (from === to) + return ''; const fromStart = 1; const fromEnd = from.length; @@ -271,13 +286,15 @@ const posix = { const toLen = to.length - toStart; // Compare paths to find the longest common path from root - const length = fromLen < toLen ? fromLen : toLen; + const length = (fromLen < toLen ? fromLen : toLen); let lastCommonSep = -1; let i = 0; for (; i < length; i++) { const fromCode = from.charCodeAt(fromStart + i); - if (fromCode !== to.charCodeAt(toStart + i)) break; - else if (fromCode === CHAR_FORWARD_SLASH) lastCommonSep = i; + if (fromCode !== to.charCodeAt(toStart + i)) + break; + else if (fromCode === CHAR_FORWARD_SLASH) + lastCommonSep = i; } if (i === length) { if (toLen > length) { @@ -304,12 +321,12 @@ const posix = { } } - let out = ""; + let out = ''; // Generate the relative path based on the path difference between `to` // and `from`. for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { if (i === fromEnd || from.charCodeAt(i) === CHAR_FORWARD_SLASH) { - out += out.length === 0 ? ".." : "/.."; + out += out.length === 0 ? '..' : '/..'; } } @@ -322,7 +339,7 @@ const posix = { * @param {string} path * @returns {string} */ - toNamespacedPath(path: string) { + toNamespacedPath(path : string) { // Non-op on posix systems return path; }, @@ -331,9 +348,10 @@ const posix = { * @param {string} path * @returns {string} */ - dirname(path: string) { - validateString(path, "path"); - if (path.length === 0) return "."; + dirname(path : string) { + validateString(path, 'path'); + if (path.length === 0) + return '.'; const hasRoot = path.charCodeAt(0) === CHAR_FORWARD_SLASH; let end = -1; let matchedSlash = true; @@ -349,8 +367,10 @@ const posix = { } } - if (end === -1) return hasRoot ? "/" : "."; - if (hasRoot && end === 1) return "//"; + if (end === -1) + return hasRoot ? '/' : '.'; + if (hasRoot && end === 1) + return '//'; return path.slice(0, end); }, @@ -359,131 +379,138 @@ const posix = { * @param {string} [suffix] * @returns {string} */ - basename(path: string, suffix?: string) { - if (suffix !== undefined) validateString(suffix, "ext"); - validateString(path, "path"); - - let start = 0; - let end = -1; - let matchedSlash = true; - - if (suffix !== undefined && suffix.length > 0 && suffix.length <= path.length) { - if (suffix === path) return ""; - let extIdx = suffix.length - 1; - let firstNonSlashEnd = -1; - for (let i = path.length - 1; i >= 0; --i) { - const code = path.charCodeAt(i); - if (code === CHAR_FORWARD_SLASH) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - start = i + 1; - break; - } - } else { - if (firstNonSlashEnd === -1) { - // We saw the first non-path separator, remember this index in case - // we need it if the extension ends up not matching - matchedSlash = false; - firstNonSlashEnd = i + 1; - } - if (extIdx >= 0) { - // Try to match the explicit extension - if (code === suffix.charCodeAt(extIdx)) { - if (--extIdx === -1) { - // We matched the extension, so mark this as the end of our path - // component - end = i; - } - } else { - // Extension does not match, so our result is the entire path - // component - extIdx = -1; - end = firstNonSlashEnd; - } - } - } - } - - if (start === end) end = firstNonSlashEnd; - else if (end === -1) end = path.length; - return path.slice(start, end); - } + basename(path : string, suffix? : string) { + if (suffix !== undefined) + validateString(suffix, 'ext'); + validateString(path, 'path'); + + let start = 0; + let end = -1; + let matchedSlash = true; + + if (suffix !== undefined && suffix.length > 0 && suffix.length <= path.length) { + if (suffix === path) + return ''; + let extIdx = suffix.length - 1; + let firstNonSlashEnd = -1; for (let i = path.length - 1; i >= 0; --i) { - if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) { + const code = path.charCodeAt(i); + if (code === CHAR_FORWARD_SLASH) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { start = i + 1; break; } - } else if (end === -1) { - // We saw the first non-path separator, mark this as the end of our - // path component - matchedSlash = false; - end = i + 1; + } else { + if (firstNonSlashEnd === -1) { + // We saw the first non-path separator, remember this index in case + // we need it if the extension ends up not matching + matchedSlash = false; + firstNonSlashEnd = i + 1; + } + if (extIdx >= 0) { + // Try to match the explicit extension + if (code === suffix.charCodeAt(extIdx)) { + if (--extIdx === -1) { + // We matched the extension, so mark this as the end of our path + // component + end = i; + } + } else { + // Extension does not match, so our result is the entire path + // component + extIdx = -1; + end = firstNonSlashEnd; + } + } } } - if (end === -1) return ""; + if (start === end) + end = firstNonSlashEnd; + else if (end === -1) + end = path.length; return path.slice(start, end); - }, - - /** - * @param {string} path - * @returns {string} - */ - extname(path: string) { - validateString(path, "path"); - let startDot = -1; - let startPart = 0; - let end = -1; - let matchedSlash = true; - // Track the state of characters (if any) we see before our first dot and - // after any path separator we find - let preDotState = 0; - for (let i = path.length - 1; i >= 0; --i) { - const code = path.charCodeAt(i); - if (code === CHAR_FORWARD_SLASH) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - startPart = i + 1; - break; - } - continue; - } - if (end === -1) { - // We saw the first non-path separator, mark this as the end of our - // extension - matchedSlash = false; - end = i + 1; - } - if (code === CHAR_DOT) { - // If this is our first dot, mark it as the start of our extension - if (startDot === -1) startDot = i; - else if (preDotState !== 1) preDotState = 1; - } else if (startDot !== -1) { - // We saw a non-dot and non-path separator before our dot, so we should - // have a good chance at having a non-empty extension - preDotState = -1; + } + for (let i = path.length - 1; i >= 0; --i) { + if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + start = i + 1; + break; } + } else if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // path component + matchedSlash = false; + end = i + 1; } + } - if ( - startDot === -1 || - end === -1 || - // We saw a non-dot character immediately before the dot - preDotState === 0 || - // The (right-most) trimmed path component is exactly '..' - (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) - ) { - return ""; + if (end === -1) + return ''; + return path.slice(start, end); +}, + +/** + * @param {string} path + * @returns {string} + */ +extname(path : string) { + validateString(path, 'path'); + let startDot = -1; + let startPart = 0; + let end = -1; + let matchedSlash = true; + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + let preDotState = 0; + for (let i = path.length - 1; i >= 0; --i) { + const code = path.charCodeAt(i); + if (code === CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + startPart = i + 1; + break; + } + continue; } - return path.slice(startDot, end); - }, + if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (code === CHAR_DOT) { + // If this is our first dot, mark it as the start of our extension + if (startDot === -1) + startDot = i; + else if (preDotState !== 1) + preDotState = 1; + } else if (startDot !== -1) { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = -1; + } + } + + if (startDot === -1 || + end === -1 || + // We saw a non-dot character immediately before the dot + preDotState === 0 || + // The (right-most) trimmed path component is exactly '..' + (preDotState === 1 && + startDot === end - 1 && + startDot === startPart + 1)) { + return ''; + } + return path.slice(startDot, end); +}, - format: _format.bind(null, "/"), +format: _format.bind(null, '/'), /** * @param {string} path @@ -495,89 +522,95 @@ const posix = { * ext: string; * }} */ - parse(path: string): PathObject { - validateString(path, "path"); - - const ret = { root: "", dir: "", base: "", ext: "", name: "" }; - if (path.length === 0) return ret; - const isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH; - let start; - if (isAbsolute) { - ret.root = "/"; - start = 1; - } else { - start = 0; - } - let startDot = -1; - let startPart = 0; - let end = -1; - let matchedSlash = true; - let i = path.length - 1; - - // Track the state of characters (if any) we see before our first dot and - // after any path separator we find - let preDotState = 0; + parse(path: string) : PathObject { + validateString(path, 'path'); - // Get non-dir info - for (; i >= start; --i) { - const code = path.charCodeAt(i); - if (code === CHAR_FORWARD_SLASH) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - startPart = i + 1; - break; - } - continue; - } - if (end === -1) { - // We saw the first non-path separator, mark this as the end of our - // extension - matchedSlash = false; - end = i + 1; - } - if (code === CHAR_DOT) { - // If this is our first dot, mark it as the start of our extension - if (startDot === -1) startDot = i; - else if (preDotState !== 1) preDotState = 1; - } else if (startDot !== -1) { - // We saw a non-dot and non-path separator before our dot, so we should - // have a good chance at having a non-empty extension - preDotState = -1; + const ret = { root: '', dir: '', base: '', ext: '', name: '' }; + if (path.length === 0) + return ret; + const isAbsolute = + path.charCodeAt(0) === CHAR_FORWARD_SLASH; + let start; + if (isAbsolute) { + ret.root = '/'; + start = 1; + } else { + start = 0; + } + let startDot = -1; + let startPart = 0; + let end = -1; + let matchedSlash = true; + let i = path.length - 1; + + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + let preDotState = 0; + + // Get non-dir info + for (; i >= start; --i) { + const code = path.charCodeAt(i); + if (code === CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + startPart = i + 1; + break; } + continue; } + if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (code === CHAR_DOT) { + // If this is our first dot, mark it as the start of our extension + if (startDot === -1) + startDot = i; + else if (preDotState !== 1) + preDotState = 1; + } else if (startDot !== -1) { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = -1; + } + } - if (end !== -1) { - const start = startPart === 0 && isAbsolute ? 1 : startPart; - if ( - startDot === -1 || - // We saw a non-dot character immediately before the dot - preDotState === 0 || - // The (right-most) trimmed path component is exactly '..' - (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) - ) { - ret.base = ret.name = path.slice(start, end); - } else { - ret.name = path.slice(start, startDot); - ret.base = path.slice(start, end); - ret.ext = path.slice(startDot, end); - } + if (end !== -1) { + const start = startPart === 0 && isAbsolute ? 1 : startPart; + if (startDot === -1 || + // We saw a non-dot character immediately before the dot + preDotState === 0 || + // The (right-most) trimmed path component is exactly '..' + (preDotState === 1 && + startDot === end - 1 && + startDot === startPart + 1)) { + ret.base = ret.name = path.slice(start, end); + } else { + ret.name = path.slice(start, startDot); + ret.base = path.slice(start, end); + ret.ext = path.slice(startDot, end); } + } - if (startPart > 0) ret.dir = path.slice(0, startPart - 1); - else if (isAbsolute) ret.dir = "/"; + if (startPart > 0) + ret.dir = path.slice(0, startPart - 1); + else if (isAbsolute) + ret.dir = '/'; - return ret; - }, + return ret; +}, - sep: "/", - delimiter: ":", - win32: null as Object | null, - posix: null as Object | null, +sep: '/', + delimiter: ':', + win32: null as Object|null, + posix: null as Object|null, }; posix.win32 = win32.win32 = win32; posix.posix = win32.posix = posix; export default posix; -export { posix, win32 }; +export { posix, win32 }; \ No newline at end of file diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_stringdecoder.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_stringdecoder.ts index 0ed5a1db5..63474c628 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_stringdecoder.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_stringdecoder.ts @@ -1,8 +1,13 @@ -import { Buffer, isEncoding } from "./internal_buffer"; -import { normalizeEncoding } from "./internal_utils"; -import { ERR_INVALID_ARG_TYPE, ERR_INVALID_THIS, ERR_UNKNOWN_ENCODING } from "./internal_errors"; -import * as bufferUtil from "./buffer"; +import { Buffer, isEncoding } from './internal_buffer'; +import { normalizeEncoding } from './internal_utils'; +import { + ERR_INVALID_ARG_TYPE, + ERR_INVALID_THIS, + ERR_UNKNOWN_ENCODING, +} from './internal_errors'; + +import * as bufferUtil from './buffer'; const kIncompleteCharactersStart = 0; const kIncompleteCharactersEnd = 4; @@ -11,83 +16,81 @@ const kBufferedBytes = 5; const kEncoding = 6; const kSize = 7; -const encodings: Record = { - ascii: 0, - latin1: 1, - utf8: 2, - utf16le: 3, - base64: 4, - base64url: 5, - hex: 6, +const encodings : Record = { + ascii: 0, + latin1: 1, + utf8: 2, + utf16le: 3, + base64: 4, + base64url: 5, + hex: 6, }; -const kNativeDecoder = Symbol("kNativeDecoder"); +const kNativeDecoder = Symbol('kNativeDecoder'); export interface StringDecoder { - encoding: string; - readonly lastChar: Uint8Array; - readonly lastNeed: number; - readonly lastTotal: number; - new (encoding?: string): StringDecoder; - write(buf: ArrayBufferView | DataView | string): string; - end(buf?: ArrayBufferView | DataView | string): string; - text(buf: ArrayBufferView | DataView | string, offset?: number): string; - new (encoding?: string): StringDecoder; + encoding: string; + readonly lastChar: Uint8Array; + readonly lastNeed: number; + readonly lastTotal: number; + new (encoding? : string): StringDecoder; + write(buf: ArrayBufferView|DataView|string): string; + end(buf?: ArrayBufferView|DataView|string): string; + text(buf: ArrayBufferView|DataView|string, offset?: number): string; + new (encoding?: string): StringDecoder; } interface InternalDecoder extends StringDecoder { - [kNativeDecoder]: Buffer; + [kNativeDecoder]: Buffer; } -export function StringDecoder(this: StringDecoder, encoding: string = "utf8") { - const normalizedEncoding = normalizeEncoding(encoding); - if (!isEncoding(normalizedEncoding)) { - throw new ERR_UNKNOWN_ENCODING(encoding); - } - (this as InternalDecoder)[kNativeDecoder] = Buffer.alloc(kSize); - (this as InternalDecoder)[kNativeDecoder][kEncoding] = encodings[normalizedEncoding!]!; - this.encoding = normalizedEncoding!; +export function StringDecoder(this: StringDecoder, encoding: string = 'utf8') { + const normalizedEncoding = normalizeEncoding(encoding); + if (!isEncoding(normalizedEncoding)) { + throw new ERR_UNKNOWN_ENCODING(encoding); + } + (this as InternalDecoder)[kNativeDecoder] = Buffer.alloc(kSize); + (this as InternalDecoder)[kNativeDecoder][kEncoding] = encodings[normalizedEncoding!]!; + this.encoding = normalizedEncoding!; } -function write(this: StringDecoder, buf: ArrayBufferView | DataView | string): string { - if ((this as InternalDecoder)[kNativeDecoder] === undefined) { - throw new ERR_INVALID_THIS("StringDecoder"); - } - if (typeof buf === "string") { - return buf; - } - if (!ArrayBuffer.isView(buf)) { - throw new ERR_INVALID_ARG_TYPE("buf", ["Buffer", "TypedArray", "DataView", "string"], buf); - } - const buffer = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); - return bufferUtil.decode(buffer, (this as InternalDecoder)[kNativeDecoder]); +function write(this: StringDecoder, buf: ArrayBufferView|DataView|string): string { + if ((this as InternalDecoder)[kNativeDecoder] === undefined) { + throw new ERR_INVALID_THIS('StringDecoder'); + } + if (typeof buf === 'string') { + return buf; + } + if (!ArrayBuffer.isView(buf)) { + throw new ERR_INVALID_ARG_TYPE('buf', [ + 'Buffer', 'TypedArray', 'DataView', 'string' + ], buf); + } + const buffer = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); + return bufferUtil.decode(buffer, (this as InternalDecoder)[kNativeDecoder]); } -function end(this: StringDecoder, buf?: ArrayBufferView | DataView | string): string { - if ((this as InternalDecoder)[kNativeDecoder] === undefined) { - throw new ERR_INVALID_THIS("StringDecoder"); - } - let ret = ""; - if (buf !== undefined) { - ret = this.write(buf); - } - if ((this as InternalDecoder)[kNativeDecoder][kBufferedBytes]! > 0) { - ret += bufferUtil.flush((this as InternalDecoder)[kNativeDecoder]); - } - return ret; +function end(this: StringDecoder, buf?: ArrayBufferView|DataView|string): string { + if ((this as InternalDecoder)[kNativeDecoder] === undefined) { + throw new ERR_INVALID_THIS('StringDecoder'); + } + let ret = ''; + if (buf !== undefined) { + ret = this.write(buf); + } + if ((this as InternalDecoder)[kNativeDecoder][kBufferedBytes]! > 0) { + ret += bufferUtil.flush((this as InternalDecoder)[kNativeDecoder]); + } + return ret; } -function text( - this: StringDecoder, - buf: ArrayBufferView | DataView | string, - offset?: number -): string { - if ((this as InternalDecoder)[kNativeDecoder] === undefined) { - throw new ERR_INVALID_THIS("StringDecoder"); - } - (this as InternalDecoder)[kNativeDecoder][kMissingBytes] = 0; - (this as InternalDecoder)[kNativeDecoder][kBufferedBytes] = 0; - return this.write((buf as any).slice(offset)); +function text(this: StringDecoder, buf: ArrayBufferView|DataView|string, offset?: number) : string { + if ((this as InternalDecoder)[kNativeDecoder] === undefined) { + throw new ERR_INVALID_THIS('StringDecoder'); + } + (this as InternalDecoder)[kNativeDecoder][kMissingBytes] = 0; + (this as InternalDecoder)[kNativeDecoder][kBufferedBytes] = 0; + return this.write((buf as any).slice(offset)); } StringDecoder.prototype.write = write; @@ -95,41 +98,37 @@ StringDecoder.prototype.end = end; StringDecoder.prototype.text = text; Object.defineProperties(StringDecoder.prototype, { - lastChar: { - enumerable: true, - get(this: StringDecoder): Buffer { - if ((this as InternalDecoder)[kNativeDecoder] === undefined) { - throw new ERR_INVALID_THIS("StringDecoder"); - } - return (this as InternalDecoder)[kNativeDecoder].subarray( - kIncompleteCharactersStart, - kIncompleteCharactersEnd - ) as Buffer; - }, + lastChar: { + enumerable: true, + get(this: StringDecoder) : Buffer { + if ((this as InternalDecoder)[kNativeDecoder] === undefined) { + throw new ERR_INVALID_THIS('StringDecoder'); + } + return (this as InternalDecoder)[kNativeDecoder].subarray( + kIncompleteCharactersStart, kIncompleteCharactersEnd) as Buffer; }, - lastNeed: { - enumerable: true, - get(this: StringDecoder): number { - if ((this as InternalDecoder)[kNativeDecoder] === undefined) { - throw new ERR_INVALID_THIS("StringDecoder"); - } - return (this as InternalDecoder)[kNativeDecoder][kMissingBytes]!; - }, + }, + lastNeed: { + enumerable: true, + get(this: StringDecoder) : number { + if ((this as InternalDecoder)[kNativeDecoder] === undefined) { + throw new ERR_INVALID_THIS('StringDecoder'); + } + return (this as InternalDecoder)[kNativeDecoder][kMissingBytes]!; }, - lastTotal: { - enumerable: true, - get(this: StringDecoder): number { - if ((this as InternalDecoder)[kNativeDecoder] === undefined) { - throw new ERR_INVALID_THIS("StringDecoder"); - } - return ( - (this as InternalDecoder)[kNativeDecoder][kBufferedBytes]! + - (this as InternalDecoder)[kNativeDecoder][kMissingBytes]! - ); - }, + }, + lastTotal: { + enumerable: true, + get(this: StringDecoder) : number { + if ((this as InternalDecoder)[kNativeDecoder] === undefined) { + throw new ERR_INVALID_THIS('StringDecoder'); + } + return (this as InternalDecoder)[kNativeDecoder][kBufferedBytes]! + + (this as InternalDecoder)[kNativeDecoder][kMissingBytes]!; }, + }, }); export default { - StringDecoder, + StringDecoder }; diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_types.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_types.ts index 5fd751258..5fb614dff 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_types.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_types.ts @@ -1,3 +1,4 @@ + import * as internal from "./util"; export function isCryptoKey(value: unknown): boolean { @@ -93,4 +94,4 @@ export default { isUint16Array, isUint32Array, // TODO(soon): isExternal -}; +}; \ No newline at end of file diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_utils.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_utils.ts index 6cf8b3848..a75b67790 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_utils.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/internal_utils.ts @@ -1,10 +1,14 @@ -export function normalizeEncoding(enc?: string): string | undefined { - if (enc == null || enc === "utf8" || enc === "utf-8" || enc === "UTF8" || enc === "UTF-8") - return "utf8"; + +export function normalizeEncoding(enc?: string) : string | undefined { + if (enc == null || + enc === "utf8" || + enc === "utf-8" || + enc === "UTF8" || + enc === "UTF-8") return "utf8"; return slowCases(enc); } -export function slowCases(enc: string): string | undefined { +export function slowCases(enc: string) : string | undefined { switch (enc.length) { case 4: if (enc === "UTF8") return "utf8"; @@ -14,7 +18,10 @@ export function slowCases(enc: string): string | undefined { if (enc === "ucs2") return "utf16le"; break; case 3: - if (enc === "hex" || enc === "HEX" || `${enc}`.toLowerCase() === "hex") { + if ( + enc === "hex" || enc === "HEX" || + `${enc}`.toLowerCase() === "hex" + ) { return "hex"; } break; @@ -39,19 +46,24 @@ export function slowCases(enc: string): string | undefined { if (enc === "latin1" || enc === "binary") return "latin1"; break; case 7: - if (enc === "utf16le" || enc === "UTF16LE" || `${enc}`.toLowerCase() === "utf16le") { + if ( + enc === "utf16le" || enc === "UTF16LE" || + `${enc}`.toLowerCase() === "utf16le" + ) { return "utf16le"; } break; case 8: - if (enc === "utf-16le" || enc === "UTF-16LE" || `${enc}`.toLowerCase() === "utf-16le") { + if ( + enc === "utf-16le" || enc === "UTF-16LE" || + `${enc}`.toLowerCase() === "utf-16le" + ) { return "utf16le"; } break; case 9: if ( - enc === "base64url" || - enc === "BASE64URL" || + enc === "base64url" || enc === "BASE64URL" || `${enc}`.toLowerCase() === "base64url" ) { return "base64url"; @@ -63,7 +75,7 @@ export function slowCases(enc: string): string | undefined { return undefined; } -export function spliceOne(list: (string | undefined)[], index: number) { +export function spliceOne(list: (string|undefined)[], index: number) { for (; index + 1 < list.length; index++) list[index] = list[index + 1]; list.pop(); } @@ -88,21 +100,20 @@ export function isArrayIndex(value: unknown): value is number | string { } const length = value.length; if (length === 0) { - return (isNumericLookup[value] = false); + return isNumericLookup[value] = false; } let ch = 0; let i = 0; for (; i < length; ++i) { ch = value.charCodeAt(i); if ( - (i === 0 && ch === 0x30 && length > 1) /* must not start with 0 */ || - ch < 0x30 /* 0 */ || - ch > 0x39 /* 9 */ + i === 0 && ch === 0x30 && length > 1 /* must not start with 0 */ || + ch < 0x30 /* 0 */ || ch > 0x39 /* 9 */ ) { - return (isNumericLookup[value] = false); + return isNumericLookup[value] = false; } } - return (isNumericLookup[value] = true); + return isNumericLookup[value] = true; } default: return false; @@ -112,9 +123,12 @@ export function isArrayIndex(value: unknown): value is number | string { export function getOwnNonIndexProperties( // deno-lint-ignore ban-types obj: object, - filter: number + filter: number, ): (string | symbol)[] { - let allProperties = [...Object.getOwnPropertyNames(obj), ...Object.getOwnPropertySymbols(obj)]; + let allProperties = [ + ...Object.getOwnPropertyNames(obj), + ...Object.getOwnPropertySymbols(obj), + ]; if (Array.isArray(obj)) { allProperties = allProperties.filter((k) => !isArrayIndex(k)); @@ -158,10 +172,11 @@ export function createDeferredPromise() { const promise = new Promise((res, rej) => { resolve = res; reject = rej; - }); + }) return { promise, resolve, reject, }; } + diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/process.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/process.ts index 522a74ecd..d72466f2c 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/process.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/process.ts @@ -1,12 +1,14 @@ -import { validateObject } from "./validators"; +import { + validateObject, +} from './validators'; -import { ERR_INVALID_ARG_VALUE } from "./internal_errors"; +import { + ERR_INVALID_ARG_VALUE, +} from './internal_errors' export function nextTick(cb: Function, ...args: unknown[]) { - queueMicrotask(() => { - cb(...args); - }); -} + queueMicrotask(() => { cb(...args); }); +}; // Note that there is no process-level environment in workers so the process.env // object is initially empty. This is different from Node.js where process.env @@ -14,67 +16,50 @@ export function nextTick(cb: Function, ...args: unknown[]) { // for the worker are accessible from the env argument passed into the fetch // handler and have no impact here. -export const env = new Proxy( - {}, - { - // Per Node.js rules. process.env values must be coerced to strings. - // When defined using defineProperty, the property descriptor must be writable, - // configurable, and enumerable using just a falsy check. Getters and setters - // are not permitted. - set(obj: object, prop: PropertyKey, value: any) { - return Reflect.set(obj, prop, `${value}`); - }, - defineProperty(obj: object, prop: PropertyKey, descriptor: PropertyDescriptor) { - validateObject(descriptor, "descriptor", {}); - if (Reflect.has(descriptor, "get") || Reflect.has(descriptor, "set")) { - throw new ERR_INVALID_ARG_VALUE( - "descriptor", - descriptor, - "process.env value must not have getter/setter" - ); - } - if (!descriptor.configurable) { - throw new ERR_INVALID_ARG_VALUE( - "descriptor.configurable", - descriptor, - "process.env value must be configurable" - ); - } - if (!descriptor.enumerable) { - throw new ERR_INVALID_ARG_VALUE( - "descriptor.enumerable", - descriptor, - "process.env value must be enumerable" - ); - } - if (!descriptor.writable) { - throw new ERR_INVALID_ARG_VALUE( - "descriptor.writable", - descriptor, - "process.env value must be writable" - ); - } - if (Reflect.has(descriptor, "value")) { - Reflect.set(descriptor, "value", `${descriptor.value}`); - } else { - throw new ERR_INVALID_ARG_VALUE( - "descriptor.value", - descriptor, - "process.env value must be specified explicitly" - ); - } - return Reflect.defineProperty(obj, prop, descriptor); - }, +export const env = new Proxy({}, { + // Per Node.js rules. process.env values must be coerced to strings. + // When defined using defineProperty, the property descriptor must be writable, + // configurable, and enumerable using just a falsy check. Getters and setters + // are not permitted. + set(obj: object, prop: PropertyKey, value: any) { + return Reflect.set(obj, prop, `${value}`); + }, + defineProperty(obj: object, prop: PropertyKey, descriptor: PropertyDescriptor) { + validateObject(descriptor, 'descriptor', {}); + if (Reflect.has(descriptor, 'get') || Reflect.has(descriptor, 'set')) { + throw new ERR_INVALID_ARG_VALUE('descriptor', descriptor, + 'process.env value must not have getter/setter'); + } + if (!descriptor.configurable) { + throw new ERR_INVALID_ARG_VALUE('descriptor.configurable', descriptor, + 'process.env value must be configurable') + } + if (!descriptor.enumerable) { + throw new ERR_INVALID_ARG_VALUE('descriptor.enumerable', descriptor, + 'process.env value must be enumerable') } -); + if (!descriptor.writable) { + throw new ERR_INVALID_ARG_VALUE('descriptor.writable', descriptor, + 'process.env value must be writable') + } + if (Reflect.has(descriptor, 'value')) { + Reflect.set(descriptor, 'value', `${descriptor.value}`); + } else { + throw new ERR_INVALID_ARG_VALUE('descriptor.value', descriptor, + 'process.env value must be specified explicitly'); + } + return Reflect.defineProperty(obj, prop, descriptor); + } +}); export const argv = []; -export const platform = "wasm"; +export const platform = 'wasm'; + export default { - nextTick, - env, - argv, - platform, + nextTick, + env, + argv, + platform, }; diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_adapters.js b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_adapters.js index 819808333..ad3aadfed 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_adapters.js +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_adapters.js @@ -1,35 +1,49 @@ /* eslint-disable */ -import { Readable } from "./streams_readable"; +import { + Readable, +} from './streams_readable'; import { TextEncoder, TextDecoder } from "@sinonjs/text-encoding"; -import { Writable } from "./streams_writable"; +import { + Writable, +} from './streams_writable'; -import { Duplex } from "./streams_duplex"; +import { + Duplex, +} from './streams_duplex'; import { - destroy, - eos as finished, - isDestroyed, - isReadable, - isWritable, - isWritableEnded, -} from "./streams_util"; + destroy, + eos as finished, + isDestroyed, + isReadable, + isWritable, + isWritableEnded, +} from './streams_util'; -import { Buffer } from "./internal_buffer"; +import { + Buffer, +} from './internal_buffer'; import { - ERR_INVALID_ARG_TYPE, - ERR_INVALID_ARG_VALUE, - ERR_STREAM_PREMATURE_CLOSE, - AbortError, -} from "./internal_errors"; + ERR_INVALID_ARG_TYPE, + ERR_INVALID_ARG_VALUE, + ERR_STREAM_PREMATURE_CLOSE, + AbortError, +} from './internal_errors'; -import { createDeferredPromise, normalizeEncoding } from "./internal_utils"; +import { + createDeferredPromise, + normalizeEncoding, +} from './internal_utils'; -import { validateBoolean, validateObject } from "./validators"; +import { + validateBoolean, + validateObject, +} from './validators'; -import * as process from "./process"; +import * as process from './process'; const encoder = new TextEncoder(); @@ -38,105 +52,107 @@ const encoder = new TextEncoder(); * @returns {WritableStream} */ export function newWritableStreamFromStreamWritable(streamWritable) { - // Not using the internal/streams/utils isWritableNodeStream utility - // here because it will return false if streamWritable is a Duplex - // whose writable option is false. For a Duplex that is not writable, - // we want it to pass this check but return a closed WritableStream. - // We check if the given stream is a stream.Writable or http.OutgoingMessage - const checkIfWritableOrOutgoingMessage = - streamWritable && - typeof streamWritable?.write === "function" && - typeof streamWritable?.on === "function"; - if (!checkIfWritableOrOutgoingMessage) { - throw new ERR_INVALID_ARG_TYPE("streamWritable", "stream.Writable", streamWritable); - } + // Not using the internal/streams/utils isWritableNodeStream utility + // here because it will return false if streamWritable is a Duplex + // whose writable option is false. For a Duplex that is not writable, + // we want it to pass this check but return a closed WritableStream. + // We check if the given stream is a stream.Writable or http.OutgoingMessage + const checkIfWritableOrOutgoingMessage = + streamWritable && + typeof streamWritable?.write === 'function' && + typeof streamWritable?.on === 'function'; + if (!checkIfWritableOrOutgoingMessage) { + throw new ERR_INVALID_ARG_TYPE( + 'streamWritable', + 'stream.Writable', + streamWritable, + ); + } - if (isDestroyed(streamWritable) || !isWritable(streamWritable)) { - const writable = new WritableStream(); - writable.close(); - return writable; + if (isDestroyed(streamWritable) || !isWritable(streamWritable)) { + const writable = new WritableStream(); + writable.close(); + return writable; + } + + const highWaterMark = streamWritable.writableHighWaterMark; + const strategy = + streamWritable.writableObjectMode ? + new CountQueuingStrategy({ highWaterMark }) : + { highWaterMark }; + + let controller; + let backpressurePromise; + let closed; + + function onDrain() { + if (backpressurePromise !== undefined) + backpressurePromise.resolve(); + } + + const cleanup = finished(streamWritable, (error) => { + if (error?.code === 'ERR_STREAM_PREMATURE_CLOSE') { + const err = new AbortError(undefined, { cause: error }); + error = err; } - const highWaterMark = streamWritable.writableHighWaterMark; - const strategy = streamWritable.writableObjectMode - ? new CountQueuingStrategy({ highWaterMark }) - : { highWaterMark }; - - let controller; - let backpressurePromise; - let closed; - - function onDrain() { - if (backpressurePromise !== undefined) backpressurePromise.resolve(); + cleanup(); + // This is a protection against non-standard, legacy streams + // that happen to emit an error event again after finished is called. + streamWritable.on('error', () => {}); + if (error != null) { + if (backpressurePromise !== undefined) + backpressurePromise.reject(error); + // If closed is not undefined, the error is happening + // after the WritableStream close has already started. + // We need to reject it here. + if (closed !== undefined) { + closed.reject(error); + closed = undefined; + } + controller.error(error); + controller = undefined; + return; } - const cleanup = finished(streamWritable, (error) => { - if (error?.code === "ERR_STREAM_PREMATURE_CLOSE") { - const err = new AbortError(undefined, { cause: error }); - error = err; - } - - cleanup(); - // This is a protection against non-standard, legacy streams - // that happen to emit an error event again after finished is called. - streamWritable.on("error", () => {}); - if (error != null) { - if (backpressurePromise !== undefined) backpressurePromise.reject(error); - // If closed is not undefined, the error is happening - // after the WritableStream close has already started. - // We need to reject it here. - if (closed !== undefined) { - closed.reject(error); - closed = undefined; - } - controller.error(error); - controller = undefined; - return; - } - - if (closed !== undefined) { - closed.resolve(); - closed = undefined; - return; - } - controller.error(new AbortError()); - controller = undefined; - }); - - streamWritable.on("drain", onDrain); - - return new WritableStream( - { - start(c) { - controller = c; - }, - - async write(chunk) { - if (streamWritable.writableNeedDrain || !streamWritable.write(chunk)) { - backpressurePromise = createDeferredPromise(); - return backpressurePromise.promise.finally(() => { - backpressurePromise = undefined; - }); - } - }, - - abort(reason) { - destroy(streamWritable, reason); - }, - - close() { - if (closed === undefined && !isWritableEnded(streamWritable)) { - closed = createDeferredPromise(); - streamWritable.end(); - return closed.promise; - } - - controller = undefined; - return Promise.resolve(); - }, - }, - strategy - ); + if (closed !== undefined) { + closed.resolve(); + closed = undefined; + return; + } + controller.error(new AbortError()); + controller = undefined; + }); + + streamWritable.on('drain', onDrain); + + return new WritableStream({ + start(c) { controller = c; }, + + async write(chunk) { + if (streamWritable.writableNeedDrain || !streamWritable.write(chunk)) { + backpressurePromise = createDeferredPromise(); + return backpressurePromise.promise.finally(() => { + backpressurePromise = undefined; + }); + } + }, + + abort(reason) { + destroy(streamWritable, reason); + }, + + close() { + if (closed === undefined && !isWritableEnded(streamWritable)) { + closed = createDeferredPromise(); + streamWritable.end(); + return closed.promise; + } + + controller = undefined; + return Promise.resolve(); + }, + }, strategy); } /** @@ -150,134 +166,146 @@ export function newWritableStreamFromStreamWritable(streamWritable) { * @returns {Writable} */ export function newStreamWritableFromWritableStream(writableStream, options = {}) { - if (!(writableStream instanceof WritableStream)) { - throw new ERR_INVALID_ARG_TYPE("writableStream", "WritableStream", writableStream); - } + if (!(writableStream instanceof WritableStream)) { + throw new ERR_INVALID_ARG_TYPE( + 'writableStream', + 'WritableStream', + writableStream); + } + + validateObject(options, 'options'); + const { + highWaterMark, + decodeStrings = true, + objectMode = false, + signal, + } = options; + + validateBoolean(objectMode, 'options.objectMode'); + validateBoolean(decodeStrings, 'options.decodeStrings'); + + const writer = writableStream.getWriter(); + let closed = false; + + const writable = new Writable({ + highWaterMark, + objectMode, + decodeStrings, + signal, + + writev(chunks, callback) { + function done(error) { + error = error.filter((e) => e); + try { + callback(error.length === 0 ? undefined : error); + } catch (error) { + // In a next tick because this is happening within + // a promise context, and if there are any errors + // thrown we don't want those to cause an unhandled + // rejection. Let's just escape the promise and + // handle it separately. + process.nextTick(() => destroy(writable, error)); + } + } + + writer.ready.then(() => { + return Promise.all(chunks.map((data) => writer.write(data))) + .then(done, done); + }, + done); + }, + + write(chunk, encoding, callback) { + if (typeof chunk === 'string' && decodeStrings && !objectMode) { + const enc = normalizeEncoding(encoding); + + if (enc === 'utf8') { + chunk = encoder.encode(chunk); + } else { + chunk = Buffer.from(chunk, encoding); + chunk = new Uint8Array( + chunk.buffer, + chunk.byteOffset, + chunk.byteLength + ); + } + } - validateObject(options, "options"); - const { highWaterMark, decodeStrings = true, objectMode = false, signal } = options; - - validateBoolean(objectMode, "options.objectMode"); - validateBoolean(decodeStrings, "options.decodeStrings"); - - const writer = writableStream.getWriter(); - let closed = false; - - const writable = new Writable({ - highWaterMark, - objectMode, - decodeStrings, - signal, - - writev(chunks, callback) { - function done(error) { - error = error.filter((e) => e); - try { - callback(error.length === 0 ? undefined : error); - } catch (error) { - // In a next tick because this is happening within - // a promise context, and if there are any errors - // thrown we don't want those to cause an unhandled - // rejection. Let's just escape the promise and - // handle it separately. - process.nextTick(() => destroy(writable, error)); - } - } - - writer.ready.then(() => { - return Promise.all(chunks.map((data) => writer.write(data))).then(done, done); - }, done); - }, - - write(chunk, encoding, callback) { - if (typeof chunk === "string" && decodeStrings && !objectMode) { - const enc = normalizeEncoding(encoding); - - if (enc === "utf8") { - chunk = encoder.encode(chunk); - } else { - chunk = Buffer.from(chunk, encoding); - chunk = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); - } - } - - function done(error) { - try { - callback(error); - } catch (error) { - destroy(writable, error); - } - } - - writer.ready.then(() => { - return writer.write(chunk).then(done, done); - }, done); - }, - - destroy(error, callback) { - function done() { - try { - callback(error); - } catch (error) { - // In a next tick because this is happening within - // a promise context, and if there are any errors - // thrown we don't want those to cause an unhandled - // rejection. Let's just escape the promise and - // handle it separately. - process.nextTick(() => { - throw error; - }); - } - } - - if (!closed) { - if (error != null) { - writer.abort(error).then(done, done); - } else { - writer.close().then(done, done); - } - return; - } - - done(); - }, - - final(callback) { - function done(error) { - try { - callback(error); - } catch (error) { - // In a next tick because this is happening within - // a promise context, and if there are any errors - // thrown we don't want those to cause an unhandled - // rejection. Let's just escape the promise and - // handle it separately. - process.nextTick(() => destroy(writable, error)); - } - } - - if (!closed) { - writer.close().then(done, done); - } - }, - }); - - writer.closed.then( - () => { - // If the WritableStream closes before the stream.Writable has been - // ended, we signal an error on the stream.Writable. - closed = true; - if (!isWritableEnded(writable)) destroy(writable, new ERR_STREAM_PREMATURE_CLOSE()); - }, - (error) => { - // If the WritableStream errors before the stream.Writable has been - // destroyed, signal an error on the stream.Writable. - closed = true; - destroy(writable, error); + function done(error) { + try { + callback(error); + } catch (error) { + destroy(writable, error); } - ); + } + + writer.ready.then(() => { + return writer.write(chunk).then(done, done); + }, + done); + }, + + destroy(error, callback) { + function done() { + try { + callback(error); + } catch (error) { + // In a next tick because this is happening within + // a promise context, and if there are any errors + // thrown we don't want those to cause an unhandled + // rejection. Let's just escape the promise and + // handle it separately. + process.nextTick(() => { throw error; }); + } + } - return writable; + if (!closed) { + if (error != null) { + writer.abort(error).then(done, done); + } else { + writer.close().then(done, done); + } + return; + } + + done(); + }, + + final(callback) { + function done(error) { + try { + callback(error); + } catch (error) { + // In a next tick because this is happening within + // a promise context, and if there are any errors + // thrown we don't want those to cause an unhandled + // rejection. Let's just escape the promise and + // handle it separately. + process.nextTick(() => destroy(writable, error)); + } + } + + if (!closed) { + writer.close().then(done, done); + } + }, + }); + + writer.closed.then(() => { + // If the WritableStream closes before the stream.Writable has been + // ended, we signal an error on the stream.Writable. + closed = true; + if (!isWritableEnded(writable)) + destroy(writable, new ERR_STREAM_PREMATURE_CLOSE()); + }, + (error) => { + // If the WritableStream errors before the stream.Writable has been + // destroyed, signal an error on the stream.Writable. + closed = true; + destroy(writable, error); + }); + + return writable; } /** @@ -289,85 +317,85 @@ export function newStreamWritableFromWritableStream(writableStream, options = {} * @returns {ReadableStream} */ export function newReadableStreamFromStreamReadable(streamReadable, options = {}) { - // Not using the internal/streams/utils isReadableNodeStream utility - // here because it will return false if streamReadable is a Duplex - // whose readable option is false. For a Duplex that is not readable, - // we want it to pass this check but return a closed ReadableStream. - if (typeof streamReadable?._readableState !== "object") { - throw new ERR_INVALID_ARG_TYPE("streamReadable", "stream.Readable", streamReadable); - } + // Not using the internal/streams/utils isReadableNodeStream utility + // here because it will return false if streamReadable is a Duplex + // whose readable option is false. For a Duplex that is not readable, + // we want it to pass this check but return a closed ReadableStream. + if (typeof streamReadable?._readableState !== 'object') { + throw new ERR_INVALID_ARG_TYPE( + 'streamReadable', + 'stream.Readable', + streamReadable); + } + + if (isDestroyed(streamReadable) || !isReadable(streamReadable)) { + const readable = new ReadableStream(); + readable.cancel(); + return readable; + } - if (isDestroyed(streamReadable) || !isReadable(streamReadable)) { - const readable = new ReadableStream(); - readable.cancel(); - return readable; - } + const objectMode = streamReadable.readableObjectMode; + const highWaterMark = streamReadable.readableHighWaterMark; - const objectMode = streamReadable.readableObjectMode; - const highWaterMark = streamReadable.readableHighWaterMark; + const evaluateStrategyOrFallback = (strategy) => { + // If there is a strategy available, use it + if (strategy) + return strategy; - const evaluateStrategyOrFallback = (strategy) => { - // If there is a strategy available, use it - if (strategy) return strategy; + if (objectMode) { + // When running in objectMode explicitly but no strategy, we just fall + // back to CountQueuingStrategy + return new CountQueuingStrategy({ highWaterMark }); + } - if (objectMode) { - // When running in objectMode explicitly but no strategy, we just fall - // back to CountQueuingStrategy - return new CountQueuingStrategy({ highWaterMark }); - } + // When not running in objectMode explicitly, we just fall + // back to a minimal strategy that just specifies the highWaterMark + // and no size algorithm. Using a ByteLengthQueuingStrategy here + // is unnecessary. + return { highWaterMark }; + }; + + const strategy = evaluateStrategyOrFallback(options?.strategy); - // When not running in objectMode explicitly, we just fall - // back to a minimal strategy that just specifies the highWaterMark - // and no size algorithm. Using a ByteLengthQueuingStrategy here - // is unnecessary. - return { highWaterMark }; - }; + let controller; - const strategy = evaluateStrategyOrFallback(options?.strategy); + function onData(chunk) { + // Copy the Buffer to detach it from the pool. + if (Buffer.isBuffer(chunk) && !objectMode) + chunk = new Uint8Array(chunk); + controller.enqueue(chunk); + if (controller.desiredSize <= 0) + streamReadable.pause(); + } - let controller; + streamReadable.pause(); - function onData(chunk) { - // Copy the Buffer to detach it from the pool. - if (Buffer.isBuffer(chunk) && !objectMode) chunk = new Uint8Array(chunk); - controller.enqueue(chunk); - if (controller.desiredSize <= 0) streamReadable.pause(); + const cleanup = finished(streamReadable, (error) => { + if (error?.code === 'ERR_STREAM_PREMATURE_CLOSE') { + const err = new AbortError(undefined, { cause: error }); + error = err; } - streamReadable.pause(); + cleanup(); + // This is a protection against non-standard, legacy streams + // that happen to emit an error event again after finished is called. + streamReadable.on('error', () => {}); + if (error) + return controller.error(error); + controller.close(); + }); - const cleanup = finished(streamReadable, (error) => { - if (error?.code === "ERR_STREAM_PREMATURE_CLOSE") { - const err = new AbortError(undefined, { cause: error }); - error = err; - } + streamReadable.on('data', onData); - cleanup(); - // This is a protection against non-standard, legacy streams - // that happen to emit an error event again after finished is called. - streamReadable.on("error", () => {}); - if (error) return controller.error(error); - controller.close(); - }); - - streamReadable.on("data", onData); - - return new ReadableStream( - { - start(c) { - controller = c; - }, - - pull() { - streamReadable.resume(); - }, - - cancel(reason) { - destroy(streamReadable, reason); - }, - }, - strategy - ); + return new ReadableStream({ + start(c) { controller = c; }, + + pull() { streamReadable.resume(); }, + + cancel(reason) { + destroy(streamReadable, reason); + }, + }, strategy); } /** @@ -381,75 +409,77 @@ export function newReadableStreamFromStreamReadable(streamReadable, options = {} * @returns {Readable} */ export function newStreamReadableFromReadableStream(readableStream, options = {}) { - if (!(readableStream instanceof ReadableStream)) { - throw new ERR_INVALID_ARG_TYPE("readableStream", "ReadableStream", readableStream); - } - - validateObject(options, "options"); - const { highWaterMark, encoding, objectMode = false, signal } = options; - - if (encoding !== undefined && !Buffer.isEncoding(encoding)) - throw new ERR_INVALID_ARG_VALUE(encoding, "options.encoding"); - validateBoolean(objectMode, "options.objectMode"); - - const reader = readableStream.getReader(); - let closed = false; - - const readable = new Readable({ - objectMode, - highWaterMark, - encoding, - signal, - - read() { - reader.read().then( - (chunk) => { - if (chunk.done) { - // Value should always be undefined here. - readable.push(null); - } else { - readable.push(chunk.value); - } - }, - (error) => destroy(readable, error) - ); - }, - - destroy(error, callback) { - function done() { - try { - callback(error); - } catch (error) { - // In a next tick because this is happening within - // a promise context, and if there are any errors - // thrown we don't want those to cause an unhandled - // rejection. Let's just escape the promise and - // handle it separately. - process.nextTick(() => { - throw error; - }); - } - } - - if (!closed) { - reader.cancel(error).then(done, done); - return; - } - done(); - }, - }); - - reader.closed.then( - () => { - closed = true; - }, - (error) => { - closed = true; - destroy(readable, error); + if (!(readableStream instanceof ReadableStream)) { + throw new ERR_INVALID_ARG_TYPE( + 'readableStream', + 'ReadableStream', + readableStream); + } + + validateObject(options, 'options'); + const { + highWaterMark, + encoding, + objectMode = false, + signal, + } = options; + + if (encoding !== undefined && !Buffer.isEncoding(encoding)) + throw new ERR_INVALID_ARG_VALUE(encoding, 'options.encoding'); + validateBoolean(objectMode, 'options.objectMode'); + + const reader = readableStream.getReader(); + let closed = false; + + const readable = new Readable({ + objectMode, + highWaterMark, + encoding, + signal, + + read() { + reader.read().then((chunk) => { + if (chunk.done) { + // Value should always be undefined here. + readable.push(null); + } else { + readable.push(chunk.value); } - ); - - return readable; + }, + (error) => destroy(readable, error)); + }, + + destroy(error, callback) { + function done() { + try { + callback(error); + } catch (error) { + // In a next tick because this is happening within + // a promise context, and if there are any errors + // thrown we don't want those to cause an unhandled + // rejection. Let's just escape the promise and + // handle it separately. + process.nextTick(() => { throw error; }); + } + } + + if (!closed) { + reader.cancel(error).then(done, done); + return; + } + done(); + }, + }); + + reader.closed.then(() => { + closed = true; + }, + (error) => { + closed = true; + destroy(readable, error); + }); + + return readable; } /** @@ -463,37 +493,42 @@ export function newStreamReadableFromReadableStream(readableStream, options = {} * @returns {ReadableWritablePair} */ export function newReadableWritablePairFromDuplex(duplex) { - // Not using the internal/streams/utils isWritableNodeStream and - // isReadableNodeStream utilities here because they will return false - // if the duplex was created with writable or readable options set to - // false. Instead, we'll check the readable and writable state after - // and return closed WritableStream or closed ReadableStream as - // necessary. - if (typeof duplex?._writableState !== "object" || typeof duplex?._readableState !== "object") { - throw new ERR_INVALID_ARG_TYPE("duplex", "stream.Duplex", duplex); - } - - if (isDestroyed(duplex)) { - const writable = new WritableStream(); - const readable = new ReadableStream(); - writable.close(); - readable.cancel(); - return { readable, writable }; - } - - const writable = isWritable(duplex) - ? newWritableStreamFromStreamWritable(duplex) - : new WritableStream(); - - if (!isWritable(duplex)) writable.close(); - - const readable = isReadable(duplex) - ? newReadableStreamFromStreamReadable(duplex) - : new ReadableStream(); - - if (!isReadable(duplex)) readable.cancel(); - - return { writable, readable }; + // Not using the internal/streams/utils isWritableNodeStream and + // isReadableNodeStream utilities here because they will return false + // if the duplex was created with writable or readable options set to + // false. Instead, we'll check the readable and writable state after + // and return closed WritableStream or closed ReadableStream as + // necessary. + if (typeof duplex?._writableState !== 'object' || + typeof duplex?._readableState !== 'object') { + throw new ERR_INVALID_ARG_TYPE('duplex', 'stream.Duplex', duplex); + } + + if (isDestroyed(duplex)) { + const writable = new WritableStream(); + const readable = new ReadableStream(); + writable.close(); + readable.cancel(); + return { readable, writable }; + } + + const writable = + isWritable(duplex) ? + newWritableStreamFromStreamWritable(duplex) : + new WritableStream(); + + if (!isWritable(duplex)) + writable.close(); + + const readable = + isReadable(duplex) ? + newReadableStreamFromStreamReadable(duplex) : + new ReadableStream(); + + if (!isReadable(duplex)) + readable.cancel(); + + return { writable, readable }; } /** @@ -509,179 +544,187 @@ export function newReadableWritablePairFromDuplex(duplex) { * @returns {Duplex} */ export function newStreamDuplexFromReadableWritablePair(pair = {}, options = {}) { - validateObject(pair, "pair"); - const { readable: readableStream, writable: writableStream } = pair; - - if (!(readableStream instanceof ReadableStream)) { - throw new ERR_INVALID_ARG_TYPE("pair.readable", "ReadableStream", readableStream); - } - if (!(writableStream instanceof WritableStream)) { - throw new ERR_INVALID_ARG_TYPE("pair.writable", "WritableStream", writableStream); - } - - validateObject(options, "options"); - const { - allowHalfOpen = false, - objectMode = false, - encoding, - decodeStrings = true, - highWaterMark, - signal, - } = options; - - validateBoolean(objectMode, "options.objectMode"); - if (encoding !== undefined && !Buffer.isEncoding(encoding)) - throw new ERR_INVALID_ARG_VALUE(encoding, "options.encoding"); - - const writer = writableStream.getWriter(); - const reader = readableStream.getReader(); - let writableClosed = false; - let readableClosed = false; - - const duplex = new Duplex({ - allowHalfOpen, - highWaterMark, - objectMode, - encoding, - decodeStrings, - signal, - - writev(chunks, callback) { - function done(error) { - error = error.filter((e) => e); - try { - callback(error.length === 0 ? undefined : error); - } catch (error) { - // In a next tick because this is happening within - // a promise context, and if there are any errors - // thrown we don't want those to cause an unhandled - // rejection. Let's just escape the promise and - // handle it separately. - process.nextTick(() => destroy(duplex, error)); - } - } - - writer.ready.then(() => { - return Promise.all( - chunks.map((data) => { - return writer.write(data); - }) - ).then(done, done); - }, done); - }, - - write(chunk, encoding, callback) { - if (typeof chunk === "string" && decodeStrings && !objectMode) { - const enc = normalizeEncoding(encoding); - - if (enc === "utf8") { - chunk = encoder.encode(chunk); - } else { - chunk = Buffer.from(chunk, encoding); - chunk = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); - } - } - - function done(error) { - try { - callback(error); - } catch (error) { - destroy(duplex, error); - } - } - - writer.ready.then(() => { - return writer.write(chunk).then(done, done); - }, done); - }, - - final(callback) { - function done(error) { - try { - callback(error); - } catch (error) { - // In a next tick because this is happening within - // a promise context, and if there are any errors - // thrown we don't want those to cause an unhandled - // rejection. Let's just escape the promise and - // handle it separately. - process.nextTick(() => destroy(duplex, error)); - } - } - - if (!writableClosed) { - writer.close().then(done, done); - } - }, - - read() { - reader.read().then( - (chunk) => { - if (chunk.done) { - duplex.push(null); - } else { - duplex.push(chunk.value); - } - }, - (error) => destroy(duplex, error) - ); - }, - - destroy(error, callback) { - function done() { - try { - callback(error); - } catch (error) { - // In a next tick because this is happening within - // a promise context, and if there are any errors - // thrown we don't want those to cause an unhandled - // rejection. Let's just escape the promise and - // handle it separately. - process.nextTick(() => { - throw error; - }); - } - } - - async function closeWriter() { - if (!writableClosed) await writer.abort(error); - } - - async function closeReader() { - if (!readableClosed) await reader.cancel(error); - } - - if (!writableClosed || !readableClosed) { - Promise.all([closeWriter(), closeReader()]).then(done, done); - return; - } - - done(); - }, - }); - - writer.closed.then( - () => { - writableClosed = true; - if (!isWritableEnded(duplex)) destroy(duplex, new ERR_STREAM_PREMATURE_CLOSE()); - }, - (error) => { - writableClosed = true; - readableClosed = true; - destroy(duplex, error); + validateObject(pair, 'pair'); + const { + readable: readableStream, + writable: writableStream, + } = pair; + + if (!(readableStream instanceof ReadableStream)) { + throw new ERR_INVALID_ARG_TYPE( + 'pair.readable', + 'ReadableStream', + readableStream); + } + if (!(writableStream instanceof WritableStream)) { + throw new ERR_INVALID_ARG_TYPE( + 'pair.writable', + 'WritableStream', + writableStream); + } + + validateObject(options, 'options'); + const { + allowHalfOpen = false, + objectMode = false, + encoding, + decodeStrings = true, + highWaterMark, + signal, + } = options; + + validateBoolean(objectMode, 'options.objectMode'); + if (encoding !== undefined && !Buffer.isEncoding(encoding)) + throw new ERR_INVALID_ARG_VALUE(encoding, 'options.encoding'); + + const writer = writableStream.getWriter(); + const reader = readableStream.getReader(); + let writableClosed = false; + let readableClosed = false; + + const duplex = new Duplex({ + allowHalfOpen, + highWaterMark, + objectMode, + encoding, + decodeStrings, + signal, + + writev(chunks, callback) { + function done(error) { + error = error.filter((e) => e); + try { + callback(error.length === 0 ? undefined : error); + } catch (error) { + // In a next tick because this is happening within + // a promise context, and if there are any errors + // thrown we don't want those to cause an unhandled + // rejection. Let's just escape the promise and + // handle it separately. + process.nextTick(() => destroy(duplex, error)); } - ); - - reader.closed.then( - () => { - readableClosed = true; - }, - (error) => { - writableClosed = true; - readableClosed = true; - destroy(duplex, error); + } + + writer.ready.then(() => { + return Promise.all(chunks.map((data) => { + return writer.write(data); + })).then(done, done); + }, + done); + }, + + write(chunk, encoding, callback) { + if (typeof chunk === 'string' && decodeStrings && !objectMode) { + const enc = normalizeEncoding(encoding); + + if (enc === 'utf8') { + chunk = encoder.encode(chunk); + } else { + chunk = Buffer.from(chunk, encoding); + chunk = new Uint8Array( + chunk.buffer, + chunk.byteOffset, + chunk.byteLength + ); } - ); + } - return duplex; + function done(error) { + try { + callback(error); + } catch (error) { + destroy(duplex, error); + } + } + + writer.ready.then(() => { + return writer.write(chunk).then(done, done); + }, + done); + }, + + final(callback) { + function done(error) { + try { + callback(error); + } catch (error) { + // In a next tick because this is happening within + // a promise context, and if there are any errors + // thrown we don't want those to cause an unhandled + // rejection. Let's just escape the promise and + // handle it separately. + process.nextTick(() => destroy(duplex, error)); + } + } + + if (!writableClosed) { + writer.close().then(done, done); + } + }, + + read() { + reader.read().then((chunk) => { + if (chunk.done) { + duplex.push(null); + } else { + duplex.push(chunk.value); + } + }, + (error) => destroy(duplex, error)); + }, + + destroy(error, callback) { + function done() { + try { + callback(error); + } catch (error) { + // In a next tick because this is happening within + // a promise context, and if there are any errors + // thrown we don't want those to cause an unhandled + // rejection. Let's just escape the promise and + // handle it separately. + process.nextTick(() => { throw error; }); + } + } + + async function closeWriter() { + if (!writableClosed) + await writer.abort(error); + } + + async function closeReader() { + if (!readableClosed) + await reader.cancel(error); + } + + if (!writableClosed || !readableClosed) { + Promise.all([ closeWriter(), closeReader() ]).then(done, done); + return; + } + + done(); + }, + }); + + writer.closed.then(() => { + writableClosed = true; + if (!isWritableEnded(duplex)) + destroy(duplex, new ERR_STREAM_PREMATURE_CLOSE()); + }, + (error) => { + writableClosed = true; + readableClosed = true; + destroy(duplex, error); + }); + + reader.closed.then(() => { + readableClosed = true; + }, + (error) => { + writableClosed = true; + readableClosed = true; + destroy(duplex, error); + }); + + return duplex; } diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_duplex.js b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_duplex.js index 61439b173..7b2b286c7 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_duplex.js +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_duplex.js @@ -1,475 +1,479 @@ -import { Readable, from } from "./streams_readable"; +import { + Readable, + from, +} from './streams_readable'; -import { Writable } from "./streams_writable"; +import { + Writable, +} from './streams_writable'; import { - newStreamDuplexFromReadableWritablePair, - newReadableWritablePairFromDuplex, -} from "./streams_adapters"; + newStreamDuplexFromReadableWritablePair, + newReadableWritablePairFromDuplex, +} from './streams_adapters'; -import { createDeferredPromise } from "./internal_utils"; +import { + createDeferredPromise, +} from './internal_utils'; -import * as process from "./process"; +import * as process from './process'; import { - destroyer, - eos, - isReadable, - isWritable, - isIterable, - isNodeStream, - isReadableNodeStream, - isWritableNodeStream, - isDuplexNodeStream, -} from "./streams_util"; + destroyer, + eos, + isReadable, + isWritable, + isIterable, + isNodeStream, + isReadableNodeStream, + isWritableNodeStream, + isDuplexNodeStream, +} from './streams_util'; -import { AbortError, ERR_INVALID_ARG_TYPE, ERR_INVALID_RETURN_VALUE } from "./internal_errors"; +import { + AbortError, + ERR_INVALID_ARG_TYPE, + ERR_INVALID_RETURN_VALUE, +} from './internal_errors'; Object.setPrototypeOf(Duplex.prototype, Readable.prototype); Object.setPrototypeOf(Duplex, Readable); { - const keys = Object.keys(Writable.prototype); - // Allow the keys array to be GC'ed. - for (let i = 0; i < keys.length; i++) { - const method = keys[i]; - if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; - } + const keys = Object.keys(Writable.prototype); + // Allow the keys array to be GC'ed. + for (let i = 0; i < keys.length; i++) { + const method = keys[i]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; + } } export function isDuplexInstance(obj) { - return obj instanceof Duplex; + return obj instanceof Duplex; } export function Duplex(options) { - if (!(this instanceof Duplex)) return new Duplex(options); - Readable.call(this, options); - Writable.call(this, options); - if (options) { - this.allowHalfOpen = options.allowHalfOpen !== false; - if (options.readable === false) { - this._readableState.readable = false; - this._readableState.ended = true; - this._readableState.endEmitted = true; - } - if (options.writable === false) { - this._writableState.writable = false; - this._writableState.ending = true; - this._writableState.ended = true; - this._writableState.finished = true; - } - } else { - this.allowHalfOpen = true; + if (!(this instanceof Duplex)) return new Duplex(options); + Readable.call(this, options); + Writable.call(this, options); + if (options) { + this.allowHalfOpen = options.allowHalfOpen !== false; + if (options.readable === false) { + this._readableState.readable = false; + this._readableState.ended = true; + this._readableState.endEmitted = true; + } + if (options.writable === false) { + this._writableState.writable = false; + this._writableState.ending = true; + this._writableState.ended = true; + this._writableState.finished = true; } + } else { + this.allowHalfOpen = true; + } } Object.defineProperties(Duplex.prototype, { - writable: { - ...Object.getOwnPropertyDescriptor(Writable.prototype, "writable"), - }, - writableHighWaterMark: { - ...Object.getOwnPropertyDescriptor(Writable.prototype, "writableHighWaterMark"), - }, - writableObjectMode: { - ...Object.getOwnPropertyDescriptor(Writable.prototype, "writableObjectMode"), - }, - writableBuffer: { - ...Object.getOwnPropertyDescriptor(Writable.prototype, "writableBuffer"), - }, - writableLength: { - ...Object.getOwnPropertyDescriptor(Writable.prototype, "writableLength"), - }, - writableFinished: { - ...Object.getOwnPropertyDescriptor(Writable.prototype, "writableFinished"), - }, - writableCorked: { - ...Object.getOwnPropertyDescriptor(Writable.prototype, "writableCorked"), - }, - writableEnded: { - ...Object.getOwnPropertyDescriptor(Writable.prototype, "writableEnded"), - }, - writableNeedDrain: { - ...Object.getOwnPropertyDescriptor(Writable.prototype, "writableNeedDrain"), - }, - destroyed: { - get() { - if (this._readableState === undefined || this._writableState === undefined) { - return false; - } - return this._readableState.destroyed && this._writableState.destroyed; - }, - set(value) { - // Backward compatibility, the user is explicitly - // managing destroyed. - if (this._readableState && this._writableState) { - this._readableState.destroyed = value; - this._writableState.destroyed = value; - } - }, + writable: { + ...Object.getOwnPropertyDescriptor(Writable.prototype, 'writable') + }, + writableHighWaterMark: { + ...Object.getOwnPropertyDescriptor(Writable.prototype, 'writableHighWaterMark') + }, + writableObjectMode: { + ...Object.getOwnPropertyDescriptor(Writable.prototype, 'writableObjectMode') + }, + writableBuffer: { + ...Object.getOwnPropertyDescriptor(Writable.prototype, 'writableBuffer') + }, + writableLength: { + ...Object.getOwnPropertyDescriptor(Writable.prototype, 'writableLength') + }, + writableFinished: { + ...Object.getOwnPropertyDescriptor(Writable.prototype, 'writableFinished') + }, + writableCorked: { + ...Object.getOwnPropertyDescriptor(Writable.prototype, 'writableCorked') + }, + writableEnded: { + ...Object.getOwnPropertyDescriptor(Writable.prototype, 'writableEnded') + }, + writableNeedDrain: { + ...Object.getOwnPropertyDescriptor(Writable.prototype, 'writableNeedDrain') + }, + destroyed: { + get() { + if (this._readableState === undefined || this._writableState === undefined) { + return false + } + return this._readableState.destroyed && this._writableState.destroyed }, + set(value) { + // Backward compatibility, the user is explicitly + // managing destroyed. + if (this._readableState && this._writableState) { + this._readableState.destroyed = value + this._writableState.destroyed = value + } + } + } }); Duplex.fromWeb = function (pair, options) { - return newStreamDuplexFromReadableWritablePair(pair, options); -}; + return newStreamDuplexFromReadableWritablePair(pair, options) +} Duplex.toWeb = function (duplex) { - return newReadableWritablePairFromDuplex(duplex); -}; + return newReadableWritablePairFromDuplex(duplex) +} // ====================================================================================== Duplex.from = function (body) { - return duplexify(body, "body"); -}; + return duplexify(body, 'body') +} function isBlob(b) { - return b instanceof Blob; + return b instanceof Blob; } // This is needed for pre node 17. -class Duplexify extends Duplex { - constructor(options) { - super(options); - // https://github.com/nodejs/node/pull/34385 +class Duplexify extends (Duplex) { + constructor(options) { + super(options); + // https://github.com/nodejs/node/pull/34385 - if ((options === null || options === undefined ? undefined : options.readable) === false) { - this["_readableState"].readable = false; - this["_readableState"].ended = true; - this["_readableState"].endEmitted = true; - } - if ((options === null || options === undefined ? undefined : options.writable) === false) { - this["_readableState"].writable = false; - this["_readableState"].ending = true; - this["_readableState"].ended = true; - this["_readableState"].finished = true; - } + if ((options === null || options === undefined ? undefined : options.readable) === false) { + this['_readableState'].readable = false; + this['_readableState'].ended = true; + this['_readableState'].endEmitted = true; } + if ((options === null || options === undefined ? undefined : options.writable) === false) { + this['_readableState'].writable = false; + this['_readableState'].ending = true; + this['_readableState'].ended = true; + this['_readableState'].finished = true; + } + } } function duplexify(body, name) { - if (isDuplexNodeStream(body)) { - return body; - } - if (isReadableNodeStream(body)) { - return _duplexify({ - readable: body, - }); - } - if (isWritableNodeStream(body)) { - return _duplexify({ - writable: body, - }); - } - if (isNodeStream(body)) { - return _duplexify({ - writable: false, - readable: false, - }); - } + if (isDuplexNodeStream(body)) { + return body; + } + if (isReadableNodeStream(body)) { + return _duplexify({ + readable: body + }); + } + if (isWritableNodeStream(body)) { + return _duplexify({ + writable: body + }); + } + if (isNodeStream(body)) { + return _duplexify({ + writable: false, + readable: false + }); + } - // TODO: Webstreams - // if (isReadableStream(body)) { - // return _duplexify({ readable: Readable.fromWeb(body) }); - // } + // TODO: Webstreams + // if (isReadableStream(body)) { + // return _duplexify({ readable: Readable.fromWeb(body) }); + // } - // TODO: Webstreams - // if (isWritableStream(body)) { - // return _duplexify({ writable: Writable.fromWeb(body) }); - // } + // TODO: Webstreams + // if (isWritableStream(body)) { + // return _duplexify({ writable: Writable.fromWeb(body) }); + // } - if (typeof body === "function") { - const { value, write, final, destroy } = fromAsyncGen(body); - if (isIterable(value)) { - return from(Duplexify, value, { - // TODO (ronag): highWaterMark? - objectMode: true, - write, - final, - destroy, - }); + if (typeof body === 'function') { + const { value, write, final, destroy } = fromAsyncGen(body) + if (isIterable(value)) { + return from(Duplexify, value, { + // TODO (ronag): highWaterMark? + objectMode: true, + write, + final, + destroy + }); + } + const then = value.then; + if (typeof then === 'function') { + let d; + const promise = Reflect.apply(then, value, [ + (val) => { + if (val != null) { + throw new ERR_INVALID_RETURN_VALUE('nully', 'body', val) + } + }, + (err) => { + destroyer(d, err) } - const then = value.then; - if (typeof then === "function") { - let d; - const promise = Reflect.apply(then, value, [ - (val) => { - if (val != null) { - throw new ERR_INVALID_RETURN_VALUE("nully", "body", val); - } - }, - (err) => { - destroyer(d, err); - }, - ]); + ]); - return (d = new Duplexify({ - // TODO (ronag): highWaterMark? - objectMode: true, - readable: false, - write, - final(cb) { - final(async () => { - try { - await promise; - process.nextTick(cb, null); - } catch (err) { - process.nextTick(cb, err); - } - }); - }, - destroy, - })); - } - throw new ERR_INVALID_RETURN_VALUE("Iterable, AsyncIterable or AsyncFunction", name, value); - } - if (isBlob(body)) { - return duplexify(body.arrayBuffer(), name); - } - if (isIterable(body)) { - return from(Duplexify, body, { - // TODO (ronag): highWaterMark? - objectMode: true, - writable: false, - }); + return (d = new Duplexify({ + // TODO (ronag): highWaterMark? + objectMode: true, + readable: false, + write, + final(cb) { + final(async () => { + try { + await promise + process.nextTick(cb, null); + } catch (err) { + process.nextTick(cb, err); + } + }) + }, + destroy + })); } + throw new ERR_INVALID_RETURN_VALUE('Iterable, AsyncIterable or AsyncFunction', name, value) + } + if (isBlob(body)) { + return duplexify(body.arrayBuffer(), name); + } + if (isIterable(body)) { + return from(Duplexify, body, { + // TODO (ronag): highWaterMark? + objectMode: true, + writable: false + }) + } - // TODO: Webstreams. - // if ( - // isReadableStream(body?.readable) && - // isWritableStream(body?.writable) - // ) { - // return Duplexify.fromWeb(body); - // } + // TODO: Webstreams. + // if ( + // isReadableStream(body?.readable) && + // isWritableStream(body?.writable) + // ) { + // return Duplexify.fromWeb(body); + // } - if ( - typeof (body === null || body === undefined ? undefined : body.writable) === "object" || - typeof (body === null || body === undefined ? undefined : body.readable) === "object" - ) { - const readable = - body !== null && body !== undefined && body.readable - ? isReadableNodeStream( - body === null || body === undefined ? undefined : body.readable - ) - ? body === null || body === undefined - ? undefined - : body.readable - : duplexify(body.readable, name) - : undefined; - const writable = - body !== null && body !== undefined && body.writable - ? isWritableNodeStream( - body === null || body === undefined ? undefined : body.writable - ) - ? body === null || body === undefined - ? undefined - : body.writable - : duplexify(body.writable, name) - : undefined; - return _duplexify({ - readable, - writable, - }); - } - const then = body?.then; - if (typeof then === "function") { - let d; - Reflect.apply(then, body, [ - (val) => { - if (val != null) { - d.push(val); - } - d.push(null); - }, - (err) => { - destroyer(d, err); - }, - ]); + if ( + typeof (body === null || body === undefined ? undefined : body.writable) === 'object' || + typeof (body === null || body === undefined ? undefined : body.readable) === 'object' + ) { + const readable = + body !== null && body !== undefined && body.readable + ? isReadableNodeStream(body === null || body === undefined ? undefined : body.readable) + ? body === null || body === undefined + ? undefined + : body.readable + : duplexify(body.readable, name) + : undefined; + const writable = + body !== null && body !== undefined && body.writable + ? isWritableNodeStream(body === null || body === undefined ? undefined : body.writable) + ? body === null || body === undefined + ? undefined + : body.writable + : duplexify(body.writable, name) + : undefined; + return _duplexify({ + readable, + writable + }); + } + const then = body?.then + if (typeof then === 'function') { + let d; + Reflect.apply(then, body, [ + (val) => { + if (val != null) { + d.push(val); + } + d.push(null); + }, + (err) => { + destroyer(d, err); + } + ]); - return (d = new Duplexify({ - objectMode: true, - writable: false, - read() {}, - })); - } - throw new ERR_INVALID_ARG_TYPE( - name, - [ - "Blob", - "ReadableStream", - "WritableStream", - "Stream", - "Iterable", - "AsyncIterable", - "Function", - "{ readable, writable } pair", - "Promise", - ], - body - ); + return (d = new Duplexify({ + objectMode: true, + writable: false, + read() {} + })); + } + throw new ERR_INVALID_ARG_TYPE( + name, + [ + 'Blob', + 'ReadableStream', + 'WritableStream', + 'Stream', + 'Iterable', + 'AsyncIterable', + 'Function', + '{ readable, writable } pair', + 'Promise' + ], + body + ) } function fromAsyncGen(fn) { - let { promise, resolve } = createDeferredPromise(); - const ac = new AbortController(); - const signal = ac.signal; - const value = fn( - (async function* () { - while (true) { - const _promise = promise; - promise = null; - const { chunk, done, cb } = await _promise; - process.nextTick(cb); - if (done) return; - if (signal.aborted) - throw new AbortError(undefined, { - cause: signal.reason, - }); - ({ promise, resolve } = createDeferredPromise()); - yield chunk; - } - })(), - { - signal, - } - ); - return { - value, - write(chunk, _encoding, cb) { - const _resolve = resolve; - resolve = null; - _resolve({ - chunk, - done: false, - cb, - }); - }, - final(cb) { - const _resolve = resolve; - resolve = null; - _resolve({ - done: true, - cb, - }); - }, - destroy(err, cb) { - ac.abort(); - cb(err); - }, - }; + let { promise, resolve } = createDeferredPromise() + const ac = new AbortController() + const signal = ac.signal + const value = fn( + (async function* () { + while (true) { + const _promise = promise; + promise = null; + const { chunk, done, cb } = await _promise; + process.nextTick(cb); + if (done) return; + if (signal.aborted) + throw new AbortError(undefined, { + cause: signal.reason + }); + ({ promise, resolve } = createDeferredPromise()); + yield chunk; + } + })(), + { + signal + } + ); + return { + value, + write(chunk, _encoding, cb) { + const _resolve = resolve; + resolve = null; + _resolve({ + chunk, + done: false, + cb + }) + }, + final(cb) { + const _resolve = resolve; + resolve = null; + (_resolve)({ + done: true, + cb + }); + }, + destroy(err, cb) { + ac.abort(); + cb(err); + } + } } function _duplexify(pair) { - const r = - pair.readable && typeof pair.readable.read !== "function" - ? Readable.wrap(pair.readable) - : pair.readable; - const w = pair.writable; - let readable = !!isReadable(r); - let writable = !!isWritable(w); - let ondrain; - let onfinish; - let onreadable; - let onclose; - let d; - function onfinished(err) { - const cb = onclose; - onclose = null; - if (cb) { - cb(err); - } else if (err) { - d.destroy(err); - } else if (!readable && !writable) { - d.destroy(); - } + const r = pair.readable && typeof pair.readable.read !== 'function' ? Readable.wrap(pair.readable) : pair.readable; + const w = pair.writable; + let readable = !!isReadable(r); + let writable = !!isWritable(w); + let ondrain; + let onfinish; + let onreadable; + let onclose; + let d; + function onfinished(err) { + const cb = onclose + onclose = null + if (cb) { + cb(err) + } else if (err) { + d.destroy(err) + } else if (!readable && !writable) { + d.destroy() } + } - // TODO(ronag): Avoid double buffering. - // Implement Writable/Readable/Duplex traits. - // See, https://github.com/nodejs/node/pull/33515. - d = new Duplexify({ - // TODO (ronag): highWaterMark? - readableObjectMode: !!(r !== null && r !== undefined && r.readableObjectMode), - writableObjectMode: !!(w !== null && w !== undefined && w.writableObjectMode), - readable, - writable, + // TODO(ronag): Avoid double buffering. + // Implement Writable/Readable/Duplex traits. + // See, https://github.com/nodejs/node/pull/33515. + d = new Duplexify({ + // TODO (ronag): highWaterMark? + readableObjectMode: !!(r !== null && r !== undefined && r.readableObjectMode), + writableObjectMode: !!(w !== null && w !== undefined && w.writableObjectMode), + readable, + writable + }); + if (writable) { + eos(w, (err) => { + writable = false; + if (err) { + destroyer(r, err); + } + onfinished(err); }); - if (writable) { - eos(w, (err) => { - writable = false; - if (err) { - destroyer(r, err); - } - onfinished(err); - }); - d._write = function (chunk, encoding, callback) { - if (w.write(chunk, encoding)) { - callback(); - } else { - ondrain = callback; - } - }; - d._final = function (callback) { - w.end(); - onfinish = callback; - }; - w.on("drain", function () { - if (ondrain) { - const cb = ondrain; - ondrain = null; - cb(); - } - }); - w.on("finish", function () { - if (onfinish) { - const cb = onfinish; - onfinish = null; - cb(); - } - }); - } - if (readable) { - eos(r, (err) => { - readable = false; - if (err) { - destroyer(r, err); - } - onfinished(err); - }); - r.on("readable", function () { - if (onreadable) { - const cb = onreadable; - onreadable = null; - cb(); - } - }); - r.on("end", function () { - d.push(null); - }); - d._read = function () { - while (true) { - const buf = r.read(); - if (buf === null) { - onreadable = d._read; - return; - } - if (!d.push(buf)) { - return; - } - } - }; - } - d._destroy = function (err, callback) { - if (!err && onclose !== null) { - err = new AbortError(); - } - onreadable = null; + d._write = function (chunk, encoding, callback) { + if (w.write(chunk, encoding)) { + callback(); + } else { + ondrain = callback; + } + }; + d._final = function (callback) { + w.end(); + onfinish = callback; + }; + w.on('drain', function () { + if (ondrain) { + const cb = ondrain; ondrain = null; + cb(); + } + }); + w.on('finish', function () { + if (onfinish) { + const cb = onfinish; onfinish = null; - if (onclose === null) { - callback(err); - } else { - onclose = callback; - destroyer(w, err); - destroyer(r, err); + cb(); + } + }); + } + if (readable) { + eos(r, (err) => { + readable = false; + if (err) { + destroyer(r, err); + } + onfinished(err); + }); + r.on('readable', function () { + if (onreadable) { + const cb = onreadable; + onreadable = null; + cb(); + } + }); + r.on('end', function () { + d.push(null); + }); + d._read = function () { + while (true) { + const buf = r.read(); + if (buf === null) { + onreadable = d._read; + return; + } + if (!d.push(buf)) { + return; } + } }; - return d; + } + d._destroy = function (err, callback) { + if (!err && onclose !== null) { + err = new AbortError(); + } + onreadable = null; + ondrain = null; + onfinish = null; + if (onclose === null) { + callback(err); + } else { + onclose = callback; + destroyer(w, err); + destroyer(r, err); + } + } + return d; } diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_legacy.js b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_legacy.js index 1f859aae7..f0b4473df 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_legacy.js +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_legacy.js @@ -1,83 +1,87 @@ -import EventEmitter from "./events"; -import { Buffer } from "./internal_buffer"; +import + EventEmitter from './events'; + +import { + Buffer, +} from './internal_buffer'; export function Stream(opts) { - EventEmitter.call(this, opts || {}); + EventEmitter.call(this, opts||{}); } Object.setPrototypeOf(Stream.prototype, EventEmitter.prototype); Object.setPrototypeOf(Stream, EventEmitter); Stream.prototype.pipe = function (dest, options) { - const source = this; - function ondata(chunk) { - if (dest.writable && dest.write(chunk) === false && source.pause) { - source.pause(); - } + const source = this; + function ondata(chunk) { + if (dest.writable && dest.write(chunk) === false && source.pause) { + source.pause(); } - source.on("data", ondata); - function ondrain() { - if (source.readable && source.resume) { - source.resume(); - } + } + source.on('data', ondata); + function ondrain() { + if (source.readable && source.resume) { + source.resume(); } - dest.on("drain", ondrain); + } + dest.on('drain', ondrain); - // If the 'end' option is not supplied, dest.end() will be called when - // source gets the 'end' or 'close' events. Only dest.end() once. - if (!dest._isStdio && (!options || options.end !== false)) { - source.on("end", onend); - source.on("close", onclose); - } - let didOnEnd = false; - function onend() { - if (didOnEnd) return; - didOnEnd = true; - dest.end(); - } - function onclose() { - if (didOnEnd) return; - didOnEnd = true; - if (typeof dest.destroy === "function") dest.destroy(); - } + // If the 'end' option is not supplied, dest.end() will be called when + // source gets the 'end' or 'close' events. Only dest.end() once. + if (!dest._isStdio && (!options || options.end !== false)) { + source.on('end', onend); + source.on('close', onclose); + } + let didOnEnd = false; + function onend() { + if (didOnEnd) return; + didOnEnd = true; + dest.end(); + } + function onclose() { + if (didOnEnd) return; + didOnEnd = true; + if (typeof dest.destroy === 'function') dest.destroy(); + } - // Don't leave dangling pipes when there are errors. - function onerror(er) { - cleanup(); - if (EventEmitter.listenerCount(this, "error") === 0) { - this.emit("error", er); - } + // Don't leave dangling pipes when there are errors. + function onerror(er) { + cleanup(); + if (EventEmitter.listenerCount(this, 'error') === 0) { + this.emit('error', er); } - source.prependListener("error", onerror); - dest.prependListener("error", onerror); + } + source.prependListener('error', onerror); + dest.prependListener('error', onerror); - // Remove all the event listeners that were added. - function cleanup() { - source.removeListener("data", ondata); - dest.removeListener("drain", ondrain); - source.removeListener("end", onend); - source.removeListener("close", onclose); - source.removeListener("error", onerror); - dest.removeListener("error", onerror); - source.removeListener("end", cleanup); - source.removeListener("close", cleanup); - dest.removeListener("close", cleanup); - } - source.on("end", cleanup); - source.on("close", cleanup); - dest.on("close", cleanup); - dest.emit("pipe", source); + // Remove all the event listeners that were added. + function cleanup() { + source.removeListener('data', ondata); + dest.removeListener('drain', ondrain); + source.removeListener('end', onend); + source.removeListener('close', onclose); + source.removeListener('error', onerror); + dest.removeListener('error', onerror); + source.removeListener('end', cleanup); + source.removeListener('close', cleanup); + dest.removeListener('close', cleanup); + } + source.on('end', cleanup); + source.on('close', cleanup); + dest.on('close', cleanup); + dest.emit('pipe', source); - // Allow for unix-like usage: A.pipe(B).pipe(C) - return dest; -}; + // Allow for unix-like usage: A.pipe(B).pipe(C) + return dest; +} // Backwards-compat with node 0.4.x -Stream.Stream = Stream; +Stream.Stream = Stream Stream._isUint8Array = function isUint8Array(value) { - return value instanceof Uint8Array; -}; + return value instanceof Uint8Array; +} Stream._uint8ArrayToBuffer = function _uint8ArrayToBuffer(chunk) { - return Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength); -}; + return Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength); +} diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_readable.js b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_readable.js index af1d687b6..0066ff927 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_readable.js +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_readable.js @@ -1,149 +1,157 @@ /* eslint-disable */ import { - nop, - getHighWaterMark, - getDefaultHighWaterMark, - kPaused, - addAbortSignal, - BufferList, - eos, - construct, - destroy, - destroyer, - undestroy, - errorOrDestroy, - finished, -} from "./streams_util"; - -import * as process from "./process"; - -import EventEmitter from "./events"; - -import { Stream } from "./streams_legacy"; + nop, + getHighWaterMark, + getDefaultHighWaterMark, + kPaused, + addAbortSignal, + BufferList, + eos, + construct, + destroy, + destroyer, + undestroy, + errorOrDestroy, + finished, +} from './streams_util'; + +import * as process from './process'; + +import EventEmitter from './events'; import { - newStreamReadableFromReadableStream, - newReadableStreamFromStreamReadable, -} from "./streams_adapters"; + Stream, +} from './streams_legacy'; -import { Buffer } from "./internal_buffer"; +import { + newStreamReadableFromReadableStream, + newReadableStreamFromStreamReadable, +} from './streams_adapters'; import { - AbortError, - aggregateTwoErrors, - ERR_INVALID_ARG_TYPE, - ERR_METHOD_NOT_IMPLEMENTED, - ERR_MISSING_ARGS, - ERR_OUT_OF_RANGE, - ERR_STREAM_PUSH_AFTER_EOF, - ERR_STREAM_UNSHIFT_AFTER_END_EVENT, - ERR_STREAM_NULL_VALUES, -} from "./internal_errors"; + Buffer, +} from './internal_buffer'; -import { validateObject, validateAbortSignal, validateInteger } from "./validators"; +import { + AbortError, + aggregateTwoErrors, + ERR_INVALID_ARG_TYPE, + ERR_METHOD_NOT_IMPLEMENTED, + ERR_MISSING_ARGS, + ERR_OUT_OF_RANGE, + ERR_STREAM_PUSH_AFTER_EOF, + ERR_STREAM_UNSHIFT_AFTER_END_EVENT, + ERR_STREAM_NULL_VALUES, +} from './internal_errors'; -import { StringDecoder } from "./internal_stringdecoder"; +import { + validateObject, + validateAbortSignal, + validateInteger, +} from './validators'; -import { isDuplexInstance } from "./streams_duplex"; +import { StringDecoder } from './internal_stringdecoder'; + +import { isDuplexInstance } from './streams_duplex'; // ====================================================================================== // ReadableState function ReadableState(options, stream, isDuplex) { - // Duplex streams are both readable and writable, but share - // the same options object. - // However, some cases require setting options to different - // values for the readable and the writable sides of the duplex stream. - // These options can be provided separately as readableXXX and writableXXX. - if (typeof isDuplex !== "boolean") isDuplex = isDuplexInstance(stream); - - // Object stream flag. Used to make read(n) ignore n and to - // make all the buffer merging and length checks go away. - this.objectMode = !!options?.objectMode; - if (isDuplex) this.objectMode = this.objectMode || !!options?.readableObjectMode; - - // The point at which it stops calling _read() to fill the buffer - // Note: 0 is a valid value, means "don't call _read preemptively ever" - this.highWaterMark = options - ? getHighWaterMark(this, options, "readableHighWaterMark", isDuplex) - : getDefaultHighWaterMark(false); - - // A linked list is used to store data chunks instead of an array because the - // linked list can remove elements from the beginning faster than - // array.shift(). - this.buffer = new BufferList(); - this.length = 0; - this.pipes = []; - this.flowing = null; - this.ended = false; - this.endEmitted = false; - this.reading = false; - - // Stream is still being constructed and cannot be - // destroyed until construction finished or failed. - // Async construction is opt in, therefore we start as - // constructed. - this.constructed = true; - - // A flag to be able to tell if the event 'readable'/'data' is emitted - // immediately, or on a later tick. We set this to true at first, because - // any actions that shouldn't happen until "later" should generally also - // not happen before the first read call. - this.sync = true; - - // Whenever we return null, then we set a flag to say - // that we're awaiting a 'readable' event emission. - this.needReadable = false; - this.emittedReadable = false; - this.readableListening = false; - this.resumeScheduled = false; - this[kPaused] = null; - - // True if the error was already emitted and should not be thrown again. - this.errorEmitted = false; - - // Should close be emitted on destroy. Defaults to true. - this.emitClose = !options || options.emitClose !== false; - - // Should .destroy() be called after 'end' (and potentially 'finish'). - this.autoDestroy = !options || options.autoDestroy !== false; - - // Has it been destroyed. - this.destroyed = false; - - // Indicates whether the stream has errored. When true no further - // _read calls, 'data' or 'readable' events should occur. This is needed - // since when autoDestroy is disabled we need a way to tell whether the - // stream has failed. - this.errored = null; - - // Indicates whether the stream has finished destroying. - this.closed = false; - - // True if close has been emitted or would have been emitted - // depending on emitClose. - this.closeEmitted = false; - - // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. - this.defaultEncoding = options?.defaultEncoding || "utf8"; - - // Ref the piped dest which we need a drain event on it - // type: null | Writable | Set. - this.awaitDrainWriters = null; - this.multiAwaitDrain = false; - - // If true, a maybeReadMore has been scheduled. - this.readingMore = false; - this.dataEmitted = false; - this.decoder = null; - this.encoding = null; - if (options && options.encoding) { - this.decoder = new StringDecoder(options.encoding); - this.encoding = options.encoding; - } + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + if (typeof isDuplex !== 'boolean') isDuplex = isDuplexInstance(stream); + + // Object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away. + this.objectMode = !!(options?.objectMode); + if (isDuplex) this.objectMode = this.objectMode || !!(options?.readableObjectMode); + + // The point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + this.highWaterMark = options + ? getHighWaterMark(this, options, 'readableHighWaterMark', isDuplex) + : getDefaultHighWaterMark(false); + + // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift(). + this.buffer = new BufferList(); + this.length = 0; + this.pipes = []; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // Stream is still being constructed and cannot be + // destroyed until construction finished or failed. + // Async construction is opt in, therefore we start as + // constructed. + this.constructed = true; + + // A flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + this.sync = true; + + // Whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + this[kPaused] = null; + + // True if the error was already emitted and should not be thrown again. + this.errorEmitted = false; + + // Should close be emitted on destroy. Defaults to true. + this.emitClose = !options || options.emitClose !== false; + + // Should .destroy() be called after 'end' (and potentially 'finish'). + this.autoDestroy = !options || options.autoDestroy !== false; + + // Has it been destroyed. + this.destroyed = false; + + // Indicates whether the stream has errored. When true no further + // _read calls, 'data' or 'readable' events should occur. This is needed + // since when autoDestroy is disabled we need a way to tell whether the + // stream has failed. + this.errored = null; + + // Indicates whether the stream has finished destroying. + this.closed = false; + + // True if close has been emitted or would have been emitted + // depending on emitClose. + this.closeEmitted = false; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options?.defaultEncoding || 'utf8'; + + // Ref the piped dest which we need a drain event on it + // type: null | Writable | Set. + this.awaitDrainWriters = null; + this.multiAwaitDrain = false; + + // If true, a maybeReadMore has been scheduled. + this.readingMore = false; + this.dataEmitted = false; + this.decoder = null; + this.encoding = null; + if (options && options.encoding) { + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } } // ====================================================================================== @@ -155,357 +163,355 @@ Object.setPrototypeOf(Readable.prototype, Stream.prototype); Object.setPrototypeOf(Readable, Stream); export function Readable(options) { - if (!(this instanceof Readable)) return new Readable(options); - - // Checking for a Stream.Duplex instance is faster here instead of inside - // the ReadableState constructor, at least with V8 6.5. - const isDuplex = isDuplexInstance(this); - this._readableState = new ReadableState(options, this, isDuplex); - if (options) { - if (typeof options.read === "function") this._read = options.read; - if (typeof options.destroy === "function") this._destroy = options.destroy; - if (typeof options.construct === "function") this._construct = options.construct; - if (options.signal && !isDuplex) addAbortSignal(options.signal, this); - } - Stream.call(this, options); - construct(this, () => { - if (this._readableState.needReadable) { - maybeReadMore(this, this._readableState); - } - }); + if (!(this instanceof Readable)) return new Readable(options); + + // Checking for a Stream.Duplex instance is faster here instead of inside + // the ReadableState constructor, at least with V8 6.5. + const isDuplex = isDuplexInstance(this); + this._readableState = new ReadableState(options, this, isDuplex); + if (options) { + if (typeof options.read === 'function') this._read = options.read; + if (typeof options.destroy === 'function') this._destroy = options.destroy; + if (typeof options.construct === 'function') this._construct = options.construct; + if (options.signal && !isDuplex) addAbortSignal(options.signal, this); + } + Stream.call(this, options); + construct(this, () => { + if (this._readableState.needReadable) { + maybeReadMore(this, this._readableState); + } + }); } -Readable.prototype.destroy = destroy; -Readable.prototype._undestroy = undestroy; +Readable.prototype.destroy = destroy +Readable.prototype._undestroy = undestroy Readable.prototype._destroy = function (err, cb) { - if (cb) cb(err); -}; + if (cb) cb(err); +} Readable.prototype[EventEmitter.captureRejectionSymbol] = function (err) { - this.destroy(err); -}; + this.destroy(err); +} // Manually shove something into the read() buffer. // This returns true if the highWaterMark has not been hit yet, // similar to how Writable.write() returns true if you should // write() some more. Readable.prototype.push = function (chunk, encoding) { - return readableAddChunk(this, chunk, encoding, false); -}; + return readableAddChunk(this, chunk, encoding, false); +} // Unshift should *always* be something directly out of read(). Readable.prototype.unshift = function (chunk, encoding) { - return readableAddChunk(this, chunk, encoding, true); -}; + return readableAddChunk(this, chunk, encoding, true); +} function readableAddChunk(stream, chunk, encoding, addToFront) { - const state = stream._readableState; - let err; - if (!state.objectMode) { - if (typeof chunk === "string") { - encoding ||= state.defaultEncoding; - if (state.encoding !== encoding) { - if (addToFront && state.encoding) { - // When unshifting, if state.encoding is set, we have to save - // the string in the BufferList with the state encoding. - chunk = Buffer.from(chunk, encoding).toString(state.encoding); - } else { - chunk = Buffer.from(chunk, encoding); - encoding = ""; - } - } - } else if (chunk instanceof Buffer) { - encoding = ""; - } else if (Stream._isUint8Array(chunk)) { - chunk = Stream._uint8ArrayToBuffer(chunk); - encoding = ""; - } else if (chunk != null) { - err = new ERR_INVALID_ARG_TYPE("chunk", ["string", "Buffer", "Uint8Array"], chunk); - } - } - if (err) { - errorOrDestroy(stream, err); - } else if (chunk === null) { - state.reading = false; - onEofChunk(stream, state); - } else if (state.objectMode || (chunk && chunk.length > 0)) { - if (addToFront) { - if (state.endEmitted) errorOrDestroy(stream, new ERR_STREAM_UNSHIFT_AFTER_END_EVENT()); - else if (state.destroyed || state.errored) return false; - else addChunk(stream, state, chunk, true); - } else if (state.ended) { - errorOrDestroy(stream, new ERR_STREAM_PUSH_AFTER_EOF()); - } else if (state.destroyed || state.errored) { - return false; + const state = stream._readableState; + let err; + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding ||= state.defaultEncoding; + if (state.encoding !== encoding) { + if (addToFront && state.encoding) { + // When unshifting, if state.encoding is set, we have to save + // the string in the BufferList with the state encoding. + chunk = Buffer.from(chunk, encoding).toString(state.encoding); } else { - state.reading = false; - if (state.decoder && !encoding) { - chunk = state.decoder.write(chunk); - if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false); - else maybeReadMore(stream, state); - } else { - addChunk(stream, state, chunk, false); - } + chunk = Buffer.from(chunk, encoding); + encoding = ''; } - } else if (!addToFront) { - state.reading = false; - maybeReadMore(stream, state); - } + } + } else if (chunk instanceof Buffer) { + encoding = '' + } else if (Stream._isUint8Array(chunk)) { + chunk = Stream._uint8ArrayToBuffer(chunk); + encoding = ''; + } else if (chunk != null) { + err = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer', 'Uint8Array'], chunk); + } + } + if (err) { + errorOrDestroy(stream, err); + } else if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else if (state.objectMode || (chunk && chunk.length > 0)) { + if (addToFront) { + if (state.endEmitted) errorOrDestroy(stream, new ERR_STREAM_UNSHIFT_AFTER_END_EVENT()); + else if (state.destroyed || state.errored) return false; + else addChunk(stream, state, chunk, true); + } else if (state.ended) { + errorOrDestroy(stream, new ERR_STREAM_PUSH_AFTER_EOF()); + } else if (state.destroyed || state.errored) { + return false; + } else { + state.reading = false; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false); + else maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + maybeReadMore(stream, state); + } - // We can push more data if we are below the highWaterMark. - // Also, if we have no data yet, we can stand some more bytes. - // This is to work around cases where hwm=0, such as the repl. - return !state.ended && (state.length < state.highWaterMark || state.length === 0); + // We can push more data if we are below the highWaterMark. + // Also, if we have no data yet, we can stand some more bytes. + // This is to work around cases where hwm=0, such as the repl. + return !state.ended && (state.length < state.highWaterMark || state.length === 0); } function addChunk(stream, state, chunk, addToFront) { - if (state.flowing && state.length === 0 && !state.sync && stream.listenerCount("data") > 0) { - // Use the guard to avoid creating `Set()` repeatedly - // when we have multiple pipes. - if (state.multiAwaitDrain) { - state.awaitDrainWriters.clear(); - } else { - state.awaitDrainWriters = null; - state.multiAwaitDrain = false; - } - state.dataEmitted = true; - stream.emit("data", chunk); + if (state.flowing && state.length === 0 && !state.sync && stream.listenerCount('data') > 0) { + // Use the guard to avoid creating `Set()` repeatedly + // when we have multiple pipes. + if (state.multiAwaitDrain) { + state.awaitDrainWriters.clear(); } else { - // Update the buffer info. - state.length += state.objectMode ? 1 : chunk.length; - if (addToFront) state.buffer.unshift(chunk); - else state.buffer.push(chunk); - if (state.needReadable) emitReadable(stream); - } - maybeReadMore(stream, state); + state.awaitDrainWriters = null; + state.multiAwaitDrain = false; + } + state.dataEmitted = true; + stream.emit('data', chunk); + } else { + // Update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk); + else state.buffer.push(chunk); + if (state.needReadable) emitReadable(stream); + } + maybeReadMore(stream, state); } Readable.prototype.isPaused = function () { - const state = this._readableState; - return state[kPaused] === true || state.flowing === false; -}; + const state = this._readableState; + return state[kPaused] === true || state.flowing === false; +} // Backwards compatibility. Readable.prototype.setEncoding = function (enc) { - const decoder = new StringDecoder(enc); - this._readableState.decoder = decoder; - // If setEncoding(null), decoder.encoding equals utf8. - this._readableState.encoding = decoder.encoding; - const buffer = this._readableState.buffer; - // Iterate over current buffer to convert already stored Buffers: - let content = ""; - for (const data of buffer) { - content += decoder.write(data); - } - buffer.clear(); - if (content !== "") buffer.push(content); - this._readableState.length = content.length; - return this; -}; + const decoder = new StringDecoder(enc); + this._readableState.decoder = decoder; + // If setEncoding(null), decoder.encoding equals utf8. + this._readableState.encoding = decoder.encoding; + const buffer = this._readableState.buffer; + // Iterate over current buffer to convert already stored Buffers: + let content = ''; + for (const data of buffer) { + content += decoder.write(data); + } + buffer.clear(); + if (content !== '') buffer.push(content); + this._readableState.length = content.length; + return this; +} // Don't raise the hwm > 1GB. const MAX_HWM = 0x40000000; function computeNewHighWaterMark(n) { - if (n > MAX_HWM) { - throw new ERR_OUT_OF_RANGE("size", "<= 1GiB", n); - } else { - // Get the next highest power of 2 to prevent increasing hwm excessively in - // tiny amounts. - n--; - n |= n >>> 1; - n |= n >>> 2; - n |= n >>> 4; - n |= n >>> 8; - n |= n >>> 16; - n++; - } - return n; + if (n > MAX_HWM) { + throw new ERR_OUT_OF_RANGE('size', '<= 1GiB', n); + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts. + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; + } + return n; } // This function is designed to be inlinable, so please take care when making // changes to the function body. function howMuchToRead(n, state) { - if (n <= 0 || (state.length === 0 && state.ended)) return 0; - if (state.objectMode) return 1; - if (Number.isNaN(n)) { - // Only flow one buffer at a time. - if (state.flowing && state.length) return state.buffer.first().length; - return state.length; - } - if (n <= state.length) return n; - return state.ended ? state.length : 0; + if (n <= 0 || (state.length === 0 && state.ended)) return 0; + if (state.objectMode) return 1; + if (Number.isNaN(n)) { + // Only flow one buffer at a time. + if (state.flowing && state.length) return state.buffer.first().length; + return state.length; + } + if (n <= state.length) return n; + return state.ended ? state.length : 0; } // You can override either this method, or the async _read(n) below. Readable.prototype.read = function (n) { - // Same as parseInt(undefined, 10), however V8 7.3 performance regressed - // in this scenario, so we are doing it manually. - if (n === undefined) { - n = NaN; - } else if (!Number.isInteger(n)) { - n = Number.parseInt(`${n}`, 10); - } - const state = this._readableState; - const nOrig = n; - - // If we're asking for more than the current hwm, then raise the hwm. - if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); - if (n !== 0) state.emittedReadable = false; - - // If we're doing read(0) to trigger a readable event, but we - // already have a bunch of data in the buffer, then just trigger - // the 'readable' event and move on. - if ( - n === 0 && - state.needReadable && - ((state.highWaterMark !== 0 ? state.length >= state.highWaterMark : state.length > 0) || - state.ended) - ) { - if (state.length === 0 && state.ended) endReadable(this); - else emitReadable(this); - return null; - } - n = howMuchToRead(n, state); - - // If we've ended, and we're now clear, then finish it up. - if (n === 0 && state.ended) { - if (state.length === 0) endReadable(this); - return null; - } - - // All the actual chunk generation logic needs to be - // *below* the call to _read. The reason is that in certain - // synthetic stream cases, such as passthrough streams, _read - // may be a completely synchronous operation which may change - // the state of the read buffer, providing enough data when - // before there was *not* enough. - // - // So, the steps are: - // 1. Figure out what the state of things will be after we do - // a read from the buffer. - // - // 2. If that resulting state will trigger a _read, then call _read. - // Note that this may be asynchronous, or synchronous. Yes, it is - // deeply ugly to write APIs this way, but that still doesn't mean - // that the Readable class should behave improperly, as streams are - // designed to be sync/async agnostic. - // Take note if the _read call is sync or async (ie, if the read call - // has returned yet), so that we know whether or not it's safe to emit - // 'readable' etc. - // - // 3. Actually pull the requested chunks out of the buffer and return. - - // if we need a readable event, then we need to do some reading. - let doRead = state.needReadable; - - // If we currently have less than the highWaterMark, then also read some. - if (state.length === 0 || state.length - n < state.highWaterMark) { - doRead = true; - } - - // However, if we've ended, then there's no point, if we're already - // reading, then it's unnecessary, if we're constructing we have to wait, - // and if we're destroyed or errored, then it's not allowed, - if (state.ended || state.reading || state.destroyed || state.errored || !state.constructed) { - doRead = false; - } else if (doRead) { - state.reading = true; - state.sync = true; - // If the length is currently zero, then we *need* a readable event. - if (state.length === 0) state.needReadable = true; - - // Call internal read method - try { - this._read(state.highWaterMark); - } catch (err) { - errorOrDestroy(this, err); - } - state.sync = false; - // If _read pushed data synchronously, then `reading` will be false, - // and we need to re-evaluate how much data we can return to the user. - if (!state.reading) n = howMuchToRead(nOrig, state); - } - let ret; - if (n > 0) ret = fromList(n, state); - else ret = null; - if (ret === null) { - state.needReadable = state.length <= state.highWaterMark; - n = 0; + // Same as parseInt(undefined, 10), however V8 7.3 performance regressed + // in this scenario, so we are doing it manually. + if (n === undefined) { + n = NaN; + } else if (!Number.isInteger(n)) { + n = Number.parseInt(`${n}`, 10); + } + const state = this._readableState; + const nOrig = n; + + // If we're asking for more than the current hwm, then raise the hwm. + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); + if (n !== 0) state.emittedReadable = false; + + // If we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if ( + n === 0 && + state.needReadable && + ((state.highWaterMark !== 0 ? state.length >= state.highWaterMark : state.length > 0) || state.ended)) { + if (state.length === 0 && state.ended) endReadable(this); + else emitReadable(this); + return null; + } + n = howMuchToRead(n, state); + + // If we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + let doRead = state.needReadable; + + // If we currently have less than the highWaterMark, then also read some. + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + } + + // However, if we've ended, then there's no point, if we're already + // reading, then it's unnecessary, if we're constructing we have to wait, + // and if we're destroyed or errored, then it's not allowed, + if (state.ended || state.reading || state.destroyed || state.errored || !state.constructed) { + doRead = false; + } else if (doRead) { + state.reading = true; + state.sync = true; + // If the length is currently zero, then we *need* a readable event. + if (state.length === 0) state.needReadable = true; + + // Call internal read method + try { + this._read(state.highWaterMark); + } catch (err) { + errorOrDestroy(this, err); + } + state.sync = false; + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (!state.reading) n = howMuchToRead(nOrig, state); + } + let ret; + if (n > 0) ret = fromList(n, state); + else ret = null; + if (ret === null) { + state.needReadable = state.length <= state.highWaterMark; + n = 0; + } else { + state.length -= n; + if (state.multiAwaitDrain) { + state.awaitDrainWriters.clear(); } else { - state.length -= n; - if (state.multiAwaitDrain) { - state.awaitDrainWriters.clear(); - } else { - state.awaitDrainWriters = null; - state.multiAwaitDrain = false; - } - } - if (state.length === 0) { - // If we have nothing in the buffer, then we want to know - // as soon as we *do* get something into the buffer. - if (!state.ended) state.needReadable = true; - - // If we tried to read() past the EOF, then emit end on the next tick. - if (nOrig !== n && state.ended) endReadable(this); - } - if (ret !== null && !state.errorEmitted && !state.closeEmitted) { - state.dataEmitted = true; - this.emit("data", ret); - } - return ret; -}; + state.awaitDrainWriters = null; + state.multiAwaitDrain = false; + } + } + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended) endReadable(this) + } + if (ret !== null && !state.errorEmitted && !state.closeEmitted) { + state.dataEmitted = true + this.emit('data', ret) + } + return ret +} function onEofChunk(stream, state) { - if (state.ended) return; - if (state.decoder) { - const chunk = state.decoder.end(); - if (chunk && chunk.length) { - state.buffer.push(chunk); - state.length += state.objectMode ? 1 : chunk.length; - } - } - state.ended = true; - if (state.sync) { - // If we are sync, wait until next tick to emit the data. - // Otherwise we risk emitting data in the flow() - // the readable code triggers during a read() call. - emitReadable(stream); - } else { - // Emit 'readable' now to make sure it gets picked up. - state.needReadable = false; - state.emittedReadable = true; - // We have to emit readable now that we are EOF. Modules - // in the ecosystem (e.g. dicer) rely on this event being sync. - emitReadable_(stream); - } + if (state.ended) return; + if (state.decoder) { + const chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + if (state.sync) { + // If we are sync, wait until next tick to emit the data. + // Otherwise we risk emitting data in the flow() + // the readable code triggers during a read() call. + emitReadable(stream); + } else { + // Emit 'readable' now to make sure it gets picked up. + state.needReadable = false; + state.emittedReadable = true; + // We have to emit readable now that we are EOF. Modules + // in the ecosystem (e.g. dicer) rely on this event being sync. + emitReadable_(stream); + } } // Don't emit readable right away in sync mode, because this can trigger // another read() call => stack overflow. This way, it might trigger // a nextTick recursion warning, but that's not so bad. function emitReadable(stream) { - const state = stream._readableState; - state.needReadable = false; - if (!state.emittedReadable) { - state.emittedReadable = true; - process.nextTick(emitReadable_, stream); - } + const state = stream._readableState; + state.needReadable = false; + if (!state.emittedReadable) { + state.emittedReadable = true; + process.nextTick(emitReadable_, stream); + } } function emitReadable_(stream) { - const state = stream._readableState; - if (!state.destroyed && !state.errored && (state.length || state.ended)) { - stream.emit("readable"); - state.emittedReadable = false; - } - - // The stream needs another readable event if: - // 1. It is not flowing, as the flow mechanism will take - // care of it. - // 2. It is not ended. - // 3. It is below the highWaterMark, so we can schedule - // another readable later. - state.needReadable = !state.flowing && !state.ended && state.length <= state.highWaterMark; - flow(stream); + const state = stream._readableState; + if (!state.destroyed && !state.errored && (state.length || state.ended)) { + stream.emit('readable'); + state.emittedReadable = false; + } + + // The stream needs another readable event if: + // 1. It is not flowing, as the flow mechanism will take + // care of it. + // 2. It is not ended. + // 3. It is below the highWaterMark, so we can schedule + // another readable later. + state.needReadable = !state.flowing && !state.ended && state.length <= state.highWaterMark; + flow(stream); } // At this point, the user has presumably seen the 'readable' event, @@ -515,48 +521,48 @@ function emitReadable_(stream) { // However, if we're not ended, or reading, and the length < hwm, // then go ahead and try to read some more preemptively. function maybeReadMore(stream, state) { - if (!state.readingMore && state.constructed) { - state.readingMore = true; - process.nextTick(maybeReadMore_, stream, state); - } + if (!state.readingMore && state.constructed) { + state.readingMore = true; + process.nextTick(maybeReadMore_, stream, state); + } } function maybeReadMore_(stream, state) { - // Attempt to read more data if we should. - // - // The conditions for reading more data are (one of): - // - Not enough data buffered (state.length < state.highWaterMark). The loop - // is responsible for filling the buffer with enough data if such data - // is available. If highWaterMark is 0 and we are not in the flowing mode - // we should _not_ attempt to buffer any extra data. We'll get more data - // when the stream consumer calls read() instead. - // - No data in the buffer, and the stream is in flowing mode. In this mode - // the loop below is responsible for ensuring read() is called. Failing to - // call read here would abort the flow and there's no other mechanism for - // continuing the flow if the stream consumer has just subscribed to the - // 'data' event. - // - // In addition to the above conditions to keep reading data, the following - // conditions prevent the data from being read: - // - The stream has ended (state.ended). - // - There is already a pending 'read' operation (state.reading). This is a - // case where the stream has called the implementation defined _read() - // method, but they are processing the call asynchronously and have _not_ - // called push() with new data. In this case we skip performing more - // read()s. The execution ends in this method again after the _read() ends - // up calling push() with more data. - while ( - !state.reading && - !state.ended && - (state.length < state.highWaterMark || (state.flowing && state.length === 0)) - ) { - const len = state.length; - stream.read(0); - if (len === state.length) - // Didn't get any data, stop spinning. - break; - } - state.readingMore = false; + // Attempt to read more data if we should. + // + // The conditions for reading more data are (one of): + // - Not enough data buffered (state.length < state.highWaterMark). The loop + // is responsible for filling the buffer with enough data if such data + // is available. If highWaterMark is 0 and we are not in the flowing mode + // we should _not_ attempt to buffer any extra data. We'll get more data + // when the stream consumer calls read() instead. + // - No data in the buffer, and the stream is in flowing mode. In this mode + // the loop below is responsible for ensuring read() is called. Failing to + // call read here would abort the flow and there's no other mechanism for + // continuing the flow if the stream consumer has just subscribed to the + // 'data' event. + // + // In addition to the above conditions to keep reading data, the following + // conditions prevent the data from being read: + // - The stream has ended (state.ended). + // - There is already a pending 'read' operation (state.reading). This is a + // case where the stream has called the implementation defined _read() + // method, but they are processing the call asynchronously and have _not_ + // called push() with new data. In this case we skip performing more + // read()s. The execution ends in this method again after the _read() ends + // up calling push() with more data. + while ( + !state.reading && + !state.ended && + (state.length < state.highWaterMark || (state.flowing && state.length === 0)) + ) { + const len = state.length; + stream.read(0); + if (len === state.length) + // Didn't get any data, stop spinning. + break; + } + state.readingMore = false; } // Abstract method. to be overridden in specific implementation classes. @@ -564,1200 +570,1183 @@ function maybeReadMore_(stream, state) { // for virtual (non-string, non-buffer) streams, "length" is somewhat // arbitrary, and perhaps not very meaningful. Readable.prototype._read = function (_size) { - throw new ERR_METHOD_NOT_IMPLEMENTED("_read()"); -}; + throw new ERR_METHOD_NOT_IMPLEMENTED('_read()'); +} Readable.prototype.pipe = function (dest, pipeOpts) { - const src = this; - const state = this._readableState; - if (state.pipes.length === 1) { - if (!state.multiAwaitDrain) { - state.multiAwaitDrain = true; - state.awaitDrainWriters = new Set( - state.awaitDrainWriters ? [state.awaitDrainWriters] : [] - ); - } - } - state.pipes.push(dest); - const doEnd = !pipeOpts || pipeOpts.end !== false; - const endFn = doEnd ? onend : unpipe; - if (state.endEmitted) process.nextTick(endFn); - else src.once("end", endFn); - dest.on("unpipe", onunpipe); - function onunpipe(readable, unpipeInfo) { - if (readable === src) { - if (unpipeInfo && unpipeInfo.hasUnpiped === false) { - unpipeInfo.hasUnpiped = true; - cleanup(); - } - } - } - function onend() { - dest.end(); - } - let ondrain; - let cleanedUp = false; - function cleanup() { - // Cleanup event handlers once the pipe is broken. - dest.removeListener("close", onclose); - dest.removeListener("finish", onfinish); - if (ondrain) { - dest.removeListener("drain", ondrain); - } - dest.removeListener("error", onerror); - dest.removeListener("unpipe", onunpipe); - src.removeListener("end", onend); - src.removeListener("end", unpipe); - src.removeListener("data", ondata); - cleanedUp = true; - - // If the reader is waiting for a drain event from this - // specific writer, then it would cause it to never start - // flowing again. - // So, if this is awaiting a drain, then we just call it now. - // If we don't know, then assume that we are waiting for one. - if ( - ondrain && - state.awaitDrainWriters && - (!dest._writableState || dest._writableState.needDrain) - ) - ondrain(); - } - function pause() { - // If the user unpiped during `dest.write()`, it is possible - // to get stuck in a permanently paused state if that write - // also returned false. - // => Check whether `dest` is still a piping destination. - if (!cleanedUp) { - if (state.pipes.length === 1 && state.pipes[0] === dest) { - state.awaitDrainWriters = dest; - state.multiAwaitDrain = false; - } else if (state.pipes.length > 1 && state.pipes.includes(dest)) { - state.awaitDrainWriters.add(dest); - } - src.pause(); - } - if (!ondrain) { - // When the dest drains, it reduces the awaitDrain counter - // on the source. This would be more elegant with a .once() - // handler in flow(), but adding and removing repeatedly is - // too slow. - ondrain = pipeOnDrain(src, dest); - dest.on("drain", ondrain); - } - } - src.on("data", ondata); - function ondata(chunk) { - const ret = dest.write(chunk); - if (ret === false) { - pause(); - } - } - - // If the dest has an error, then stop piping into it. - // However, don't suppress the throwing behavior for this. - function onerror(er) { - unpipe(); - dest.removeListener("error", onerror); - if (dest.listenerCount("error") === 0) { - const s = dest._writableState || dest._readableState; - if (s && !s.errorEmitted) { - // User incorrectly emitted 'error' directly on the stream. - errorOrDestroy(dest, er); - } else { - dest.emit("error", er); - } - } - } - - // Make sure our error handler is attached before userland ones. - dest.prependListener("error", onerror); - - // Both close and finish should trigger unpipe, but only once. - function onclose() { - dest.removeListener("finish", onfinish); - unpipe(); - } - dest.once("close", onclose); - function onfinish() { - dest.removeListener("close", onclose); - unpipe(); - } - dest.once("finish", onfinish); - function unpipe() { - src.unpipe(dest); - } - - // Tell the dest that it's being piped to. - dest.emit("pipe", src); - - // Start the flow if it hasn't been started already. - - if (dest.writableNeedDrain === true) { - if (state.flowing) { - pause(); - } - } else if (!state.flowing) { - src.resume(); - } - return dest; -}; + const src = this; + const state = this._readableState; + if (state.pipes.length === 1) { + if (!state.multiAwaitDrain) { + state.multiAwaitDrain = true; + state.awaitDrainWriters = new Set( + state.awaitDrainWriters ? [state.awaitDrainWriters] : []); + } + } + state.pipes.push(dest); + const doEnd = (!pipeOpts || pipeOpts.end !== false); + const endFn = doEnd ? onend : unpipe; + if (state.endEmitted) process.nextTick(endFn); + else src.once('end', endFn); + dest.on('unpipe', onunpipe); + function onunpipe(readable, unpipeInfo) { + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } + function onend() { + dest.end(); + } + let ondrain; + let cleanedUp = false; + function cleanup() { + // Cleanup event handlers once the pipe is broken. + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + if (ondrain) { + dest.removeListener('drain', ondrain); + } + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', unpipe); + src.removeListener('data', ondata); + cleanedUp = true; + + // If the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (ondrain && state.awaitDrainWriters && (!dest._writableState || dest._writableState.needDrain)) ondrain(); + } + function pause() { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if (!cleanedUp) { + if (state.pipes.length === 1 && state.pipes[0] === dest) { + state.awaitDrainWriters = dest; + state.multiAwaitDrain = false; + } else if (state.pipes.length > 1 && state.pipes.includes(dest)) { + state.awaitDrainWriters.add(dest); + } + src.pause(); + } + if (!ondrain) { + // When the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + ondrain = pipeOnDrain(src, dest); + dest.on('drain', ondrain); + } + } + src.on('data', ondata); + function ondata(chunk) { + const ret = dest.write(chunk); + if (ret === false) { + pause(); + } + } + + // If the dest has an error, then stop piping into it. + // However, don't suppress the throwing behavior for this. + function onerror(er) { + unpipe(); + dest.removeListener('error', onerror); + if (dest.listenerCount('error') === 0) { + const s = dest._writableState || dest._readableState; + if (s && !s.errorEmitted) { + // User incorrectly emitted 'error' directly on the stream. + errorOrDestroy(dest, er); + } else { + dest.emit('error', er); + } + } + } + + // Make sure our error handler is attached before userland ones. + dest.prependListener('error', onerror); + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + function unpipe() { + src.unpipe(dest); + } + + // Tell the dest that it's being piped to. + dest.emit('pipe', src); + + // Start the flow if it hasn't been started already. + + if (dest.writableNeedDrain === true) { + if (state.flowing) { + pause(); + } + } else if (!state.flowing) { + src.resume(); + } + return dest; +} function pipeOnDrain(src, dest) { - return function pipeOnDrainFunctionResult() { - const state = src._readableState; - - // `ondrain` will call directly, - // `this` maybe not a reference to dest, - // so we use the real dest here. - if (state.awaitDrainWriters === dest) { - state.awaitDrainWriters = null; - } else if (state.multiAwaitDrain) { - state.awaitDrainWriters.delete(dest); - } - if ( - (!state.awaitDrainWriters || state.awaitDrainWriters.size === 0) && - src.listenerCount("data") - ) { - src.resume(); - } - }; + return function pipeOnDrainFunctionResult() { + const state = src._readableState; + + // `ondrain` will call directly, + // `this` maybe not a reference to dest, + // so we use the real dest here. + if (state.awaitDrainWriters === dest) { + state.awaitDrainWriters = null; + } else if (state.multiAwaitDrain) { + state.awaitDrainWriters.delete(dest); + } + if ((!state.awaitDrainWriters || state.awaitDrainWriters.size === 0) && + src.listenerCount('data')) { + src.resume(); + } + } } Readable.prototype.unpipe = function (dest) { - const state = this._readableState; - const unpipeInfo = { - hasUnpiped: false, - }; - - // If we're not piping anywhere, then do nothing. - if (state.pipes.length === 0) return this; - if (!dest) { - // remove all. - const dests = state.pipes; - state.pipes = []; - this.pause(); - for (let i = 0; i < dests.length; i++) - dests[i].emit("unpipe", this, { - hasUnpiped: false, - }); - return this; - } - - // Try to find the right one. - const index = state.pipes.indexOf(dest); - if (index === -1) return this; - state.pipes.splice(index, 1); - if (state.pipes.length === 0) this.pause(); - dest.emit("unpipe", this, unpipeInfo); + const state = this._readableState; + const unpipeInfo = { + hasUnpiped: false + }; + + // If we're not piping anywhere, then do nothing. + if (state.pipes.length === 0) return this; + if (!dest) { + // remove all. + const dests = state.pipes; + state.pipes = []; + this.pause(); + for (let i = 0; i < dests.length; i++) + dests[i].emit('unpipe', this, { + hasUnpiped: false + }) return this; -}; + } + + // Try to find the right one. + const index = state.pipes.indexOf(dest); + if (index === -1) return this; + state.pipes.splice(index, 1); + if (state.pipes.length === 0) this.pause(); + dest.emit('unpipe', this, unpipeInfo); + return this; +} // Set up data events if they are asked for // Ensure readable listeners eventually get something. Readable.prototype.on = function (ev, fn) { - const res = Stream.prototype.on.call(this, ev, fn); - const state = this._readableState; - if (ev === "data") { - // Update readableListening so that resume() may be a no-op - // a few lines down. This is needed to support once('readable'). - state.readableListening = this.listenerCount("readable") > 0; - - // Try start flowing on next tick if stream isn't explicitly paused. - if (state.flowing !== false) this.resume(); - } else if (ev === "readable") { - if (!state.endEmitted && !state.readableListening) { - state.readableListening = state.needReadable = true; - state.flowing = false; - state.emittedReadable = false; - if (state.length) { - emitReadable(this); - } else if (!state.reading) { - process.nextTick(nReadingNextTick, this); - } - } - } - return res; -}; -Readable.prototype.addListener = Readable.prototype.on; + const res = Stream.prototype.on.call(this, ev, fn); + const state = this._readableState; + if (ev === 'data') { + // Update readableListening so that resume() may be a no-op + // a few lines down. This is needed to support once('readable'). + state.readableListening = this.listenerCount('readable') > 0; + + // Try start flowing on next tick if stream isn't explicitly paused. + if (state.flowing !== false) this.resume(); + } else if (ev === 'readable') { + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.flowing = false; + state.emittedReadable = false; + if (state.length) { + emitReadable(this); + } else if (!state.reading) { + process.nextTick(nReadingNextTick, this); + } + } + } + return res; +} +Readable.prototype.addListener = Readable.prototype.on Readable.prototype.removeListener = function (ev, fn) { - const res = Stream.prototype.removeListener.call(this, ev, fn); - if (ev === "readable") { - // We need to check if there is someone still listening to - // readable and reset the state. However this needs to happen - // after readable has been emitted but before I/O (nextTick) to - // support once('readable', fn) cycles. This means that calling - // resume within the same tick will have no - // effect. - process.nextTick(updateReadableListening, this); - } - return res; -}; -Readable.prototype.off = Readable.prototype.removeListener; + const res = Stream.prototype.removeListener.call(this, ev, fn); + if (ev === 'readable') { + // We need to check if there is someone still listening to + // readable and reset the state. However this needs to happen + // after readable has been emitted but before I/O (nextTick) to + // support once('readable', fn) cycles. This means that calling + // resume within the same tick will have no + // effect. + process.nextTick(updateReadableListening, this); + } + return res; +} +Readable.prototype.off = Readable.prototype.removeListener Readable.prototype.removeAllListeners = function (ev) { - const res = Stream.prototype.removeAllListeners.apply(this, arguments); - if (ev === "readable" || ev === undefined) { - // We need to check if there is someone still listening to - // readable and reset the state. However this needs to happen - // after readable has been emitted but before I/O (nextTick) to - // support once('readable', fn) cycles. This means that calling - // resume within the same tick will have no - // effect. - process.nextTick(updateReadableListening, this); - } - return res; -}; + const res = Stream.prototype.removeAllListeners.apply(this, arguments); + if (ev === 'readable' || ev === undefined) { + // We need to check if there is someone still listening to + // readable and reset the state. However this needs to happen + // after readable has been emitted but before I/O (nextTick) to + // support once('readable', fn) cycles. This means that calling + // resume within the same tick will have no + // effect. + process.nextTick(updateReadableListening, this); + } + return res; +} function updateReadableListening(self) { - const state = self._readableState; - state.readableListening = self.listenerCount("readable") > 0; - if (state.resumeScheduled && state[kPaused] === false) { - // Flowing needs to be set to true now, otherwise - // the upcoming resume will not flow. - state.flowing = true; - - // Crude way to check if we should resume. - } else if (self.listenerCount("data") > 0) { - self.resume(); - } else if (!state.readableListening) { - state.flowing = null; - } + const state = self._readableState; + state.readableListening = self.listenerCount('readable') > 0; + if (state.resumeScheduled && state[kPaused] === false) { + // Flowing needs to be set to true now, otherwise + // the upcoming resume will not flow. + state.flowing = true; + + // Crude way to check if we should resume. + } else if (self.listenerCount('data') > 0) { + self.resume(); + } else if (!state.readableListening) { + state.flowing = null; + } } function nReadingNextTick(self) { - self.read(0); + self.read(0); } // pause() and resume() are remnants of the legacy readable stream API // If the user uses them, then switch into old mode. Readable.prototype.resume = function () { - const state = this._readableState; - if (!state.flowing) { - // We flow only if there is no one listening - // for readable, but we still have to call - // resume(). - state.flowing = !state.readableListening; - resume(this, state); - } - state[kPaused] = false; - return this; -}; + const state = this._readableState; + if (!state.flowing) { + // We flow only if there is no one listening + // for readable, but we still have to call + // resume(). + state.flowing = !state.readableListening; + resume(this, state); + } + state[kPaused] = false; + return this; +} function resume(stream, state) { - if (!state.resumeScheduled) { - state.resumeScheduled = true; - process.nextTick(resume_, stream, state); - } + if (!state.resumeScheduled) { + state.resumeScheduled = true; + process.nextTick(resume_, stream, state); + } } function resume_(stream, state) { - if (!state.reading) { - stream.read(0); - } - state.resumeScheduled = false; - stream.emit("resume"); - flow(stream); - if (state.flowing && !state.reading) stream.read(0); + if (!state.reading) { + stream.read(0); + } + state.resumeScheduled = false; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) stream.read(0); } Readable.prototype.pause = function () { - if (this._readableState.flowing !== false) { - this._readableState.flowing = false; - this.emit("pause"); - } - this._readableState[kPaused] = true; - return this; -}; + if (this._readableState.flowing !== false) { + this._readableState.flowing = false; + this.emit('pause'); + } + this._readableState[kPaused] = true; + return this; +} function flow(stream) { - const state = stream._readableState; - while (state.flowing && stream.read() !== null); + const state = stream._readableState; + while (state.flowing && stream.read() !== null); } // Wrap an old-style stream as the async data source. // This is *not* part of the readable stream interface. // It is an ugly unfortunate mess of history. Readable.prototype.wrap = function (stream) { - let paused = false; - - // TODO (ronag): Should this.destroy(err) emit - // 'error' on the wrapped stream? Would require - // a static factory method, e.g. Readable.wrap(stream). - stream.on("data", (chunk) => { - if (!this.push(chunk) && stream.pause) { - paused = true; - stream.pause(); - } - }); - - stream.on("end", () => { - this.push(null); - }); - stream.on("error", (err) => { - errorOrDestroy(this, err); - }); - stream.on("close", () => { - this.destroy(); - }); - stream.on("destroy", () => { - this.destroy(); - }); - this._read = () => { - if (paused && stream.resume) { - paused = false; - stream.resume(); - } - }; - - // Proxy all the other methods. Important when wrapping filters and duplexes. - const streamKeys = Object.keys(stream); - for (let j = 1; j < streamKeys.length; j++) { - const i = streamKeys[j]; - if (this[i] === undefined && typeof stream[i] === "function") { - this[i] = stream[i].bind(stream); - } - } - return this; -}; + let paused = false; + + // TODO (ronag): Should this.destroy(err) emit + // 'error' on the wrapped stream? Would require + // a static factory method, e.g. Readable.wrap(stream). + stream.on('data', (chunk) => { + if (!this.push(chunk) && stream.pause) { + paused = true; + stream.pause(); + } + }); + + stream.on('end', () => { + this.push(null); + }); + stream.on('error', (err) => { + errorOrDestroy(this, err); + }); + stream.on('close', () => { + this.destroy(); + }); + stream.on('destroy', () => { + this.destroy(); + }); + this._read = () => { + if (paused && stream.resume) { + paused = false; + stream.resume(); + } + }; + + // Proxy all the other methods. Important when wrapping filters and duplexes. + const streamKeys = Object.keys(stream); + for (let j = 1; j < streamKeys.length; j++) { + const i = streamKeys[j]; + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = stream[i].bind(stream); + } + } + return this; +} Readable.prototype[Symbol.asyncIterator] = function () { - return streamToAsyncIterator(this); -}; + return streamToAsyncIterator(this); +} Readable.prototype.iterator = function (options) { - if (options !== undefined) { - validateObject(options, "options", options); - } - return streamToAsyncIterator(this, options); -}; + if (options !== undefined) { + validateObject(options, 'options', options); + } + return streamToAsyncIterator(this, options); +} function streamToAsyncIterator(stream, options) { - if (typeof stream.read !== "function") { - stream = Readable.wrap(stream, { - objectMode: true, - }); - } - const iter = createAsyncIterator(stream, options); - iter.stream = stream; - return iter; + if (typeof stream.read !== 'function') { + stream = Readable.wrap(stream, { + objectMode: true + }); + } + const iter = createAsyncIterator(stream, options); + iter.stream = stream; + return iter; } async function* createAsyncIterator(stream, options) { - let callback = nop; - function next(resolve) { - if (this === stream) { - callback(); - callback = nop; - } else { - callback = resolve; - } - } - stream.on("readable", next); - let error; - const cleanup = eos( - stream, - { - writable: false, - }, - (err) => { - error = err ? aggregateTwoErrors(error, err) : null; - callback(); - callback = nop; - } - ); - try { - while (true) { - const chunk = stream.destroyed ? null : stream.read(); - if (chunk !== null) { - yield chunk; - } else if (error) { - throw error; - } else if (error === null) { - return; - } else { - await new Promise(next); - } - } - } catch (err) { - error = aggregateTwoErrors(error, err); + let callback = nop; + function next(resolve) { + if (this === stream) { + callback(); + callback = nop; + } else { + callback = resolve; + } + } + stream.on('readable', next); + let error; + const cleanup = eos( + stream, + { + writable: false + }, + (err) => { + error = err ? aggregateTwoErrors(error, err) : null + callback() + callback = nop + } + ); + try { + while (true) { + const chunk = stream.destroyed ? null : stream.read(); + if (chunk !== null) { + yield chunk; + } else if (error) { throw error; - } finally { - if ( - (error || - (options === null || options === undefined - ? undefined - : options.destroyOnReturn) !== false) && - (error === undefined || stream._readableState.autoDestroy) - ) { - destroyer(stream, null); - } else { - stream.off("readable", next); - cleanup(); - } + } else if (error === null) { + return; + } else { + await new Promise(next); + } + } + } catch (err) { + error = aggregateTwoErrors(error, err); + throw error; + } finally { + if ( + (error || (options === null || options === undefined ? undefined : options.destroyOnReturn) !== false) && + (error === undefined || stream._readableState.autoDestroy) + ) { + destroyer(stream, null); + } else { + stream.off('readable', next); + cleanup(); } + } } // Making it explicit these properties are not enumerable // because otherwise some prototype manipulation in // userland will fail. Object.defineProperties(Readable.prototype, { - readable: { - get() { - const r = this._readableState; - // r.readable === false means that this is part of a Duplex stream - // where the readable side was disabled upon construction. - // Compat. The user might manually disable readable side through - // deprecated setter. - return !!r && r.readable !== false && !r.destroyed && !r.errorEmitted && !r.endEmitted; - }, - set(val) { - // Backwards compat. - if (this._readableState) { - this._readableState.readable = !!val; - } - }, - }, - readableDidRead: { - enumerable: false, - get: function () { - return !!this._readableState?.dataEmitted; - }, + readable: { + get() { + const r = this._readableState; + // r.readable === false means that this is part of a Duplex stream + // where the readable side was disabled upon construction. + // Compat. The user might manually disable readable side through + // deprecated setter. + return !!r && r.readable !== false && !r.destroyed && !r.errorEmitted && !r.endEmitted; }, - readableAborted: { - enumerable: false, - get: function () { - return !!( - this._readableState?.readable !== false && - (this._readableState?.destroyed || this._readableState?.errored) && - !this._readableState?.endEmitted - ); - }, + set(val) { + // Backwards compat. + if (this._readableState) { + this._readableState.readable = !!val; + } + } + }, + readableDidRead: { + enumerable: false, + get: function () { + return !!(this._readableState?.dataEmitted); + } + }, + readableAborted: { + enumerable: false, + get: function () { + return !!( + this._readableState?.readable !== false && + (this._readableState?.destroyed || this._readableState?.errored) && + !this._readableState?.endEmitted + ); + } + }, + readableHighWaterMark: { + enumerable: false, + get: function () { + return this._readableState?.highWaterMark; + } + }, + readableBuffer: { + enumerable: false, + get: function () { + return this._readableState?.buffer; + } + }, + readableFlowing: { + enumerable: false, + get: function () { + return !!(this._readableState?.flowing); }, - readableHighWaterMark: { - enumerable: false, - get: function () { - return this._readableState?.highWaterMark; - }, - }, - readableBuffer: { - enumerable: false, - get: function () { - return this._readableState?.buffer; - }, - }, - readableFlowing: { - enumerable: false, - get: function () { - return !!this._readableState?.flowing; - }, - set: function (state) { - if (this._readableState) { - this._readableState.flowing = state; - } - }, - }, - readableLength: { - enumerable: false, - get() { - return this._readableState?.length | 0; - }, - }, - readableObjectMode: { - enumerable: false, - get() { - return this._readableState ? this._readableState.objectMode : false; - }, - }, - readableEncoding: { - enumerable: false, - get() { - return this._readableState?.encoding || null; - }, - }, - errored: { - enumerable: false, - get() { - return this._readableState?.errored || null; - }, - }, - closed: { - get() { - return !!this._readableState?.closed; - }, - }, - destroyed: { - enumerable: false, - get() { - return !!this._readableState?.destroyed; - }, - set(value) { - // We ignore the value if the stream - // has not been initialized yet. - if (!this._readableState) { - return; - } - - // Backward compatibility, the user is explicitly - // managing destroyed. - this._readableState.destroyed = value; - }, - }, - readableEnded: { - enumerable: false, - get() { - return !!this._readableState?.endEmitted; - }, + set: function (state) { + if (this._readableState) { + this._readableState.flowing = state + } + } + }, + readableLength: { + enumerable: false, + get() { + return this._readableState?.length | 0; + } + }, + readableObjectMode: { + enumerable: false, + get() { + return this._readableState ? this._readableState.objectMode : false; + } + }, + readableEncoding: { + enumerable: false, + get() { + return this._readableState?.encoding || null; + } + }, + errored: { + enumerable: false, + get() { + return this._readableState?.errored || null; + } + }, + closed: { + get() { + return !!(this._readableState?.closed); + } + }, + destroyed: { + enumerable: false, + get() { + return !!(this._readableState?.destroyed); }, + set(value) { + // We ignore the value if the stream + // has not been initialized yet. + if (!this._readableState) { + return + } + + // Backward compatibility, the user is explicitly + // managing destroyed. + this._readableState.destroyed = value + } + }, + readableEnded: { + enumerable: false, + get() { + return !!(this._readableState?.endEmitted); + } + } }); Object.defineProperties(ReadableState.prototype, { - // Legacy getter for `pipesCount`. - pipesCount: { - get() { - return this.pipes.length; - }, - }, - // Legacy property for `paused`. - paused: { - get() { - return this[kPaused] !== false; - }, - set(value) { - this[kPaused] = !!value; - }, + // Legacy getter for `pipesCount`. + pipesCount: { + get() { + return this.pipes.length + } + }, + // Legacy property for `paused`. + paused: { + get() { + return this[kPaused] !== false }, + set(value) { + this[kPaused] = !!value + } + } }); // Exposed for testing purposes only. -Readable._fromList = fromList; +Readable._fromList = fromList // Pluck off n bytes from an array of buffers. // Length is the combined lengths of all the buffers in the list. // This function is designed to be inlinable, so please take care when making // changes to the function body. function fromList(n, state) { - // nothing buffered. - if (state.length === 0) return null; - let ret; - if (state.objectMode) ret = state.buffer.shift(); - else if (!n || n >= state.length) { - // Read it all, truncate the list. - if (state.decoder) ret = state.buffer.join(""); - else if (state.buffer.length === 1) ret = state.buffer.first(); - else ret = state.buffer.concat(state.length); - state.buffer.clear(); - } else { - // read part of list. - ret = state.buffer.consume(n, !!state.decoder); - } - return ret; + // nothing buffered. + if (state.length === 0) return null + let ret + if (state.objectMode) ret = state.buffer.shift() + else if (!n || n >= state.length) { + // Read it all, truncate the list. + if (state.decoder) ret = state.buffer.join('') + else if (state.buffer.length === 1) ret = state.buffer.first(); + else ret = state.buffer.concat(state.length); + state.buffer.clear() + } else { + // read part of list. + ret = state.buffer.consume(n, !!state.decoder); + } + return ret } function endReadable(stream) { - const state = stream._readableState; - if (!state.endEmitted) { - state.ended = true; - process.nextTick(endReadableNT, state, stream); - } + const state = stream._readableState + if (!state.endEmitted) { + state.ended = true; + process.nextTick(endReadableNT, state, stream); + } } function endReadableNT(state, stream) { - // Check that we didn't get one last unshift. - if (!state.errored && !state.closeEmitted && !state.endEmitted && state.length === 0) { - state.endEmitted = true; - stream.emit("end"); - if (stream.writable && stream.allowHalfOpen === false) { - process.nextTick(endWritableNT, stream); - } else if (state.autoDestroy) { - // In case of duplex streams we need a way to detect - // if the writable side is ready for autoDestroy as well. - const wState = stream._writableState; - const autoDestroy = - !wState || - (wState.autoDestroy && - // We don't expect the writable to ever 'finish' - // if writable is explicitly set to false. - (wState.finished || wState.writable === false)); - if (autoDestroy) { - stream.destroy(); - } - } - } + // Check that we didn't get one last unshift. + if (!state.errored && !state.closeEmitted && !state.endEmitted && state.length === 0) { + state.endEmitted = true + stream.emit('end') + if (stream.writable && stream.allowHalfOpen === false) { + process.nextTick(endWritableNT, stream); + } else if (state.autoDestroy) { + // In case of duplex streams we need a way to detect + // if the writable side is ready for autoDestroy as well. + const wState = stream._writableState + const autoDestroy = + !wState || + (wState.autoDestroy && + // We don't expect the writable to ever 'finish' + // if writable is explicitly set to false. + (wState.finished || wState.writable === false)) + if (autoDestroy) { + stream.destroy() + } + } + } } function endWritableNT(stream) { - const writable = stream.writable && !stream.writableEnded && !stream.destroyed; - if (writable) { - stream.end(); - } + const writable = stream.writable && !stream.writableEnded && !stream.destroyed + if (writable) { + stream.end() + } } Readable.fromWeb = function (readableStream, options) { - return newStreamReadableFromReadableStream(readableStream, options); -}; + return newStreamReadableFromReadableStream(readableStream, options) +} Readable.toWeb = function (streamReadable, options) { - return newReadableStreamFromStreamReadable(streamReadable, options); -}; + return newReadableStreamFromStreamReadable(streamReadable, options) +} Readable.wrap = function (src, options) { - let _ref, _src$readableObjectMo; - return new Readable({ - objectMode: - (_ref = - (_src$readableObjectMo = src.readableObjectMode) !== null && - _src$readableObjectMo !== undefined - ? _src$readableObjectMo - : src.objectMode) !== null && _ref !== undefined - ? _ref - : true, - ...options, - destroy(err, callback) { - destroyer(src, err); - callback(err); - }, - }).wrap(src); + let _ref, _src$readableObjectMo; + return new Readable({ + objectMode: + (_ref = + (_src$readableObjectMo = src.readableObjectMode) !== null && _src$readableObjectMo !== undefined + ? _src$readableObjectMo + : src.objectMode) !== null && _ref !== undefined + ? _ref + : true, + ...options, + destroy(err, callback) { + destroyer(src, err) + callback(err) + } + }).wrap(src); }; // ====================================================================================== // Readable.from = function (iterable, opts) { - return from(Readable, iterable, opts); + return from(Readable, iterable, opts) }; export function from(Readable, iterable, opts) { - let iterator; - if (typeof iterable === "string" || iterable instanceof Buffer) { - return new Readable({ - objectMode: true, - ...opts, - read() { - this.push(iterable); - this.push(null); - }, - }); - } - let isAsync; - if (iterable && iterable[Symbol.asyncIterator]) { - isAsync = true; - iterator = iterable[Symbol.asyncIterator](); - } else if (iterable && iterable[Symbol.iterator]) { - isAsync = false; - iterator = iterable[Symbol.iterator](); - } else { - throw new ERR_INVALID_ARG_TYPE("iterable", ["Iterable"], iterable); - } - const readable = new Readable({ - objectMode: true, - highWaterMark: 1, - // TODO(ronag): What options should be allowed? - ...opts, - }); - - // Flag to protect against _read - // being called before last iteration completion. - let reading = false; - readable._read = function () { - if (!reading) { - reading = true; - next(); - } - }; - readable._destroy = function (error, cb) { - close(error).then( - () => process.nextTick(cb, error), - (err) => process.nextTick(cb, err || error) - ); - }; - async function close(error) { - const hadError = error !== undefined && error !== null; - const hasThrow = typeof iterator.throw === "function"; - if (hadError && hasThrow) { - const { value, done } = await iterator.throw(error); - await value; - if (done) { - return; - } - } - if (typeof iterator.return === "function") { - const { value } = await iterator.return(); - await value; - } - } - async function next() { - for (;;) { - try { - const { value, done } = isAsync ? await iterator.next() : iterator.next(); - if (done) { - readable.push(null); - } else { - const res = value && typeof value.then === "function" ? await value : value; - if (res === null) { - reading = false; - throw new ERR_STREAM_NULL_VALUES(); - } else if (readable.push(res)) { - continue; - } else { - reading = false; - } - } - } catch (err) { - readable.destroy(err); - } - break; + let iterator; + if (typeof iterable === 'string' || iterable instanceof Buffer) { + return new Readable({ + objectMode: true, + ...opts, + read() { + this.push(iterable) + this.push(null) + } + }) + } + let isAsync; + if (iterable && iterable[Symbol.asyncIterator]) { + isAsync = true + iterator = iterable[Symbol.asyncIterator]() + } else if (iterable && iterable[Symbol.iterator]) { + isAsync = false + iterator = iterable[Symbol.iterator]() + } else { + throw new ERR_INVALID_ARG_TYPE('iterable', ['Iterable'], iterable) + } + const readable = new Readable({ + objectMode: true, + highWaterMark: 1, + // TODO(ronag): What options should be allowed? + ...opts + }) + + // Flag to protect against _read + // being called before last iteration completion. + let reading = false + readable._read = function () { + if (!reading) { + reading = true + next() + } + } + readable._destroy = function (error, cb) { + close(error).then( + () => process.nextTick(cb, error), + (err) => process.nextTick(cb, err || error)); + } + async function close(error) { + const hadError = error !== undefined && error !== null + const hasThrow = typeof iterator.throw === 'function' + if (hadError && hasThrow) { + const { value, done } = await iterator.throw(error) + await value + if (done) { + return + } + } + if (typeof iterator.return === 'function') { + const { value } = await iterator.return() + await value + } + } + async function next() { + for (;;) { + try { + const { value, done } = isAsync ? await iterator.next() : iterator.next() + if (done) { + readable.push(null) + } else { + const res = value && typeof value.then === 'function' ? await value : value + if (res === null) { + reading = false + throw new ERR_STREAM_NULL_VALUES() + } else if (readable.push(res)) { + continue + } else { + reading = false + } } + } catch (err) { + readable.destroy(err) + } + break } - return readable; + } + return readable } // ====================================================================================== // Operators -const kWeakHandler = Symbol("kWeak"); -const kEmpty = Symbol("kEmpty"); -const kEof = Symbol("kEof"); +const kWeakHandler = Symbol('kWeak') +const kEmpty = Symbol('kEmpty') +const kEof = Symbol('kEof') function map(fn, options) { - if (typeof fn !== "function") { - throw new ERR_INVALID_ARG_TYPE("fn", ["Function", "AsyncFunction"], fn); - } - if (options != null) { - validateObject(options, "options", options); - } - if (options?.signal != null) { - validateAbortSignal(options.signal, "options.signal"); - } - let concurrency = 1; - if (options?.concurrency != null) { - concurrency = Math.floor(options.concurrency); - } - validateInteger(concurrency, "concurrency", 1); - return async function* map() { - let _options$signal, _options$signal2; - const ac = new AbortController(); - const stream = this; - const queue = []; - const signal = ac.signal; - const signalOpt = { - signal, - }; - const abort = () => ac.abort(); - if ( - options !== null && - options !== undefined && - (_options$signal = options.signal) !== null && - _options$signal !== undefined && - _options$signal.aborted - ) { - abort(); - } - options === null || options === undefined - ? undefined - : (_options$signal2 = options.signal) === null || _options$signal2 === undefined - ? undefined - : _options$signal2.addEventListener("abort", abort); - let next; - let resume; - let done = false; - function onDone() { - done = true; + if (typeof fn !== 'function') { + throw new ERR_INVALID_ARG_TYPE('fn', ['Function', 'AsyncFunction'], fn) + } + if (options != null) { + validateObject(options, 'options', options); + } + if (options?.signal != null) { + validateAbortSignal(options.signal, 'options.signal'); + } + let concurrency = 1; + if (options?.concurrency != null) { + concurrency = Math.floor(options.concurrency); + } + validateInteger(concurrency, 'concurrency', 1); + return async function* map() { + let _options$signal, _options$signal2; + const ac = new AbortController(); + const stream = this; + const queue = []; + const signal = ac.signal; + const signalOpt = { + signal + }; + const abort = () => ac.abort(); + if ( + options !== null && + options !== undefined && + (_options$signal = options.signal) !== null && + _options$signal !== undefined && + _options$signal.aborted + ) { + abort(); + } + options === null || options === undefined + ? undefined + : (_options$signal2 = options.signal) === null || _options$signal2 === undefined + ? undefined + : _options$signal2.addEventListener('abort', abort); + let next; + let resume; + let done = false; + function onDone() { + done = true; + } + async function pump() { + try { + for await (let val of stream) { + let _val; + if (done) { + return; + } + if (signal.aborted) { + throw new AbortError(); + } + try { + val = fn(val, signalOpt); + } catch (err) { + val = Promise.reject(err); + } + if (val === kEmpty) { + continue; + } + if (typeof ((_val = val) === null || _val === undefined ? undefined : _val.catch) === 'function') { + val.catch(onDone); + } + queue.push(val); + if (next) { + next(); + next = null; + } + if (!done && queue.length && queue.length >= concurrency) { + await new Promise((resolve) => { + resume = resolve; + }); + } } - async function pump() { - try { - for await (let val of stream) { - let _val; - if (done) { - return; - } - if (signal.aborted) { - throw new AbortError(); - } - try { - val = fn(val, signalOpt); - } catch (err) { - val = Promise.reject(err); - } - if (val === kEmpty) { - continue; - } - if ( - typeof ((_val = val) === null || _val === undefined - ? undefined - : _val.catch) === "function" - ) { - val.catch(onDone); - } - queue.push(val); - if (next) { - next(); - next = null; - } - if (!done && queue.length && queue.length >= concurrency) { - await new Promise((resolve) => { - resume = resolve; - }); - } - } - queue.push(kEof); - } catch (err) { - const val = Promise.reject(err); - val.then(undefined, onDone); - queue.push(val); - } finally { - let _options$signal3; - done = true; - if (next) { - next(); - next = null; - } - options === null || options === undefined - ? undefined - : (_options$signal3 = options.signal) === null || _options$signal3 === undefined - ? undefined - : _options$signal3.removeEventListener("abort", abort); - } + queue.push(kEof); + } catch (err) { + const val = Promise.reject(err); + val.then(undefined, onDone);; + queue.push(val); + } finally { + let _options$signal3; + done = true; + if (next) { + next(); + next = null; } - pump(); - try { - while (true) { - while (queue.length > 0) { - const val = await queue[0]; - if (val === kEof) { - return; - } - if (signal.aborted) { - throw new AbortError(); - } - if (val !== kEmpty) { - yield val; - } - queue.shift(); - if (resume) { - resume(); - resume = null; - } - } - await new Promise((resolve) => { - next = resolve; - }); - } - } finally { - ac.abort(); - done = true; - if (resume) { - resume(); - resume = null; - } + options === null || options === undefined + ? undefined + : (_options$signal3 = options.signal) === null || _options$signal3 === undefined + ? undefined + : _options$signal3.removeEventListener('abort', abort); + } + } + pump(); + try { + while (true) { + while (queue.length > 0) { + const val = await queue[0]; + if (val === kEof) { + return; + } + if (signal.aborted) { + throw new AbortError(); + } + if (val !== kEmpty) { + yield val; + } + queue.shift() + if (resume) { + resume(); + resume = null; + } } - }.call(this); + await new Promise((resolve) => { + next = resolve + }); + } + } finally { + ac.abort(); + done = true; + if (resume) { + resume(); + resume = null; + } + } + }.call(this); } function asIndexedPairs(options) { - if (options != null) { - validateObject(options, "options", options); - } - if ((options === null || options === undefined ? undefined : options.signal) != null) { - validateAbortSignal(options.signal, "options.signal"); + if (options != null) { + validateObject(options, 'options', options); + } + if ((options === null || options === undefined ? undefined : options.signal) != null) { + validateAbortSignal(options.signal, 'options.signal'); + } + return async function* asIndexedPairs() { + let index = 0; + for await (const val of this) { + let _options$signal4; + if ( + options !== null && + options !== undefined && + (_options$signal4 = options.signal) !== null && + _options$signal4 !== undefined && + _options$signal4.aborted + ) { + throw new AbortError('Aborted', { + cause: options.signal?.reason + }); + } + yield [index++, val]; } - return async function* asIndexedPairs() { - let index = 0; - for await (const val of this) { - let _options$signal4; - if ( - options !== null && - options !== undefined && - (_options$signal4 = options.signal) !== null && - _options$signal4 !== undefined && - _options$signal4.aborted - ) { - throw new AbortError("Aborted", { - cause: options.signal?.reason, - }); - } - yield [index++, val]; - } - }.call(this); + }.call(this); } async function some(fn, options) { - if (typeof fn !== "function") { - throw new ERR_INVALID_ARG_TYPE("fn", ["Function", "AsyncFunction"], fn); - } - for await (const _ of filter.call(this, fn, options)) { - return true; - } - return false; + if (typeof fn !== 'function') { + throw new ERR_INVALID_ARG_TYPE('fn', ['Function', 'AsyncFunction'], fn); + } + for await (const _ of filter.call(this, fn, options)) { + return true; + } + return false; } async function every(fn, options) { - if (typeof fn !== "function") { - throw new ERR_INVALID_ARG_TYPE("fn", ["Function", "AsyncFunction"], fn); - } - // https://en.wikipedia.org/wiki/De_Morgan%27s_laws - return !(await some.call( - this, - async (...args) => { - return !(await fn(...args)); - }, - options - )); + if (typeof fn !== 'function') { + throw new ERR_INVALID_ARG_TYPE('fn', ['Function', 'AsyncFunction'], fn); + } + // https://en.wikipedia.org/wiki/De_Morgan%27s_laws + return !(await some.call( + this, + async (...args) => { + return !(await fn(...args)) + }, + options + )); } async function find(fn, options) { - for await (const result of filter.call(this, fn, options)) { - return result; - } - return undefined; + for await (const result of filter.call(this, fn, options)) { + return result; + } + return undefined; } async function forEach(fn, options) { - if (typeof fn !== "function") { - throw new ERR_INVALID_ARG_TYPE("fn", ["Function", "AsyncFunction"], fn); - } - async function forEachFn(value, options) { - await fn(value, options); - return kEmpty; - } - // eslint-disable-next-line no-unused-vars - for await (const _ of map.call(this, forEachFn, options)); + if (typeof fn !== 'function') { + throw new ERR_INVALID_ARG_TYPE('fn', ['Function', 'AsyncFunction'], fn) + } + async function forEachFn(value, options) { + await fn(value, options); + return kEmpty + } + // eslint-disable-next-line no-unused-vars + for await (const _ of map.call(this, forEachFn, options)); } function filter(fn, options) { - if (typeof fn !== "function") { - throw new ERR_INVALID_ARG_TYPE("fn", ["Function", "AsyncFunction"], fn); - } - async function filterFn(value, options) { - if (await fn(value, options)) { - return value; - } - return kEmpty; - } - return map.call(this, filterFn, options); + if (typeof fn !== 'function') { + throw new ERR_INVALID_ARG_TYPE('fn', ['Function', 'AsyncFunction'], fn) + } + async function filterFn(value, options) { + if (await fn(value, options)) { + return value + } + return kEmpty + } + return map.call(this, filterFn, options) } // Specific to provide better error to reduce since the argument is only // missing if the stream has no items in it - but the code is still appropriate class ReduceAwareErrMissingArgs extends ERR_MISSING_ARGS { - constructor() { - super("reduce"); - this.message = "Reduce of an empty stream requires an initial value"; - } + constructor() { + super('reduce') + this.message = 'Reduce of an empty stream requires an initial value' + } } async function reduce(reducer, initialValue, options) { - let _options$signal5; - if (typeof reducer !== "function") { - throw new ERR_INVALID_ARG_TYPE("reducer", ["Function", "AsyncFunction"], reducer); - } - if (options != null) { - validateObject(options, "options", options); - } - if (options?.signal != null) { - validateAbortSignal(options?.signal, "options.signal"); - } - let hasInitialValue = arguments.length > 1; - if ( + let _options$signal5; + if (typeof reducer !== 'function') { + throw new ERR_INVALID_ARG_TYPE('reducer', ['Function', 'AsyncFunction'], reducer); + } + if (options != null) { + validateObject(options, 'options', options); + } + if (options?.signal != null) { + validateAbortSignal(options?.signal, 'options.signal'); + } + let hasInitialValue = arguments.length > 1; + if ( + options !== null && + options !== undefined && + (_options$signal5 = options.signal) !== null && + _options$signal5 !== undefined && + _options$signal5.aborted + ) { + const err = new AbortError(undefined, { + cause: options.signal?.reason + }) + this.once('error', () => {}); // The error is already propagated + await finished(this.destroy(err)); + throw err; + } + const ac = new AbortController(); + const signal = ac.signal; + if (options?.signal) { + const opts = { + once: true, + [kWeakHandler]: this + }; + options.signal.addEventListener('abort', () => ac.abort(), opts); + } + let gotAnyItemFromStream = false; + try { + for await (const value of this) { + let _options$signal6; + gotAnyItemFromStream = true; + if ( options !== null && options !== undefined && - (_options$signal5 = options.signal) !== null && - _options$signal5 !== undefined && - _options$signal5.aborted - ) { - const err = new AbortError(undefined, { - cause: options.signal?.reason, + (_options$signal6 = options.signal) !== null && + _options$signal6 !== undefined && + _options$signal6.aborted + ) { + throw new AbortError(); + } + if (!hasInitialValue) { + initialValue = value; + hasInitialValue = true; + } else { + initialValue = await reducer(initialValue, value, { + signal }); - this.once("error", () => {}); // The error is already propagated - await finished(this.destroy(err)); - throw err; - } - const ac = new AbortController(); - const signal = ac.signal; - if (options?.signal) { - const opts = { - once: true, - [kWeakHandler]: this, - }; - options.signal.addEventListener("abort", () => ac.abort(), opts); + } } - let gotAnyItemFromStream = false; - try { - for await (const value of this) { - let _options$signal6; - gotAnyItemFromStream = true; - if ( - options !== null && - options !== undefined && - (_options$signal6 = options.signal) !== null && - _options$signal6 !== undefined && - _options$signal6.aborted - ) { - throw new AbortError(); - } - if (!hasInitialValue) { - initialValue = value; - hasInitialValue = true; - } else { - initialValue = await reducer(initialValue, value, { - signal, - }); - } - } - if (!gotAnyItemFromStream && !hasInitialValue) { - throw new ReduceAwareErrMissingArgs(); - } - } finally { - ac.abort(); + if (!gotAnyItemFromStream && !hasInitialValue) { + throw new ReduceAwareErrMissingArgs(); } - return initialValue; + } finally { + ac.abort(); + } + return initialValue; } async function toArray(options) { - if (options != null) { - validateObject(options, "options", options); - } - if (options?.signal != null) { - validateAbortSignal(options?.signal, "options.signal"); - } - const result = []; - for await (const val of this) { - let _options$signal7; - if ( - options !== null && - options !== undefined && - (_options$signal7 = options.signal) !== null && - _options$signal7 !== undefined && - _options$signal7.aborted - ) { - throw new AbortError(undefined, { - cause: options.signal?.reason, - }); - } - result.push(val); + if (options != null) { + validateObject(options, 'options', options); + } + if (options?.signal != null) { + validateAbortSignal(options?.signal, 'options.signal') + } + const result = []; + for await (const val of this) { + let _options$signal7; + if ( + options !== null && + options !== undefined && + (_options$signal7 = options.signal) !== null && + _options$signal7 !== undefined && + _options$signal7.aborted + ) { + throw new AbortError(undefined, { + cause: options.signal?.reason + }); } - return result; + result.push(val); + } + return result; } function flatMap(fn, options) { - const values = map.call(this, fn, options); - return async function* flatMap() { - for await (const val of values) { - yield* val; - } - }.call(this); + const values = map.call(this, fn, options) + return async function* flatMap() { + for await (const val of values) { + yield* val + } + }.call(this) } function toIntegerOrInfinity(number) { - // We coerce here to align with the spec - // https://github.com/tc39/proposal-iterator-helpers/issues/169 - number = Number(number); - if (Number.isNaN(number)) { - return 0; - } - if (number < 0) { - throw new ERR_OUT_OF_RANGE("number", ">= 0", number); - } - return number; + // We coerce here to align with the spec + // https://github.com/tc39/proposal-iterator-helpers/issues/169 + number = Number(number) + if (Number.isNaN(number)) { + return 0 + } + if (number < 0) { + throw new ERR_OUT_OF_RANGE('number', '>= 0', number) + } + return number } function drop(number, options) { - if (options != null) { - validateObject(options, "options", options); - } - if (options?.signal != null) { - validateAbortSignal(options?.signal, "options.signal"); + if (options != null) { + validateObject(options, 'options', options); + } + if (options?.signal != null) { + validateAbortSignal(options?.signal, 'options.signal'); + } + number = toIntegerOrInfinity(number); + return async function* drop() { + let _options$signal8; + if ( + options !== null && + options !== undefined && + (_options$signal8 = options.signal) !== null && + _options$signal8 !== undefined && + _options$signal8.aborted + ) { + throw new AbortError(); } - number = toIntegerOrInfinity(number); - return async function* drop() { - let _options$signal8; - if ( - options !== null && - options !== undefined && - (_options$signal8 = options.signal) !== null && - _options$signal8 !== undefined && - _options$signal8.aborted - ) { - throw new AbortError(); - } - for await (const val of this) { - let _options$signal9; - if ( - options !== null && - options !== undefined && - (_options$signal9 = options.signal) !== null && - _options$signal9 !== undefined && - _options$signal9.aborted - ) { - throw new AbortError(); - } - if (number-- <= 0) { - yield val; - } - } - }.call(this); + for await (const val of this) { + let _options$signal9; + if ( + options !== null && + options !== undefined && + (_options$signal9 = options.signal) !== null && + _options$signal9 !== undefined && + _options$signal9.aborted + ) { + throw new AbortError(); + } + if (number-- <= 0) { + yield val; + } + } + }.call(this); } function take(number, options) { - if (options != null) { - validateObject(options, "options", options); - } - if (options?.signal != null) { - validateAbortSignal(options?.signal, "options.signal"); + if (options != null) { + validateObject(options, 'options', options); + } + if (options?.signal != null) { + validateAbortSignal(options?.signal, 'options.signal'); + } + number = toIntegerOrInfinity(number); + return async function* take() { + let _options$signal10; + if ( + options !== null && + options !== undefined && + (_options$signal10 = options.signal) !== null && + _options$signal10 !== undefined && + _options$signal10.aborted + ) { + throw new AbortError(); } - number = toIntegerOrInfinity(number); - return async function* take() { - let _options$signal10; - if ( - options !== null && - options !== undefined && - (_options$signal10 = options.signal) !== null && - _options$signal10 !== undefined && - _options$signal10.aborted - ) { - throw new AbortError(); - } - for await (const val of this) { - let _options$signal11; - if ( - options !== null && - options !== undefined && - (_options$signal11 = options.signal) !== null && - _options$signal11 !== undefined && - _options$signal11.aborted - ) { - throw new AbortError(); - } - if (number-- > 0) { - yield val; - } else { - return; - } - } - }.call(this); + for await (const val of this) { + let _options$signal11; + if ( + options !== null && + options !== undefined && + (_options$signal11 = options.signal) !== null && + _options$signal11 !== undefined && + _options$signal11.aborted + ) { + throw new AbortError(); + } + if (number-- > 0) { + yield val; + } else { + return; + } + } + }.call(this); } -Readable.prototype.map = function (fn, options) { - return from(Readable, map.call(this, fn, options)); -}; +Readable.prototype.map = function(fn, options) { + return from(Readable, map.call(this, fn, options)); +} -Readable.prototype.asIndexedPairs = function (options) { - return from(Readable, asIndexedPairs.call(this, options)); -}; +Readable.prototype.asIndexedPairs = function(options) { + return from(Readable, asIndexedPairs.call(this, options)); +} -Readable.prototype.drop = function (number, options) { - return from(Readable, drop.call(this, number, options)); -}; +Readable.prototype.drop = function(number, options) { + return from(Readable, drop.call(this, number, options)); +} -Readable.prototype.filter = function (fn, options) { - return from(Readable, filter.call(this, fn, options)); -}; +Readable.prototype.filter = function(fn, options) { + return from(Readable, filter.call(this, fn, options)); +} -Readable.prototype.flatMap = function (fn, options) { - return from(Readable, flatMap.call(this, fn, options)); +Readable.prototype.flatMap = function(fn, options) { + return from(Readable, flatMap.call(this, fn, options)); }; -Readable.prototype.take = function (number, options) { - return from(Readable, take.call(this, number, options)); -}; +Readable.prototype.take = function(number, options) { + return from(Readable, take.call(this, number, options)); +} Readable.prototype.every = every; Readable.prototype.forEach = forEach; @@ -1765,3 +1754,4 @@ Readable.prototype.reduce = reduce; Readable.prototype.toArray = toArray; Readable.prototype.some = some; Readable.prototype.find = find; + diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_transform.d.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_transform.d.ts index 7add11339..127ce7887 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_transform.d.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_transform.d.ts @@ -1,392 +1,344 @@ -import EventEmitter from "./events"; +import EventEmitter from './events'; interface WritableOptions { - highWaterMark?: number | undefined; - decodeStrings?: boolean | undefined; - defaultEncoding?: BufferEncoding | undefined; - objectMode?: boolean | undefined; - emitClose?: boolean | undefined; - write?( - this: Writable, - chunk: any, - encoding: BufferEncoding, - callback: (error?: Error | null) => void - ): void; - writev?( - this: Writable, - chunks: Array<{ chunk: any; encoding: BufferEncoding }>, - callback: (error?: Error | null) => void - ): void; - destroy?(this: Writable, error: Error | null, callback: (error: Error | null) => void): void; - final?(this: Writable, callback: (error?: Error | null) => void): void; - autoDestroy?: boolean | undefined; + highWaterMark?: number | undefined; + decodeStrings?: boolean | undefined; + defaultEncoding?: BufferEncoding | undefined; + objectMode?: boolean | undefined; + emitClose?: boolean | undefined; + write?(this: Writable, chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void; + writev?(this: Writable, chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void; + destroy?(this: Writable, error: Error | null, callback: (error: Error | null) => void): void; + final?(this: Writable, callback: (error?: Error | null) => void): void; + autoDestroy?: boolean | undefined; } export class internal extends EventEmitter { - pipe( - destination: T, - options?: { end?: boolean | undefined } - ): T; + pipe(destination: T, options?: { end?: boolean | undefined; }): T; } export class Stream extends internal { - constructor(opts?: ReadableOptions); + constructor(opts?: ReadableOptions); } interface ReadableOptions { - highWaterMark?: number | undefined; - encoding?: BufferEncoding | undefined; - objectMode?: boolean | undefined; - read?(this: Readable, size: number): void; - destroy?(this: Readable, error: Error | null, callback: (error: Error | null) => void): void; - autoDestroy?: boolean | undefined; + highWaterMark?: number | undefined; + encoding?: BufferEncoding | undefined; + objectMode?: boolean | undefined; + read?(this: Readable, size: number): void; + destroy?(this: Readable, error: Error | null, callback: (error: Error | null) => void): void; + autoDestroy?: boolean | undefined; } export class Readable extends Stream implements NodeJS.ReadableStream { - static from(iterable: Iterable | AsyncIterable, options?: ReadableOptions): Readable; + static from(iterable: Iterable | AsyncIterable, options?: ReadableOptions): Readable; - readable: boolean; - readonly readableEncoding: BufferEncoding | null; - readonly readableEnded: boolean; - readonly readableFlowing: boolean | null; - readonly readableHighWaterMark: number; - readonly readableLength: number; - readonly readableObjectMode: boolean; - destroyed: boolean; - constructor(opts?: ReadableOptions); - _read(size: number): void; - read(size?: number): any; - setEncoding(encoding: BufferEncoding): this; - pause(): this; - resume(): this; - isPaused(): boolean; - unpipe(destination?: NodeJS.WritableStream): this; - unshift(chunk: any, encoding?: BufferEncoding): void; - wrap(oldStream: NodeJS.ReadableStream): this; - push(chunk: any, encoding?: BufferEncoding): boolean; - _destroy(error: Error | null, callback: (error?: Error | null) => void): void; - destroy(error?: Error): this; + readable: boolean; + readonly readableEncoding: BufferEncoding | null; + readonly readableEnded: boolean; + readonly readableFlowing: boolean | null; + readonly readableHighWaterMark: number; + readonly readableLength: number; + readonly readableObjectMode: boolean; + destroyed: boolean; + constructor(opts?: ReadableOptions); + _read(size: number): void; + read(size?: number): any; + setEncoding(encoding: BufferEncoding): this; + pause(): this; + resume(): this; + isPaused(): boolean; + unpipe(destination?: NodeJS.WritableStream): this; + unshift(chunk: any, encoding?: BufferEncoding): void; + wrap(oldStream: NodeJS.ReadableStream): this; + push(chunk: any, encoding?: BufferEncoding): boolean; + _destroy(error: Error | null, callback: (error?: Error | null) => void): void; + destroy(error?: Error): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "data", listener: (chunk: any) => void): this; - addListener(event: "end", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "pause", listener: () => void): this; - addListener(event: "readable", listener: () => void): this; - addListener(event: "resume", listener: () => void): this; - addListener(event: string | symbol, listener: (...args: any[]) => void): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "data", listener: (chunk: any) => void): this; + addListener(event: "end", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "pause", listener: () => void): this; + addListener(event: "readable", listener: () => void): this; + addListener(event: "resume", listener: () => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; - emit(event: "close"): boolean; - emit(event: "data", chunk: any): boolean; - emit(event: "end"): boolean; - emit(event: "error", err: Error): boolean; - emit(event: "pause"): boolean; - emit(event: "readable"): boolean; - emit(event: "resume"): boolean; - emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close"): boolean; + emit(event: "data", chunk: any): boolean; + emit(event: "end"): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "pause"): boolean; + emit(event: "readable"): boolean; + emit(event: "resume"): boolean; + emit(event: string | symbol, ...args: any[]): boolean; - on(event: "close", listener: () => void): this; - on(event: "data", listener: (chunk: any) => void): this; - on(event: "end", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "pause", listener: () => void): this; - on(event: "readable", listener: () => void): this; - on(event: "resume", listener: () => void): this; - on(event: string | symbol, listener: (...args: any[]) => void): this; + on(event: "close", listener: () => void): this; + on(event: "data", listener: (chunk: any) => void): this; + on(event: "end", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "pause", listener: () => void): this; + on(event: "readable", listener: () => void): this; + on(event: "resume", listener: () => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; - once(event: "close", listener: () => void): this; - once(event: "data", listener: (chunk: any) => void): this; - once(event: "end", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "pause", listener: () => void): this; - once(event: "readable", listener: () => void): this; - once(event: "resume", listener: () => void): this; - once(event: string | symbol, listener: (...args: any[]) => void): this; + once(event: "close", listener: () => void): this; + once(event: "data", listener: (chunk: any) => void): this; + once(event: "end", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "pause", listener: () => void): this; + once(event: "readable", listener: () => void): this; + once(event: "resume", listener: () => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "data", listener: (chunk: any) => void): this; - prependListener(event: "end", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "pause", listener: () => void): this; - prependListener(event: "readable", listener: () => void): this; - prependListener(event: "resume", listener: () => void): this; - prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "data", listener: (chunk: any) => void): this; + prependListener(event: "end", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "pause", listener: () => void): this; + prependListener(event: "readable", listener: () => void): this; + prependListener(event: "resume", listener: () => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "data", listener: (chunk: any) => void): this; - prependOnceListener(event: "end", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "pause", listener: () => void): this; - prependOnceListener(event: "readable", listener: () => void): this; - prependOnceListener(event: "resume", listener: () => void): this; - prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "data", listener: (chunk: any) => void): this; + prependOnceListener(event: "end", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "pause", listener: () => void): this; + prependOnceListener(event: "readable", listener: () => void): this; + prependOnceListener(event: "resume", listener: () => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; - removeListener(event: "close", listener: () => void): this; - removeListener(event: "data", listener: (chunk: any) => void): this; - removeListener(event: "end", listener: () => void): this; - removeListener(event: "error", listener: (err: Error) => void): this; - removeListener(event: "pause", listener: () => void): this; - removeListener(event: "readable", listener: () => void): this; - removeListener(event: "resume", listener: () => void): this; - removeListener(event: string | symbol, listener: (...args: any[]) => void): this; + removeListener(event: "close", listener: () => void): this; + removeListener(event: "data", listener: (chunk: any) => void): this; + removeListener(event: "end", listener: () => void): this; + removeListener(event: "error", listener: (err: Error) => void): this; + removeListener(event: "pause", listener: () => void): this; + removeListener(event: "readable", listener: () => void): this; + removeListener(event: "resume", listener: () => void): this; + removeListener(event: string | symbol, listener: (...args: any[]) => void): this; - [Symbol.asyncIterator](): AsyncIterableIterator; + [Symbol.asyncIterator](): AsyncIterableIterator; } export class Writable extends Stream implements NodeJS.WritableStream { - readonly writable: boolean; - readonly writableEnded: boolean; - readonly writableFinished: boolean; - readonly writableHighWaterMark: number; - readonly writableLength: number; - readonly writableObjectMode: boolean; - readonly writableCorked: number; - destroyed: boolean; - constructor(opts?: WritableOptions); - _write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void; - _writev?( - chunks: Array<{ chunk: any; encoding: BufferEncoding }>, - callback: (error?: Error | null) => void - ): void; - _destroy(error: Error | null, callback: (error?: Error | null) => void): void; - _final(callback: (error?: Error | null) => void): void; - write(chunk: any, cb?: (error: Error | null | undefined) => void): boolean; - write( - chunk: any, - encoding: BufferEncoding, - cb?: (error: Error | null | undefined) => void - ): boolean; - setDefaultEncoding(encoding: BufferEncoding): this; - end(cb?: () => void): this; - end(chunk: any, cb?: () => void): this; - end(chunk: any, encoding: BufferEncoding, cb?: () => void): this; - cork(): void; - uncork(): void; - destroy(error?: Error): this; + readonly writable: boolean; + readonly writableEnded: boolean; + readonly writableFinished: boolean; + readonly writableHighWaterMark: number; + readonly writableLength: number; + readonly writableObjectMode: boolean; + readonly writableCorked: number; + destroyed: boolean; + constructor(opts?: WritableOptions); + _write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void; + _writev?(chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void; + _destroy(error: Error | null, callback: (error?: Error | null) => void): void; + _final(callback: (error?: Error | null) => void): void; + write(chunk: any, cb?: (error: Error | null | undefined) => void): boolean; + write(chunk: any, encoding: BufferEncoding, cb?: (error: Error | null | undefined) => void): boolean; + setDefaultEncoding(encoding: BufferEncoding): this; + end(cb?: () => void): this; + end(chunk: any, cb?: () => void): this; + end(chunk: any, encoding: BufferEncoding, cb?: () => void): this; + cork(): void; + uncork(): void; + destroy(error?: Error): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "drain", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "finish", listener: () => void): this; - addListener(event: "pipe", listener: (src: Readable) => void): this; - addListener(event: "unpipe", listener: (src: Readable) => void): this; - addListener(event: string | symbol, listener: (...args: any[]) => void): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "drain", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "finish", listener: () => void): this; + addListener(event: "pipe", listener: (src: Readable) => void): this; + addListener(event: "unpipe", listener: (src: Readable) => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; - emit(event: "close"): boolean; - emit(event: "drain"): boolean; - emit(event: "error", err: Error): boolean; - emit(event: "finish"): boolean; - emit(event: "pipe", src: Readable): boolean; - emit(event: "unpipe", src: Readable): boolean; - emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close"): boolean; + emit(event: "drain"): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "finish"): boolean; + emit(event: "pipe", src: Readable): boolean; + emit(event: "unpipe", src: Readable): boolean; + emit(event: string | symbol, ...args: any[]): boolean; - on(event: "close", listener: () => void): this; - on(event: "drain", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "finish", listener: () => void): this; - on(event: "pipe", listener: (src: Readable) => void): this; - on(event: "unpipe", listener: (src: Readable) => void): this; - on(event: string | symbol, listener: (...args: any[]) => void): this; + on(event: "close", listener: () => void): this; + on(event: "drain", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "finish", listener: () => void): this; + on(event: "pipe", listener: (src: Readable) => void): this; + on(event: "unpipe", listener: (src: Readable) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; - once(event: "close", listener: () => void): this; - once(event: "drain", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "finish", listener: () => void): this; - once(event: "pipe", listener: (src: Readable) => void): this; - once(event: "unpipe", listener: (src: Readable) => void): this; - once(event: string | symbol, listener: (...args: any[]) => void): this; + once(event: "close", listener: () => void): this; + once(event: "drain", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "finish", listener: () => void): this; + once(event: "pipe", listener: (src: Readable) => void): this; + once(event: "unpipe", listener: (src: Readable) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "drain", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "finish", listener: () => void): this; - prependListener(event: "pipe", listener: (src: Readable) => void): this; - prependListener(event: "unpipe", listener: (src: Readable) => void): this; - prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "drain", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "finish", listener: () => void): this; + prependListener(event: "pipe", listener: (src: Readable) => void): this; + prependListener(event: "unpipe", listener: (src: Readable) => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "drain", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "finish", listener: () => void): this; - prependOnceListener(event: "pipe", listener: (src: Readable) => void): this; - prependOnceListener(event: "unpipe", listener: (src: Readable) => void): this; - prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "drain", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "finish", listener: () => void): this; + prependOnceListener(event: "pipe", listener: (src: Readable) => void): this; + prependOnceListener(event: "unpipe", listener: (src: Readable) => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; - removeListener(event: "close", listener: () => void): this; - removeListener(event: "drain", listener: () => void): this; - removeListener(event: "error", listener: (err: Error) => void): this; - removeListener(event: "finish", listener: () => void): this; - removeListener(event: "pipe", listener: (src: Readable) => void): this; - removeListener(event: "unpipe", listener: (src: Readable) => void): this; - removeListener(event: string | symbol, listener: (...args: any[]) => void): this; + removeListener(event: "close", listener: () => void): this; + removeListener(event: "drain", listener: () => void): this; + removeListener(event: "error", listener: (err: Error) => void): this; + removeListener(event: "finish", listener: () => void): this; + removeListener(event: "pipe", listener: (src: Readable) => void): this; + removeListener(event: "unpipe", listener: (src: Readable) => void): this; + removeListener(event: string | symbol, listener: (...args: any[]) => void): this; } + export class Duplex extends Readable implements Writable { - readonly writable: boolean; - readonly writableEnded: boolean; - readonly writableFinished: boolean; - readonly writableHighWaterMark: number; - readonly writableLength: number; - readonly writableObjectMode: boolean; - readonly writableCorked: number; - allowHalfOpen: boolean; - constructor(opts?: DuplexOptions); - _write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void; - _writev?( - chunks: Array<{ chunk: any; encoding: BufferEncoding }>, - callback: (error?: Error | null) => void - ): void; - _destroy(error: Error | null, callback: (error: Error | null) => void): void; - _final(callback: (error?: Error | null) => void): void; - write( - chunk: any, - encoding?: BufferEncoding, - cb?: (error: Error | null | undefined) => void - ): boolean; - write(chunk: any, cb?: (error: Error | null | undefined) => void): boolean; - setDefaultEncoding(encoding: BufferEncoding): this; - end(cb?: () => void): this; - end(chunk: any, cb?: () => void): this; - end(chunk: any, encoding?: BufferEncoding, cb?: () => void): this; - cork(): void; - uncork(): void; - addListener(event: "close", listener: () => void): this; - addListener(event: "data", listener: (chunk: any) => void): this; - addListener(event: "drain", listener: () => void): this; - addListener(event: "end", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "finish", listener: () => void): this; - addListener(event: "pause", listener: () => void): this; - addListener(event: "pipe", listener: (src: Readable) => void): this; - addListener(event: "readable", listener: () => void): this; - addListener(event: "resume", listener: () => void): this; - addListener(event: "unpipe", listener: (src: Readable) => void): this; - addListener(event: string | symbol, listener: (...args: any[]) => void): this; - emit(event: "close"): boolean; - emit(event: "data", chunk: any): boolean; - emit(event: "drain"): boolean; - emit(event: "end"): boolean; - emit(event: "error", err: Error): boolean; - emit(event: "finish"): boolean; - emit(event: "pause"): boolean; - emit(event: "pipe", src: Readable): boolean; - emit(event: "readable"): boolean; - emit(event: "resume"): boolean; - emit(event: "unpipe", src: Readable): boolean; - emit(event: string | symbol, ...args: any[]): boolean; - on(event: "close", listener: () => void): this; - on(event: "data", listener: (chunk: any) => void): this; - on(event: "drain", listener: () => void): this; - on(event: "end", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "finish", listener: () => void): this; - on(event: "pause", listener: () => void): this; - on(event: "pipe", listener: (src: Readable) => void): this; - on(event: "readable", listener: () => void): this; - on(event: "resume", listener: () => void): this; - on(event: "unpipe", listener: (src: Readable) => void): this; - on(event: string | symbol, listener: (...args: any[]) => void): this; - once(event: "close", listener: () => void): this; - once(event: "data", listener: (chunk: any) => void): this; - once(event: "drain", listener: () => void): this; - once(event: "end", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "finish", listener: () => void): this; - once(event: "pause", listener: () => void): this; - once(event: "pipe", listener: (src: Readable) => void): this; - once(event: "readable", listener: () => void): this; - once(event: "resume", listener: () => void): this; - once(event: "unpipe", listener: (src: Readable) => void): this; - once(event: string | symbol, listener: (...args: any[]) => void): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "data", listener: (chunk: any) => void): this; - prependListener(event: "drain", listener: () => void): this; - prependListener(event: "end", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "finish", listener: () => void): this; - prependListener(event: "pause", listener: () => void): this; - prependListener(event: "pipe", listener: (src: Readable) => void): this; - prependListener(event: "readable", listener: () => void): this; - prependListener(event: "resume", listener: () => void): this; - prependListener(event: "unpipe", listener: (src: Readable) => void): this; - prependListener(event: string | symbol, listener: (...args: any[]) => void): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "data", listener: (chunk: any) => void): this; - prependOnceListener(event: "drain", listener: () => void): this; - prependOnceListener(event: "end", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "finish", listener: () => void): this; - prependOnceListener(event: "pause", listener: () => void): this; - prependOnceListener(event: "pipe", listener: (src: Readable) => void): this; - prependOnceListener(event: "readable", listener: () => void): this; - prependOnceListener(event: "resume", listener: () => void): this; - prependOnceListener(event: "unpipe", listener: (src: Readable) => void): this; - prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; - removeListener(event: "close", listener: () => void): this; - removeListener(event: "data", listener: (chunk: any) => void): this; - removeListener(event: "drain", listener: () => void): this; - removeListener(event: "end", listener: () => void): this; - removeListener(event: "error", listener: (err: Error) => void): this; - removeListener(event: "finish", listener: () => void): this; - removeListener(event: "pause", listener: () => void): this; - removeListener(event: "pipe", listener: (src: Readable) => void): this; - removeListener(event: "readable", listener: () => void): this; - removeListener(event: "resume", listener: () => void): this; - removeListener(event: "unpipe", listener: (src: Readable) => void): this; - removeListener(event: string | symbol, listener: (...args: any[]) => void): this; + readonly writable: boolean; + readonly writableEnded: boolean; + readonly writableFinished: boolean; + readonly writableHighWaterMark: number; + readonly writableLength: number; + readonly writableObjectMode: boolean; + readonly writableCorked: number; + allowHalfOpen: boolean; + constructor(opts?: DuplexOptions); + _write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void; + _writev?(chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void; + _destroy(error: Error | null, callback: (error: Error | null) => void): void; + _final(callback: (error?: Error | null) => void): void; + write(chunk: any, encoding?: BufferEncoding, cb?: (error: Error | null | undefined) => void): boolean; + write(chunk: any, cb?: (error: Error | null | undefined) => void): boolean; + setDefaultEncoding(encoding: BufferEncoding): this; + end(cb?: () => void): this; + end(chunk: any, cb?: () => void): this; + end(chunk: any, encoding?: BufferEncoding, cb?: () => void): this; + cork(): void; + uncork(): void; + addListener(event: 'close', listener: () => void): this; + addListener(event: 'data', listener: (chunk: any) => void): this; + addListener(event: 'drain', listener: () => void): this; + addListener(event: 'end', listener: () => void): this; + addListener(event: 'error', listener: (err: Error) => void): this; + addListener(event: 'finish', listener: () => void): this; + addListener(event: 'pause', listener: () => void): this; + addListener(event: 'pipe', listener: (src: Readable) => void): this; + addListener(event: 'readable', listener: () => void): this; + addListener(event: 'resume', listener: () => void): this; + addListener(event: 'unpipe', listener: (src: Readable) => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + emit(event: 'close'): boolean; + emit(event: 'data', chunk: any): boolean; + emit(event: 'drain'): boolean; + emit(event: 'end'): boolean; + emit(event: 'error', err: Error): boolean; + emit(event: 'finish'): boolean; + emit(event: 'pause'): boolean; + emit(event: 'pipe', src: Readable): boolean; + emit(event: 'readable'): boolean; + emit(event: 'resume'): boolean; + emit(event: 'unpipe', src: Readable): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + on(event: 'close', listener: () => void): this; + on(event: 'data', listener: (chunk: any) => void): this; + on(event: 'drain', listener: () => void): this; + on(event: 'end', listener: () => void): this; + on(event: 'error', listener: (err: Error) => void): this; + on(event: 'finish', listener: () => void): this; + on(event: 'pause', listener: () => void): this; + on(event: 'pipe', listener: (src: Readable) => void): this; + on(event: 'readable', listener: () => void): this; + on(event: 'resume', listener: () => void): this; + on(event: 'unpipe', listener: (src: Readable) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + once(event: 'close', listener: () => void): this; + once(event: 'data', listener: (chunk: any) => void): this; + once(event: 'drain', listener: () => void): this; + once(event: 'end', listener: () => void): this; + once(event: 'error', listener: (err: Error) => void): this; + once(event: 'finish', listener: () => void): this; + once(event: 'pause', listener: () => void): this; + once(event: 'pipe', listener: (src: Readable) => void): this; + once(event: 'readable', listener: () => void): this; + once(event: 'resume', listener: () => void): this; + once(event: 'unpipe', listener: (src: Readable) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + prependListener(event: 'close', listener: () => void): this; + prependListener(event: 'data', listener: (chunk: any) => void): this; + prependListener(event: 'drain', listener: () => void): this; + prependListener(event: 'end', listener: () => void): this; + prependListener(event: 'error', listener: (err: Error) => void): this; + prependListener(event: 'finish', listener: () => void): this; + prependListener(event: 'pause', listener: () => void): this; + prependListener(event: 'pipe', listener: (src: Readable) => void): this; + prependListener(event: 'readable', listener: () => void): this; + prependListener(event: 'resume', listener: () => void): this; + prependListener(event: 'unpipe', listener: (src: Readable) => void): this; + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener(event: 'close', listener: () => void): this; + prependOnceListener(event: 'data', listener: (chunk: any) => void): this; + prependOnceListener(event: 'drain', listener: () => void): this; + prependOnceListener(event: 'end', listener: () => void): this; + prependOnceListener(event: 'error', listener: (err: Error) => void): this; + prependOnceListener(event: 'finish', listener: () => void): this; + prependOnceListener(event: 'pause', listener: () => void): this; + prependOnceListener(event: 'pipe', listener: (src: Readable) => void): this; + prependOnceListener(event: 'readable', listener: () => void): this; + prependOnceListener(event: 'resume', listener: () => void): this; + prependOnceListener(event: 'unpipe', listener: (src: Readable) => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + removeListener(event: 'close', listener: () => void): this; + removeListener(event: 'data', listener: (chunk: any) => void): this; + removeListener(event: 'drain', listener: () => void): this; + removeListener(event: 'end', listener: () => void): this; + removeListener(event: 'error', listener: (err: Error) => void): this; + removeListener(event: 'finish', listener: () => void): this; + removeListener(event: 'pause', listener: () => void): this; + removeListener(event: 'pipe', listener: (src: Readable) => void): this; + removeListener(event: 'readable', listener: () => void): this; + removeListener(event: 'resume', listener: () => void): this; + removeListener(event: 'unpipe', listener: (src: Readable) => void): this; + removeListener(event: string | symbol, listener: (...args: any[]) => void): this; } interface DuplexOptions extends ReadableOptions, WritableOptions { - allowHalfOpen?: boolean | undefined; - readableObjectMode?: boolean | undefined; - writableObjectMode?: boolean | undefined; - readableHighWaterMark?: number | undefined; - writableHighWaterMark?: number | undefined; - writableCorked?: number | undefined; - read?(this: Duplex, size: number): void; - write?( - this: Duplex, - chunk: any, - encoding: BufferEncoding, - callback: (error?: Error | null) => void - ): void; - writev?( - this: Duplex, - chunks: Array<{ chunk: any; encoding: BufferEncoding }>, - callback: (error?: Error | null) => void - ): void; - final?(this: Duplex, callback: (error?: Error | null) => void): void; - destroy?(this: Duplex, error: Error | null, callback: (error: Error | null) => void): void; + allowHalfOpen?: boolean | undefined; + readableObjectMode?: boolean | undefined; + writableObjectMode?: boolean | undefined; + readableHighWaterMark?: number | undefined; + writableHighWaterMark?: number | undefined; + writableCorked?: number | undefined; + read?(this: Duplex, size: number): void; + write?(this: Duplex, chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void; + writev?(this: Duplex, chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void; + final?(this: Duplex, callback: (error?: Error | null) => void): void; + destroy?(this: Duplex, error: Error | null, callback: (error: Error | null) => void): void; } interface TransformOptions extends DuplexOptions { - read?(this: Transform, size: number): void; - write?( - this: Transform, - chunk: any, - encoding: BufferEncoding, - callback: (error?: Error | null) => void - ): void; - writev?( - this: Transform, - chunks: Array<{ chunk: any; encoding: BufferEncoding }>, - callback: (error?: Error | null) => void - ): void; - final?(this: Transform, callback: (error?: Error | null) => void): void; - destroy?(this: Transform, error: Error | null, callback: (error: Error | null) => void): void; - transform?( - this: Transform, - chunk: any, - encoding: BufferEncoding, - callback: TransformCallback - ): void; - flush?(this: Transform, callback: TransformCallback): void; + read?(this: Transform, size: number): void; + write?(this: Transform, chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void; + writev?(this: Transform, chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void; + final?(this: Transform, callback: (error?: Error | null) => void): void; + destroy?(this: Transform, error: Error | null, callback: (error: Error | null) => void): void; + transform?(this: Transform, chunk: any, encoding: BufferEncoding, callback: TransformCallback): void; + flush?(this: Transform, callback: TransformCallback): void; } type TransformCallback = (error?: Error | null, data?: any) => void; export class Transform extends Duplex { - constructor(opts?: TransformOptions); - _transform(chunk: any, encoding: BufferEncoding, callback: TransformCallback): void; - _flush(callback: TransformCallback): void; + constructor(opts?: TransformOptions); + _transform(chunk: any, encoding: BufferEncoding, callback: TransformCallback): void; + _flush(callback: TransformCallback): void; } diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_transform.js b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_transform.js index 213c21c61..3abb6ddca 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_transform.js +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_transform.js @@ -1,143 +1,147 @@ -"use strict"; +'use strict' -import { ERR_METHOD_NOT_IMPLEMENTED } from "./internal_errors"; +import { + ERR_METHOD_NOT_IMPLEMENTED +} from './internal_errors'; -import { Duplex } from "./streams_duplex"; +import { + Duplex, +} from './streams_duplex'; -import { getHighWaterMark } from "./streams_util"; +import { + getHighWaterMark, +} from './streams_util'; Object.setPrototypeOf(Transform.prototype, Duplex.prototype); Object.setPrototypeOf(Transform, Duplex); -const kCallback = Symbol("kCallback"); +const kCallback = Symbol('kCallback'); export function Transform(options) { - if (!(this instanceof Transform)) return new Transform(options); - - // TODO (ronag): This should preferably always be - // applied but would be semver-major. Or even better; - // make Transform a Readable with the Writable interface. - const readableHighWaterMark = options - ? getHighWaterMark(options, "readableHighWaterMark", true) - : null; - if (readableHighWaterMark === 0) { - // A Duplex will buffer both on the writable and readable side while - // a Transform just wants to buffer hwm number of elements. To avoid - // buffering twice we disable buffering on the writable side. - options = { - ...options, - highWaterMark: null, - readableHighWaterMark, - // TODO (ronag): 0 is not optimal since we have - // a "bug" where we check needDrain before calling _write and not after. - // Refs: https://github.com/nodejs/node/pull/32887 - // Refs: https://github.com/nodejs/node/pull/35941 - writableHighWaterMark: options?.writableHighWaterMark || 0, - }; - } - Duplex.call(this, options); - - // We have implemented the _read method, and done the other things - // that Readable wants before the first _read call, so unset the - // sync guard flag. - this._readableState.sync = false; - this[kCallback] = null; - if (options) { - if (typeof options.transform === "function") this._transform = options.transform; - if (typeof options.flush === "function") this._flush = options.flush; - } - - // When the writable side finishes, then flush out anything remaining. - // Backwards compat. Some Transform streams incorrectly implement _final - // instead of or in addition to _flush. By using 'prefinish' instead of - // implementing _final we continue supporting this unfortunate use case. - this.on("prefinish", prefinish); + if (!(this instanceof Transform)) return new Transform(options); + + // TODO (ronag): This should preferably always be + // applied but would be semver-major. Or even better; + // make Transform a Readable with the Writable interface. + const readableHighWaterMark = options ? getHighWaterMark(options, 'readableHighWaterMark', true) : null; + if (readableHighWaterMark === 0) { + // A Duplex will buffer both on the writable and readable side while + // a Transform just wants to buffer hwm number of elements. To avoid + // buffering twice we disable buffering on the writable side. + options = { + ...options, + highWaterMark: null, + readableHighWaterMark, + // TODO (ronag): 0 is not optimal since we have + // a "bug" where we check needDrain before calling _write and not after. + // Refs: https://github.com/nodejs/node/pull/32887 + // Refs: https://github.com/nodejs/node/pull/35941 + writableHighWaterMark: options?.writableHighWaterMark || 0 + }; + } + Duplex.call(this, options); + + // We have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + this[kCallback] = null; + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform; + if (typeof options.flush === 'function') this._flush = options.flush; + } + + // When the writable side finishes, then flush out anything remaining. + // Backwards compat. Some Transform streams incorrectly implement _final + // instead of or in addition to _flush. By using 'prefinish' instead of + // implementing _final we continue supporting this unfortunate use case. + this.on('prefinish', prefinish); } function final(cb) { - if (typeof this._flush === "function" && !this.destroyed) { - this._flush((er, data) => { - if (er) { - if (cb) { - cb(er); - } else { - this.destroy(er); - } - return; - } - if (data != null) { - this.push(data); - } - this.push(null); - if (cb) { - cb(); - } - }); - } else { - this.push(null); + if (typeof this._flush === 'function' && !this.destroyed) { + this._flush((er, data) => { + if (er) { if (cb) { - cb(); + cb(er); + } else { + this.destroy(er); } + return; + } + if (data != null) { + this.push(data); + } + this.push(null); + if (cb) { + cb(); + } + }) + } else { + this.push(null); + if (cb) { + cb(); } + } } function prefinish() { - if (this._final !== final) { - final.call(this); - } + if (this._final !== final) { + final.call(this); + } } Transform.prototype._final = final; Transform.prototype._transform = function () { - throw new ERR_METHOD_NOT_IMPLEMENTED("_transform()"); -}; + throw new ERR_METHOD_NOT_IMPLEMENTED('_transform()') +} Transform.prototype._write = function (chunk, encoding, callback) { - const rState = this._readableState; - const wState = this._writableState; - const length = rState.length; - this._transform(chunk, encoding, (err, val) => { - if (err) { - callback(err); - return; - } - if (val != null) { - this.push(val); - } - if ( - wState.ended || - // Backwards compat. - length === rState.length || - // Backwards compat. - rState.length < rState.highWaterMark - ) { - callback(); - } else { - this[kCallback] = callback; - } - }); -}; + const rState = this._readableState; + const wState = this._writableState; + const length = rState.length; + this._transform(chunk, encoding, (err, val) => { + if (err) { + callback(err); + return; + } + if (val != null) { + this.push(val); + } + if ( + wState.ended || + // Backwards compat. + length === rState.length || + // Backwards compat. + rState.length < rState.highWaterMark + ) { + callback(); + } else { + this[kCallback] = callback; + } + }) +} Transform.prototype._read = function (_size) { - if (this[kCallback]) { - const callback = this[kCallback]; - this[kCallback] = null; - callback(); - } -}; + if (this[kCallback]) { + const callback = this[kCallback]; + this[kCallback] = null; + callback(); + } +} Object.setPrototypeOf(PassThrough.prototype, Transform.prototype); Object.setPrototypeOf(PassThrough, Transform); export function PassThrough(options) { - if (!(this instanceof PassThrough)) return new PassThrough(options); - Transform.call(this, { - ...options, - transform: undefined, - flush: undefined, - }); + if (!(this instanceof PassThrough)) return new PassThrough(options); + Transform.call(this, { + ...options, + transform: undefined, + flush: undefined, + }); } PassThrough.prototype._transform = function (chunk, _, cb) { - cb(null, chunk); -}; + cb(null, chunk); +} diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_util.js b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_util.js index 91949bd71..e9c50973b 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_util.js +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_util.js @@ -1,767 +1,723 @@ -export const kDestroyed = Symbol("kDestroyed"); -export const kIsErrored = Symbol("kIsErrored"); -export const kIsReadable = Symbol("kIsReadable"); -export const kIsDisturbed = Symbol("kIsDisturbed"); -export const kPaused = Symbol("kPaused"); -export const kOnFinished = Symbol("kOnFinished"); -export const kDestroy = Symbol("kDestroy"); -export const kConstruct = Symbol("kConstruct"); +export const kDestroyed = Symbol('kDestroyed'); +export const kIsErrored = Symbol('kIsErrored'); +export const kIsReadable = Symbol('kIsReadable'); +export const kIsDisturbed = Symbol('kIsDisturbed'); +export const kPaused = Symbol('kPaused'); +export const kOnFinished = Symbol('kOnFinished'); +export const kDestroy = Symbol('kDestroy'); +export const kConstruct = Symbol('kConstruct'); import { - AbortError, - ERR_INVALID_ARG_TYPE, - ERR_INVALID_ARG_VALUE, - ERR_STREAM_PREMATURE_CLOSE, - ERR_MULTIPLE_CALLBACK, - aggregateTwoErrors, -} from "./internal_errors"; + AbortError, + ERR_INVALID_ARG_TYPE, + ERR_INVALID_ARG_VALUE, + ERR_STREAM_PREMATURE_CLOSE, + ERR_MULTIPLE_CALLBACK, + aggregateTwoErrors, +} from './internal_errors'; -import * as process from "./process"; +import * as process from './process'; -import { Buffer } from "./internal_buffer"; +import { Buffer } from './internal_buffer'; -import { validateAbortSignal, validateFunction, validateObject } from "./validators"; +import { + validateAbortSignal, + validateFunction, + validateObject, +} from './validators'; export function isReadableNodeStream(obj, strict = false) { - let _obj$_readableState; - return !!( - ( - obj && - typeof obj.pipe === "function" && - typeof obj.on === "function" && - (!strict || (typeof obj.pause === "function" && typeof obj.resume === "function")) && - (!obj._writableState || - ((_obj$_readableState = obj._readableState) === null || - _obj$_readableState === undefined - ? undefined - : _obj$_readableState.readable) !== false) && - // Duplex - (!obj._writableState || obj._readableState) - ) // Writable has .pipe. - ); + let _obj$_readableState; + return !!( + ( + obj && + typeof obj.pipe === 'function' && + typeof obj.on === 'function' && + (!strict || (typeof obj.pause === 'function' && + typeof obj.resume === 'function')) && + (!obj._writableState || + ((_obj$_readableState = obj._readableState) === null || + _obj$_readableState === undefined ? undefined + : _obj$_readableState.readable) !== false) && + // Duplex + (!obj._writableState || obj._readableState) + ) // Writable has .pipe. + ); } export function isWritableNodeStream(obj) { - let _obj$_writableState; - return !!( - ( - obj && - typeof obj.write === "function" && - typeof obj.on === "function" && - (!obj._readableState || - ((_obj$_writableState = obj._writableState) === null || - _obj$_writableState === undefined - ? undefined - : _obj$_writableState.writable) !== false) - ) // Duplex - ); + let _obj$_writableState; + return !!( + ( + obj && + typeof obj.write === 'function' && + typeof obj.on === 'function' && + (!obj._readableState || + ((_obj$_writableState = obj._writableState) === null || + _obj$_writableState === undefined ? undefined + : _obj$_writableState.writable) !== false) + ) // Duplex + ); } export function isDuplexNodeStream(obj) { - return !!( - obj && - typeof obj.pipe === "function" && - obj._readableState && - typeof obj.on === "function" && - typeof obj.write === "function" - ); + return !!( + obj && + typeof obj.pipe === 'function' && + obj._readableState && + typeof obj.on === 'function' && + typeof obj.write === 'function' + ); } export function isNodeStream(obj) { - return ( - obj && - (obj._readableState || - obj._writableState || - (typeof obj.write === "function" && typeof obj.on === "function") || - (typeof obj.pipe === "function" && typeof obj.on === "function")) - ); + return ( + obj && + (obj._readableState || + obj._writableState || + (typeof obj.write === 'function' && + typeof obj.on === 'function') || + (typeof obj.pipe === 'function' && + typeof obj.on === 'function')) + ); } export function isIterable(obj, isAsync = false) { - if (obj == null) return false; - if (isAsync === true) return typeof obj[Symbol.asyncIterator] === "function"; - if (isAsync === false) return typeof obj[Symbol.iterator] === "function"; - return ( - typeof obj[Symbol.asyncIterator] === "function" || - typeof obj[Symbol.iterator] === "function" - ); + if (obj == null) return false; + if (isAsync === true) return typeof obj[Symbol.asyncIterator] === 'function'; + if (isAsync === false) return typeof obj[Symbol.iterator] === 'function'; + return typeof obj[Symbol.asyncIterator] === 'function' || + typeof obj[Symbol.iterator] === 'function'; } export function isDestroyed(stream) { - if (!isNodeStream(stream)) return null; - const wState = stream._writableState; - const rState = stream._readableState; - const state = wState || rState; - return !!( - stream.destroyed || - stream[kDestroyed] || - (state !== null && state !== undefined && state.destroyed) - ); + if (!isNodeStream(stream)) return null; + const wState = stream._writableState; + const rState = stream._readableState; + const state = wState || rState; + return !!(stream.destroyed || stream[kDestroyed] || (state !== null && state !== undefined && state.destroyed)); } export function isWritableEnded(stream) { - if (!isWritableNodeStream(stream)) return null; - if (stream.writableEnded === true) return true; - const wState = stream._writableState; - if (wState !== null && wState !== undefined && wState.errored) return false; - if (typeof (wState === null || wState === undefined ? undefined : wState.ended) !== "boolean") - return null; - return wState.ended; + if (!isWritableNodeStream(stream)) return null; + if (stream.writableEnded === true) return true; + const wState = stream._writableState; + if (wState !== null && wState !== undefined && wState.errored) return false; + if (typeof (wState === null || wState === undefined ? undefined : wState.ended) !== 'boolean') return null; + return wState.ended; } export function isWritableFinished(stream, strict = false) { - if (!isWritableNodeStream(stream)) return null; - if (stream.writableFinished === true) return true; - const wState = stream._writableState; - if (wState !== null && wState !== undefined && wState.errored) return false; - if ( - typeof (wState === null || wState === undefined ? undefined : wState.finished) !== "boolean" - ) - return null; - return !!( - wState.finished || - (strict === false && wState.ended === true && wState.length === 0) - ); + if (!isWritableNodeStream(stream)) return null; + if (stream.writableFinished === true) return true; + const wState = stream._writableState; + if (wState !== null && wState !== undefined && wState.errored) return false; + if (typeof (wState === null || wState === undefined ? undefined : wState.finished) !== 'boolean') return null; + return !!(wState.finished || (strict === false && wState.ended === true && wState.length === 0)); } export function isReadableEnded(stream) { - if (!isReadableNodeStream(stream)) return null; - if (stream.readableEnded === true) return true; - const rState = stream._readableState; - if (!rState || rState.errored) return false; - if (typeof (rState === null || rState === undefined ? undefined : rState.ended) !== "boolean") - return null; - return rState.ended; + if (!isReadableNodeStream(stream)) return null; + if (stream.readableEnded === true) return true; + const rState = stream._readableState; + if (!rState || rState.errored) return false; + if (typeof (rState === null || rState === undefined ? undefined : rState.ended) !== 'boolean') return null; + return rState.ended; } export function isReadableFinished(stream, strict = false) { - if (!isReadableNodeStream(stream)) return null; - const rState = stream._readableState; - if (rState !== null && rState !== undefined && rState.errored) return false; - if ( - typeof (rState === null || rState === undefined ? undefined : rState.endEmitted) !== - "boolean" - ) - return null; - return !!( - rState.endEmitted || - (strict === false && rState.ended === true && rState.length === 0) - ); + if (!isReadableNodeStream(stream)) return null; + const rState = stream._readableState; + if (rState !== null && rState !== undefined && rState.errored) return false; + if (typeof (rState === null || rState === undefined ? undefined : rState.endEmitted) !== 'boolean') return null; + return !!(rState.endEmitted || (strict === false && rState.ended === true && rState.length === 0)); } export function isReadable(stream) { - if (stream && stream[kIsReadable] != null) return stream[kIsReadable]; - if ( - typeof (stream === null || stream === undefined ? undefined : stream.readable) !== "boolean" - ) - return null; - if (isDestroyed(stream)) return false; - return isReadableNodeStream(stream) && stream.readable && !isReadableFinished(stream); + if (stream && stream[kIsReadable] != null) return stream[kIsReadable]; + if (typeof (stream === null || stream === undefined ? undefined : stream.readable) !== 'boolean') return null; + if (isDestroyed(stream)) return false; + return isReadableNodeStream(stream) && stream.readable && !isReadableFinished(stream); } export function isWritable(stream) { - if ( - typeof (stream === null || stream === undefined ? undefined : stream.writable) !== "boolean" - ) - return null; - if (isDestroyed(stream)) return false; - return isWritableNodeStream(stream) && stream.writable && !isWritableEnded(stream); + if (typeof (stream === null || stream === undefined ? undefined : stream.writable) !== 'boolean') return null; + if (isDestroyed(stream)) return false; + return isWritableNodeStream(stream) && stream.writable && !isWritableEnded(stream); } export function isFinished(stream, opts = {}) { - if (!isNodeStream(stream)) { - return null; - } - if (isDestroyed(stream)) { - return true; - } - if ( - (opts === null || opts === undefined ? undefined : opts.readable) !== false && - isReadable(stream) - ) { - return false; - } - if ( - (opts === null || opts === undefined ? undefined : opts.writable) !== false && - isWritable(stream) - ) { - return false; - } + if (!isNodeStream(stream)) { + return null; + } + if (isDestroyed(stream)) { return true; + } + if ((opts === null || opts === undefined ? undefined : opts.readable) !== false && + isReadable(stream)) { + return false; + } + if ((opts === null || opts === undefined ? undefined : opts.writable) !== false && + isWritable(stream)) { + return false; + } + return true; } export function isWritableErrored(stream) { - let _stream$_writableStat, _stream$_writableStat2; - if (!isNodeStream(stream)) { - return null; - } - if (stream.writableErrored) { - return stream.writableErrored; - } - return (_stream$_writableStat = - (_stream$_writableStat2 = stream._writableState) === null || - _stream$_writableStat2 === undefined - ? undefined - : _stream$_writableStat2.errored) !== null && _stream$_writableStat !== undefined - ? _stream$_writableStat - : null; + let _stream$_writableStat, _stream$_writableStat2; + if (!isNodeStream(stream)) { + return null; + } + if (stream.writableErrored) { + return stream.writableErrored; + } + return (_stream$_writableStat = + (_stream$_writableStat2 = stream._writableState) === null || _stream$_writableStat2 === undefined + ? undefined + : _stream$_writableStat2.errored) !== null && _stream$_writableStat !== undefined + ? _stream$_writableStat + : null; } export function isReadableErrored(stream) { - let _stream$_readableStat, _stream$_readableStat2; - if (!isNodeStream(stream)) { - return null; - } - if (stream.readableErrored) { - return stream.readableErrored; - } - return (_stream$_readableStat = - (_stream$_readableStat2 = stream._readableState) === null || - _stream$_readableStat2 === undefined - ? undefined - : _stream$_readableStat2.errored) !== null && _stream$_readableStat !== undefined - ? _stream$_readableStat - : null; + let _stream$_readableStat, _stream$_readableStat2; + if (!isNodeStream(stream)) { + return null; + } + if (stream.readableErrored) { + return stream.readableErrored; + } + return (_stream$_readableStat = + (_stream$_readableStat2 = stream._readableState) === null || _stream$_readableStat2 === undefined + ? undefined + : _stream$_readableStat2.errored) !== null && _stream$_readableStat !== undefined + ? _stream$_readableStat + : null; } export function isClosed(stream) { - if (!isNodeStream(stream)) { - return null; - } - if (typeof stream.closed === "boolean") { - return stream.closed; - } - const wState = stream._writableState; - const rState = stream._readableState; - if ( - typeof (wState === null || wState === undefined ? undefined : wState.closed) === - "boolean" || - typeof (rState === null || rState === undefined ? undefined : rState.closed) === "boolean" - ) { - return ( - (wState === null || wState === undefined ? undefined : wState.closed) || - (rState === null || rState === undefined ? undefined : rState.closed) - ); - } - if (typeof stream._closed === "boolean" && isOutgoingMessage(stream)) { - return stream._closed; - } - return null; + if (!isNodeStream(stream)) { + return null + } + if (typeof stream.closed === 'boolean') { + return stream.closed + } + const wState = stream._writableState + const rState = stream._readableState + if ( + typeof (wState === null || wState === undefined ? undefined : wState.closed) === 'boolean' || + typeof (rState === null || rState === undefined ? undefined : rState.closed) === 'boolean' + ) { + return ( + (wState === null || wState === undefined ? undefined : wState.closed) || + (rState === null || rState === undefined ? undefined : rState.closed) + ) + } + if (typeof stream._closed === 'boolean' && isOutgoingMessage(stream)) { + return stream._closed + } + return null } // TODO(later): We do not actually support OutgoingMessage yet. Might not ever? // Keeping this here tho just to keep things simple. export function isOutgoingMessage(stream) { - return ( - typeof stream._closed === "boolean" && - typeof stream._defaultKeepAlive === "boolean" && - typeof stream._removedConnection === "boolean" && - typeof stream._removedContLen === "boolean" - ); + return ( + typeof stream._closed === 'boolean' && + typeof stream._defaultKeepAlive === 'boolean' && + typeof stream._removedConnection === 'boolean' && + typeof stream._removedContLen === 'boolean' + ); } // TODO(later): We do not actually support Server Response yet. Might not ever? // Keeping this here tho just to keep things simple. export function isServerResponse(stream) { - return typeof stream._sent100 === "boolean" && isOutgoingMessage(stream); + return typeof stream._sent100 === 'boolean' && isOutgoingMessage(stream); } // TODO(later): We do not actually support Server Request yet. Might not ever? // Keeping this here tho just to keep things simple. export function isServerRequest(stream) { - let _stream$req; - return ( - typeof stream._consuming === "boolean" && - typeof stream._dumped === "boolean" && - ((_stream$req = stream.req) === null || _stream$req === undefined - ? undefined - : _stream$req.upgradeOrConnect) === undefined - ); + let _stream$req; + return ( + typeof stream._consuming === 'boolean' && + typeof stream._dumped === 'boolean' && + ((_stream$req = stream.req) === null || _stream$req === undefined ? undefined : _stream$req.upgradeOrConnect) === + undefined + ); } export function willEmitClose(stream) { - if (!isNodeStream(stream)) return null; - const wState = stream._writableState; - const rState = stream._readableState; - const state = wState || rState; - return ( - (!state && isServerResponse(stream)) || - !!(state && state.autoDestroy && state.emitClose && state.closed === false) - ); + if (!isNodeStream(stream)) return null; + const wState = stream._writableState; + const rState = stream._readableState; + const state = wState || rState; + return ( + (!state && isServerResponse(stream)) || !!(state && state.autoDestroy && state.emitClose && state.closed === false) + ); } export function isDisturbed(stream) { - let _stream$kIsDisturbed; - return !!( - stream && - ((_stream$kIsDisturbed = stream[kIsDisturbed]) !== null && - _stream$kIsDisturbed !== undefined - ? _stream$kIsDisturbed - : stream.readableDidRead || stream.readableAborted) - ); + let _stream$kIsDisturbed; + return !!( + stream && + ((_stream$kIsDisturbed = stream[kIsDisturbed]) !== null && _stream$kIsDisturbed !== undefined + ? _stream$kIsDisturbed + : stream.readableDidRead || stream.readableAborted) + ); } export function isErrored(stream) { - var _ref, - _ref2, - _ref3, - _ref4, - _ref5, - _stream$kIsErrored, - _stream$_readableStat3, - _stream$_writableStat3, - _stream$_readableStat4, - _stream$_writableStat4; - return !!( - stream && - ((_ref = - (_ref2 = - (_ref3 = - (_ref4 = - (_ref5 = - (_stream$kIsErrored = stream[kIsErrored]) !== null && - _stream$kIsErrored !== undefined - ? _stream$kIsErrored - : stream.readableErrored) !== null && _ref5 !== undefined - ? _ref5 - : stream.writableErrored) !== null && _ref4 !== undefined - ? _ref4 - : (_stream$_readableStat3 = stream._readableState) === null || - _stream$_readableStat3 === undefined - ? undefined - : _stream$_readableStat3.errorEmitted) !== null && _ref3 !== undefined - ? _ref3 - : (_stream$_writableStat3 = stream._writableState) === null || - _stream$_writableStat3 === undefined - ? undefined - : _stream$_writableStat3.errorEmitted) !== null && _ref2 !== undefined - ? _ref2 - : (_stream$_readableStat4 = stream._readableState) === null || - _stream$_readableStat4 === undefined - ? undefined - : _stream$_readableStat4.errored) !== null && _ref !== undefined - ? _ref - : (_stream$_writableStat4 = stream._writableState) === null || - _stream$_writableStat4 === undefined - ? undefined - : _stream$_writableStat4.errored) - ); + var _ref, + _ref2, + _ref3, + _ref4, + _ref5, + _stream$kIsErrored, + _stream$_readableStat3, + _stream$_writableStat3, + _stream$_readableStat4, + _stream$_writableStat4 + return !!( + stream && + ((_ref = + (_ref2 = + (_ref3 = + (_ref4 = + (_ref5 = + (_stream$kIsErrored = stream[kIsErrored]) !== null && _stream$kIsErrored !== undefined + ? _stream$kIsErrored + : stream.readableErrored) !== null && _ref5 !== undefined + ? _ref5 + : stream.writableErrored) !== null && _ref4 !== undefined + ? _ref4 + : (_stream$_readableStat3 = stream._readableState) === null || _stream$_readableStat3 === undefined + ? undefined + : _stream$_readableStat3.errorEmitted) !== null && _ref3 !== undefined + ? _ref3 + : (_stream$_writableStat3 = stream._writableState) === null || _stream$_writableStat3 === undefined + ? undefined + : _stream$_writableStat3.errorEmitted) !== null && _ref2 !== undefined + ? _ref2 + : (_stream$_readableStat4 = stream._readableState) === null || _stream$_readableStat4 === undefined + ? undefined + : _stream$_readableStat4.errored) !== null && _ref !== undefined + ? _ref + : (_stream$_writableStat4 = stream._writableState) === null || _stream$_writableStat4 === undefined + ? undefined + : _stream$_writableStat4.errored) + ) } export const nop = () => {}; export function once(callback) { - let called = false; - return function (...args) { - if (called) { - return; - } - called = true; - callback.apply(this, args); - }; + let called = false + return function (...args) { + if (called) { + return + } + called = true + callback.apply(this, args) + } } // ====================================================================================== // highWaterMark handling export function highWaterMarkFrom(options, isDuplex, duplexKey) { - return options.highWaterMark != null - ? options.highWaterMark - : isDuplex - ? options[duplexKey] - : null; + return options.highWaterMark != null ? options.highWaterMark : + isDuplex ? options[duplexKey] : null } export function getDefaultHighWaterMark(objectMode = false) { - return objectMode ? 16 : 16 * 1024; + return objectMode ? 16 : 16 * 1024 } export function getHighWaterMark(state, options, duplexKey, isDuplex) { - const hwm = highWaterMarkFrom(options, isDuplex, duplexKey); - if (hwm != null) { - if (!Number.isInteger(hwm) || hwm < 0) { - const name = isDuplex ? `options.${duplexKey}` : "options.highWaterMark"; - throw new ERR_INVALID_ARG_VALUE(name, hwm, name); - } - return Math.floor(hwm); + const hwm = highWaterMarkFrom(options, isDuplex, duplexKey) + if (hwm != null) { + if (!Number.isInteger(hwm) || hwm < 0) { + const name = isDuplex ? `options.${duplexKey}` : 'options.highWaterMark'; + throw new ERR_INVALID_ARG_VALUE(name, hwm, name); } + return Math.floor(hwm); + } - // Default value - return getDefaultHighWaterMark(state.objectMode); + // Default value + return getDefaultHighWaterMark(state.objectMode) } // ====================================================================================== // addAbortSignal export function addAbortSignal(signal, stream) { - validateAbortSignal(signal, "signal"); - if (!isNodeStream(stream)) { - throw new ERR_INVALID_ARG_TYPE("stream", "stream.Stream", stream); - } - const onAbort = () => { - stream.destroy( - new AbortError(undefined, { - cause: signal.reason, - }) - ); - }; - if (signal.aborted) { - onAbort(); - } else { - signal.addEventListener("abort", onAbort); - eos(stream, () => signal.removeEventListener("abort", onAbort)); - } - return stream; + validateAbortSignal(signal, 'signal'); + if (!isNodeStream(stream)) { + throw new ERR_INVALID_ARG_TYPE('stream', 'stream.Stream', stream); + } + const onAbort = () => { + stream.destroy( + new AbortError(undefined, { + cause: signal.reason + }) + ); + } + if (signal.aborted) { + onAbort(); + } else { + signal.addEventListener('abort', onAbort); + eos(stream, () => signal.removeEventListener('abort', onAbort)); + } + return stream; } // ====================================================================================== // BufferList export class BufferList { - head = null; - tail = null; - length = 0; - - push(v) { - const entry = { - data: v, - next: null, - }; - if (this.length > 0) this.tail.next = entry; - else this.head = entry; - this.tail = entry; - ++this.length; - } - unshift(v) { - const entry = { - data: v, - next: this.head, - }; - if (this.length === 0) this.tail = entry; - this.head = entry; - ++this.length; - } - shift() { - if (this.length === 0) return; - const ret = this.head.data; - if (this.length === 1) this.head = this.tail = null; - else this.head = this.head.next; - --this.length; - return ret; - } - - clear() { - this.head = this.tail = null; - this.length = 0; - } - - join(s) { - if (this.length === 0) return ""; - let p = this.head; - let ret = "" + p.data; - while ((p = p.next) !== null) ret += s + p.data; - return ret; - } - - concat(n) { - if (this.length === 0) return Buffer.alloc(0); - const ret = Buffer.allocUnsafe(n >>> 0); - let p = this.head; - let i = 0; - while (p) { - ret.set(p.data, i); - i += p.data.length; - p = p.next; - } - return ret; - } - - consume(n, hasStrings = false) { - const data = this.head.data; - if (n < data.length) { - // `slice` is the same for buffers and strings. - const slice = data.slice(0, n); - this.head.data = data.slice(n); - return slice; - } - if (n === data.length) { - // First chunk is a perfect match. - return this.shift(); - } - // Result spans more than one buffer. - return hasStrings ? this._getString(n) : this._getBuffer(n); - } - - first() { - return this.head.data; - } - - *[Symbol.iterator]() { - for (let p = this.head; p; p = p.next) { - yield p.data; + head = null; + tail = null; + length = 0; + + push(v) { + const entry = { + data: v, + next: null, + } + if (this.length > 0) this.tail.next = entry; + else this.head = entry; + this.tail = entry; + ++this.length; + } + unshift(v) { + const entry = { + data: v, + next: this.head, + } + if (this.length === 0) this.tail = entry; + this.head = entry; + ++this.length; + } + shift() { + if (this.length === 0) return; + const ret = this.head.data; + if (this.length === 1) this.head = this.tail = null; + else this.head = this.head.next; + --this.length; + return ret; + } + + clear() { + this.head = this.tail = null; + this.length = 0; + } + + join(s) { + if (this.length === 0) return ''; + let p = this.head; + let ret = '' + p.data; + while ((p = p.next) !== null) ret += s + p.data; + return ret; + } + + concat(n) { + if (this.length === 0) return Buffer.alloc(0); + const ret = Buffer.allocUnsafe(n >>> 0); + let p = this.head; + let i = 0; + while (p) { + ret.set(p.data, i); + i += p.data.length; + p = p.next; + } + return ret; + } + + consume(n, hasStrings = false) { + const data = this.head.data; + if (n < data.length) { + // `slice` is the same for buffers and strings. + const slice = data.slice(0, n); + this.head.data = data.slice(n); + return slice; + } + if (n === data.length) { + // First chunk is a perfect match. + return this.shift(); + } + // Result spans more than one buffer. + return hasStrings ? this._getString(n) : this._getBuffer(n); + } + + first() { + return this.head.data; + } + + *[Symbol.iterator]() { + for (let p = this.head; p; p = p.next) { + yield p.data; + } + } + + _getString(n) { + let ret = ''; + let p = this.head; + let c = 0; + do { + const str = p.data; + if (n > str.length) { + ret += str; + n -= str.length; + } else { + if (n === str.length) { + ret += str + ++c + if (p.next) this.head = p.next; + else this.head = this.tail = null; + } else { + ret += str.slice(0, n); + this.head = p; + p.data = str.slice(n); + } + break; + } + ++c; + } while ((p = p.next) !== null); + this.length -= c; + return ret; + } + + _getBuffer(n) { + const ret = Buffer.allocUnsafe(n); + const retLen = n; + let p = this.head; + let c = 0; + do { + const buf = p.data; + if (n > buf.length) { + ret.set(buf, retLen - n); + n -= buf.length; + } else { + if (n === buf.length) { + ret.set(buf, retLen - n); + ++c; + if (p.next) this.head = p.next; + else this.head = this.tail = null; + } else { + ret.set(new Uint8Array(buf.buffer, buf.byteOffset, n), retLen - n); + this.head = p; + p.data = buf.slice(n); } - } - - _getString(n) { - let ret = ""; - let p = this.head; - let c = 0; - do { - const str = p.data; - if (n > str.length) { - ret += str; - n -= str.length; - } else { - if (n === str.length) { - ret += str; - ++c; - if (p.next) this.head = p.next; - else this.head = this.tail = null; - } else { - ret += str.slice(0, n); - this.head = p; - p.data = str.slice(n); - } - break; - } - ++c; - } while ((p = p.next) !== null); - this.length -= c; - return ret; - } - - _getBuffer(n) { - const ret = Buffer.allocUnsafe(n); - const retLen = n; - let p = this.head; - let c = 0; - do { - const buf = p.data; - if (n > buf.length) { - ret.set(buf, retLen - n); - n -= buf.length; - } else { - if (n === buf.length) { - ret.set(buf, retLen - n); - ++c; - if (p.next) this.head = p.next; - else this.head = this.tail = null; - } else { - ret.set(new Uint8Array(buf.buffer, buf.byteOffset, n), retLen - n); - this.head = p; - p.data = buf.slice(n); - } - break; - } - ++c; - } while ((p = p.next) !== null); - this.length -= c; - return ret; - } + break; + } + ++c + } while ((p = p.next) !== null); + this.length -= c; + return ret; + } } // ====================================================================================== // TODO(later): We do not current implement Node.js' Request object. Might never? function isRequest(stream) { - return stream && stream.setHeader && typeof stream.abort === "function"; + return stream && stream.setHeader && typeof stream.abort === 'function' } export function eos(stream, options, callback) { - let _options$readable, _options$writable; - if (arguments.length === 2) { - callback = options; - options = {}; - } else if (options == null) { - options = {}; + let _options$readable, _options$writable; + if (arguments.length === 2) { + callback = options; + options = {}; + } else if (options == null) { + options = {}; + } else { + validateObject(options, 'options', options); + } + validateFunction(callback, 'callback'); + validateAbortSignal(options.signal, 'options.signal'); + callback = once(callback); + const readable = + (_options$readable = options.readable) !== null && _options$readable !== undefined + ? _options$readable + : isReadableNodeStream(stream); + const writable = + (_options$writable = options.writable) !== null && _options$writable !== undefined + ? _options$writable + : isWritableNodeStream(stream); + if (!isNodeStream(stream)) { + // TODO: Webstreams. + throw new ERR_INVALID_ARG_TYPE('stream', 'Stream', stream); + } + const wState = stream._writableState; + const rState = stream._readableState; + const onlegacyfinish = () => { + if (!stream.writable) { + onfinish(); + } + }; + + // TODO (ronag): Improve soft detection to include core modules and + // common ecosystem modules that do properly emit 'close' but fail + // this generic check. + let _willEmitClose = + willEmitClose(stream) && isReadableNodeStream(stream) === readable && isWritableNodeStream(stream) === writable; + let writableFinished = isWritableFinished((stream), false); + const onfinish = () => { + writableFinished = true; + // Stream should not be destroyed here. If it is that + // means that user space is doing something differently and + // we cannot trust willEmitClose. + if (stream.destroyed) { + _willEmitClose = false; + } + if (_willEmitClose && (!stream.readable || readable)) { + return; + } + if (!readable || readableFinished) { + callback.call(stream); + } + }; + let readableFinished = isReadableFinished(stream, false); + const onend = () => { + readableFinished = true; + // Stream should not be destroyed here. If it is that + // means that user space is doing something differently and + // we cannot trust willEmitClose. + if (stream.destroyed) { + _willEmitClose = false; + } + if (_willEmitClose && (!stream.writable || writable)) { + return; + } + if (!writable || writableFinished) { + callback.call(stream); + } + }; + const onerror = (err) => { + callback.call(stream, err); + }; + let closed = isClosed(stream); + const onclose = () => { + closed = true; + const errored = isWritableErrored(stream) || isReadableErrored(stream) + if (errored && typeof errored !== 'boolean') { + return callback.call(stream, errored); + } + if (readable && !readableFinished && isReadableNodeStream(stream, true)) { + if (!isReadableFinished(stream, false)) return callback.call(stream, new ERR_STREAM_PREMATURE_CLOSE()); + } + if (writable && !writableFinished) { + if (!isWritableFinished(stream, false)) return callback.call(stream, new ERR_STREAM_PREMATURE_CLOSE()); + } + callback.call(stream); + }; + const onrequest = () => { + stream.req.on('finish', onfinish); + }; + if (isRequest(stream)) { + stream.on('complete', onfinish); + if (!_willEmitClose) { + stream.on('abort', onclose); + } + if (stream.req) { + onrequest(); } else { - validateObject(options, "options", options); - } - validateFunction(callback, "callback"); - validateAbortSignal(options.signal, "options.signal"); - callback = once(callback); - const readable = - (_options$readable = options.readable) !== null && _options$readable !== undefined - ? _options$readable - : isReadableNodeStream(stream); - const writable = - (_options$writable = options.writable) !== null && _options$writable !== undefined - ? _options$writable - : isWritableNodeStream(stream); - if (!isNodeStream(stream)) { - // TODO: Webstreams. - throw new ERR_INVALID_ARG_TYPE("stream", "Stream", stream); - } - const wState = stream._writableState; - const rState = stream._readableState; - const onlegacyfinish = () => { - if (!stream.writable) { - onfinish(); - } - }; - - // TODO (ronag): Improve soft detection to include core modules and - // common ecosystem modules that do properly emit 'close' but fail - // this generic check. - let _willEmitClose = - willEmitClose(stream) && - isReadableNodeStream(stream) === readable && - isWritableNodeStream(stream) === writable; - let writableFinished = isWritableFinished(stream, false); - const onfinish = () => { - writableFinished = true; - // Stream should not be destroyed here. If it is that - // means that user space is doing something differently and - // we cannot trust willEmitClose. - if (stream.destroyed) { - _willEmitClose = false; - } - if (_willEmitClose && (!stream.readable || readable)) { - return; - } - if (!readable || readableFinished) { - callback.call(stream); - } - }; - let readableFinished = isReadableFinished(stream, false); - const onend = () => { - readableFinished = true; - // Stream should not be destroyed here. If it is that - // means that user space is doing something differently and - // we cannot trust willEmitClose. - if (stream.destroyed) { - _willEmitClose = false; - } - if (_willEmitClose && (!stream.writable || writable)) { - return; - } - if (!writable || writableFinished) { - callback.call(stream); - } - }; - const onerror = (err) => { - callback.call(stream, err); - }; - let closed = isClosed(stream); - const onclose = () => { - closed = true; - const errored = isWritableErrored(stream) || isReadableErrored(stream); - if (errored && typeof errored !== "boolean") { - return callback.call(stream, errored); - } - if (readable && !readableFinished && isReadableNodeStream(stream, true)) { - if (!isReadableFinished(stream, false)) - return callback.call(stream, new ERR_STREAM_PREMATURE_CLOSE()); - } - if (writable && !writableFinished) { - if (!isWritableFinished(stream, false)) - return callback.call(stream, new ERR_STREAM_PREMATURE_CLOSE()); - } - callback.call(stream); - }; - const onrequest = () => { - stream.req.on("finish", onfinish); - }; - if (isRequest(stream)) { - stream.on("complete", onfinish); - if (!_willEmitClose) { - stream.on("abort", onclose); - } - if (stream.req) { - onrequest(); - } else { - stream.on("request", onrequest); - } - } else if (writable && !wState) { - // legacy streams - stream.on("end", onlegacyfinish); - stream.on("close", onlegacyfinish); - } - - // Not all streams will emit 'close' after 'aborted'. - if (!_willEmitClose && typeof stream.aborted === "boolean") { - stream.on("aborted", onclose); - } - stream.on("end", onend); - stream.on("finish", onfinish); - if (options.error !== false) { - stream.on("error", onerror); - } - stream.on("close", onclose); - if (closed) { - process.nextTick(onclose); - } else if ( - (wState !== null && wState !== undefined && wState.errorEmitted) || - (rState !== null && rState !== undefined && rState.errorEmitted) - ) { - if (!_willEmitClose) { - process.nextTick(onclose); - } - } else if ( - !readable && - (!_willEmitClose || isReadable(stream)) && - (writableFinished || isWritable(stream) === false) - ) { - process.nextTick(onclose); - } else if ( - !writable && - (!_willEmitClose || isWritable(stream)) && - (readableFinished || isReadable(stream) === false) - ) { - process.nextTick(onclose); - } else if (rState && stream.req && stream.aborted) { - process.nextTick(onclose); - } - const cleanup = () => { - callback = nop; - stream.removeListener("aborted", onclose); - stream.removeListener("complete", onfinish); - stream.removeListener("abort", onclose); - stream.removeListener("request", onrequest); - if (stream.req) stream.req.removeListener("finish", onfinish); - stream.removeListener("end", onlegacyfinish); - stream.removeListener("close", onlegacyfinish); - stream.removeListener("finish", onfinish); - stream.removeListener("end", onend); - stream.removeListener("error", onerror); - stream.removeListener("close", onclose); - }; - if (options.signal && !closed) { - const abort = () => { - // Keep it because cleanup removes it. - const endCallback = callback; - cleanup(); - endCallback.call( - stream, - new AbortError(undefined, { - cause: options.signal?.reason, - }) - ); - }; - if (options.signal.aborted) { - process.nextTick(abort); - } else { - const originalCallback = callback; - callback = once((...args) => { - options.signal.removeEventListener("abort", abort); - originalCallback.apply(stream, args); - }); - options.signal.addEventListener("abort", abort); - } + stream.on('request', onrequest); + } + } else if (writable && !wState) { + // legacy streams + stream.on('end', onlegacyfinish); + stream.on('close', onlegacyfinish); + } + + // Not all streams will emit 'close' after 'aborted'. + if (!_willEmitClose && typeof stream.aborted === 'boolean') { + stream.on('aborted', onclose); + } + stream.on('end', onend); + stream.on('finish', onfinish); + if (options.error !== false) { + stream.on('error', onerror); + } + stream.on('close', onclose); + if (closed) { + process.nextTick(onclose); + } else if ( + (wState !== null && wState !== undefined && wState.errorEmitted) || + (rState !== null && rState !== undefined && rState.errorEmitted) + ) { + if (!_willEmitClose) { + process.nextTick(onclose); + } + } else if ( + !readable && + (!_willEmitClose || isReadable(stream)) && + (writableFinished || isWritable(stream) === false) + ) { + process.nextTick(onclose); + } else if ( + !writable && + (!_willEmitClose || isWritable(stream)) && + (readableFinished || isReadable(stream) === false) + ) { + process.nextTick(onclose); + } else if (rState && stream.req && stream.aborted) { + process.nextTick(onclose); + } + const cleanup = () => { + callback = nop; + stream.removeListener('aborted', onclose); + stream.removeListener('complete', onfinish); + stream.removeListener('abort', onclose); + stream.removeListener('request', onrequest); + if (stream.req) stream .req.removeListener('finish', onfinish); + stream.removeListener('end', onlegacyfinish); + stream.removeListener('close', onlegacyfinish); + stream.removeListener('finish', onfinish); + stream.removeListener('end', onend); + stream.removeListener('error', onerror); + stream.removeListener('close', onclose); + } + if (options.signal && !closed) { + const abort = () => { + // Keep it because cleanup removes it. + const endCallback = callback + cleanup() + endCallback.call( + stream, + new AbortError(undefined, { + cause: options.signal?.reason + }) + ) + } + if (options.signal.aborted) { + process.nextTick(abort); + } else { + const originalCallback = callback; + callback = once((...args) => { + options.signal.removeEventListener('abort', abort) + originalCallback.apply(stream, args); + }); + options.signal.addEventListener('abort', abort); } - return cleanup; + } + return cleanup; } export function finished(stream, opts) { - return new Promise((resolve, reject) => { - eos(stream, opts, (err) => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); + return new Promise((resolve, reject) => { + eos(stream, opts, (err) => { + if (err) { + reject(err); + } else { + resolve(); + } + }) + }); } eos.finished = finished; @@ -770,274 +726,272 @@ eos.finished = finished; // Destroy function checkError(err, w, r) { - if (err) { - // Avoid V8 leak, https://github.com/nodejs/node/pull/34103#issuecomment-652002364 - err.stack; // eslint-disable-line no-unused-expressions + if (err) { + // Avoid V8 leak, https://github.com/nodejs/node/pull/34103#issuecomment-652002364 + err.stack; // eslint-disable-line no-unused-expressions - if (w && !w.errored) { - w.errored = err; - } - if (r && !r.errored) { - r.errored = err; - } + if (w && !w.errored) { + w.errored = err; } + if (r && !r.errored) { + r.errored = err; + } + } } export function destroy(err, cb) { - const r = this._readableState; - const w = this._writableState; - // With duplex streams we use the writable side for state. - const s = w || r; - if ((w && w.destroyed) || (r && r.destroyed)) { - if (typeof cb === "function") { - cb(); - } - return this; + const r = this._readableState; + const w = this._writableState; + // With duplex streams we use the writable side for state. + const s = w || r; + if ((w && w.destroyed) || (r && r.destroyed)) { + if (typeof cb === 'function') { + cb(); } + return this; + } + + // We set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + checkError(err, w, r); + if (w) { + w.destroyed = true; + } + if (r) { + r.destroyed = true; + } + + // If still constructing then defer calling _destroy. + if (!s.constructed) { + this.once(kDestroy, function (er) { + _destroy(this, aggregateTwoErrors(er, err), cb); + }); + } else { + _destroy(this, err, cb); + } + return this; +} - // We set destroyed to true before firing error callbacks in order - // to make it re-entrance safe in case destroy() is called within callbacks +function _destroy(self, err, cb) { + let called = false; + function onDestroy(err) { + if (called) { + return; + } + called = true; + const r = self._readableState; + const w = self._writableState; checkError(err, w, r); if (w) { - w.destroyed = true; + w.closed = true; } if (r) { - r.destroyed = true; - } - - // If still constructing then defer calling _destroy. - if (!s.constructed) { - this.once(kDestroy, function (er) { - _destroy(this, aggregateTwoErrors(er, err), cb); - }); - } else { - _destroy(this, err, cb); + r.closed = true; } - return this; -} - -function _destroy(self, err, cb) { - let called = false; - function onDestroy(err) { - if (called) { - return; - } - called = true; - const r = self._readableState; - const w = self._writableState; - checkError(err, w, r); - if (w) { - w.closed = true; - } - if (r) { - r.closed = true; - } - if (typeof cb === "function") { - cb(err); - } - if (err) { - process.nextTick(emitErrorCloseNT, self, err); - } else { - process.nextTick(emitCloseNT, self); - } + if (typeof cb === 'function') { + cb(err); } - try { - self._destroy(err || null, onDestroy); - } catch (err) { - onDestroy(err); + if (err) { + process.nextTick(emitErrorCloseNT, self, err); + } else { + process.nextTick(emitCloseNT, self); } + } + try { + self._destroy(err || null, onDestroy); + } catch (err) { + onDestroy(err); + } } function emitErrorCloseNT(self, err) { - emitErrorNT(self, err); - emitCloseNT(self); + emitErrorNT(self, err); + emitCloseNT(self); } function emitCloseNT(self) { - const r = self._readableState; - const w = self._writableState; - if (w) { - w.closeEmitted = true; - } - if (r) { - r.closeEmitted = true; - } - if ((w && w.emitClose) || (r && r.emitClose)) { - self.emit("close"); - } + const r = self._readableState; + const w = self._writableState; + if (w) { + w.closeEmitted = true; + } + if (r) { + r.closeEmitted = true; + } + if ((w && w.emitClose) || (r && r.emitClose)) { + self.emit('close'); + } } function emitErrorNT(self, err) { - const r = self._readableState; - const w = self._writableState; - if ((w && w.errorEmitted) || (r && r.errorEmitted)) { - return; - } - if (w) { - w.errorEmitted = true; - } - if (r) { - r.errorEmitted = true; - } - self.emit("error", err); + const r = self._readableState; + const w = self._writableState; + if ((w && w.errorEmitted) || (r && r.errorEmitted)) { + return; + } + if (w) { + w.errorEmitted = true; + } + if (r) { + r.errorEmitted = true; + } + self.emit('error', err); } export function undestroy() { - const r = this._readableState; - const w = this._writableState; - if (r) { - r.constructed = true; - r.closed = false; - r.closeEmitted = false; - r.destroyed = false; - r.errored = null; - r.errorEmitted = false; - r.reading = false; - r.ended = r.readable === false; - r.endEmitted = r.readable === false; - } - if (w) { - w.constructed = true; - w.destroyed = false; - w.closed = false; - w.closeEmitted = false; - w.errored = null; - w.errorEmitted = false; - w.finalCalled = false; - w.prefinished = false; - w.ended = w.writable === false; - w.ending = w.writable === false; - w.finished = w.writable === false; - } + const r = this._readableState; + const w = this._writableState; + if (r) { + r.constructed = true; + r.closed = false; + r.closeEmitted = false; + r.destroyed = false; + r.errored = null; + r.errorEmitted = false; + r.reading = false; + r.ended = r.readable === false; + r.endEmitted = r.readable === false; + } + if (w) { + w.constructed = true; + w.destroyed = false; + w.closed = false; + w.closeEmitted = false; + w.errored = null; + w.errorEmitted = false; + w.finalCalled = false; + w.prefinished = false; + w.ended = w.writable === false; + w.ending = w.writable === false; + w.finished = w.writable === false; + } } export function errorOrDestroy(stream, err, sync = false) { - // We have tests that rely on errors being emitted - // in the same tick, so changing this is semver major. - // For now when you opt-in to autoDestroy we allow - // the error to be emitted nextTick. In a future - // semver major update we should change the default to this. - - const r = stream._readableState; - const w = stream._writableState; - if ((w && w.destroyed) || (r && r.destroyed)) { - return; - } - if ((r && r.autoDestroy) || (w && w.autoDestroy)) stream.destroy(err); - else if (err) { - // Avoid V8 leak, https://github.com/nodejs/node/pull/34103#issuecomment-652002364 - err.stack; // eslint-disable-line no-unused-expressions - - if (w && !w.errored) { - w.errored = err; - } - if (r && !r.errored) { - r.errored = err; - } - if (sync) { - process.nextTick(emitErrorNT, stream, err); - } else { - emitErrorNT(stream, err); - } + // We have tests that rely on errors being emitted + // in the same tick, so changing this is semver major. + // For now when you opt-in to autoDestroy we allow + // the error to be emitted nextTick. In a future + // semver major update we should change the default to this. + + const r = stream._readableState; + const w = stream._writableState; + if ((w && w.destroyed) || (r && r.destroyed)) { + return; + } + if ((r && r.autoDestroy) || (w && w.autoDestroy)) stream.destroy(err); + else if (err) { + // Avoid V8 leak, https://github.com/nodejs/node/pull/34103#issuecomment-652002364 + err.stack; // eslint-disable-line no-unused-expressions + + if (w && !w.errored) { + w.errored = err; + } + if (r && !r.errored) { + r.errored = err; + } + if (sync) { + process.nextTick(emitErrorNT, stream, err); + } else { + emitErrorNT(stream, err) } + } } export function construct(stream, cb) { - if (typeof stream._construct !== "function") { - return; + if (typeof stream._construct !== 'function') { + return; + } + const r = stream._readableState; + const w = stream._writableState; + if (r) { + r.constructed = false; + } + if (w) { + w.constructed = false; + } + stream.once(kConstruct, cb) + if (stream.listenerCount(kConstruct) > 1) { + // Duplex + return; + } + process.nextTick(constructNT, stream); +} + +function constructNT(stream) { + let called = false; + function onConstruct(err) { + if (called) { + errorOrDestroy(stream, err !== null && err !== undefined ? err : new ERR_MULTIPLE_CALLBACK()); + return; } + called = true; const r = stream._readableState; const w = stream._writableState; + const s = w || r; if (r) { - r.constructed = false; + r.constructed = true; } if (w) { - w.constructed = false; + w.constructed = true; } - stream.once(kConstruct, cb); - if (stream.listenerCount(kConstruct) > 1) { - // Duplex - return; - } - process.nextTick(constructNT, stream); -} - -function constructNT(stream) { - let called = false; - function onConstruct(err) { - if (called) { - errorOrDestroy( - stream, - err !== null && err !== undefined ? err : new ERR_MULTIPLE_CALLBACK() - ); - return; - } - called = true; - const r = stream._readableState; - const w = stream._writableState; - const s = w || r; - if (r) { - r.constructed = true; - } - if (w) { - w.constructed = true; - } - if (s.destroyed) { - stream.emit(kDestroy, err); - } else if (err) { - errorOrDestroy(stream, err, true); - } else { - process.nextTick(emitConstructNT, stream); - } - } - try { - stream._construct(onConstruct); - } catch (err) { - onConstruct(err); + if (s.destroyed) { + stream.emit(kDestroy, err); + } else if (err) { + errorOrDestroy(stream, err, true); + } else { + process.nextTick(emitConstructNT, stream); } + } + try { + stream._construct(onConstruct); + } catch (err) { + onConstruct(err); + } } function emitConstructNT(stream) { - stream.emit(kConstruct); + stream.emit(kConstruct); } function emitCloseLegacy(stream) { - stream.emit("close"); + stream.emit('close'); } function emitErrorCloseLegacy(stream, err) { - stream.emit("error", err); - process.nextTick(emitCloseLegacy, stream); + stream.emit('error', err); + process.nextTick(emitCloseLegacy, stream); } // Normalize destroy for legacy. export function destroyer(stream, err) { - if (!stream || isDestroyed(stream)) { - return; - } - if (!err && !isFinished(stream)) { - err = new AbortError(); - } - - // TODO: Remove isRequest branches. - if (isServerRequest(stream)) { - stream.socket = null; - stream.destroy(err); - } else if (isRequest(stream)) { - stream.abort(); - } else if (isRequest(stream.req)) { - stream.req.abort(); - } else if (typeof stream.destroy === "function") { - stream.destroy(err); - } else if (typeof stream.close === "function") { - // TODO: Don't lose err? - stream.close(); - } else if (err) { - process.nextTick(emitErrorCloseLegacy, stream, err); - } else { - process.nextTick(emitCloseLegacy, stream); - } - if (!stream.destroyed) { - stream[kDestroyed] = true; - } + if (!stream || isDestroyed(stream)) { + return; + } + if (!err && !isFinished(stream)) { + err = new AbortError(); + } + + // TODO: Remove isRequest branches. + if (isServerRequest(stream)) { + stream.socket = null; + stream.destroy(err); + } else if (isRequest(stream)) { + stream.abort(); + } else if (isRequest(stream.req)) { + stream.req.abort(); + } else if (typeof stream.destroy === 'function') { + stream.destroy(err); + } else if (typeof stream.close === 'function') { + // TODO: Don't lose err? + stream.close(); + } else if (err) { + process.nextTick(emitErrorCloseLegacy, stream, err); + } else { + process.nextTick(emitCloseLegacy, stream); + } + if (!stream.destroyed) { + stream[kDestroyed] = true; + } } + diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_writable.js b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_writable.js index 6a288b6d6..f356c6794 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_writable.js +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/streams_writable.js @@ -1,179 +1,185 @@ -import EventEmitter from "./events"; +import + EventEmitter + from './events'; -import { Stream } from "./streams_legacy"; +import { + Stream +} from './streams_legacy'; -import { Buffer } from "./internal_buffer"; +import { + Buffer, +} from './internal_buffer'; -import * as process from "./process"; +import * as process from './process'; import { - nop, - kOnFinished, - getHighWaterMark, - getDefaultHighWaterMark, - addAbortSignal, - construct, - destroy, - undestroy, - errorOrDestroy, -} from "./streams_util"; + nop, + kOnFinished, + getHighWaterMark, + getDefaultHighWaterMark, + addAbortSignal, + construct, + destroy, + undestroy, + errorOrDestroy, +} from './streams_util'; import { - newStreamWritableFromWritableStream, - newWritableStreamFromStreamWritable, -} from "./streams_adapters"; + newStreamWritableFromWritableStream, + newWritableStreamFromStreamWritable, +} from './streams_adapters'; import { - ERR_INVALID_ARG_TYPE, - ERR_METHOD_NOT_IMPLEMENTED, - ERR_MULTIPLE_CALLBACK, - ERR_STREAM_CANNOT_PIPE, - ERR_STREAM_DESTROYED, - ERR_STREAM_ALREADY_FINISHED, - ERR_STREAM_NULL_VALUES, - ERR_STREAM_WRITE_AFTER_END, - ERR_UNKNOWN_ENCODING, -} from "./internal_errors"; - -import { isDuplexInstance } from "./streams_duplex"; + ERR_INVALID_ARG_TYPE, + ERR_METHOD_NOT_IMPLEMENTED, + ERR_MULTIPLE_CALLBACK, + ERR_STREAM_CANNOT_PIPE, + ERR_STREAM_DESTROYED, + ERR_STREAM_ALREADY_FINISHED, + ERR_STREAM_NULL_VALUES, + ERR_STREAM_WRITE_AFTER_END, + ERR_UNKNOWN_ENCODING +} from './internal_errors'; + +import { isDuplexInstance } from './streams_duplex'; // ====================================================================================== // WritableState function WritableState(options, stream, isDuplex) { - // Duplex streams are both readable and writable, but share - // the same options object. - // However, some cases require setting options to different - // values for the readable and the writable sides of the duplex stream, - // e.g. options.readableObjectMode vs. options.writableObjectMode, etc. - if (typeof isDuplex !== "boolean") isDuplex = isDuplexInstance(stream); - - // Object stream flag to indicate whether or not this stream - // contains buffers or objects. - this.objectMode = !!options?.objectMode; - if (isDuplex) this.objectMode = this.objectMode || !!options?.writableObjectMode; - - // The point at which write() starts returning false - // Note: 0 is a valid value, means that we always return false if - // the entire buffer is not flushed immediately on write(). - this.highWaterMark = options - ? getHighWaterMark(this, options, "writableHighWaterMark", isDuplex) - : getDefaultHighWaterMark(false); - - // if _final has been called. - this.finalCalled = false; - - // drain event flag. - this.needDrain = false; - // At the start of calling end() - this.ending = false; - // When end() has been called, and returned. - this.ended = false; - // When 'finish' is emitted. - this.finished = false; - - // Has it been destroyed - this.destroyed = false; - - // Should we decode strings into buffers before passing to _write? - // this is here so that some node-core streams can optimize string - // handling at a lower level. - const noDecode = !!(options?.decodeStrings === false); - this.decodeStrings = !noDecode; - - // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. - this.defaultEncoding = options?.defaultEncoding || "utf8"; - - // Not an actual buffer we keep track of, but a measurement - // of how much we're waiting to get pushed to some underlying - // socket or file. - this.length = 0; - - // A flag to see when we're in the middle of a write. - this.writing = false; - - // When true all writes will be buffered until .uncork() call. - this.corked = 0; - - // A flag to be able to tell if the onwrite cb is called immediately, - // or on a later tick. We set this to true at first, because any - // actions that shouldn't happen until "later" should generally also - // not happen before the first write call. - this.sync = true; - - // A flag to know if we're processing previously buffered items, which - // may call the _write() callback in the same tick, so that we don't - // end up in an overlapped onwrite situation. - this.bufferProcessing = false; - - // The callback that's passed to _write(chunk, cb). - this.onwrite = (err) => onwrite.call(undefined, stream, err); - - // The callback that the user supplies to write(chunk, encoding, cb). - this.writecb = null; - - // The amount that is being written when _write is called. - this.writelen = 0; - - // Storage for data passed to the afterWrite() callback in case of - // synchronous _write() completion. - this.afterWriteTickInfo = null; - resetBuffer(this); - - // Number of pending user-supplied write callbacks - // this must be 0 before 'finish' can be emitted. - this.pendingcb = 0; - - // Stream is still being constructed and cannot be - // destroyed until construction finished or failed. - // Async construction is opt in, therefore we start as - // constructed. - this.constructed = true; - - // Emit prefinish if the only thing we're waiting for is _write cbs - // This is relevant for synchronous Transform streams. - this.prefinished = false; - - // True if the error was already emitted and should not be thrown again. - this.errorEmitted = false; - - // Should close be emitted on destroy. Defaults to true. - this.emitClose = !options || options.emitClose !== false; - - // Should .destroy() be called after 'finish' (and potentially 'end'). - this.autoDestroy = !options || options.autoDestroy !== false; - - // Indicates whether the stream has errored. When true all write() calls - // should return false. This is needed since when autoDestroy - // is disabled we need a way to tell whether the stream has failed. - this.errored = null; - - // Indicates whether the stream has finished destroying. - this.closed = false; - - // True if close has been emitted or would have been emitted - // depending on emitClose. - this.closeEmitted = false; - this[kOnFinished] = []; + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream, + // e.g. options.readableObjectMode vs. options.writableObjectMode, etc. + if (typeof isDuplex !== 'boolean') isDuplex = isDuplexInstance(stream); + + // Object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!(options?.objectMode); + if (isDuplex) this.objectMode = this.objectMode || !!(options?.writableObjectMode); + + // The point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write(). + this.highWaterMark = options + ? getHighWaterMark(this, options, 'writableHighWaterMark', isDuplex) + : getDefaultHighWaterMark(false); + + // if _final has been called. + this.finalCalled = false; + + // drain event flag. + this.needDrain = false; + // At the start of calling end() + this.ending = false; + // When end() has been called, and returned. + this.ended = false; + // When 'finish' is emitted. + this.finished = false; + + // Has it been destroyed + this.destroyed = false; + + // Should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + const noDecode = !!(options?.decodeStrings === false); + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = (options?.defaultEncoding) || 'utf8'; + + // Not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // A flag to see when we're in the middle of a write. + this.writing = false; + + // When true all writes will be buffered until .uncork() call. + this.corked = 0; + + // A flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // A flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // The callback that's passed to _write(chunk, cb). + this.onwrite = (err) => onwrite.call(undefined, stream, err); + + // The callback that the user supplies to write(chunk, encoding, cb). + this.writecb = null; + + // The amount that is being written when _write is called. + this.writelen = 0; + + // Storage for data passed to the afterWrite() callback in case of + // synchronous _write() completion. + this.afterWriteTickInfo = null; + resetBuffer(this); + + // Number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted. + this.pendingcb = 0; + + // Stream is still being constructed and cannot be + // destroyed until construction finished or failed. + // Async construction is opt in, therefore we start as + // constructed. + this.constructed = true; + + // Emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams. + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again. + this.errorEmitted = false; + + // Should close be emitted on destroy. Defaults to true. + this.emitClose = !options || options.emitClose !== false; + + // Should .destroy() be called after 'finish' (and potentially 'end'). + this.autoDestroy = !options || options.autoDestroy !== false; + + // Indicates whether the stream has errored. When true all write() calls + // should return false. This is needed since when autoDestroy + // is disabled we need a way to tell whether the stream has failed. + this.errored = null; + + // Indicates whether the stream has finished destroying. + this.closed = false; + + // True if close has been emitted or would have been emitted + // depending on emitClose. + this.closeEmitted = false; + this[kOnFinished] = []; } function resetBuffer(state) { - state.buffered = []; - state.bufferedIndex = 0; - state.allBuffers = true; - state.allNoop = true; + state.buffered = []; + state.bufferedIndex = 0; + state.allBuffers = true; + state.allNoop = true; } WritableState.prototype.getBuffer = function getBuffer() { - return this.buffered.slice(this.bufferedIndex); -}; + return this.buffered.slice(this.bufferedIndex); +} -Object.defineProperty(WritableState.prototype, "bufferedRequestCount", { - get() { - return this.buffered.length - this.bufferedIndex; - }, +Object.defineProperty(WritableState.prototype, 'bufferedRequestCount', { + get() { + return this.buffered.length - this.bufferedIndex; + } }); // ====================================================================================== @@ -185,117 +191,117 @@ Object.setPrototypeOf(Writable.prototype, Stream.prototype); Object.setPrototypeOf(Writable, Stream); export function Writable(options) { - // Writable ctor is applied to Duplexes, too. - // `realHasInstance` is necessary because using plain `instanceof` - // would return false, as no `_writableState` property is attached. - - // Trying to use the custom `instanceof` for Writable here will also break the - // Node.js LazyTransform implementation, which has a non-trivial getter for - // `_writableState` that would lead to infinite recursion. - - // Checking for a Stream.Duplex instance is faster here instead of inside - // the WritableState constructor, at least with V8 6.5. - const isDuplex = isDuplexInstance(this); - if (!isDuplex && !Writable[Symbol.hasInstance](this)) return new Writable(options); - this._writableState = new WritableState(options, this, isDuplex); - if (options) { - if (typeof options.write === "function") this._write = options.write; - if (typeof options.writev === "function") this._writev = options.writev; - if (typeof options.destroy === "function") this._destroy = options.destroy; - if (typeof options.final === "function") this._final = options.final; - if (typeof options.construct === "function") this._construct = options.construct; - if (options.signal) addAbortSignal(options.signal, this); + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + + // Checking for a Stream.Duplex instance is faster here instead of inside + // the WritableState constructor, at least with V8 6.5. + const isDuplex = isDuplexInstance(this); + if (!isDuplex && !Writable[Symbol.hasInstance](this)) return new Writable(options); + this._writableState = new WritableState(options, this, isDuplex) + if (options) { + if (typeof options.write === 'function') this._write = options.write; + if (typeof options.writev === 'function') this._writev = options.writev; + if (typeof options.destroy === 'function') this._destroy = options.destroy; + if (typeof options.final === 'function') this._final = options.final; + if (typeof options.construct === 'function') this._construct = options.construct; + if (options.signal) addAbortSignal(options.signal, this); + } + Stream.call(this, options); + construct(this, () => { + const state = this._writableState; + if (!state.writing) { + clearBuffer(this, state); } - Stream.call(this, options); - construct(this, () => { - const state = this._writableState; - if (!state.writing) { - clearBuffer(this, state); - } - finishMaybe(this, state); - }); + finishMaybe(this, state); + }) } Object.defineProperty(Writable, Symbol.hasInstance, { - value: function (object) { - if (Function.prototype[Symbol.hasInstance].call(this, object)) return true; - if (this !== Writable) return false; - return object?._writableState instanceof WritableState; - }, -}); + value: function (object) { + if (Function.prototype[Symbol.hasInstance].call(this, object)) return true; + if (this !== Writable) return false; + return object?._writableState instanceof WritableState; + } +}) // Otherwise people can pipe Writable streams, which is just wrong. Writable.prototype.pipe = function (_1, _2) { - errorOrDestroy(this, new ERR_STREAM_CANNOT_PIPE()); -}; + errorOrDestroy(this, new ERR_STREAM_CANNOT_PIPE()); +} function _write(stream, chunk, encoding, cb) { - const state = stream._writableState; - if (typeof encoding === "function") { - cb = encoding; - encoding = state.defaultEncoding; - } else { - if (!encoding) encoding = state.defaultEncoding; - else if (encoding !== "buffer" && !Buffer.isEncoding(encoding)) { - throw new ERR_UNKNOWN_ENCODING(encoding); - } - if (typeof cb !== "function") cb = nop; + const state = stream._writableState; + if (typeof encoding === 'function') { + cb = encoding; + encoding = state.defaultEncoding; + } else { + if (!encoding) encoding = state.defaultEncoding; + else if (encoding !== 'buffer' && !Buffer.isEncoding(encoding)) { + throw new ERR_UNKNOWN_ENCODING(encoding); } - if (chunk === null) { - throw new ERR_STREAM_NULL_VALUES(); - } else if (!state.objectMode) { - if (typeof chunk === "string") { - if (state.decodeStrings !== false) { - chunk = Buffer.from(chunk, encoding); - encoding = "buffer"; - } - } else if (chunk instanceof Buffer) { - encoding = "buffer"; - } else if (Stream._isUint8Array(chunk)) { - chunk = Stream._uint8ArrayToBuffer(chunk); - encoding = "buffer"; - } else { - throw new ERR_INVALID_ARG_TYPE("chunk", ["string", "Buffer", "Uint8Array"], chunk); - } - } - let err; - if (state.ending) { - err = new ERR_STREAM_WRITE_AFTER_END(); - } else if (state.destroyed) { - err = new ERR_STREAM_DESTROYED("write"); - } - if (err) { - process.nextTick(cb, err); - errorOrDestroy(stream, err, true); - return err; + if (typeof cb !== 'function') cb = nop; + } + if (chunk === null) { + throw new ERR_STREAM_NULL_VALUES(); + } else if (!state.objectMode) { + if (typeof chunk === 'string') { + if (state.decodeStrings !== false) { + chunk = Buffer.from(chunk, encoding); + encoding = 'buffer'; + } + } else if (chunk instanceof Buffer) { + encoding = 'buffer'; + } else if (Stream._isUint8Array(chunk)) { + chunk = Stream._uint8ArrayToBuffer(chunk); + encoding = 'buffer'; + } else { + throw new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer', 'Uint8Array'], chunk); } - state.pendingcb++; - return writeOrBuffer(stream, state, chunk, encoding, cb); + } + let err; + if (state.ending) { + err = new ERR_STREAM_WRITE_AFTER_END(); + } else if (state.destroyed) { + err = new ERR_STREAM_DESTROYED('write'); + } + if (err) { + process.nextTick(cb, err); + errorOrDestroy(stream, err, true); + return err; + } + state.pendingcb++; + return writeOrBuffer(stream, state, chunk, encoding, cb); } function write(chunk, encoding, cb) { - return _write(this, chunk, encoding, cb) === true; + return _write(this, chunk, encoding, cb) === true; } Writable.prototype.write = write; Writable.prototype.cork = function () { - this._writableState.corked++; -}; + this._writableState.corked++; +} Writable.prototype.uncork = function () { - const state = this._writableState; - if (state.corked) { - state.corked--; - if (!state.writing) clearBuffer(this, state); - } -}; + const state = this._writableState; + if (state.corked) { + state.corked--; + if (!state.writing) clearBuffer(this, state); + } +} function setDefaultEncoding(encoding) { - if (typeof encoding === "string") encoding = encoding.toLowerCase(); - if (!Buffer.isEncoding(encoding)) throw new ERR_UNKNOWN_ENCODING(encoding); - this._writableState.defaultEncoding = encoding; - return this; + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!Buffer.isEncoding(encoding)) throw new ERR_UNKNOWN_ENCODING(encoding); + this._writableState.defaultEncoding = encoding; + return this; } Writable.prototype.setDefaultEncoding = setDefaultEncoding; @@ -304,513 +310,506 @@ Writable.prototype.setDefaultEncoding = setDefaultEncoding; // in the queue, and wait our turn. Otherwise, call _write // If we return false, then we need a drain event, so set that flag. function writeOrBuffer(stream, state, chunk, encoding, callback) { - const len = state.objectMode ? 1 : chunk.length; - state.length += len; - - // stream._write resets state.length - const ret = state.length < state.highWaterMark; - // We must ensure that previous needDrain will not be reset to false. - if (!ret) state.needDrain = true; - if (state.writing || state.corked || state.errored || !state.constructed) { - state.buffered.push({ - chunk, - encoding, - callback, - }); - if (state.allBuffers && encoding !== "buffer") { - state.allBuffers = false; - } - if (state.allNoop && callback !== nop) { - state.allNoop = false; - } - } else { - state.writelen = len; - state.writecb = callback; - state.writing = true; - state.sync = true; - stream._write(chunk, encoding, state.onwrite); - state.sync = false; + const len = state.objectMode ? 1 : chunk.length; + state.length += len; + + // stream._write resets state.length + const ret = state.length < state.highWaterMark; + // We must ensure that previous needDrain will not be reset to false. + if (!ret) state.needDrain = true; + if (state.writing || state.corked || state.errored || !state.constructed) { + state.buffered.push({ + chunk, + encoding, + callback, + }); + if (state.allBuffers && encoding !== 'buffer') { + state.allBuffers = false; } - - // Return false if errored or destroyed in order to break - // any synchronous while(stream.write(data)) loops. - return ret && !state.errored && !state.destroyed; -} - -function doWrite(stream, state, writev, len, chunk, encoding, cb) { + if (state.allNoop && callback !== nop) { + state.allNoop = false; + } + } else { state.writelen = len; - state.writecb = cb; + state.writecb = callback; state.writing = true; state.sync = true; - if (state.destroyed) state.onwrite(new ERR_STREAM_DESTROYED("write")); - else if (writev) stream._writev(chunk, state.onwrite); - else stream._write(chunk, encoding, state.onwrite); + stream._write(chunk, encoding, state.onwrite); state.sync = false; + } + + // Return false if errored or destroyed in order to break + // any synchronous while(stream.write(data)) loops. + return ret && !state.errored && !state.destroyed; +} + +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (state.destroyed) state.onwrite(new ERR_STREAM_DESTROYED('write')); + else if (writev) stream._writev(chunk, state.onwrite); + else stream._write(chunk, encoding, state.onwrite); + state.sync = false; } function onwriteError(stream, state, er, cb) { - --state.pendingcb; - cb(er); - // Ensure callbacks are invoked even when autoDestroy is - // not enabled. Passing `er` here doesn't make sense since - // it's related to one specific write, not to the buffered - // writes. - errorBuffer(state); - // This can emit error, but error must always follow cb. - errorOrDestroy(stream, er); + --state.pendingcb; + cb(er); + // Ensure callbacks are invoked even when autoDestroy is + // not enabled. Passing `er` here doesn't make sense since + // it's related to one specific write, not to the buffered + // writes. + errorBuffer(state); + // This can emit error, but error must always follow cb. + errorOrDestroy(stream, er); } function onwrite(stream, er) { - const state = stream._writableState; - const sync = state.sync; - const cb = state.writecb; - if (typeof cb !== "function") { - errorOrDestroy(stream, new ERR_MULTIPLE_CALLBACK()); - return; + const state = stream._writableState; + const sync = state.sync; + const cb = state.writecb; + if (typeof cb !== 'function') { + errorOrDestroy(stream, new ERR_MULTIPLE_CALLBACK()); + return; + } + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; + if (er) { + // Avoid V8 leak, https://github.com/nodejs/node/pull/34103#issuecomment-652002364 + er.stack; // eslint-disable-line no-unused-expressions + + if (!state.errored) { + state.errored = er; } - state.writing = false; - state.writecb = null; - state.length -= state.writelen; - state.writelen = 0; - if (er) { - // Avoid V8 leak, https://github.com/nodejs/node/pull/34103#issuecomment-652002364 - er.stack; // eslint-disable-line no-unused-expressions - - if (!state.errored) { - state.errored = er; - } - // In case of duplex streams we need to notify the readable side of the - // error. - if (stream._readableState && !stream._readableState.errored) { - stream._readableState.errored = er; - } - if (sync) { - process.nextTick(onwriteError, stream, state, er, cb); - } else { - onwriteError(stream, state, er, cb); - } + // In case of duplex streams we need to notify the readable side of the + // error. + if (stream._readableState && !stream._readableState.errored) { + stream._readableState.errored = er; + } + if (sync) { + process.nextTick(onwriteError, stream, state, er, cb); } else { - if (state.buffered.length > state.bufferedIndex) { - clearBuffer(stream, state); - } - if (sync) { - // It is a common case that the callback passed to .write() is always - // the same. In that case, we do not schedule a new nextTick(), but - // rather just increase a counter, to improve performance and avoid - // memory allocations. - if (state.afterWriteTickInfo !== null && state.afterWriteTickInfo.cb === cb) { - state.afterWriteTickInfo.count++; - } else { - state.afterWriteTickInfo = { - count: 1, - cb, - stream, - state, - }; - process.nextTick(afterWriteTick, state.afterWriteTickInfo); - } - } else { - afterWrite(stream, state, 1, cb); - } + onwriteError(stream, state, er, cb); + } + } else { + if (state.buffered.length > state.bufferedIndex) { + clearBuffer(stream, state); + } + if (sync) { + // It is a common case that the callback passed to .write() is always + // the same. In that case, we do not schedule a new nextTick(), but + // rather just increase a counter, to improve performance and avoid + // memory allocations. + if (state.afterWriteTickInfo !== null && state.afterWriteTickInfo.cb === cb) { + state.afterWriteTickInfo.count++; + } else { + state.afterWriteTickInfo = { + count: 1, + cb, + stream, + state + }; + process.nextTick(afterWriteTick, state.afterWriteTickInfo); + } + } else { + afterWrite(stream, state, 1, cb); } + } } function afterWriteTick({ stream, state, count, cb }) { - state.afterWriteTickInfo = null; - return afterWrite(stream, state, count, cb); + state.afterWriteTickInfo = null; + return afterWrite(stream, state, count, cb); } function afterWrite(stream, state, count, cb) { - const needDrain = !state.ending && !stream.destroyed && state.length === 0 && state.needDrain; - if (needDrain) { - state.needDrain = false; - stream.emit("drain"); - } - while (count-- > 0) { - state.pendingcb--; - cb(); - } - if (state.destroyed) { - errorBuffer(state); - } - finishMaybe(stream, state); + const needDrain = !state.ending && !stream.destroyed && state.length === 0 && state.needDrain; + if (needDrain) { + state.needDrain = false; + stream.emit('drain'); + } + while (count-- > 0) { + state.pendingcb--; + cb(); + } + if (state.destroyed) { + errorBuffer(state); + } + finishMaybe(stream, state); } // If there's something in the buffer waiting, then invoke callbacks. function errorBuffer(state) { - if (state.writing) { - return; - } - for (let n = state.bufferedIndex; n < state.buffered.length; ++n) { - let _state$errored; - const { chunk, callback } = state.buffered[n]; - const len = state.objectMode ? 1 : chunk.length; - state.length -= len; - callback( - (_state$errored = state.errored) !== null && _state$errored !== undefined - ? _state$errored - : new ERR_STREAM_DESTROYED("write") - ); - } - const onfinishCallbacks = state[kOnFinished].splice(0); - for (let i = 0; i < onfinishCallbacks.length; i++) { - let _state$errored2; - onfinishCallbacks[i]( - (_state$errored2 = state.errored) !== null && _state$errored2 !== undefined - ? _state$errored2 - : new ERR_STREAM_DESTROYED("end") - ); - } - resetBuffer(state); + if (state.writing) { + return; + } + for (let n = state.bufferedIndex; n < state.buffered.length; ++n) { + let _state$errored; + const { chunk, callback } = state.buffered[n]; + const len = state.objectMode ? 1 : chunk.length; + state.length -= len; + callback( + (_state$errored = state.errored) !== null && _state$errored !== undefined + ? _state$errored + : new ERR_STREAM_DESTROYED('write')); + } + const onfinishCallbacks = state[kOnFinished].splice(0); + for (let i = 0; i < onfinishCallbacks.length; i++) { + let _state$errored2; + onfinishCallbacks[i]( + (_state$errored2 = state.errored) !== null && _state$errored2 !== undefined + ? _state$errored2 + : new ERR_STREAM_DESTROYED('end')); + } + resetBuffer(state); } // If there's something in the buffer waiting, then process it. function clearBuffer(stream, state) { - if (state.corked || state.bufferProcessing || state.destroyed || !state.constructed) { - return; - } - const { buffered, bufferedIndex, objectMode } = state; - const bufferedLength = buffered.length - bufferedIndex; - if (!bufferedLength) { - return; - } - let i = bufferedIndex; - state.bufferProcessing = true; - if (bufferedLength > 1 && stream._writev) { - state.pendingcb -= bufferedLength - 1; - const callback = state.allNoop - ? nop - : (err) => { - for (let n = i; n < buffered.length; ++n) { - buffered[n].callback(err); - } - }; - // Make a copy of `buffered` if it's going to be used by `callback` above, - // since `doWrite` will mutate the array. - const chunks = state.allNoop && i === 0 ? buffered : buffered.slice(i); - chunks.allBuffers = state.allBuffers; - doWrite(stream, state, true, state.length, chunks, "", callback); - resetBuffer(state); + if (state.corked || state.bufferProcessing || state.destroyed || !state.constructed) { + return; + } + const { buffered, bufferedIndex, objectMode } = state; + const bufferedLength = buffered.length - bufferedIndex; + if (!bufferedLength) { + return; + } + let i = bufferedIndex; + state.bufferProcessing = true; + if (bufferedLength > 1 && stream._writev) { + state.pendingcb -= bufferedLength - 1; + const callback = state.allNoop + ? nop + : (err) => { + for (let n = i; n < buffered.length; ++n) { + buffered[n].callback(err) + } + }; + // Make a copy of `buffered` if it's going to be used by `callback` above, + // since `doWrite` will mutate the array. + const chunks = state.allNoop && i === 0 ? buffered : buffered.slice(i); + chunks.allBuffers = state.allBuffers; + doWrite(stream, state, true, state.length, chunks, '', callback); + resetBuffer(state); + } else { + do { + const { chunk, encoding, callback } = buffered[i]; + buffered[i++] = null; + const len = objectMode ? 1 : chunk.length; + doWrite(stream, state, false, len, chunk, encoding, callback); + } while (i < buffered.length && !state.writing) + if (i === buffered.length) { + resetBuffer(state); + } else if (i > 256) { + buffered.splice(0, i); + state.bufferedIndex = 0; } else { - do { - const { chunk, encoding, callback } = buffered[i]; - buffered[i++] = null; - const len = objectMode ? 1 : chunk.length; - doWrite(stream, state, false, len, chunk, encoding, callback); - } while (i < buffered.length && !state.writing); - if (i === buffered.length) { - resetBuffer(state); - } else if (i > 256) { - buffered.splice(0, i); - state.bufferedIndex = 0; - } else { - state.bufferedIndex = i; - } + state.bufferedIndex = i; } - state.bufferProcessing = false; + } + state.bufferProcessing = false; } Writable.prototype._write = function (chunk, encoding, cb) { - if (this._writev) { - this._writev( - [ - { - chunk, - encoding, - }, - ], - cb - ); - } else { - throw new ERR_METHOD_NOT_IMPLEMENTED("_write()"); - } -}; + if (this._writev) { + this._writev( + [ + { + chunk, + encoding + } + ], + cb, + ); + } else { + throw new ERR_METHOD_NOT_IMPLEMENTED('_write()'); + } +} Writable.prototype._writev = null; function end(chunk, encoding, cb) { - const state = this._writableState; - if (typeof chunk === "function") { - cb = chunk; - chunk = null; - encoding = null; - } else if (typeof encoding === "function") { - cb = encoding; - encoding = null; + const state = this._writableState; + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + let err; + if (chunk !== null && chunk !== undefined) { + const ret = _write(this, chunk, encoding); + if (ret instanceof Error) { + err = ret; } - let err; - if (chunk !== null && chunk !== undefined) { - const ret = _write(this, chunk, encoding); - if (ret instanceof Error) { - err = ret; - } - } - - // .end() fully uncorks. - if (state.corked) { - state.corked = 1; - this.uncork(); - } - if (err) { - // Do nothing... - } else if (!state.errored && !state.ending) { - // This is forgiving in terms of unnecessary calls to end() and can hide - // logic errors. However, usually such errors are harmless and causing a - // hard error can be disproportionately destructive. It is not always - // trivial for the user to determine whether end() needs to be called - // or not. - - state.ending = true; - finishMaybe(this, state, true); - state.ended = true; - } else if (state.finished) { - err = new ERR_STREAM_ALREADY_FINISHED("end"); - } else if (state.destroyed) { - err = new ERR_STREAM_DESTROYED("end"); - } - if (typeof cb === "function") { - if (err || state.finished) { - process.nextTick(cb, err); - } else { - state[kOnFinished].push(cb); - } + } + + // .end() fully uncorks. + if (state.corked) { + state.corked = 1; + this.uncork(); + } + if (err) { + // Do nothing... + } else if (!state.errored && !state.ending) { + // This is forgiving in terms of unnecessary calls to end() and can hide + // logic errors. However, usually such errors are harmless and causing a + // hard error can be disproportionately destructive. It is not always + // trivial for the user to determine whether end() needs to be called + // or not. + + state.ending = true; + finishMaybe(this, state, true); + state.ended = true; + } else if (state.finished) { + err = new ERR_STREAM_ALREADY_FINISHED('end'); + } else if (state.destroyed) { + err = new ERR_STREAM_DESTROYED('end'); + } + if (typeof cb === 'function') { + if (err || state.finished) { + process.nextTick(cb, err); + } else { + state[kOnFinished].push(cb); } - return this; + } + return this; } Writable.prototype.end = end; function needFinish(state) { - return ( - state.ending && - !state.destroyed && - state.constructed && - state.length === 0 && - !state.errored && - state.buffered.length === 0 && - !state.finished && - !state.writing && - !state.errorEmitted && - !state.closeEmitted - ); + return ( + state.ending && + !state.destroyed && + state.constructed && + state.length === 0 && + !state.errored && + state.buffered.length === 0 && + !state.finished && + !state.writing && + !state.errorEmitted && + !state.closeEmitted + ); } function callFinal(stream, state) { - let called = false; - function onFinish(err) { - if (called) { - errorOrDestroy(stream, err || new ERR_MULTIPLE_CALLBACK()); - return; - } - called = true; - state.pendingcb--; - if (err) { - const onfinishCallbacks = state[kOnFinished].splice(0); - for (let i = 0; i < onfinishCallbacks.length; i++) { - onfinishCallbacks[i](err); - } - errorOrDestroy(stream, err, state.sync); - } else if (needFinish(state)) { - state.prefinished = true; - stream.emit("prefinish"); - // Backwards compat. Don't check state.sync here. - // Some streams assume 'finish' will be emitted - // asynchronously relative to _final callback. - state.pendingcb++; - process.nextTick(finish, stream, state); - } + let called = false; + function onFinish(err) { + if (called) { + errorOrDestroy(stream, err || new ERR_MULTIPLE_CALLBACK()); + return; } - state.sync = true; - state.pendingcb++; - try { - stream._final(onFinish); - } catch (err) { - onFinish(err); + called = true; + state.pendingcb--; + if (err) { + const onfinishCallbacks = state[kOnFinished].splice(0); + for (let i = 0; i < onfinishCallbacks.length; i++) { + onfinishCallbacks[i](err); + } + errorOrDestroy(stream, err, state.sync); + } else if (needFinish(state)) { + state.prefinished = true; + stream.emit('prefinish'); + // Backwards compat. Don't check state.sync here. + // Some streams assume 'finish' will be emitted + // asynchronously relative to _final callback. + state.pendingcb++; + process.nextTick(finish, stream, state); } - state.sync = false; + } + state.sync = true; + state.pendingcb++; + try { + stream._final(onFinish); + } catch (err) { + onFinish(err); + } + state.sync = false; } function prefinish(stream, state) { - if (!state.prefinished && !state.finalCalled) { - if (typeof stream._final === "function" && !state.destroyed) { - state.finalCalled = true; - callFinal(stream, state); - } else { - state.prefinished = true; - stream.emit("prefinish"); - } + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function' && !state.destroyed) { + state.finalCalled = true; + callFinal(stream, state); + } else { + state.prefinished = true; + stream.emit('prefinish'); } + } } function finishMaybe(stream, state, sync = false) { - if (needFinish(state)) { - prefinish(stream, state); - if (state.pendingcb === 0) { - if (sync) { - state.pendingcb++; - process.nextTick(() => { - ((stream, state) => { - if (needFinish(state)) { - finish(stream, state); - } else { - state.pendingcb--; - } - })(stream, state); - }); - } else if (needFinish(state)) { - state.pendingcb++; - finish(stream, state); + if (needFinish(state)) { + prefinish(stream, state); + if (state.pendingcb === 0) { + if (sync) { + state.pendingcb++; + process.nextTick(() => { + ((stream, state) => { + if (needFinish(state)) { + finish(stream, state); + } else { + state.pendingcb--; } - } + })(stream, state); + }); + } else if (needFinish(state)) { + state.pendingcb++; + finish(stream, state); + } } + } } function finish(stream, state) { - state.pendingcb--; - state.finished = true; - const onfinishCallbacks = state[kOnFinished].splice(0); - for (let i = 0; i < onfinishCallbacks.length; i++) { - onfinishCallbacks[i](); - } - stream.emit("finish"); - if (state.autoDestroy) { - // In case of duplex streams we need a way to detect - // if the readable side is ready for autoDestroy as well. - const rState = stream._readableState; - const autoDestroy = - !rState || - (rState.autoDestroy && - // We don't expect the readable to ever 'end' - // if readable is explicitly set to false. - (rState.endEmitted || rState.readable === false)); - if (autoDestroy) { - stream.destroy(); - } + state.pendingcb--; + state.finished = true; + const onfinishCallbacks = state[kOnFinished].splice(0); + for (let i = 0; i < onfinishCallbacks.length; i++) { + onfinishCallbacks[i](); + } + stream.emit('finish'); + if (state.autoDestroy) { + // In case of duplex streams we need a way to detect + // if the readable side is ready for autoDestroy as well. + const rState = stream._readableState; + const autoDestroy = + !rState || + (rState.autoDestroy && + // We don't expect the readable to ever 'end' + // if readable is explicitly set to false. + (rState.endEmitted || rState.readable === false)); + if (autoDestroy) { + stream.destroy(); } + } } Object.defineProperties(Writable.prototype, { - closed: { - get() { - return !!this._writableState?.closed; - }, - }, - destroyed: { - get() { - return !!this._writableState?.destroyed; - }, - set(value) { - // Backward compatibility, the user is explicitly managing destroyed. - if (this._writableState) { - this._writableState.destroyed = value; - } - }, - }, - errored: { - enumerable: false, - get() { - return this._writableState?.errored || null; - }, - }, - writable: { - get() { - const w = this._writableState; - // w.writable === false means that this is part of a Duplex stream - // where the writable side was disabled upon construction. - // Compat. The user might manually disable writable side through - // deprecated setter. - return ( - !!w && w.writable !== false && !w.destroyed && !w.errored && !w.ending && !w.ended - ); - }, - set(val) { - // Backwards compatible. - if (this._writableState) { - this._writableState.writable = !!val; - } - }, - }, - writableFinished: { - get() { - return !!this._writableState?.finished; - }, - }, - writableObjectMode: { - get() { - return !!this._writableState?.objectMode; - }, - }, - writableBuffer: { - get() { - return this._writableState?.getBuffer(); - }, - }, - writableEnded: { - get() { - return !!this._writableState?.ending; - }, - }, - writableNeedDrain: { - get() { - const wState = this._writableState; - if (!wState) return false; - return !wState.destroyed && !wState.ending && wState.needDrain; - }, - }, - writableHighWaterMark: { - get() { - return this._writableState?.highWaterMark; - }, - }, - writableCorked: { - get() { - return this._writableState?.corked | 0; - }, - }, - writableLength: { - get() { - return this._writableState?.length; - }, + closed: { + get() { + return !!(this._writableState?.closed); + } + }, + destroyed: { + get() { + return !!(this._writableState?.destroyed); }, - writableAborted: { - enumerable: false, - get() { - return !!( - this._writableState.writable !== false && - (this._writableState.destroyed || this._writableState.errored) && - !this._writableState.finished - ); - }, + set(value) { + // Backward compatibility, the user is explicitly managing destroyed. + if (this._writableState) { + this._writableState.destroyed = value + } + } + }, + errored: { + enumerable: false, + get() { + return this._writableState?.errored || null; + } + }, + writable: { + get() { + const w = this._writableState + // w.writable === false means that this is part of a Duplex stream + // where the writable side was disabled upon construction. + // Compat. The user might manually disable writable side through + // deprecated setter. + return !!w && w.writable !== false && !w.destroyed && !w.errored && !w.ending && !w.ended; }, + set(val) { + // Backwards compatible. + if (this._writableState) { + this._writableState.writable = !!val; + } + } + }, + writableFinished: { + get() { + return !!(this._writableState?.finished); + } + }, + writableObjectMode: { + get() { + return !!(this._writableState?.objectMode); + } + }, + writableBuffer: { + get() { + return this._writableState?.getBuffer(); + } + }, + writableEnded: { + get() { + return !!(this._writableState?.ending); + } + }, + writableNeedDrain: { + get() { + const wState = this._writableState; + if (!wState) return false; + return !wState.destroyed && !wState.ending && wState.needDrain; + } + }, + writableHighWaterMark: { + get() { + return this._writableState?.highWaterMark; + } + }, + writableCorked: { + get() { + return this._writableState?.corked | 0; + } + }, + writableLength: { + get() { + return this._writableState?.length; + } + }, + writableAborted: { + enumerable: false, + get() { + return !!( + this._writableState.writable !== false && + (this._writableState.destroyed || this._writableState.errored) && + !this._writableState.finished + ) + } + } }); Writable.prototype.destroy = function (err, cb) { - const state = this._writableState; - - // Invoke pending callbacks. - if ( - !state.destroyed && - (state.bufferedIndex < state.buffered.length || state[kOnFinished].length) - ) { - process.nextTick(errorBuffer, state); - } - destroy.call(this, err, cb); - return this; -}; + const state = this._writableState; + + // Invoke pending callbacks. + if (!state.destroyed && (state.bufferedIndex < state.buffered.length || state[kOnFinished].length)) { + process.nextTick(errorBuffer, state); + } + destroy.call(this, err, cb); + return this; +} -Writable.prototype._undestroy = undestroy; +Writable.prototype._undestroy = undestroy Writable.prototype._destroy = function (err, cb) { - if (cb) cb(err); -}; + if (cb) cb(err); +} Writable.prototype[EventEmitter.captureRejectionSymbol] = function (err) { - this.destroy(err); -}; + this.destroy(err); +} Writable.fromWeb = function (writableStream, options) { - return newStreamWritableFromWritableStream(writableStream, options); -}; + return newStreamWritableFromWritableStream(writableStream, options) +} Writable.toWeb = function (streamWritable) { - return newWritableStreamFromStreamWritable(streamWritable); -}; + return newWritableStreamFromStreamWritable(streamWritable) +} diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/util.d.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/util.d.ts index d97761026..400179abc 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/util.d.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/util.d.ts @@ -11,7 +11,7 @@ export abstract class MIMEType { export abstract class MIMEParams { public constructor(); public delete(name: string): void; - public get(name: string): string | undefined; + public get(name: string): string|undefined; public has(name: string): boolean; public set(name: string, value: string): void; public entries(): Iterable; @@ -23,10 +23,7 @@ export const kResourceTypeInspect: unique symbol; export const ALL_PROPERTIES: 0; export const ONLY_ENUMERABLE: 1; -export function getOwnNonIndexProperties( - value: unknown, - filter: typeof ALL_PROPERTIES | typeof ONLY_ENUMERABLE -): PropertyKey[]; +export function getOwnNonIndexProperties(value: unknown, filter: typeof ALL_PROPERTIES | typeof ONLY_ENUMERABLE): PropertyKey[]; export const kPending: 0; export const kFulfilled: 1; @@ -102,6 +99,4 @@ export function isUint32Array(value: unknown): value is Uint32Array; export function isWeakMap(value: unknown): value is WeakMap; export function isWeakSet(value: unknown): value is WeakSet; export function isAnyArrayBuffer(value: unknown): value is ArrayBuffer | SharedArrayBuffer; -export function isBoxedPrimitive( - value: unknown -): value is Number | String | Boolean | BigInt | Symbol; +export function isBoxedPrimitive(value: unknown): value is Number | String | Boolean | BigInt | Symbol; diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/util.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/util.ts index 13f506b0b..2821fd065 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/util.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/util.ts @@ -1,15 +1,7 @@ -import { - ALL_PROPERTIES as A_PROPERTIES, - ONLY_CONFIGURABLE, - ONLY_ENUMERABLE as O_ENUMERABLE, - ONLY_WRITABLE, - SKIP_STRINGS, - SKIP_SYMBOLS, - isArrayIndex, -} from "./internal_utils"; +import { ALL_PROPERTIES as A_PROPERTIES, ONLY_CONFIGURABLE, ONLY_ENUMERABLE as O_ENUMERABLE, ONLY_WRITABLE, SKIP_STRINGS, SKIP_SYMBOLS, isArrayIndex } from "./internal_utils"; export const kPending = 0; -export const kFulfilled = 1; +export const kFulfilled= 1; export const kRejected = 2; export const kResourceTypeInspect: unique symbol = Symbol.for("nodejs.util.inspect.custom"); @@ -44,9 +36,12 @@ export interface ProxyDetails { export function getOwnNonIndexProperties( // deno-lint-ignore ban-types obj: object, - filter: number + filter: number, ): (string | symbol)[] { - let allProperties = [...Object.getOwnPropertyNames(obj), ...Object.getOwnPropertySymbols(obj)]; + let allProperties = [ + ...Object.getOwnPropertyNames(obj), + ...Object.getOwnPropertySymbols(obj), + ]; if (Array.isArray(obj)) { allProperties = allProperties.filter((k) => !isArrayIndex(k)); @@ -238,18 +233,17 @@ export function isAnyArrayBuffer(value: unknown): value is ArrayBuffer | SharedA return false; } -export function isBoxedPrimitive( - value: unknown -): value is Number | String | Boolean | BigInt | Symbol { +export function isBoxedPrimitive(value: unknown): value is Number | String | Boolean | BigInt | Symbol { return false; } + export function getPromiseDetails(value: unknown): PromiseDetails | undefined { - return undefined; + return undefined } export function getProxyDetails(value: unknown): ProxyDetails | undefined { - return undefined; + return undefined } export function previewEntries(value: unknown): PreviewedEntries | undefined { @@ -259,3 +253,4 @@ export function previewEntries(value: unknown): PreviewedEntries | undefined { export function getConstructorName(value: unknown): string { return ""; } + diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/internal/validators.ts b/JS/wasm/crates/wasmjs-engine/shims/src/internal/validators.ts index f34d63533..58985a377 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/internal/validators.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/internal/validators.ts @@ -1,24 +1,31 @@ import { isArrayBufferView } from "./internal_types"; import { normalizeEncoding } from "./internal_utils"; -import { ERR_INVALID_ARG_TYPE, ERR_INVALID_ARG_VALUE, ERR_OUT_OF_RANGE } from "./internal_errors"; +import { + ERR_INVALID_ARG_TYPE, + ERR_INVALID_ARG_VALUE, + ERR_OUT_OF_RANGE, +} from "./internal_errors"; // TODO(someday): Not current implementing parseFileMode, validatePort export const isInt32 = (value: any) => value === (value | 0); -export const isUint32 = (value: any) => value === value >>> 0; +export const isUint32 = (value: any) => value === (value >>> 0); export function validateBuffer(buffer: unknown, name = "buffer") { if (!isArrayBufferView(buffer)) { - throw new ERR_INVALID_ARG_TYPE(name, ["Buffer", "TypedArray", "DataView"], buffer); + throw new ERR_INVALID_ARG_TYPE( + name, + ["Buffer", "TypedArray", "DataView"], + buffer, + ); } -} +}; export function validateInteger( value: unknown, name: string, min = Number.MIN_SAFE_INTEGER, - max = Number.MAX_SAFE_INTEGER -) { + max = Number.MAX_SAFE_INTEGER) { if (typeof value !== "number") { throw new ERR_INVALID_ARG_TYPE(name, "number", value); } @@ -34,7 +41,7 @@ export interface ValidateObjectOptions { allowArray?: boolean; allowFunction?: boolean; nullable?: boolean; -} +}; export function validateObject(value: unknown, name: string, options?: ValidateObjectOptions) { const useDefaultOptions = options == null; @@ -44,11 +51,13 @@ export function validateObject(value: unknown, name: string, options?: ValidateO if ( (!nullable && value === null) || (!allowArray && Array.isArray(value)) || - (typeof value !== "object" && (!allowFunction || typeof value !== "function")) + (typeof value !== "object" && ( + !allowFunction || typeof value !== "function" + )) ) { throw new ERR_INVALID_ARG_TYPE(name, "Object", value); } -} +}; export function validateInt32(value: any, name: string, min = -2147483648, max = 2147483647) { if (!isInt32(value)) { @@ -78,7 +87,11 @@ export function validateUint32(value: unknown, name: string, positive?: boolean) } const min = positive ? 1 : 0; // 2 ** 32 === 4294967296 - throw new ERR_OUT_OF_RANGE(name, `>= ${min} && < 4294967296`, value); + throw new ERR_OUT_OF_RANGE( + name, + `>= ${min} && < 4294967296`, + value, + ); } if (positive && value === 0) { throw new ERR_OUT_OF_RANGE(name, ">= 1 && < 4294967296", value); @@ -106,8 +119,11 @@ export function validateBoolean(value: unknown, name: string) { export function validateOneOf(value: unknown, name: string, oneOf: any[]) { if (!Array.prototype.includes.call(oneOf, value)) { const allowed = Array.prototype.join.call( - Array.prototype.map.call(oneOf, (v) => (typeof v === "string" ? `'${v}'` : String(v))), - ", " + Array.prototype.map.call( + oneOf, + (v) => (typeof v === "string" ? `'${v}'` : String(v)), + ), + ", ", ); const reason = "must be one of: " + allowed; @@ -123,7 +139,7 @@ export function validateEncoding(data: unknown, encoding: string): void { throw new ERR_INVALID_ARG_VALUE( "encoding", encoding, - `is invalid for data of length ${length}` + `is invalid for data of length ${length}`, ); } } @@ -131,11 +147,13 @@ export function validateEncoding(data: unknown, encoding: string): void { export function validateAbortSignal(signal: unknown, name: string) { if ( signal !== undefined && - (signal === null || typeof signal !== "object" || !("aborted" in signal)) + (signal === null || + typeof signal !== "object" || + !("aborted" in signal)) ) { throw new ERR_INVALID_ARG_TYPE(name, "AbortSignal", signal); } -} +}; export function validateFunction(value: unknown, name: string) { if (typeof value !== "function") { @@ -168,4 +186,4 @@ export default { validateOneOf, validateString, validateUint32, -}; +}; \ No newline at end of file diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/path.js b/JS/wasm/crates/wasmjs-engine/shims/src/path.js index f5f64f2c4..08cce9319 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/path.js +++ b/JS/wasm/crates/wasmjs-engine/shims/src/path.js @@ -1,4 +1,7 @@ -import { posix, win32 } from "./internal/internal_path"; +import { + posix, + win32, +} from './internal/internal_path'; const { resolve, @@ -34,8 +37,8 @@ export { win32, }; -export { default } from "./internal/internal_path"; -import process from "./internal/process"; +export { default } from './internal/internal_path' +import process from './internal/process'; globalThis.process = process; @@ -55,4 +58,4 @@ globalThis.path = { delimiter, posix, win32, -}; +} diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/path/posix.ts b/JS/wasm/crates/wasmjs-engine/shims/src/path/posix.ts index 7a16fe830..03168d917 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/path/posix.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/path/posix.ts @@ -1,3 +1,3 @@ -import { posix } from "../internal/internal_path"; +import { posix } from '../internal/internal_path'; export default posix; diff --git a/JS/wasm/crates/wasmjs-engine/shims/src/path/win32.ts b/JS/wasm/crates/wasmjs-engine/shims/src/path/win32.ts index f67ec9e71..440107305 100644 --- a/JS/wasm/crates/wasmjs-engine/shims/src/path/win32.ts +++ b/JS/wasm/crates/wasmjs-engine/shims/src/path/win32.ts @@ -1,3 +1,3 @@ -import { win32 } from "../internal/internal_path"; +import { win32 } from '../internal/internal_path'; export default win32; diff --git a/JS/wasm/crates/wasmjs-engine/src/main.rs b/JS/wasm/crates/wasmjs-engine/src/main.rs index afa620a1b..6ccb308f0 100644 --- a/JS/wasm/crates/wasmjs-engine/src/main.rs +++ b/JS/wasm/crates/wasmjs-engine/src/main.rs @@ -131,15 +131,71 @@ pub fn load_bindings(context: &JSContextRef, global: JSValueRef) -> Result<(), R invalid_export: "console_log".to_string(), })?; + global + .set_property( + "readBytes", + context + .wrap_callback(|_ctx, _this_arg, args| { + let path = args[0].to_string(); + match read_bytes(path.as_str()) { + Ok(result) => Ok(JSValue::String(result)), + Err(err) => { + let kind = match err { + FileError::NotFound => "File not found".to_string(), + FileError::InvalidPath => "Not allowed".to_string(), + }; + + Ok(JSValue::from_hashmap(HashMap::from([ + ("error", JSValue::Bool(true)), + ("type", JSValue::String(kind)), + ]))) + } + } + }) + .map_err(|_| RuntimeError::InvalidBinding { + invalid_export: "readBytes".to_string(), + })?, + ) + .map_err(|_| RuntimeError::InvalidBinding { + invalid_export: "readBytes".to_string(), + })?; + + global + .set_property( + "parseJsonnet", + context + .wrap_callback(|_ctx, _this_arg, args| { + let path = args[0].to_string(); + match parse_jsonnet(path.as_str()) { + Ok(result) => Ok(JSValue::String(result)), + Err(err) => { + let kind = match err { + FileError::NotFound => "File not found".to_string(), + FileError::InvalidPath => "Not allowed".to_string(), + }; + + Ok(JSValue::from_hashmap(HashMap::from([ + ("error", JSValue::Bool(true)), + ("type", JSValue::String(kind)), + ]))) + } + } + }) + .map_err(|_| RuntimeError::InvalidBinding { + invalid_export: "parseJsonnet".to_string(), + })?, + ) + .map_err(|_| RuntimeError::InvalidBinding { + invalid_export: "parseJsonnet".to_string(), + })?; Ok(()) } static POLYFILL: &str = include_str!("../shims/dist/index.js"); static POLYFILL_BUFFER: &str = include_str!("../shims/dist/buffer.js"); - static POLYFILL_PATH: &str = include_str!("../shims/dist/path.js"); - static POLYFILL_CRYPTO: &str = include_str!("../shims/dist/crypto.js"); +static ARAKOOJSONNET: &str = include_str!("../shims/dist/arakoo-jsonnet.js"); fn main() { let runtime = Runtime::default(); @@ -171,16 +227,19 @@ fn main() { let global = context.global_object().unwrap(); match load_bindings(context, global) { Ok(_) => {} - Err(e) => match e { - RuntimeError::InvalidBinding { invalid_export } => { - eprintln!("There was an error adding the '{invalid_export}' binding"); + Err(e) => { + match e { + RuntimeError::InvalidBinding { invalid_export } => { + eprintln!("There was an error adding the '{invalid_export}' binding"); + } } - }, + } } context.eval_module("buffer", &buffer).unwrap(); context.eval_module("crypto", &crypto).unwrap(); - + context.eval_module("arakoo-jsonnet", &ARAKOOJSONNET).unwrap(); + match context.eval_module("path", &path) { Ok(_) => {} Err(err) => eprintln!("Error loading the path shim: {err}"), diff --git a/JS/wasm/crates/wasmjs-engine/taskfile.yml b/JS/wasm/crates/wasmjs-engine/taskfile.yml index 26ac78188..69d28cf08 100644 --- a/JS/wasm/crates/wasmjs-engine/taskfile.yml +++ b/JS/wasm/crates/wasmjs-engine/taskfile.yml @@ -1,23 +1,23 @@ version: "3" tasks: - add:wasm32-wasi:target: rustup target add wasm32-wasi - build: - deps: - - add:wasm32-wasi:target - - build-shims - cmds: - - cargo build --target wasm32-wasi --release - - cp ./target/wasm32-wasi/release/wasmjs-engine.wasm ./ - build-shims: - deps: - - shims-install - dir: shims - cmds: - - echo pwd - - npm run build - shims-install: - dir: shims - cmds: - - pwd - - npm install + add:wasm32-wasi:target: rustup target add wasm32-wasi + build: + deps: + - add:wasm32-wasi:target + - build-shims + cmds: + - cargo build --target wasm32-wasi --release + - cp ./target/wasm32-wasi/release/wasmjs-engine.wasm ./ + build-shims: + deps: + - shims-install + dir: shims + cmds: + - echo pwd + - npm run build + shims-install: + dir: shims + cmds: + - pwd + - npm install \ No newline at end of file diff --git a/JS/wasm/crates/wasmjs-engine/wasmjs-engine.wasm b/JS/wasm/crates/wasmjs-engine/wasmjs-engine.wasm index 49b685141..a6796d523 100755 Binary files a/JS/wasm/crates/wasmjs-engine/wasmjs-engine.wasm and b/JS/wasm/crates/wasmjs-engine/wasmjs-engine.wasm differ diff --git a/JS/wasm/crates/wasmjs-runtime/Cargo.lock b/JS/wasm/crates/wasmjs-runtime/Cargo.lock index 9477b9411..2beed09ee 100644 --- a/JS/wasm/crates/wasmjs-runtime/Cargo.lock +++ b/JS/wasm/crates/wasmjs-runtime/Cargo.lock @@ -1418,6 +1418,26 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonnet-rs" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b396bdfc3ae94965555c9ec3efa2214e5f3921545a943ef9fc9873ff5e4723" +dependencies = [ + "jsonnet-sys", + "libc", +] + +[[package]] +name = "jsonnet-sys" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02347cbdf34234f30f0d92f0f8f678a15883bd5e1e4b3def4ed4a14f691d9add" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "language-tags" version = "0.3.2" @@ -2766,6 +2786,7 @@ dependencies = [ "blake3", "clap", "http", + "jsonnet-rs", "lazy_static", "regex", "reqwest", diff --git a/JS/wasm/crates/wasmjs-runtime/Cargo.toml b/JS/wasm/crates/wasmjs-runtime/Cargo.toml index a675c8278..3f6e47f8d 100644 --- a/JS/wasm/crates/wasmjs-runtime/Cargo.toml +++ b/JS/wasm/crates/wasmjs-runtime/Cargo.toml @@ -33,3 +33,4 @@ wiggle = "15.0.0" thiserror = "1.0" tracing = "0.1.40" semver = "^0.10.0" +jsonnet-rs = "0.17.0" diff --git a/JS/wasm/crates/wasmjs-runtime/src/bindings.rs b/JS/wasm/crates/wasmjs-runtime/src/bindings.rs index 3d748c6eb..591fcbd0c 100644 --- a/JS/wasm/crates/wasmjs-runtime/src/bindings.rs +++ b/JS/wasm/crates/wasmjs-runtime/src/bindings.rs @@ -1,4 +1,5 @@ use actix_web::http::Uri; +use jsonnet::JsonnetVm; use reqwest::Method; use serde::Deserialize; use tokio::runtime::Builder; @@ -21,7 +22,7 @@ impl GuestErrorType for ArakooStatus { } } -use self::{http::{Http, HttpRequest, HttpRequestError, HttpResponse, HttpError, HttpMethod}, types::ArakooStatus}; +use self::{http::{Http, HttpRequest, HttpRequestError, HttpResponse, HttpError, HttpMethod, FileError}, types::ArakooStatus}; #[derive(Deserialize, Clone)] #[serde(default)] @@ -51,7 +52,7 @@ pub struct HttpBindings { pub http_config: HttpRequestsConfig, } -impl From for reqwest::Method { +impl From for Method { fn from(value: HttpMethod) -> Self { match value { HttpMethod::Get => Method::GET, @@ -191,4 +192,72 @@ impl Http for HttpBindings { }), } } + + fn read_bytes(&mut self, path: &str) -> Result { + // read the file from the path and return the bytes + // if the file does not exist, return FileError::NotFound + let path = path.to_owned(); + let thread_result = std::thread::spawn(move || { + Builder::new_current_thread() + .enable_all() + .build() + .unwrap() + .block_on(async { + let bytes = tokio::fs::read(path).await; + match bytes { + Ok(bytes) => + Ok(std::str::from_utf8(&bytes).unwrap().to_string()), + Err(_) => { + Err(FileError::NotFound) + } + } + }) + }) + .join(); + + match thread_result { + Ok(res) => match res { + Ok(res) => Ok(res), + Err(err) => Err(err), + }, + Err(_) => Err(FileError::NotFound), + } + } + + + fn parse_jsonnet(&mut self, file: &str) -> Result { + parse_jsonnet(file) + } +} + + +pub fn parse_jsonnet(file: &str) -> Result { + let file = file.to_owned(); + let thread_result = std::thread::spawn(move || { + Builder::new_current_thread() + .enable_all() + .build() + .unwrap() + .block_on(async { + let mut vm = JsonnetVm::new(); + let json = vm.evaluate_file(&file); + + match json { + Ok(json) => Ok(json.to_string()), + Err(e) => { + println!("Error: {}", e); + Err(FileError::NotFound) + }, + } + }) + }) + .join(); + + match thread_result { + Ok(res) => match res { + Ok(res) => Ok(res), + Err(err) => Err(err), + }, + Err(_) => Err(FileError::NotFound), + } } diff --git a/JS/wasm/crates/wasmjs-runtime/src/handlers.rs b/JS/wasm/crates/wasmjs-runtime/src/handlers.rs index ec7a7416b..e70c556e3 100644 --- a/JS/wasm/crates/wasmjs-runtime/src/handlers.rs +++ b/JS/wasm/crates/wasmjs-runtime/src/handlers.rs @@ -1,17 +1,21 @@ -use crate::{io::WasmOutput, routes::WORKERS, server::AppData}; +use std::{ + io::{Error, ErrorKind}, + path::{Component, Path, PathBuf}, +}; + use actix_files::NamedFile; use actix_web::{ http::StatusCode, web::{Bytes, Data}, HttpRequest, HttpResponse, }; -use std::{ - io::{Error, ErrorKind}, - path::{Component, Path, PathBuf}, -}; + use std::net::{IpAddr, Ipv4Addr}; use std::str::FromStr; use crate::geolocation::GeolocationData; +use crate::io::WasmOutput; +use crate::routes::WORKERS; +use crate::server::AppData; fn clean_up_path(uri: &str) -> PathBuf { let path = PathBuf::from_iter(uri.split('/')); diff --git a/JS/wasm/crates/wasmjs-runtime/src/io.rs b/JS/wasm/crates/wasmjs-runtime/src/io.rs index 4058e9f90..c08511e3d 100644 --- a/JS/wasm/crates/wasmjs-runtime/src/io.rs +++ b/JS/wasm/crates/wasmjs-runtime/src/io.rs @@ -1,9 +1,10 @@ +use std::{collections::HashMap, fmt::Debug}; + use actix_web::{ http::{header::HeaderMap, StatusCode, Uri}, HttpRequest, }; use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, fmt::Debug}; use serde_json::{Map, Value as SerdeValue}; use crate::geolocation::GeolocationData; diff --git a/JS/wasm/crates/wasmjs-runtime/src/routes.rs b/JS/wasm/crates/wasmjs-runtime/src/routes.rs index c2718dd12..7cebe67f9 100644 --- a/JS/wasm/crates/wasmjs-runtime/src/routes.rs +++ b/JS/wasm/crates/wasmjs-runtime/src/routes.rs @@ -1,14 +1,17 @@ +use std::{ + collections::HashMap, + ffi::OsStr, + path::{Component, Path, PathBuf}, + str::FromStr, + sync::{Arc, RwLock}, +}; + use lazy_static::lazy_static; use regex::Regex; -use std::path::{Path, PathBuf}; -use std::str::FromStr; -use std::sync::RwLock; -use std::{collections::HashMap, ffi::OsStr, path::Component, sync::Arc}; use wax::{Glob, WalkEntry}; use crate::ServeArgs; -use crate::store::STORE_FOLDER; -use crate::workers::Worker; +use crate::{store::STORE_FOLDER, workers::Worker}; pub struct Files<'t> { root: PathBuf, diff --git a/JS/wasm/crates/wasmjs-runtime/src/server.rs b/JS/wasm/crates/wasmjs-runtime/src/server.rs index f24e78ea9..7d9e0aeb6 100644 --- a/JS/wasm/crates/wasmjs-runtime/src/server.rs +++ b/JS/wasm/crates/wasmjs-runtime/src/server.rs @@ -1,4 +1,3 @@ -use std::fmt::Debug; use std::path::PathBuf; use actix_web::{ diff --git a/JS/wasm/crates/wasmjs-runtime/src/store.rs b/JS/wasm/crates/wasmjs-runtime/src/store.rs index 744576cf7..3b72b7b97 100644 --- a/JS/wasm/crates/wasmjs-runtime/src/store.rs +++ b/JS/wasm/crates/wasmjs-runtime/src/store.rs @@ -1,9 +1,10 @@ -use anyhow::Result; use std::{ fs, path::{Path, PathBuf}, }; +use anyhow::Result; + pub const STORE_FOLDER: &str = ".wasmjs"; pub struct Store { diff --git a/JS/wasm/crates/wasmjs-runtime/src/wiggle_abi.rs b/JS/wasm/crates/wasmjs-runtime/src/wiggle_abi.rs index f0fbdddfb..834ccf472 100644 --- a/JS/wasm/crates/wasmjs-runtime/src/wiggle_abi.rs +++ b/JS/wasm/crates/wasmjs-runtime/src/wiggle_abi.rs @@ -13,7 +13,6 @@ pub struct Session { } impl Session { - pub fn geolocation_lookup(&self, addr: &IpAddr) -> Option { self.geolocation.lookup(addr).map(|data| data.to_string()) } diff --git a/JS/wasm/crates/wasmjs-runtime/src/wiggle_abi/geo_impl.rs b/JS/wasm/crates/wasmjs-runtime/src/wiggle_abi/geo_impl.rs index 58fefa2ae..ab5d39114 100644 --- a/JS/wasm/crates/wasmjs-runtime/src/wiggle_abi/geo_impl.rs +++ b/JS/wasm/crates/wasmjs-runtime/src/wiggle_abi/geo_impl.rs @@ -1,7 +1,3 @@ -//! edge_geo` hostcall implementations. - - - use crate::bindings::types::ArakooStatus; #[derive(Debug, thiserror::Error)] diff --git a/JS/wasm/crates/wasmjs-runtime/src/workers.rs b/JS/wasm/crates/wasmjs-runtime/src/workers.rs index fd8fd7b19..cbe403958 100644 --- a/JS/wasm/crates/wasmjs-runtime/src/workers.rs +++ b/JS/wasm/crates/wasmjs-runtime/src/workers.rs @@ -3,16 +3,18 @@ use crate::config::{ArakooConfig, Config}; use crate::io::{WasmInput, WasmOutput}; use crate::runtime::{init_runtime, CtxBuilder, Runtime}; use crate::bindings::http; +use std::{ + collections::HashMap, + io::Cursor, + path::{Path, PathBuf}, +}; + use actix_web::HttpRequest; use sha256::digest as sha256_digest; -use std::path::PathBuf; -use std::{collections::HashMap, path::Path}; -use wasmtime::Linker; -use wasmtime::{Config as WasmtimeConfig, Engine, Module, Store}; +use wasmtime::{Config as WasmtimeConfig, Engine, Linker, Module, Store}; use wasmtime_wasi::{ambient_authority, Dir, WasiCtxBuilder}; use anyhow::Result; -use std::io::Cursor; use wasi_common::pipe::{ReadPipe, WritePipe}; use crate::ServeArgs; use crate::geolocation::GeolocationData; diff --git a/JS/wasm/examples/ec-wasmjs-hono/build.js b/JS/wasm/examples/ec-wasmjs-hono/build.js index 50f5f006a..64bbadaec 100644 --- a/JS/wasm/examples/ec-wasmjs-hono/build.js +++ b/JS/wasm/examples/ec-wasmjs-hono/build.js @@ -8,6 +8,9 @@ build({ format: "esm", target: "esnext", platform: "node", + external:[ + "arakoo-jsonnet" + ] }).catch((error) => { console.error(error); process.exit(1); diff --git a/JS/wasm/examples/ec-wasmjs-hono/package-lock.json b/JS/wasm/examples/ec-wasmjs-hono/package-lock.json index cf6c18ec9..ae5bd0d88 100644 --- a/JS/wasm/examples/ec-wasmjs-hono/package-lock.json +++ b/JS/wasm/examples/ec-wasmjs-hono/package-lock.json @@ -7,6 +7,7 @@ "name": "hono", "dependencies": { "@hono/node-server": "^1.3.1", + "arakoo-jsonnet": "file:../../types/jsonnet", "axios": "^1.6.2", "crypto": "^1.0.1", "http": "^0.0.1-security", @@ -18,6 +19,14 @@ "hono": "^3.9" } }, + "../../types/jsonnet": { + "version": "0.1.0", + "hasInstallScript": true, + "license": "ISC", + "devDependencies": { + "cargo-cp-artifact": "^0.1" + } + }, "node_modules/@esbuild/android-arm": { "version": "0.19.5", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.5.tgz", @@ -387,6 +396,10 @@ "node": ">=16" } }, + "node_modules/arakoo-jsonnet": { + "resolved": "../../types/jsonnet", + "link": true + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", diff --git a/JS/wasm/examples/ec-wasmjs-hono/package.json b/JS/wasm/examples/ec-wasmjs-hono/package.json index 49e60ff54..08f95e85d 100644 --- a/JS/wasm/examples/ec-wasmjs-hono/package.json +++ b/JS/wasm/examples/ec-wasmjs-hono/package.json @@ -14,6 +14,7 @@ "@hono/node-server": "^1.3.1", "axios": "^1.6.2", "crypto": "^1.0.1", + "arakoo-jsonnet": "file:../../types/jsonnet", "http": "^0.0.1-security", "stream": "^0.0.2" } diff --git a/JS/wasm/types/jsonnet/.gitignore b/JS/wasm/types/jsonnet/.gitignore new file mode 100644 index 000000000..8ea5b111e --- /dev/null +++ b/JS/wasm/types/jsonnet/.gitignore @@ -0,0 +1,6 @@ +target +index.node +**/node_modules +**/.DS_Store +npm-debug.log* + diff --git a/JS/wasm/types/jsonnet/Cargo.lock b/JS/wasm/types/jsonnet/Cargo.lock new file mode 100644 index 000000000..bd343e56a --- /dev/null +++ b/JS/wasm/types/jsonnet/Cargo.lock @@ -0,0 +1,192 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "arakoo-jsonnet" +version = "0.1.0" +dependencies = [ + "jsonnet-rs", + "neon", +] + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "jsonnet-rs" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b396bdfc3ae94965555c9ec3efa2214e5f3921545a943ef9fc9873ff5e4723" +dependencies = [ + "jsonnet-sys", + "libc", +] + +[[package]] +name = "jsonnet-sys" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02347cbdf34234f30f0d92f0f8f678a15883bd5e1e4b3def4ed4a14f691d9add" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "libc" +version = "0.2.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" + +[[package]] +name = "libloading" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "neon" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28e15415261d880aed48122e917a45e87bb82cf0260bb6db48bbab44b7464373" +dependencies = [ + "neon-build", + "neon-macros", + "neon-runtime", + "semver", + "smallvec", +] + +[[package]] +name = "neon-build" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bac98a702e71804af3dacfde41edde4a16076a7bbe889ae61e56e18c5b1c811" + +[[package]] +name = "neon-macros" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7288eac8b54af7913c60e0eb0e2a7683020dffa342ab3fd15e28f035ba897cf" +dependencies = [ + "quote", + "syn", + "syn-mid", +] + +[[package]] +name = "neon-runtime" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4676720fa8bb32c64c3d9f49c47a47289239ec46b4bdb66d0913cc512cb0daca" +dependencies = [ + "cfg-if", + "libloading", + "smallvec", +] + +[[package]] +name = "proc-macro2" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "smallvec" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn-mid" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea305d57546cc8cd04feb14b62ec84bf17f50e3f7b12560d7bfa9265f39d9ed" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/JS/wasm/types/jsonnet/Cargo.toml b/JS/wasm/types/jsonnet/Cargo.toml new file mode 100644 index 000000000..0b5163643 --- /dev/null +++ b/JS/wasm/types/jsonnet/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "arakoo-jsonnet" +version = "0.1.0" +license = "ISC" +edition = "2018" +exclude = ["index.node"] + +[lib] +crate-type = ["cdylib"] +path = "src/lib.rs" +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +jsonnet-rs = "0.17" + +[dependencies.neon] +version = "0.10" +default-features = false +features = ["napi-6"] diff --git a/JS/wasm/types/jsonnet/package-lock.json b/JS/wasm/types/jsonnet/package-lock.json new file mode 100644 index 000000000..369f0ebff --- /dev/null +++ b/JS/wasm/types/jsonnet/package-lock.json @@ -0,0 +1,26 @@ +{ + "name": "arakoo-jsonnet", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "arakoo-jsonnet", + "version": "0.1.0", + "hasInstallScript": true, + "license": "ISC", + "devDependencies": { + "cargo-cp-artifact": "^0.1" + } + }, + "node_modules/cargo-cp-artifact": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.8.tgz", + "integrity": "sha512-3j4DaoTrsCD1MRkTF2Soacii0Nx7UHCce0EwUf4fHnggwiE4fbmF2AbnfzayR36DF8KGadfh7M/Yfy625kgPlA==", + "dev": true, + "bin": { + "cargo-cp-artifact": "bin/cargo-cp-artifact.js" + } + } + } +} diff --git a/JS/wasm/types/jsonnet/package.json b/JS/wasm/types/jsonnet/package.json new file mode 100644 index 000000000..9ff3eeada --- /dev/null +++ b/JS/wasm/types/jsonnet/package.json @@ -0,0 +1,25 @@ +{ + "name": "arakoo-jsonnet", + "version": "0.1.0", + "description": "", + "main": "index.node", + "scripts": { + "build": "cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics", + "build-debug": "npm run build --", + "build-release": "npm run build -- --release", + "install": "npm run build-release", + "test": "cargo test", + "preinstall": "npm install cargo-cp-artifact --no-save" + }, + "author": "", + "exports": { + ".": { + "require": "./src/index.js", + "default": "./src/module.mjs" + } + }, + "license": "ISC", + "devDependencies": { + "cargo-cp-artifact": "^0.1" + } +} diff --git a/JS/wasm/types/jsonnet/src/index.d.ts b/JS/wasm/types/jsonnet/src/index.d.ts new file mode 100644 index 000000000..c08e25f03 --- /dev/null +++ b/JS/wasm/types/jsonnet/src/index.d.ts @@ -0,0 +1 @@ +export function parseJsonnet(filename: string): Promise; diff --git a/JS/wasm/types/jsonnet/src/index.js b/JS/wasm/types/jsonnet/src/index.js new file mode 100644 index 000000000..057355a78 --- /dev/null +++ b/JS/wasm/types/jsonnet/src/index.js @@ -0,0 +1,5 @@ +const {parseJsonnet} = require("../index.node") + +module.exports = { + parseJsonnet, +}; diff --git a/JS/wasm/types/jsonnet/src/lib.rs b/JS/wasm/types/jsonnet/src/lib.rs new file mode 100644 index 000000000..70aa202fc --- /dev/null +++ b/JS/wasm/types/jsonnet/src/lib.rs @@ -0,0 +1,27 @@ +use std::fs; + +use neon::prelude::*; + +use jsonnet::JsonnetVm; + +pub fn parse_jsonnet( + mut cx: FunctionContext, +) -> JsResult { + let path: String = cx.argument::(0)?.value(&mut cx); + let mut vm = JsonnetVm::new(); + let snippet = fs::read_to_string(path).unwrap(); + let output = vm.evaluate_snippet("snippet", &snippet); + let output = match output { + Ok(output) => output, + Err(e) => { + return cx.throw_error(format!("Error: {}", e)); + } + }; + Ok(cx.string(output.to_string())) +} + +#[neon::main] +fn main(mut cx: ModuleContext) -> NeonResult<()> { + cx.export_function("parseJsonnet", parse_jsonnet)?; + Ok(()) +} diff --git a/JS/wasm/types/jsonnet/src/module.mjs b/JS/wasm/types/jsonnet/src/module.mjs new file mode 100644 index 000000000..5ea50ab49 --- /dev/null +++ b/JS/wasm/types/jsonnet/src/module.mjs @@ -0,0 +1,7 @@ +import parseJson from "./index.js" + +const {parseJsonnet} = parseJson; + +export { + parseJsonnet, +}; diff --git a/JS/wasm/types/jsonnet/tsconfig.json b/JS/wasm/types/jsonnet/tsconfig.json new file mode 100644 index 000000000..c97a99990 --- /dev/null +++ b/JS/wasm/types/jsonnet/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es6"], + "strict": true, + "baseUrl": ".", + "paths": { "arakoo-jsonnet": ["."] } + }, + "typedocOptions": { + "entryPoints": ["index.d.ts"], + "out": "../docs", + "excludeExternals": true + }, + "include": ["."] + }