@ricsam/isolate 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -2
- package/dist/cjs/internal/async-context/index.cjs +140 -0
- package/dist/cjs/internal/async-context/index.cjs.map +10 -0
- package/dist/cjs/internal/client/connection.cjs +175 -123
- package/dist/cjs/internal/client/connection.cjs.map +3 -3
- package/dist/cjs/internal/console/index.cjs +2 -2
- package/dist/cjs/internal/console/index.cjs.map +2 -2
- package/dist/cjs/internal/core/index.cjs +13 -5
- package/dist/cjs/internal/core/index.cjs.map +3 -3
- package/dist/cjs/internal/crypto/index.cjs +2 -2
- package/dist/cjs/internal/crypto/index.cjs.map +2 -2
- package/dist/cjs/internal/daemon/connection.cjs +77 -12
- package/dist/cjs/internal/daemon/connection.cjs.map +3 -3
- package/dist/cjs/internal/encoding/index.cjs.map +1 -1
- package/dist/cjs/internal/fetch/index.cjs +80 -18
- package/dist/cjs/internal/fetch/index.cjs.map +3 -3
- package/dist/cjs/internal/fetch/stream-state.cjs.map +1 -1
- package/dist/cjs/internal/fs/index.cjs +2 -2
- package/dist/cjs/internal/fs/index.cjs.map +2 -2
- package/dist/cjs/internal/module-loader/bundle.cjs +225 -8
- package/dist/cjs/internal/module-loader/bundle.cjs.map +3 -3
- package/dist/cjs/internal/path/index.cjs.map +1 -1
- package/dist/cjs/internal/playwright/index.cjs +2 -2
- package/dist/cjs/internal/playwright/index.cjs.map +2 -2
- package/dist/cjs/internal/runtime/index.cjs +78 -6
- package/dist/cjs/internal/runtime/index.cjs.map +3 -3
- package/dist/cjs/internal/test-environment/index.cjs +2 -2
- package/dist/cjs/internal/test-environment/index.cjs.map +2 -2
- package/dist/cjs/internal/timers/index.cjs +9 -4
- package/dist/cjs/internal/timers/index.cjs.map +3 -3
- package/dist/cjs/internal/typecheck/isolate-types.cjs +36 -1
- package/dist/cjs/internal/typecheck/isolate-types.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/internal/async-context/index.mjs +100 -0
- package/dist/mjs/internal/async-context/index.mjs.map +10 -0
- package/dist/mjs/internal/client/connection.mjs +176 -123
- package/dist/mjs/internal/client/connection.mjs.map +3 -3
- package/dist/mjs/internal/console/index.mjs +2 -2
- package/dist/mjs/internal/console/index.mjs.map +2 -2
- package/dist/mjs/internal/core/index.mjs +13 -5
- package/dist/mjs/internal/core/index.mjs.map +3 -3
- package/dist/mjs/internal/crypto/index.mjs +2 -2
- package/dist/mjs/internal/crypto/index.mjs.map +2 -2
- package/dist/mjs/internal/daemon/connection.mjs +77 -12
- package/dist/mjs/internal/daemon/connection.mjs.map +3 -3
- package/dist/mjs/internal/encoding/index.mjs.map +1 -1
- package/dist/mjs/internal/fetch/index.mjs +80 -18
- package/dist/mjs/internal/fetch/index.mjs.map +3 -3
- package/dist/mjs/internal/fetch/stream-state.mjs.map +1 -1
- package/dist/mjs/internal/fs/index.mjs +2 -2
- package/dist/mjs/internal/fs/index.mjs.map +2 -2
- package/dist/mjs/internal/module-loader/bundle.mjs +225 -8
- package/dist/mjs/internal/module-loader/bundle.mjs.map +3 -3
- package/dist/mjs/internal/path/index.mjs.map +1 -1
- package/dist/mjs/internal/playwright/index.mjs +2 -2
- package/dist/mjs/internal/playwright/index.mjs.map +2 -2
- package/dist/mjs/internal/runtime/index.mjs +78 -6
- package/dist/mjs/internal/runtime/index.mjs.map +3 -3
- package/dist/mjs/internal/test-environment/index.mjs +2 -2
- package/dist/mjs/internal/test-environment/index.mjs.map +2 -2
- package/dist/mjs/internal/timers/index.mjs +9 -4
- package/dist/mjs/internal/timers/index.mjs.map +3 -3
- package/dist/mjs/internal/typecheck/isolate-types.mjs +36 -1
- package/dist/mjs/internal/typecheck/isolate-types.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/types/internal/async-context/index.d.ts +5 -0
- package/dist/types/internal/console/index.d.ts +1 -1
- package/dist/types/internal/core/index.d.ts +2 -2
- package/dist/types/internal/crypto/index.d.ts +1 -1
- package/dist/types/internal/daemon/types.d.ts +1 -0
- package/dist/types/internal/encoding/index.d.ts +1 -1
- package/dist/types/internal/fetch/index.d.ts +1 -1
- package/dist/types/internal/fetch/stream-state.d.ts +1 -1
- package/dist/types/internal/fs/index.d.ts +1 -1
- package/dist/types/internal/path/index.d.ts +1 -1
- package/dist/types/internal/playwright/index.d.ts +1 -1
- package/dist/types/internal/test-environment/index.d.ts +1 -1
- package/dist/types/internal/timers/index.d.ts +1 -1
- package/dist/types/internal/typecheck/isolate-types.d.ts +2 -2
- package/package.json +8 -3
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/internal/crypto/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import ivm from \"isolated-vm\";\nimport crypto from \"node:crypto\";\n\nexport interface CryptoHandle {\n dispose(): void;\n}\n\n// Host-side key storage for crypto.subtle\nconst cryptoKeysByContext = new WeakMap<ivm.Context, Map<number, crypto.webcrypto.CryptoKey>>();\nlet nextKeyId = 1;\n\nfunction getKeyMapForContext(context: ivm.Context): Map<number, crypto.webcrypto.CryptoKey> {\n let map = cryptoKeysByContext.get(context);\n if (!map) {\n map = new Map();\n cryptoKeysByContext.set(context, map);\n }\n return map;\n}\n\nfunction deserializeAlgorithm(algorithm: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(algorithm)) {\n if (value && typeof value === 'object' && !Array.isArray(value) &&\n Object.keys(value).every(k => /^\\d+$/.test(k))) {\n // Convert {\"0\": n, \"1\": m, ...} back to Uint8Array\n const length = Object.keys(value).length;\n const arr = new Uint8Array(length);\n for (let i = 0; i < length; i++) {\n arr[i] = (value as Record<string, number>)[String(i)] ?? 0;\n }\n result[key] = arr;\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Setup Web Crypto API in an isolated-vm context\n *\n * Provides crypto.getRandomValues and crypto.randomUUID\n *\n * @example\n * const handle = await setupCrypto(context);\n * await context.eval(`\n * const uuid = crypto.randomUUID();\n * const array = new Uint8Array(16);\n * crypto.getRandomValues(array);\n * `);\n */\nexport async function setupCrypto(\n context: ivm.Context\n): Promise<CryptoHandle> {\n const global = context.global;\n\n // Register host callbacks\n global.setSync(\n \"__crypto_randomUUID\",\n new ivm.Callback(() => {\n return crypto.randomUUID();\n })\n );\n\n global.setSync(\n \"__crypto_getRandomValues\",\n new ivm.Callback((byteLength: number) => {\n const buffer = Buffer.alloc(byteLength);\n crypto.randomFillSync(buffer);\n return Array.from(buffer);\n })\n );\n\n // Get key map for this context\n const keyMap = getKeyMapForContext(context);\n\n // crypto.subtle.importKey - async reference\n const importKeyRef = new ivm.Reference(\n async (\n format: string,\n keyDataJson: string,\n algorithmJson: string,\n extractable: boolean,\n keyUsagesJson: string\n ) => {\n const keyData = JSON.parse(keyDataJson) as number[];\n const algorithm = JSON.parse(algorithmJson);\n const keyUsages = JSON.parse(keyUsagesJson) as crypto.webcrypto.KeyUsage[];\n\n try {\n let cryptoKey: crypto.webcrypto.CryptoKey;\n if (format === \"raw\") {\n const importData = new Uint8Array(keyData);\n cryptoKey = await crypto.webcrypto.subtle.importKey(\n \"raw\",\n importData,\n algorithm,\n extractable,\n keyUsages\n );\n } else if (format === \"jwk\") {\n const importData = keyData as unknown as crypto.webcrypto.JsonWebKey;\n cryptoKey = await crypto.webcrypto.subtle.importKey(\n \"jwk\",\n importData,\n algorithm,\n extractable,\n keyUsages\n );\n } else {\n throw new Error(`[NotSupportedError]Unsupported key format: ${format}`);\n }\n\n // Store key on host and return ID\n const keyId = nextKeyId++;\n keyMap.set(keyId, cryptoKey);\n return keyId;\n } catch (err) {\n if (err instanceof Error) {\n throw new Error(`[${err.name}]${err.message}`);\n }\n throw err;\n }\n }\n );\n global.setSync(\"__crypto_subtle_importKey_ref\", importKeyRef);\n\n // crypto.subtle.sign - async reference\n const signRef = new ivm.Reference(\n async (algorithmJson: string, keyId: number, dataJson: string) => {\n const algorithm = JSON.parse(algorithmJson);\n const data = new Uint8Array(JSON.parse(dataJson) as number[]);\n\n const cryptoKey = keyMap.get(keyId);\n if (!cryptoKey) {\n throw new Error(\"[InvalidAccessError]Key not found\");\n }\n\n try {\n const signature = await crypto.webcrypto.subtle.sign(\n algorithm,\n cryptoKey,\n data\n );\n return JSON.stringify(Array.from(new Uint8Array(signature)));\n } catch (err) {\n if (err instanceof Error) {\n throw new Error(`[${err.name}]${err.message}`);\n }\n throw err;\n }\n }\n );\n global.setSync(\"__crypto_subtle_sign_ref\", signRef);\n\n // crypto.subtle.verify - async reference\n const verifyRef = new ivm.Reference(\n async (\n algorithmJson: string,\n keyId: number,\n signatureJson: string,\n dataJson: string\n ) => {\n const algorithm = JSON.parse(algorithmJson);\n const signature = new Uint8Array(JSON.parse(signatureJson) as number[]);\n const data = new Uint8Array(JSON.parse(dataJson) as number[]);\n\n const cryptoKey = keyMap.get(keyId);\n if (!cryptoKey) {\n throw new Error(\"[InvalidAccessError]Key not found\");\n }\n\n try {\n return await crypto.webcrypto.subtle.verify(\n algorithm,\n cryptoKey,\n signature,\n data\n );\n } catch (err) {\n if (err instanceof Error) {\n throw new Error(`[${err.name}]${err.message}`);\n }\n throw err;\n }\n }\n );\n global.setSync(\"__crypto_subtle_verify_ref\", verifyRef);\n\n // crypto.subtle.digest - async reference\n const digestRef = new ivm.Reference(\n async (algorithmJson: string, dataJson: string) => {\n const algorithm = JSON.parse(algorithmJson);\n const data = new Uint8Array(JSON.parse(dataJson) as number[]);\n\n try {\n const hash = await crypto.webcrypto.subtle.digest(algorithm, data);\n return JSON.stringify(Array.from(new Uint8Array(hash)));\n } catch (err) {\n if (err instanceof Error) {\n throw new Error(`[${err.name}]${err.message}`);\n }\n throw err;\n }\n }\n );\n global.setSync(\"__crypto_subtle_digest_ref\", digestRef);\n\n // crypto.subtle.deriveBits - async reference\n const deriveBitsRef = new ivm.Reference(\n async (algorithmJson: string, keyId: number, length: number) => {\n const algorithm = deserializeAlgorithm(JSON.parse(algorithmJson));\n\n const cryptoKey = keyMap.get(keyId);\n if (!cryptoKey) {\n throw new Error(\"[InvalidAccessError]Key not found\");\n }\n\n try {\n const bits = await crypto.webcrypto.subtle.deriveBits(\n algorithm as unknown as crypto.webcrypto.EcdhKeyDeriveParams | crypto.webcrypto.HkdfParams | crypto.webcrypto.Pbkdf2Params,\n cryptoKey,\n length\n );\n return JSON.stringify(Array.from(new Uint8Array(bits)));\n } catch (err) {\n if (err instanceof Error) {\n throw new Error(`[${err.name}]${err.message}`);\n }\n throw err;\n }\n }\n );\n global.setSync(\"__crypto_subtle_deriveBits_ref\", deriveBitsRef);\n\n // crypto.subtle.deriveKey - async reference\n const deriveKeyRef = new ivm.Reference(\n async (\n algorithmJson: string,\n baseKeyId: number,\n derivedKeyAlgorithmJson: string,\n extractable: boolean,\n keyUsagesJson: string\n ) => {\n const algorithm = deserializeAlgorithm(JSON.parse(algorithmJson));\n const derivedKeyAlgorithm = JSON.parse(derivedKeyAlgorithmJson);\n const keyUsages = JSON.parse(keyUsagesJson) as crypto.webcrypto.KeyUsage[];\n\n const baseKey = keyMap.get(baseKeyId);\n if (!baseKey) {\n throw new Error(\"[InvalidAccessError]Key not found\");\n }\n\n try {\n const derivedKey = await crypto.webcrypto.subtle.deriveKey(\n algorithm as unknown as crypto.webcrypto.EcdhKeyDeriveParams | crypto.webcrypto.HkdfParams | crypto.webcrypto.Pbkdf2Params,\n baseKey,\n derivedKeyAlgorithm,\n extractable,\n keyUsages\n );\n\n // Store derived key on host and return ID\n const keyId = nextKeyId++;\n keyMap.set(keyId, derivedKey);\n return keyId;\n } catch (err) {\n if (err instanceof Error) {\n throw new Error(`[${err.name}]${err.message}`);\n }\n throw err;\n }\n }\n );\n global.setSync(\"__crypto_subtle_deriveKey_ref\", deriveKeyRef);\n\n // Inject the crypto object into the isolate\n const cryptoCode = `\n(function() {\n // DOMException polyfill (Pattern #12)\n if (typeof DOMException === 'undefined') {\n globalThis.DOMException = class DOMException extends Error {\n constructor(message, name) {\n super(message);\n this.name = name || 'DOMException';\n }\n };\n }\n\n // Helper to decode error from host\n function __decodeError(err) {\n if (!(err instanceof Error)) return err;\n const match = err.message.match(/^\\\\[(TypeError|RangeError|NotSupportedError|InvalidAccessError|OperationError|DataError|Error)\\\\](.*)$/);\n if (match) {\n if (['NotSupportedError', 'InvalidAccessError', 'OperationError', 'DataError'].includes(match[1])) {\n return new DOMException(match[2], match[1]);\n }\n const ErrorType = globalThis[match[1]] || Error;\n return new ErrorType(match[2]);\n }\n return err;\n }\n\n // CryptoKey class to wrap key IDs\n const _cryptoKeyIds = new WeakMap();\n\n class CryptoKey {\n constructor(keyId, algorithm, extractable, usages, type) {\n _cryptoKeyIds.set(this, keyId);\n this._algorithm = algorithm;\n this._extractable = extractable;\n this._usages = usages;\n this._type = type || 'secret';\n }\n\n _getKeyId() {\n return _cryptoKeyIds.get(this);\n }\n\n get algorithm() {\n return this._algorithm;\n }\n\n get extractable() {\n return this._extractable;\n }\n\n get usages() {\n return [...this._usages];\n }\n\n get type() {\n return this._type;\n }\n }\n\n globalThis.CryptoKey = CryptoKey;\n\n // Helper to convert data to byte array\n function toByteArray(data) {\n if (typeof data === 'string') {\n return Array.from(new TextEncoder().encode(data));\n }\n if (data instanceof ArrayBuffer) {\n return Array.from(new Uint8Array(data));\n }\n if (ArrayBuffer.isView(data)) {\n return Array.from(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));\n }\n throw new TypeError('Data must be a BufferSource');\n }\n\n // Normalize algorithm to object form\n function normalizeAlgorithm(algorithm) {\n if (typeof algorithm === 'string') {\n return { name: algorithm };\n }\n return algorithm;\n }\n\n globalThis.crypto = {\n randomUUID() {\n return __crypto_randomUUID();\n },\n\n getRandomValues(typedArray) {\n // Validate input is an integer TypedArray\n if (!(typedArray instanceof Int8Array ||\n typedArray instanceof Uint8Array ||\n typedArray instanceof Uint8ClampedArray ||\n typedArray instanceof Int16Array ||\n typedArray instanceof Uint16Array ||\n typedArray instanceof Int32Array ||\n typedArray instanceof Uint32Array ||\n typedArray instanceof BigInt64Array ||\n typedArray instanceof BigUint64Array)) {\n throw new TypeError(\"Argument 1 must be an integer typed array\");\n }\n\n const byteLength = typedArray.byteLength;\n if (byteLength > 65536) {\n throw new DOMException(\n \"The ArrayBufferView's byte length exceeds the number of bytes of entropy available via this API (65536)\",\n \"QuotaExceededError\"\n );\n }\n\n // Get random bytes from host\n const bytes = __crypto_getRandomValues(byteLength);\n\n // Copy bytes into the TypedArray\n const view = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);\n for (let i = 0; i < bytes.length; i++) {\n view[i] = bytes[i];\n }\n\n return typedArray;\n },\n\n subtle: {\n async importKey(format, keyData, algorithm, extractable, keyUsages) {\n try {\n const normalizedAlgo = normalizeAlgorithm(algorithm);\n let keyDataJson;\n\n if (format === 'raw') {\n keyDataJson = JSON.stringify(toByteArray(keyData));\n } else if (format === 'jwk') {\n keyDataJson = JSON.stringify(keyData);\n } else {\n throw new DOMException('Unsupported key format: ' + format, 'NotSupportedError');\n }\n\n const keyId = await __crypto_subtle_importKey_ref.apply(undefined, [\n format,\n keyDataJson,\n JSON.stringify(normalizedAlgo),\n extractable,\n JSON.stringify(keyUsages)\n ], { result: { promise: true, copy: true } });\n\n return new CryptoKey(keyId, normalizedAlgo, extractable, keyUsages);\n } catch (err) {\n throw __decodeError(err);\n }\n },\n\n async sign(algorithm, key, data) {\n try {\n if (!(key instanceof CryptoKey)) {\n throw new TypeError('Key must be a CryptoKey');\n }\n const normalizedAlgo = normalizeAlgorithm(algorithm);\n const signatureBytesJson = await __crypto_subtle_sign_ref.apply(undefined, [\n JSON.stringify(normalizedAlgo),\n key._getKeyId(),\n JSON.stringify(toByteArray(data))\n ], { result: { promise: true, copy: true } });\n const signatureBytes = JSON.parse(signatureBytesJson);\n return new Uint8Array(signatureBytes).buffer;\n } catch (err) {\n throw __decodeError(err);\n }\n },\n\n async verify(algorithm, key, signature, data) {\n try {\n if (!(key instanceof CryptoKey)) {\n throw new TypeError('Key must be a CryptoKey');\n }\n const normalizedAlgo = normalizeAlgorithm(algorithm);\n return await __crypto_subtle_verify_ref.apply(undefined, [\n JSON.stringify(normalizedAlgo),\n key._getKeyId(),\n JSON.stringify(toByteArray(signature)),\n JSON.stringify(toByteArray(data))\n ], { result: { promise: true, copy: true } });\n } catch (err) {\n throw __decodeError(err);\n }\n },\n\n async digest(algorithm, data) {\n try {\n const normalizedAlgo = normalizeAlgorithm(algorithm);\n const hashBytesJson = await __crypto_subtle_digest_ref.apply(undefined, [\n JSON.stringify(normalizedAlgo),\n JSON.stringify(toByteArray(data))\n ], { result: { promise: true, copy: true } });\n const hashBytes = JSON.parse(hashBytesJson);\n return new Uint8Array(hashBytes).buffer;\n } catch (err) {\n throw __decodeError(err);\n }\n },\n\n async deriveBits(algorithm, baseKey, length) {\n try {\n if (!(baseKey instanceof CryptoKey)) {\n throw new TypeError('Key must be a CryptoKey');\n }\n const normalizedAlgo = normalizeAlgorithm(algorithm);\n const bitsBytesJson = await __crypto_subtle_deriveBits_ref.apply(undefined, [\n JSON.stringify(normalizedAlgo),\n baseKey._getKeyId(),\n length\n ], { result: { promise: true, copy: true } });\n const bitsBytes = JSON.parse(bitsBytesJson);\n return new Uint8Array(bitsBytes).buffer;\n } catch (err) {\n throw __decodeError(err);\n }\n },\n\n async deriveKey(algorithm, baseKey, derivedKeyAlgorithm, extractable, keyUsages) {\n try {\n if (!(baseKey instanceof CryptoKey)) {\n throw new TypeError('Key must be a CryptoKey');\n }\n const normalizedAlgo = normalizeAlgorithm(algorithm);\n const normalizedDerivedAlgo = normalizeAlgorithm(derivedKeyAlgorithm);\n const keyId = await __crypto_subtle_deriveKey_ref.apply(undefined, [\n JSON.stringify(normalizedAlgo),\n baseKey._getKeyId(),\n JSON.stringify(normalizedDerivedAlgo),\n extractable,\n JSON.stringify(keyUsages)\n ], { result: { promise: true, copy: true } });\n return new CryptoKey(keyId, normalizedDerivedAlgo, extractable, keyUsages);\n } catch (err) {\n throw __decodeError(err);\n }\n }\n }\n };\n})();\n`;\n\n context.evalSync(cryptoCode);\n\n return {\n dispose() {\n // Clean up key storage for this context\n keyMap.clear();\n },\n };\n}\n"
|
|
5
|
+
"import ivm from \"@ricsam/isolated-vm\";\nimport crypto from \"node:crypto\";\n\nexport interface CryptoHandle {\n dispose(): void;\n}\n\n// Host-side key storage for crypto.subtle\nconst cryptoKeysByContext = new WeakMap<ivm.Context, Map<number, crypto.webcrypto.CryptoKey>>();\nlet nextKeyId = 1;\n\nfunction getKeyMapForContext(context: ivm.Context): Map<number, crypto.webcrypto.CryptoKey> {\n let map = cryptoKeysByContext.get(context);\n if (!map) {\n map = new Map();\n cryptoKeysByContext.set(context, map);\n }\n return map;\n}\n\nfunction deserializeAlgorithm(algorithm: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(algorithm)) {\n if (value && typeof value === 'object' && !Array.isArray(value) &&\n Object.keys(value).every(k => /^\\d+$/.test(k))) {\n // Convert {\"0\": n, \"1\": m, ...} back to Uint8Array\n const length = Object.keys(value).length;\n const arr = new Uint8Array(length);\n for (let i = 0; i < length; i++) {\n arr[i] = (value as Record<string, number>)[String(i)] ?? 0;\n }\n result[key] = arr;\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Setup Web Crypto API in an isolated-vm context\n *\n * Provides crypto.getRandomValues and crypto.randomUUID\n *\n * @example\n * const handle = await setupCrypto(context);\n * await context.eval(`\n * const uuid = crypto.randomUUID();\n * const array = new Uint8Array(16);\n * crypto.getRandomValues(array);\n * `);\n */\nexport async function setupCrypto(\n context: ivm.Context\n): Promise<CryptoHandle> {\n const global = context.global;\n\n // Register host callbacks\n global.setSync(\n \"__crypto_randomUUID\",\n new ivm.Callback(() => {\n return crypto.randomUUID();\n })\n );\n\n global.setSync(\n \"__crypto_getRandomValues\",\n new ivm.Callback((byteLength: number) => {\n const buffer = Buffer.alloc(byteLength);\n crypto.randomFillSync(buffer);\n return Array.from(buffer);\n })\n );\n\n // Get key map for this context\n const keyMap = getKeyMapForContext(context);\n\n // crypto.subtle.importKey - async reference\n const importKeyRef = new ivm.Reference(\n async (\n format: string,\n keyDataJson: string,\n algorithmJson: string,\n extractable: boolean,\n keyUsagesJson: string\n ) => {\n const keyData = JSON.parse(keyDataJson) as number[];\n const algorithm = JSON.parse(algorithmJson);\n const keyUsages = JSON.parse(keyUsagesJson) as crypto.webcrypto.KeyUsage[];\n\n try {\n let cryptoKey: crypto.webcrypto.CryptoKey;\n if (format === \"raw\") {\n const importData = new Uint8Array(keyData);\n cryptoKey = await crypto.webcrypto.subtle.importKey(\n \"raw\",\n importData,\n algorithm,\n extractable,\n keyUsages\n );\n } else if (format === \"jwk\") {\n const importData = keyData as unknown as crypto.webcrypto.JsonWebKey;\n cryptoKey = await crypto.webcrypto.subtle.importKey(\n \"jwk\",\n importData,\n algorithm,\n extractable,\n keyUsages\n );\n } else {\n throw new Error(`[NotSupportedError]Unsupported key format: ${format}`);\n }\n\n // Store key on host and return ID\n const keyId = nextKeyId++;\n keyMap.set(keyId, cryptoKey);\n return keyId;\n } catch (err) {\n if (err instanceof Error) {\n throw new Error(`[${err.name}]${err.message}`);\n }\n throw err;\n }\n }\n );\n global.setSync(\"__crypto_subtle_importKey_ref\", importKeyRef);\n\n // crypto.subtle.sign - async reference\n const signRef = new ivm.Reference(\n async (algorithmJson: string, keyId: number, dataJson: string) => {\n const algorithm = JSON.parse(algorithmJson);\n const data = new Uint8Array(JSON.parse(dataJson) as number[]);\n\n const cryptoKey = keyMap.get(keyId);\n if (!cryptoKey) {\n throw new Error(\"[InvalidAccessError]Key not found\");\n }\n\n try {\n const signature = await crypto.webcrypto.subtle.sign(\n algorithm,\n cryptoKey,\n data\n );\n return JSON.stringify(Array.from(new Uint8Array(signature)));\n } catch (err) {\n if (err instanceof Error) {\n throw new Error(`[${err.name}]${err.message}`);\n }\n throw err;\n }\n }\n );\n global.setSync(\"__crypto_subtle_sign_ref\", signRef);\n\n // crypto.subtle.verify - async reference\n const verifyRef = new ivm.Reference(\n async (\n algorithmJson: string,\n keyId: number,\n signatureJson: string,\n dataJson: string\n ) => {\n const algorithm = JSON.parse(algorithmJson);\n const signature = new Uint8Array(JSON.parse(signatureJson) as number[]);\n const data = new Uint8Array(JSON.parse(dataJson) as number[]);\n\n const cryptoKey = keyMap.get(keyId);\n if (!cryptoKey) {\n throw new Error(\"[InvalidAccessError]Key not found\");\n }\n\n try {\n return await crypto.webcrypto.subtle.verify(\n algorithm,\n cryptoKey,\n signature,\n data\n );\n } catch (err) {\n if (err instanceof Error) {\n throw new Error(`[${err.name}]${err.message}`);\n }\n throw err;\n }\n }\n );\n global.setSync(\"__crypto_subtle_verify_ref\", verifyRef);\n\n // crypto.subtle.digest - async reference\n const digestRef = new ivm.Reference(\n async (algorithmJson: string, dataJson: string) => {\n const algorithm = JSON.parse(algorithmJson);\n const data = new Uint8Array(JSON.parse(dataJson) as number[]);\n\n try {\n const hash = await crypto.webcrypto.subtle.digest(algorithm, data);\n return JSON.stringify(Array.from(new Uint8Array(hash)));\n } catch (err) {\n if (err instanceof Error) {\n throw new Error(`[${err.name}]${err.message}`);\n }\n throw err;\n }\n }\n );\n global.setSync(\"__crypto_subtle_digest_ref\", digestRef);\n\n // crypto.subtle.deriveBits - async reference\n const deriveBitsRef = new ivm.Reference(\n async (algorithmJson: string, keyId: number, length: number) => {\n const algorithm = deserializeAlgorithm(JSON.parse(algorithmJson));\n\n const cryptoKey = keyMap.get(keyId);\n if (!cryptoKey) {\n throw new Error(\"[InvalidAccessError]Key not found\");\n }\n\n try {\n const bits = await crypto.webcrypto.subtle.deriveBits(\n algorithm as unknown as crypto.webcrypto.EcdhKeyDeriveParams | crypto.webcrypto.HkdfParams | crypto.webcrypto.Pbkdf2Params,\n cryptoKey,\n length\n );\n return JSON.stringify(Array.from(new Uint8Array(bits)));\n } catch (err) {\n if (err instanceof Error) {\n throw new Error(`[${err.name}]${err.message}`);\n }\n throw err;\n }\n }\n );\n global.setSync(\"__crypto_subtle_deriveBits_ref\", deriveBitsRef);\n\n // crypto.subtle.deriveKey - async reference\n const deriveKeyRef = new ivm.Reference(\n async (\n algorithmJson: string,\n baseKeyId: number,\n derivedKeyAlgorithmJson: string,\n extractable: boolean,\n keyUsagesJson: string\n ) => {\n const algorithm = deserializeAlgorithm(JSON.parse(algorithmJson));\n const derivedKeyAlgorithm = JSON.parse(derivedKeyAlgorithmJson);\n const keyUsages = JSON.parse(keyUsagesJson) as crypto.webcrypto.KeyUsage[];\n\n const baseKey = keyMap.get(baseKeyId);\n if (!baseKey) {\n throw new Error(\"[InvalidAccessError]Key not found\");\n }\n\n try {\n const derivedKey = await crypto.webcrypto.subtle.deriveKey(\n algorithm as unknown as crypto.webcrypto.EcdhKeyDeriveParams | crypto.webcrypto.HkdfParams | crypto.webcrypto.Pbkdf2Params,\n baseKey,\n derivedKeyAlgorithm,\n extractable,\n keyUsages\n );\n\n // Store derived key on host and return ID\n const keyId = nextKeyId++;\n keyMap.set(keyId, derivedKey);\n return keyId;\n } catch (err) {\n if (err instanceof Error) {\n throw new Error(`[${err.name}]${err.message}`);\n }\n throw err;\n }\n }\n );\n global.setSync(\"__crypto_subtle_deriveKey_ref\", deriveKeyRef);\n\n // Inject the crypto object into the isolate\n const cryptoCode = `\n(function() {\n // DOMException polyfill (Pattern #12)\n if (typeof DOMException === 'undefined') {\n globalThis.DOMException = class DOMException extends Error {\n constructor(message, name) {\n super(message);\n this.name = name || 'DOMException';\n }\n };\n }\n\n // Helper to decode error from host\n function __decodeError(err) {\n if (!(err instanceof Error)) return err;\n const match = err.message.match(/^\\\\[(TypeError|RangeError|NotSupportedError|InvalidAccessError|OperationError|DataError|Error)\\\\](.*)$/);\n if (match) {\n if (['NotSupportedError', 'InvalidAccessError', 'OperationError', 'DataError'].includes(match[1])) {\n return new DOMException(match[2], match[1]);\n }\n const ErrorType = globalThis[match[1]] || Error;\n return new ErrorType(match[2]);\n }\n return err;\n }\n\n // CryptoKey class to wrap key IDs\n const _cryptoKeyIds = new WeakMap();\n\n class CryptoKey {\n constructor(keyId, algorithm, extractable, usages, type) {\n _cryptoKeyIds.set(this, keyId);\n this._algorithm = algorithm;\n this._extractable = extractable;\n this._usages = usages;\n this._type = type || 'secret';\n }\n\n _getKeyId() {\n return _cryptoKeyIds.get(this);\n }\n\n get algorithm() {\n return this._algorithm;\n }\n\n get extractable() {\n return this._extractable;\n }\n\n get usages() {\n return [...this._usages];\n }\n\n get type() {\n return this._type;\n }\n }\n\n globalThis.CryptoKey = CryptoKey;\n\n // Helper to convert data to byte array\n function toByteArray(data) {\n if (typeof data === 'string') {\n return Array.from(new TextEncoder().encode(data));\n }\n if (data instanceof ArrayBuffer) {\n return Array.from(new Uint8Array(data));\n }\n if (ArrayBuffer.isView(data)) {\n return Array.from(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));\n }\n throw new TypeError('Data must be a BufferSource');\n }\n\n // Normalize algorithm to object form\n function normalizeAlgorithm(algorithm) {\n if (typeof algorithm === 'string') {\n return { name: algorithm };\n }\n return algorithm;\n }\n\n globalThis.crypto = {\n randomUUID() {\n return __crypto_randomUUID();\n },\n\n getRandomValues(typedArray) {\n // Validate input is an integer TypedArray\n if (!(typedArray instanceof Int8Array ||\n typedArray instanceof Uint8Array ||\n typedArray instanceof Uint8ClampedArray ||\n typedArray instanceof Int16Array ||\n typedArray instanceof Uint16Array ||\n typedArray instanceof Int32Array ||\n typedArray instanceof Uint32Array ||\n typedArray instanceof BigInt64Array ||\n typedArray instanceof BigUint64Array)) {\n throw new TypeError(\"Argument 1 must be an integer typed array\");\n }\n\n const byteLength = typedArray.byteLength;\n if (byteLength > 65536) {\n throw new DOMException(\n \"The ArrayBufferView's byte length exceeds the number of bytes of entropy available via this API (65536)\",\n \"QuotaExceededError\"\n );\n }\n\n // Get random bytes from host\n const bytes = __crypto_getRandomValues(byteLength);\n\n // Copy bytes into the TypedArray\n const view = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);\n for (let i = 0; i < bytes.length; i++) {\n view[i] = bytes[i];\n }\n\n return typedArray;\n },\n\n subtle: {\n async importKey(format, keyData, algorithm, extractable, keyUsages) {\n try {\n const normalizedAlgo = normalizeAlgorithm(algorithm);\n let keyDataJson;\n\n if (format === 'raw') {\n keyDataJson = JSON.stringify(toByteArray(keyData));\n } else if (format === 'jwk') {\n keyDataJson = JSON.stringify(keyData);\n } else {\n throw new DOMException('Unsupported key format: ' + format, 'NotSupportedError');\n }\n\n const keyId = await __crypto_subtle_importKey_ref.apply(undefined, [\n format,\n keyDataJson,\n JSON.stringify(normalizedAlgo),\n extractable,\n JSON.stringify(keyUsages)\n ], { result: { promise: true, copy: true } });\n\n return new CryptoKey(keyId, normalizedAlgo, extractable, keyUsages);\n } catch (err) {\n throw __decodeError(err);\n }\n },\n\n async sign(algorithm, key, data) {\n try {\n if (!(key instanceof CryptoKey)) {\n throw new TypeError('Key must be a CryptoKey');\n }\n const normalizedAlgo = normalizeAlgorithm(algorithm);\n const signatureBytesJson = await __crypto_subtle_sign_ref.apply(undefined, [\n JSON.stringify(normalizedAlgo),\n key._getKeyId(),\n JSON.stringify(toByteArray(data))\n ], { result: { promise: true, copy: true } });\n const signatureBytes = JSON.parse(signatureBytesJson);\n return new Uint8Array(signatureBytes).buffer;\n } catch (err) {\n throw __decodeError(err);\n }\n },\n\n async verify(algorithm, key, signature, data) {\n try {\n if (!(key instanceof CryptoKey)) {\n throw new TypeError('Key must be a CryptoKey');\n }\n const normalizedAlgo = normalizeAlgorithm(algorithm);\n return await __crypto_subtle_verify_ref.apply(undefined, [\n JSON.stringify(normalizedAlgo),\n key._getKeyId(),\n JSON.stringify(toByteArray(signature)),\n JSON.stringify(toByteArray(data))\n ], { result: { promise: true, copy: true } });\n } catch (err) {\n throw __decodeError(err);\n }\n },\n\n async digest(algorithm, data) {\n try {\n const normalizedAlgo = normalizeAlgorithm(algorithm);\n const hashBytesJson = await __crypto_subtle_digest_ref.apply(undefined, [\n JSON.stringify(normalizedAlgo),\n JSON.stringify(toByteArray(data))\n ], { result: { promise: true, copy: true } });\n const hashBytes = JSON.parse(hashBytesJson);\n return new Uint8Array(hashBytes).buffer;\n } catch (err) {\n throw __decodeError(err);\n }\n },\n\n async deriveBits(algorithm, baseKey, length) {\n try {\n if (!(baseKey instanceof CryptoKey)) {\n throw new TypeError('Key must be a CryptoKey');\n }\n const normalizedAlgo = normalizeAlgorithm(algorithm);\n const bitsBytesJson = await __crypto_subtle_deriveBits_ref.apply(undefined, [\n JSON.stringify(normalizedAlgo),\n baseKey._getKeyId(),\n length\n ], { result: { promise: true, copy: true } });\n const bitsBytes = JSON.parse(bitsBytesJson);\n return new Uint8Array(bitsBytes).buffer;\n } catch (err) {\n throw __decodeError(err);\n }\n },\n\n async deriveKey(algorithm, baseKey, derivedKeyAlgorithm, extractable, keyUsages) {\n try {\n if (!(baseKey instanceof CryptoKey)) {\n throw new TypeError('Key must be a CryptoKey');\n }\n const normalizedAlgo = normalizeAlgorithm(algorithm);\n const normalizedDerivedAlgo = normalizeAlgorithm(derivedKeyAlgorithm);\n const keyId = await __crypto_subtle_deriveKey_ref.apply(undefined, [\n JSON.stringify(normalizedAlgo),\n baseKey._getKeyId(),\n JSON.stringify(normalizedDerivedAlgo),\n extractable,\n JSON.stringify(keyUsages)\n ], { result: { promise: true, copy: true } });\n return new CryptoKey(keyId, normalizedDerivedAlgo, extractable, keyUsages);\n } catch (err) {\n throw __decodeError(err);\n }\n }\n }\n };\n})();\n`;\n\n context.evalSync(cryptoCode);\n\n return {\n dispose() {\n // Clean up key storage for this context\n keyMap.clear();\n },\n };\n}\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": "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",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "0B21DFAE8F92325664756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -78,6 +78,7 @@ function handleConnection(socket, state) {
|
|
|
78
78
|
pendingCallbacks: new Map,
|
|
79
79
|
nextRequestId: 1,
|
|
80
80
|
nextCallbackId: 1,
|
|
81
|
+
nextLocalCallbackId: 1e6,
|
|
81
82
|
nextStreamId: 1,
|
|
82
83
|
activeStreams: new Map,
|
|
83
84
|
streamReceivers: new Map,
|
|
@@ -192,6 +193,9 @@ async function handleMessage(message, connection, state) {
|
|
|
192
193
|
case MessageType.CALLBACK_RESPONSE:
|
|
193
194
|
handleCallbackResponse(message, connection);
|
|
194
195
|
break;
|
|
196
|
+
case MessageType.CALLBACK_INVOKE:
|
|
197
|
+
await handleCallbackInvoke(message, connection, state);
|
|
198
|
+
break;
|
|
195
199
|
case MessageType.WS_OPEN:
|
|
196
200
|
await handleWsOpen(message, connection, state);
|
|
197
201
|
break;
|
|
@@ -605,19 +609,26 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
605
609
|
let bridgedCustomFunctions;
|
|
606
610
|
let customFnMarshalOptions;
|
|
607
611
|
if (customCallbacks) {
|
|
612
|
+
const allocateLocalCallbackId = () => {
|
|
613
|
+
const currentConnection = callbackContext.connection;
|
|
614
|
+
if (!currentConnection) {
|
|
615
|
+
throw new Error("Cannot register callback without an active client connection");
|
|
616
|
+
}
|
|
617
|
+
return currentConnection.nextLocalCallbackId++;
|
|
618
|
+
};
|
|
608
619
|
const createMarshalContext = () => ({
|
|
609
620
|
registerCallback: (fn) => {
|
|
610
|
-
const callbackId =
|
|
621
|
+
const callbackId = allocateLocalCallbackId();
|
|
611
622
|
instance.returnedCallbacks.set(callbackId, fn);
|
|
612
623
|
return callbackId;
|
|
613
624
|
},
|
|
614
625
|
registerPromise: (promise) => {
|
|
615
|
-
const promiseId =
|
|
626
|
+
const promiseId = allocateLocalCallbackId();
|
|
616
627
|
instance.returnedPromises.set(promiseId, promise);
|
|
617
628
|
return promiseId;
|
|
618
629
|
},
|
|
619
630
|
registerIterator: (iterator) => {
|
|
620
|
-
const iteratorId =
|
|
631
|
+
const iteratorId = allocateLocalCallbackId();
|
|
621
632
|
instance.returnedIterators.set(iteratorId, iterator);
|
|
622
633
|
return iteratorId;
|
|
623
634
|
}
|
|
@@ -628,7 +639,7 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
628
639
|
if (isPromiseRef(value)) {
|
|
629
640
|
if ("__resolveCallbackId" in value)
|
|
630
641
|
return value;
|
|
631
|
-
const resolveCallbackId =
|
|
642
|
+
const resolveCallbackId = allocateLocalCallbackId();
|
|
632
643
|
instance.returnedCallbacks.set(resolveCallbackId, async (promiseId) => {
|
|
633
644
|
const promise = instance.returnedPromises.get(promiseId);
|
|
634
645
|
if (!promise)
|
|
@@ -644,7 +655,7 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
644
655
|
if (isAsyncIteratorRef(value)) {
|
|
645
656
|
if ("__nextCallbackId" in value)
|
|
646
657
|
return value;
|
|
647
|
-
const nextCallbackId =
|
|
658
|
+
const nextCallbackId = allocateLocalCallbackId();
|
|
648
659
|
instance.returnedCallbacks.set(nextCallbackId, async (iteratorId) => {
|
|
649
660
|
const iterator = instance.returnedIterators.get(iteratorId);
|
|
650
661
|
if (!iterator)
|
|
@@ -656,7 +667,7 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
656
667
|
const marshalledValue = await marshalValue(result2.value, ctx);
|
|
657
668
|
return { done: result2.done, value: addCallbackIdsToRefs(marshalledValue) };
|
|
658
669
|
});
|
|
659
|
-
const returnCallbackId =
|
|
670
|
+
const returnCallbackId = allocateLocalCallbackId();
|
|
660
671
|
instance.returnedCallbacks.set(returnCallbackId, async (iteratorId, returnValue) => {
|
|
661
672
|
const iterator = instance.returnedIterators.get(iteratorId);
|
|
662
673
|
instance.returnedIterators.delete(iteratorId);
|
|
@@ -667,7 +678,7 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
667
678
|
const marshalledValue = await marshalValue(result2.value, ctx);
|
|
668
679
|
return { done: true, value: addCallbackIdsToRefs(marshalledValue) };
|
|
669
680
|
});
|
|
670
|
-
const throwCallbackId =
|
|
681
|
+
const throwCallbackId = allocateLocalCallbackId();
|
|
671
682
|
instance.returnedCallbacks.set(throwCallbackId, async (iteratorId, errorValue) => {
|
|
672
683
|
const iterator = instance.returnedIterators.get(iteratorId);
|
|
673
684
|
if (!iterator) {
|
|
@@ -706,6 +717,11 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
706
717
|
return result;
|
|
707
718
|
};
|
|
708
719
|
const LOCAL_CALLBACK_THRESHOLD = 1e6;
|
|
720
|
+
const marshalArgsForClient = async (args) => {
|
|
721
|
+
const ctx = createMarshalContext();
|
|
722
|
+
const marshalledArgs = await marshalValue(args, ctx);
|
|
723
|
+
return addCallbackIdsToRefs(marshalledArgs);
|
|
724
|
+
};
|
|
709
725
|
const invokeCallback = async (callbackId, args) => {
|
|
710
726
|
if (callbackId >= LOCAL_CALLBACK_THRESHOLD) {
|
|
711
727
|
const callback = instance.returnedCallbacks.get(callbackId);
|
|
@@ -715,14 +731,15 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
715
731
|
return await callback(...args);
|
|
716
732
|
} else {
|
|
717
733
|
const conn = await waitForConnection(callbackContext);
|
|
734
|
+
const marshalledArgs = await marshalArgsForClient(args);
|
|
718
735
|
try {
|
|
719
|
-
return await invokeClientCallback(conn, callbackId,
|
|
736
|
+
return await invokeClientCallback(conn, callbackId, marshalledArgs, {
|
|
720
737
|
signal: getCurrentHostSignal(instance)
|
|
721
738
|
});
|
|
722
739
|
} catch (err) {
|
|
723
740
|
if (callbackContext.reconnectionPromise && !callbackContext.connection) {
|
|
724
741
|
const newConn = await callbackContext.reconnectionPromise.promise;
|
|
725
|
-
return invokeClientCallback(newConn, callbackId,
|
|
742
|
+
return invokeClientCallback(newConn, callbackId, marshalledArgs, {
|
|
726
743
|
signal: getCurrentHostSignal(instance)
|
|
727
744
|
});
|
|
728
745
|
}
|
|
@@ -744,7 +761,8 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
744
761
|
const nextCallbackId = callbackContext_.custom.get(`${name}:next`);
|
|
745
762
|
const returnCallbackId = callbackContext_.custom.get(`${name}:return`);
|
|
746
763
|
async function* bridgedIterator() {
|
|
747
|
-
const
|
|
764
|
+
const marshalledArgs = await marshalArgsForClient(args);
|
|
765
|
+
const startResult = await invokeCallbackWithReconnect(callbackContext_, () => callbackContext_.custom.get(`${name}:start`), marshalledArgs, `AsyncIterator '${name}' start`, invokeClientCallback, { signal: getCurrentHostSignal(instance) });
|
|
748
766
|
const iteratorId = startResult.iteratorId;
|
|
749
767
|
try {
|
|
750
768
|
while (true) {
|
|
@@ -770,7 +788,8 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
770
788
|
bridgedCustomFunctions[name] = {
|
|
771
789
|
type: registration.type,
|
|
772
790
|
fn: async (...args) => {
|
|
773
|
-
|
|
791
|
+
const marshalledArgs = await marshalArgsForClient(args);
|
|
792
|
+
return invokeCallbackWithReconnect(callbackContext_, () => callbackContext_.custom.get(name), marshalledArgs, `Custom function '${name}'`, invokeClientCallback, { signal: getCurrentHostSignal(instance) });
|
|
774
793
|
}
|
|
775
794
|
};
|
|
776
795
|
}
|
|
@@ -1430,6 +1449,52 @@ function handleCallbackResponse(message, connection) {
|
|
|
1430
1449
|
pending.resolve(message.result);
|
|
1431
1450
|
}
|
|
1432
1451
|
}
|
|
1452
|
+
async function handleCallbackInvoke(message, connection, state) {
|
|
1453
|
+
const response = {
|
|
1454
|
+
type: MessageType.CALLBACK_RESPONSE,
|
|
1455
|
+
requestId: message.requestId
|
|
1456
|
+
};
|
|
1457
|
+
let instance;
|
|
1458
|
+
for (const isolateId of connection.isolates) {
|
|
1459
|
+
const candidate = state.isolates.get(isolateId);
|
|
1460
|
+
if (candidate?.returnedCallbacks?.has(message.callbackId)) {
|
|
1461
|
+
instance = candidate;
|
|
1462
|
+
break;
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
if (!instance) {
|
|
1466
|
+
response.error = {
|
|
1467
|
+
name: "Error",
|
|
1468
|
+
message: `Unknown callback: ${message.callbackId}`
|
|
1469
|
+
};
|
|
1470
|
+
sendMessage(connection.socket, response);
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1473
|
+
instance.lastActivity = Date.now();
|
|
1474
|
+
const callback = instance.returnedCallbacks.get(message.callbackId);
|
|
1475
|
+
if (!callback) {
|
|
1476
|
+
response.error = {
|
|
1477
|
+
name: "Error",
|
|
1478
|
+
message: `Unknown callback: ${message.callbackId}`
|
|
1479
|
+
};
|
|
1480
|
+
sendMessage(connection.socket, response);
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1483
|
+
try {
|
|
1484
|
+
response.result = await requestContextStorage.run({
|
|
1485
|
+
...message.context ?? {},
|
|
1486
|
+
signal: getCurrentHostSignal(instance)
|
|
1487
|
+
}, async () => await callback(...message.args));
|
|
1488
|
+
} catch (err) {
|
|
1489
|
+
const error = err;
|
|
1490
|
+
response.error = {
|
|
1491
|
+
name: error.name,
|
|
1492
|
+
message: error.message,
|
|
1493
|
+
stack: error.stack
|
|
1494
|
+
};
|
|
1495
|
+
}
|
|
1496
|
+
sendMessage(connection.socket, response);
|
|
1497
|
+
}
|
|
1433
1498
|
async function invokeClientCallback(connection, callbackId, args, options) {
|
|
1434
1499
|
const requestId = connection.nextCallbackId++;
|
|
1435
1500
|
const timeoutMs = options?.timeoutMs ?? DEFAULT_CALLBACK_TIMEOUT_MS;
|
|
@@ -1928,4 +1993,4 @@ export {
|
|
|
1928
1993
|
handleConnection
|
|
1929
1994
|
};
|
|
1930
1995
|
|
|
1931
|
-
//# debugId=
|
|
1996
|
+
//# debugId=665A564AAE317D3264756E2164756E21
|