@n8n/expression-runtime 0.30.0 → 0.31.0
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 +4 -0
- package/dist/bundle/runtime.esm.js +17 -17
- package/dist/bundle/runtime.esm.js.map +4 -4
- package/dist/bundle/runtime.iife.js +17 -17
- package/dist/bundle/runtime.iife.js.map +4 -4
- package/dist/cjs/bridge/host-functions.d.ts +74 -0
- package/dist/cjs/bridge/host-functions.d.ts.map +1 -0
- package/dist/cjs/bridge/host-functions.js +336 -0
- package/dist/cjs/bridge/host-functions.js.map +1 -0
- package/dist/cjs/bridge/isolated-vm-bridge.d.ts +24 -150
- package/dist/cjs/bridge/isolated-vm-bridge.d.ts.map +1 -1
- package/dist/cjs/bridge/isolated-vm-bridge.js +130 -429
- package/dist/cjs/bridge/isolated-vm-bridge.js.map +1 -1
- package/dist/cjs/bridge/quickjs-bridge.d.ts +21 -6
- package/dist/cjs/bridge/quickjs-bridge.d.ts.map +1 -1
- package/dist/cjs/bridge/quickjs-bridge.js +377 -402
- package/dist/cjs/bridge/quickjs-bridge.js.map +1 -1
- package/dist/cjs/build.tsbuildinfo +1 -1
- package/dist/cjs/evaluator/expression-evaluator.d.ts +17 -0
- package/dist/cjs/evaluator/expression-evaluator.d.ts.map +1 -1
- package/dist/cjs/evaluator/expression-evaluator.js +61 -1
- package/dist/cjs/evaluator/expression-evaluator.js.map +1 -1
- package/dist/cjs/extensions/array-extensions.d.ts.map +1 -1
- package/dist/cjs/extensions/array-extensions.js +7 -15
- package/dist/cjs/extensions/array-extensions.js.map +1 -1
- package/dist/cjs/extensions/function-extensions.d.ts.map +1 -1
- package/dist/cjs/extensions/function-extensions.js +2 -10
- package/dist/cjs/extensions/function-extensions.js.map +1 -1
- package/dist/cjs/extensions/object-extensions.d.ts.map +1 -1
- package/dist/cjs/extensions/object-extensions.js +3 -11
- package/dist/cjs/extensions/object-extensions.js.map +1 -1
- package/dist/cjs/extensions/utils.d.ts +1 -0
- package/dist/cjs/extensions/utils.d.ts.map +1 -1
- package/dist/cjs/extensions/utils.js +10 -0
- package/dist/cjs/extensions/utils.js.map +1 -1
- package/dist/cjs/observability/metrics.d.ts +12 -0
- package/dist/cjs/observability/metrics.d.ts.map +1 -1
- package/dist/cjs/observability/metrics.js +12 -0
- package/dist/cjs/observability/metrics.js.map +1 -1
- package/dist/cjs/runtime/lazy-proxy.d.ts +2 -0
- package/dist/cjs/runtime/lazy-proxy.d.ts.map +1 -1
- package/dist/cjs/runtime/lazy-proxy.js +29 -15
- package/dist/cjs/runtime/lazy-proxy.js.map +1 -1
- package/dist/cjs/runtime/luxon-transfer.d.ts +62 -0
- package/dist/cjs/runtime/luxon-transfer.d.ts.map +1 -0
- package/dist/cjs/runtime/luxon-transfer.js +200 -0
- package/dist/cjs/runtime/luxon-transfer.js.map +1 -0
- package/dist/cjs/runtime/serialize.d.ts +7 -7
- package/dist/cjs/runtime/serialize.d.ts.map +1 -1
- package/dist/cjs/runtime/serialize.js +42 -30
- package/dist/cjs/runtime/serialize.js.map +1 -1
- package/dist/cjs/runtime/transfer.d.ts +77 -0
- package/dist/cjs/runtime/transfer.d.ts.map +1 -0
- package/dist/cjs/runtime/transfer.js +183 -0
- package/dist/cjs/runtime/transfer.js.map +1 -0
- package/dist/cjs/types/bridge.d.ts +16 -0
- package/dist/cjs/types/bridge.d.ts.map +1 -1
- package/dist/cjs/types/bridge.js +1 -0
- package/dist/cjs/types/bridge.js.map +1 -1
- package/dist/cjs/types/evaluator.d.ts +9 -0
- package/dist/cjs/types/evaluator.d.ts.map +1 -1
- package/dist/cjs/types/evaluator.js.map +1 -1
- package/dist/esm/bridge/host-functions.d.ts +74 -0
- package/dist/esm/bridge/host-functions.d.ts.map +1 -0
- package/dist/esm/bridge/host-functions.js +328 -0
- package/dist/esm/bridge/host-functions.js.map +1 -0
- package/dist/esm/bridge/isolated-vm-bridge.d.ts +24 -150
- package/dist/esm/bridge/isolated-vm-bridge.d.ts.map +1 -1
- package/dist/esm/bridge/isolated-vm-bridge.js +126 -425
- package/dist/esm/bridge/isolated-vm-bridge.js.map +1 -1
- package/dist/esm/bridge/quickjs-bridge.d.ts +21 -6
- package/dist/esm/bridge/quickjs-bridge.d.ts.map +1 -1
- package/dist/esm/bridge/quickjs-bridge.js +368 -393
- package/dist/esm/bridge/quickjs-bridge.js.map +1 -1
- package/dist/esm/build.tsbuildinfo +1 -1
- package/dist/esm/evaluator/expression-evaluator.d.ts +17 -0
- package/dist/esm/evaluator/expression-evaluator.d.ts.map +1 -1
- package/dist/esm/evaluator/expression-evaluator.js +61 -1
- package/dist/esm/evaluator/expression-evaluator.js.map +1 -1
- package/dist/esm/extensions/array-extensions.d.ts.map +1 -1
- package/dist/esm/extensions/array-extensions.js +1 -9
- package/dist/esm/extensions/array-extensions.js.map +1 -1
- package/dist/esm/extensions/function-extensions.d.ts.map +1 -1
- package/dist/esm/extensions/function-extensions.js +1 -9
- package/dist/esm/extensions/function-extensions.js.map +1 -1
- package/dist/esm/extensions/object-extensions.d.ts.map +1 -1
- package/dist/esm/extensions/object-extensions.js +1 -9
- package/dist/esm/extensions/object-extensions.js.map +1 -1
- package/dist/esm/extensions/utils.d.ts +1 -0
- package/dist/esm/extensions/utils.d.ts.map +1 -1
- package/dist/esm/extensions/utils.js +9 -0
- package/dist/esm/extensions/utils.js.map +1 -1
- package/dist/esm/observability/metrics.d.ts +12 -0
- package/dist/esm/observability/metrics.d.ts.map +1 -1
- package/dist/esm/observability/metrics.js +12 -0
- package/dist/esm/observability/metrics.js.map +1 -1
- package/dist/esm/runtime/lazy-proxy.d.ts +2 -0
- package/dist/esm/runtime/lazy-proxy.d.ts.map +1 -1
- package/dist/esm/runtime/lazy-proxy.js +29 -15
- package/dist/esm/runtime/lazy-proxy.js.map +1 -1
- package/dist/esm/runtime/luxon-transfer.d.ts +62 -0
- package/dist/esm/runtime/luxon-transfer.d.ts.map +1 -0
- package/dist/esm/runtime/luxon-transfer.js +183 -0
- package/dist/esm/runtime/luxon-transfer.js.map +1 -0
- package/dist/esm/runtime/serialize.d.ts +7 -7
- package/dist/esm/runtime/serialize.d.ts.map +1 -1
- package/dist/esm/runtime/serialize.js +42 -30
- package/dist/esm/runtime/serialize.js.map +1 -1
- package/dist/esm/runtime/transfer.d.ts +77 -0
- package/dist/esm/runtime/transfer.d.ts.map +1 -0
- package/dist/esm/runtime/transfer.js +173 -0
- package/dist/esm/runtime/transfer.js.map +1 -0
- package/dist/esm/types/bridge.d.ts +16 -0
- package/dist/esm/types/bridge.d.ts.map +1 -1
- package/dist/esm/types/bridge.js +1 -0
- package/dist/esm/types/bridge.js.map +1 -1
- package/dist/esm/types/evaluator.d.ts +9 -0
- package/dist/esm/types/evaluator.d.ts.map +1 -1
- package/dist/esm/types/evaluator.js.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { WorkflowData } from '../types';
|
|
2
|
+
import type { ErrorSentinel } from '../runtime/lazy-proxy';
|
|
3
|
+
/** Check if a value is an error sentinel returned by serializeError. */
|
|
4
|
+
export declare function isErrorSentinel(value: unknown): value is ErrorSentinel;
|
|
5
|
+
/**
|
|
6
|
+
* Serialize an error into a transferable metadata object.
|
|
7
|
+
*
|
|
8
|
+
* Host-side callbacks (getValueAtPath, etc.) catch errors and return this
|
|
9
|
+
* sentinel instead of letting the error cross the boundary (which strips
|
|
10
|
+
* custom class identity and properties). The guest-side proxy detects
|
|
11
|
+
* __isError and throws the sentinel; the host reconstructs a real Error
|
|
12
|
+
* after it round-trips back (see reconstructError).
|
|
13
|
+
*/
|
|
14
|
+
export declare function serializeError(err: unknown): ErrorSentinel;
|
|
15
|
+
/**
|
|
16
|
+
* Reconstruct an error from a serialized error sentinel.
|
|
17
|
+
*
|
|
18
|
+
* Restores the name, stack, and custom properties that would otherwise be
|
|
19
|
+
* lost crossing the guest boundary.
|
|
20
|
+
*/
|
|
21
|
+
export declare function reconstructError(data: ErrorSentinel): Error;
|
|
22
|
+
/**
|
|
23
|
+
* Navigate the data object by path and return metadata or a primitive value.
|
|
24
|
+
*
|
|
25
|
+
* Used by createDeepLazyProxy when accessing properties. Returns metadata
|
|
26
|
+
* markers for arrays and objects, or the primitive value directly.
|
|
27
|
+
*
|
|
28
|
+
* Special-case: paths starting with ['$item', index] call data.$item(index)
|
|
29
|
+
* to get the sub-proxy for that item, then continue navigating the rest;
|
|
30
|
+
* likewise ['$', nodeName] calls data.$(nodeName).
|
|
31
|
+
*
|
|
32
|
+
* Function-typed values are returned as `undefined` — every callable on
|
|
33
|
+
* the host data surface (`$('Foo').first()`, `$items()`, `$fromAI()`,
|
|
34
|
+
* `$evaluateExpression()`, `$getPairedItem()`) is wired guest-side via
|
|
35
|
+
* the typed-RPC dispatcher (`callHost`). No expression form should
|
|
36
|
+
* reach a function through this path (invariant:
|
|
37
|
+
* __tests__/host-fn-shadowing.test.ts).
|
|
38
|
+
*/
|
|
39
|
+
export declare function getValueAtPath(data: WorkflowData, pathArr: string[]): unknown;
|
|
40
|
+
/**
|
|
41
|
+
* Get an array element at an index, navigating to the array by path first
|
|
42
|
+
* (same `$`/`$item` special-casing as getValueAtPath).
|
|
43
|
+
*
|
|
44
|
+
* Used by the array proxy when accessing numeric indices.
|
|
45
|
+
*/
|
|
46
|
+
export declare function getArrayElement(data: WorkflowData, pathArr: string[], index: number): unknown;
|
|
47
|
+
/**
|
|
48
|
+
* Host-side dispatcher for the typed-RPC `callHost` channel.
|
|
49
|
+
*
|
|
50
|
+
* The guest sends one envelope per typed RPC invocation:
|
|
51
|
+
* `callHost({ type: 'getNodeFirst', nodeName, branchIndex?, runIndex? })`
|
|
52
|
+
*
|
|
53
|
+
* Inputs cross a trust boundary, so the dispatcher parses every envelope
|
|
54
|
+
* with the host-side zod schema (`bridgeMessageSchema`) before any
|
|
55
|
+
* dispatch happens. Anything that deviates from the declared shape —
|
|
56
|
+
* unknown `type`, missing required fields, extra unexpected fields,
|
|
57
|
+
* wrong field types — fails the parse and throws; the calling bridge
|
|
58
|
+
* catches and returns an error sentinel to the guest.
|
|
59
|
+
*
|
|
60
|
+
* After parsing, `switch (msg.type)` dispatches with a fully narrowed
|
|
61
|
+
* message type. The operation set is exactly the cases in this switch;
|
|
62
|
+
* the `type` field selects a static branch in source, not a property
|
|
63
|
+
* lookup on a runtime object. Each case reads a fixed literal property
|
|
64
|
+
* name off the host-side data proxy — the guest cannot influence which
|
|
65
|
+
* property is dereferenced.
|
|
66
|
+
*
|
|
67
|
+
* Return-value note: cases must return plain, structured-clone-able,
|
|
68
|
+
* JSON-shaped data. Each bridge marshals the result across its own
|
|
69
|
+
* boundary (structured clone for isolated-vm, sentinel-wrapped JSON
|
|
70
|
+
* round-trip for QuickJS), so engine objects or other non-cloneable
|
|
71
|
+
* values must not be returned.
|
|
72
|
+
*/
|
|
73
|
+
export declare function dispatchHostCall(rawMsg: unknown, data: WorkflowData): unknown;
|
|
74
|
+
//# sourceMappingURL=host-functions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-functions.d.ts","sourceRoot":"","sources":["../../../src/bridge/host-functions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAc3D,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAMtE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,CAc1D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,KAAK,CAa3D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CA0D7E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAmE7F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CA2G7E"}
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isErrorSentinel = isErrorSentinel;
|
|
4
|
+
exports.serializeError = serializeError;
|
|
5
|
+
exports.reconstructError = reconstructError;
|
|
6
|
+
exports.getValueAtPath = getValueAtPath;
|
|
7
|
+
exports.getArrayElement = getArrayElement;
|
|
8
|
+
exports.dispatchHostCall = dispatchHostCall;
|
|
9
|
+
const bridge_messages_1 = require("./bridge-messages");
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Host-side functions shared by the expression bridges.
|
|
12
|
+
//
|
|
13
|
+
// Both IsolatedVmBridge and QuickJsBridge expose the same three host
|
|
14
|
+
// callbacks to the guest — getValueAtPath, getArrayElement, callHost — plus
|
|
15
|
+
// the error-sentinel helpers and bundle loader around them. The logic is
|
|
16
|
+
// engine-agnostic: each bridge wraps these pure functions in its own
|
|
17
|
+
// callback mechanism (ivm.Callback / vm.newFunction) and marshals the
|
|
18
|
+
// plain, JSON-shaped return values across its own boundary.
|
|
19
|
+
// ============================================================================
|
|
20
|
+
/** Check if a value is an error sentinel returned by serializeError. */
|
|
21
|
+
function isErrorSentinel(value) {
|
|
22
|
+
return (typeof value === 'object' &&
|
|
23
|
+
value !== null &&
|
|
24
|
+
value.__isError === true);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Serialize an error into a transferable metadata object.
|
|
28
|
+
*
|
|
29
|
+
* Host-side callbacks (getValueAtPath, etc.) catch errors and return this
|
|
30
|
+
* sentinel instead of letting the error cross the boundary (which strips
|
|
31
|
+
* custom class identity and properties). The guest-side proxy detects
|
|
32
|
+
* __isError and throws the sentinel; the host reconstructs a real Error
|
|
33
|
+
* after it round-trips back (see reconstructError).
|
|
34
|
+
*/
|
|
35
|
+
function serializeError(err) {
|
|
36
|
+
if (err instanceof Error) {
|
|
37
|
+
const extra = Object.fromEntries(Object.entries(err).filter(([key]) => key !== 'name' && key !== 'message' && key !== 'stack'));
|
|
38
|
+
return {
|
|
39
|
+
__isError: true,
|
|
40
|
+
name: err.name,
|
|
41
|
+
message: err.message,
|
|
42
|
+
stack: err.stack,
|
|
43
|
+
extra,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return { __isError: true, name: 'Error', message: String(err), extra: {} };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Reconstruct an error from a serialized error sentinel.
|
|
50
|
+
*
|
|
51
|
+
* Restores the name, stack, and custom properties that would otherwise be
|
|
52
|
+
* lost crossing the guest boundary.
|
|
53
|
+
*/
|
|
54
|
+
function reconstructError(data) {
|
|
55
|
+
const error = new Error(data.message);
|
|
56
|
+
error.name = data.name || 'Error';
|
|
57
|
+
if (data.stack) {
|
|
58
|
+
error.stack = data.stack;
|
|
59
|
+
}
|
|
60
|
+
// Restore custom properties transferred across the boundary
|
|
61
|
+
if (data.extra) {
|
|
62
|
+
Object.assign(error, data.extra);
|
|
63
|
+
}
|
|
64
|
+
return error;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Navigate the data object by path and return metadata or a primitive value.
|
|
68
|
+
*
|
|
69
|
+
* Used by createDeepLazyProxy when accessing properties. Returns metadata
|
|
70
|
+
* markers for arrays and objects, or the primitive value directly.
|
|
71
|
+
*
|
|
72
|
+
* Special-case: paths starting with ['$item', index] call data.$item(index)
|
|
73
|
+
* to get the sub-proxy for that item, then continue navigating the rest;
|
|
74
|
+
* likewise ['$', nodeName] calls data.$(nodeName).
|
|
75
|
+
*
|
|
76
|
+
* Function-typed values are returned as `undefined` — every callable on
|
|
77
|
+
* the host data surface (`$('Foo').first()`, `$items()`, `$fromAI()`,
|
|
78
|
+
* `$evaluateExpression()`, `$getPairedItem()`) is wired guest-side via
|
|
79
|
+
* the typed-RPC dispatcher (`callHost`). No expression form should
|
|
80
|
+
* reach a function through this path (invariant:
|
|
81
|
+
* __tests__/host-fn-shadowing.test.ts).
|
|
82
|
+
*/
|
|
83
|
+
function getValueAtPath(data, pathArr) {
|
|
84
|
+
let value = data;
|
|
85
|
+
let startIndex = 0;
|
|
86
|
+
const itemFn = data.$item;
|
|
87
|
+
if (pathArr.length >= 2 && pathArr[0] === '$item' && typeof itemFn === 'function') {
|
|
88
|
+
const itemIndex = parseInt(pathArr[1], 10);
|
|
89
|
+
if (!isNaN(itemIndex)) {
|
|
90
|
+
value = itemFn(itemIndex);
|
|
91
|
+
startIndex = 2;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
const dollarFn = data.$;
|
|
96
|
+
if (pathArr.length >= 2 && pathArr[0] === '$' && typeof dollarFn === 'function') {
|
|
97
|
+
value = dollarFn(pathArr[1]);
|
|
98
|
+
startIndex = 2;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
for (let i = startIndex; i < pathArr.length; i++) {
|
|
102
|
+
value = value?.[pathArr[i]];
|
|
103
|
+
if (value === undefined || value === null) {
|
|
104
|
+
return value;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Functions are not reachable via the lazy-proxy data path —
|
|
108
|
+
// every callable on the host data surface routes through the
|
|
109
|
+
// typed-RPC dispatcher. Return undefined so any residual
|
|
110
|
+
// access surfaces as missing rather than as a stale metadata
|
|
111
|
+
// marker the runtime no longer knows how to interpret.
|
|
112
|
+
if (typeof value === 'function') {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
// Handle arrays - always lazy, only transfer length
|
|
116
|
+
if (Array.isArray(value)) {
|
|
117
|
+
return {
|
|
118
|
+
__isArray: true,
|
|
119
|
+
__length: value.length,
|
|
120
|
+
__data: null,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
// Dates have no enumerable own keys; pass through instead of
|
|
124
|
+
// marshaling as an empty object.
|
|
125
|
+
if (value instanceof Date) {
|
|
126
|
+
return value;
|
|
127
|
+
}
|
|
128
|
+
// Handle objects - return metadata with keys
|
|
129
|
+
if (value !== null && typeof value === 'object') {
|
|
130
|
+
return {
|
|
131
|
+
__isObject: true,
|
|
132
|
+
__keys: Object.keys(value),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// Primitive value
|
|
136
|
+
return value;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get an array element at an index, navigating to the array by path first
|
|
140
|
+
* (same `$`/`$item` special-casing as getValueAtPath).
|
|
141
|
+
*
|
|
142
|
+
* Used by the array proxy when accessing numeric indices.
|
|
143
|
+
*/
|
|
144
|
+
function getArrayElement(data, pathArr, index) {
|
|
145
|
+
let arr = data;
|
|
146
|
+
let startIndex = 0;
|
|
147
|
+
const itemFn = data.$item;
|
|
148
|
+
if (pathArr.length >= 2 && pathArr[0] === '$item' && typeof itemFn === 'function') {
|
|
149
|
+
const itemIndex = parseInt(pathArr[1], 10);
|
|
150
|
+
if (!isNaN(itemIndex)) {
|
|
151
|
+
arr = itemFn(itemIndex);
|
|
152
|
+
startIndex = 2;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
const dollarFn = data.$;
|
|
157
|
+
if (pathArr.length >= 2 && pathArr[0] === '$' && typeof dollarFn === 'function') {
|
|
158
|
+
arr = dollarFn(pathArr[1]);
|
|
159
|
+
startIndex = 2;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
for (let i = startIndex; i < pathArr.length; i++) {
|
|
163
|
+
arr = arr?.[pathArr[i]];
|
|
164
|
+
if (arr === undefined || arr === null) {
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (!Array.isArray(arr)) {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
// Only genuine array indices are reachable; anything else (e.g.
|
|
172
|
+
// 'constructor', '__lookupGetter__') would read off the prototype
|
|
173
|
+
// chain and could leak a host function reference across the boundary.
|
|
174
|
+
if (!Number.isInteger(index) || index < 0) {
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
const element = arr[index];
|
|
178
|
+
// Functions are never reachable through the data surface — mirror the
|
|
179
|
+
// guard in getValueAtPath so a host callable can't cross the boundary
|
|
180
|
+
// (invariant: __tests__/host-fn-shadowing.test.ts).
|
|
181
|
+
if (typeof element === 'function') {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
// Dates have no enumerable own keys; pass through instead of
|
|
185
|
+
// marshaling as an empty object.
|
|
186
|
+
if (element instanceof Date) {
|
|
187
|
+
return element;
|
|
188
|
+
}
|
|
189
|
+
// If element is object/array, return metadata
|
|
190
|
+
if (element !== null && typeof element === 'object') {
|
|
191
|
+
if (Array.isArray(element)) {
|
|
192
|
+
return {
|
|
193
|
+
__isArray: true,
|
|
194
|
+
__length: element.length,
|
|
195
|
+
__data: null,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
__isObject: true,
|
|
200
|
+
__keys: Object.keys(element),
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
// Primitive element
|
|
204
|
+
return element;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Host-side dispatcher for the typed-RPC `callHost` channel.
|
|
208
|
+
*
|
|
209
|
+
* The guest sends one envelope per typed RPC invocation:
|
|
210
|
+
* `callHost({ type: 'getNodeFirst', nodeName, branchIndex?, runIndex? })`
|
|
211
|
+
*
|
|
212
|
+
* Inputs cross a trust boundary, so the dispatcher parses every envelope
|
|
213
|
+
* with the host-side zod schema (`bridgeMessageSchema`) before any
|
|
214
|
+
* dispatch happens. Anything that deviates from the declared shape —
|
|
215
|
+
* unknown `type`, missing required fields, extra unexpected fields,
|
|
216
|
+
* wrong field types — fails the parse and throws; the calling bridge
|
|
217
|
+
* catches and returns an error sentinel to the guest.
|
|
218
|
+
*
|
|
219
|
+
* After parsing, `switch (msg.type)` dispatches with a fully narrowed
|
|
220
|
+
* message type. The operation set is exactly the cases in this switch;
|
|
221
|
+
* the `type` field selects a static branch in source, not a property
|
|
222
|
+
* lookup on a runtime object. Each case reads a fixed literal property
|
|
223
|
+
* name off the host-side data proxy — the guest cannot influence which
|
|
224
|
+
* property is dereferenced.
|
|
225
|
+
*
|
|
226
|
+
* Return-value note: cases must return plain, structured-clone-able,
|
|
227
|
+
* JSON-shaped data. Each bridge marshals the result across its own
|
|
228
|
+
* boundary (structured clone for isolated-vm, sentinel-wrapped JSON
|
|
229
|
+
* round-trip for QuickJS), so engine objects or other non-cloneable
|
|
230
|
+
* values must not be returned.
|
|
231
|
+
*/
|
|
232
|
+
function dispatchHostCall(rawMsg, data) {
|
|
233
|
+
const msg = bridge_messages_1.bridgeMessageSchema.parse(rawMsg);
|
|
234
|
+
switch (msg.type) {
|
|
235
|
+
// The `$('Foo').{first,last,all}` typed RPCs.
|
|
236
|
+
//
|
|
237
|
+
// Eliminating `data.$` as a host-callable entirely would require
|
|
238
|
+
// reaching the `WorkflowDataProxy` internals (e.g.
|
|
239
|
+
// `getNodeExecutionOrPinnedData`) rather than the public `$()` API;
|
|
240
|
+
// that's a follow-up.
|
|
241
|
+
//
|
|
242
|
+
// `data.$` is a host-wired function (`WorkflowDataProxy`'s `$`). If it
|
|
243
|
+
// ever isn't, optional chaining short-circuits to `undefined` — the
|
|
244
|
+
// same observable result the runtime's `E()` handler produces from any
|
|
245
|
+
// thrown error here.
|
|
246
|
+
case 'getNodeFirst':
|
|
247
|
+
return data.$?.(msg.nodeName)?.first?.(msg.branchIndex, msg.runIndex);
|
|
248
|
+
case 'getNodeLast':
|
|
249
|
+
return data.$?.(msg.nodeName)?.last?.(msg.branchIndex, msg.runIndex);
|
|
250
|
+
case 'getNodeAll':
|
|
251
|
+
return data.$?.(msg.nodeName)?.all?.(msg.branchIndex, msg.runIndex);
|
|
252
|
+
// The `$input.{first,last,all}` typed RPCs.
|
|
253
|
+
//
|
|
254
|
+
// Each reads a fixed literal property name off `data.$input` (the
|
|
255
|
+
// host's `WorkflowDataProxy` input proxy). The host enforces zero
|
|
256
|
+
// arguments on these methods — the schemas have no fields besides
|
|
257
|
+
// `type`, so the guest cannot pass anything that would trigger the
|
|
258
|
+
// "should have no arguments" error path on the host side.
|
|
259
|
+
case 'getInputFirst':
|
|
260
|
+
return data.$input?.first?.();
|
|
261
|
+
case 'getInputLast':
|
|
262
|
+
return data.$input?.last?.();
|
|
263
|
+
case 'getInputAll':
|
|
264
|
+
return data.$input?.all?.();
|
|
265
|
+
// `$items(nodeName?, outputIndex?, runIndex?)` — the global accessor
|
|
266
|
+
// for a node's execution data. Reads the literal `$items` property
|
|
267
|
+
// off `data` (host-wired by `WorkflowDataProxy`) and forwards the
|
|
268
|
+
// validated args verbatim. The host applies its own defaults when
|
|
269
|
+
// fields are `undefined`.
|
|
270
|
+
case 'getItems':
|
|
271
|
+
return data.$items?.(msg.nodeName, msg.outputIndex, msg.runIndex);
|
|
272
|
+
// `$fromAI(name, description?, type?, defaultValue?)` and its
|
|
273
|
+
// `$fromAi` / `$fromai` aliases. Reads the literal `$fromAI` property
|
|
274
|
+
// off `data` (host-wired) and forwards the args. The host validates
|
|
275
|
+
// `name` (required + regex) and applies its own resolution / fallback
|
|
276
|
+
// logic, so empty / invalid names surface as the host's structured
|
|
277
|
+
// `ExpressionError` rather than a generic zod parse error.
|
|
278
|
+
//
|
|
279
|
+
// Note: `msg.valueType` maps to the host's third positional parameter
|
|
280
|
+
// (`_type` in `WorkflowDataProxy.handleFromAi`). The bridge protocol
|
|
281
|
+
// renames it to avoid collision with the `type` discriminator on the
|
|
282
|
+
// envelope — the host parameter currently goes unused, but if it ever
|
|
283
|
+
// gains a name (`type`), this mapping should stay explicit.
|
|
284
|
+
case 'fromAi':
|
|
285
|
+
return data.$fromAI?.(msg.name, msg.description, msg.valueType, msg.defaultValue);
|
|
286
|
+
// The `$('Foo').pairedItem(itemIndex?)` / `.itemMatching(...)` /
|
|
287
|
+
// `.item` cluster. Three separate typed RPCs, each reading exactly one
|
|
288
|
+
// literal property off the host node proxy.
|
|
289
|
+
//
|
|
290
|
+
// The split is load-bearing: the host's `pairedItemMethod` closure
|
|
291
|
+
// captures which property name the proxy `get` trap saw, and uses
|
|
292
|
+
// that to pick the right error message (e.g. "Missing item index for
|
|
293
|
+
// .itemMatching()") and to decide between method-call vs getter
|
|
294
|
+
// semantics for `.item`. Reading the matching property here lets
|
|
295
|
+
// those host-side branches fire exactly as they do in the legacy
|
|
296
|
+
// engine; no in-guest validation needed.
|
|
297
|
+
case 'getNodePairedItem':
|
|
298
|
+
return data.$?.(msg.nodeName)?.pairedItem?.(msg.itemIndex);
|
|
299
|
+
case 'getNodeItemMatching':
|
|
300
|
+
return data.$?.(msg.nodeName)?.itemMatching?.(msg.itemIndex);
|
|
301
|
+
case 'getNodeItem':
|
|
302
|
+
// `.item` is a host getter — accessing it invokes the resolver and
|
|
303
|
+
// returns the value immediately. Optional chaining only short-
|
|
304
|
+
// circuits on null/undefined; the getter still fires on access.
|
|
305
|
+
return data.$?.(msg.nodeName)?.item;
|
|
306
|
+
// `$evaluateExpression(expression, itemIndex?)`. Forwards the string
|
|
307
|
+
// to the host's nested-evaluation helper, which re-enters the
|
|
308
|
+
// expression engine on the inner expression. Under the VM engine this
|
|
309
|
+
// round-trips through the bridge again on a fresh evaluation cycle,
|
|
310
|
+
// which is the same shape the legacy engine supports.
|
|
311
|
+
case 'evaluateExpression':
|
|
312
|
+
return data.$evaluateExpression?.(msg.expression, msg.itemIndex);
|
|
313
|
+
// `$getPairedItem(destinationNodeName, incomingSourceData,
|
|
314
|
+
// initialPairedItem)`. Forwards directly to the host binding, which
|
|
315
|
+
// walks the paired-item ancestry chain back to the named upstream
|
|
316
|
+
// node and returns the matching execution item.
|
|
317
|
+
//
|
|
318
|
+
// The two trailing host parameters — `usedMethodName` and
|
|
319
|
+
// `nodeBeforeLast` — are deliberately not part of the wire protocol:
|
|
320
|
+
// the host's default for `usedMethodName` is already `$getPairedItem`,
|
|
321
|
+
// and `nodeBeforeLast` is an internal recursion argument the host sets
|
|
322
|
+
// during traversal.
|
|
323
|
+
case 'getPairedItem':
|
|
324
|
+
return data.$getPairedItem?.(msg.destinationNodeName, msg.incomingSourceData, msg.initialPairedItem);
|
|
325
|
+
default: {
|
|
326
|
+
// Unreachable at runtime — zod rejects unknown `type` values
|
|
327
|
+
// before the switch. The `never` assignment is the compile-time
|
|
328
|
+
// guard: a new schema added to `bridgeMessageSchema` without a
|
|
329
|
+
// matching case here becomes a type error.
|
|
330
|
+
const exhaustive = msg;
|
|
331
|
+
void exhaustive;
|
|
332
|
+
throw new Error('Unhandled bridge message');
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
//# sourceMappingURL=host-functions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-functions.js","sourceRoot":"","sources":["../../../src/bridge/host-functions.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,16 +43,6 @@ export declare class IsolatedVmBridge implements RuntimeBridge {
|
|
|
43
43
|
* @throws {Error} If context not initialized or bundle loading fails
|
|
44
44
|
*/
|
|
45
45
|
private loadVendorLibraries;
|
|
46
|
-
/**
|
|
47
|
-
* Verify the proxy system loaded correctly.
|
|
48
|
-
*
|
|
49
|
-
* The proxy system is loaded as part of the runtime bundle in loadVendorLibraries().
|
|
50
|
-
* This method verifies all required components are available.
|
|
51
|
-
*
|
|
52
|
-
* @private
|
|
53
|
-
* @throws {Error} If context not initialized or proxy system verification fails
|
|
54
|
-
*/
|
|
55
|
-
private verifyProxySystem;
|
|
56
46
|
/**
|
|
57
47
|
* Inject the E() error handler into the isolate context.
|
|
58
48
|
*
|
|
@@ -77,17 +67,20 @@ export declare class IsolatedVmBridge implements RuntimeBridge {
|
|
|
77
67
|
* @throws {Error} If context not initialized
|
|
78
68
|
*/
|
|
79
69
|
private injectErrorHandler;
|
|
70
|
+
/**
|
|
71
|
+
* Synchronous variant of initialize(): the same steps through isolated-vm's
|
|
72
|
+
* sync APIs, for on-demand creation inside the synchronous evaluate() path
|
|
73
|
+
* (lazy acquisition with an exhausted pool). Blocks the event loop for the
|
|
74
|
+
* duration of one isolate setup — pool warmup should stay on the async
|
|
75
|
+
* initialize().
|
|
76
|
+
*/
|
|
77
|
+
initializeSync(): void;
|
|
80
78
|
/**
|
|
81
79
|
* Create an ivm.Callback for getting value/metadata at a path.
|
|
82
80
|
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* Function-typed values are returned as `undefined` — every callable on
|
|
87
|
-
* the host data surface (`$('Foo').first()`, `$items()`, `$fromAI()`,
|
|
88
|
-
* `$evaluateExpression()`, `$getPairedItem()`) is wired in-isolate via
|
|
89
|
-
* the typed-RPC dispatcher (`callHost`). No expression form should
|
|
90
|
-
* reach a function through this path.
|
|
81
|
+
* Thin wrapper around the shared getValueAtPath (see host-functions.ts
|
|
82
|
+
* for navigation and guard semantics); errors are caught and returned
|
|
83
|
+
* as sentinels instead of crossing the isolate boundary.
|
|
91
84
|
*
|
|
92
85
|
* @param data - Current workflow data to use for callback responses
|
|
93
86
|
* @private
|
|
@@ -96,144 +89,32 @@ export declare class IsolatedVmBridge implements RuntimeBridge {
|
|
|
96
89
|
/**
|
|
97
90
|
* Create an ivm.Callback for getting array elements at an index.
|
|
98
91
|
*
|
|
99
|
-
*
|
|
92
|
+
* Thin wrapper around the shared getArrayElement (see host-functions.ts
|
|
93
|
+
* for navigation and guard semantics); errors are caught and returned
|
|
94
|
+
* as sentinels instead of crossing the isolate boundary.
|
|
100
95
|
*
|
|
101
96
|
* @param data - Current workflow data to use for callback responses
|
|
102
97
|
* @private
|
|
103
98
|
*/
|
|
104
99
|
private createGetArrayElementRef;
|
|
105
100
|
/**
|
|
106
|
-
* Create the
|
|
107
|
-
*
|
|
108
|
-
* The isolate sends one envelope per typed RPC invocation:
|
|
109
|
-
* `callHost({ type: 'getNodeFirst', nodeName, branchIndex?, runIndex? })`
|
|
101
|
+
* Create the ivm.Callback for the typed-RPC `callHost` channel.
|
|
110
102
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* wrong field types — fails the parse and an error sentinel is returned
|
|
116
|
-
* to the caller.
|
|
103
|
+
* Thin wrapper around the shared dispatchHostCall (see host-functions.ts
|
|
104
|
+
* for envelope validation and per-message rationale); errors — including
|
|
105
|
+
* zod parse failures — are caught and returned as sentinels instead of
|
|
106
|
+
* crossing the isolate boundary.
|
|
117
107
|
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* not
|
|
122
|
-
*
|
|
123
|
-
* Return-value note: handlers must return plain, structured-clone-able
|
|
124
|
-
* data. Results cross into the isolate through an ivm.Callback, which copies
|
|
125
|
-
* them via the structured-clone algorithm — return JSON-shaped values, not
|
|
126
|
-
* isolated-vm objects (`Reference`/`ExternalCopy`) or other non-cloneable
|
|
127
|
-
* values.
|
|
108
|
+
* Return-value note: the dispatcher returns plain, structured-clone-able
|
|
109
|
+
* data. Results cross into the isolate through an ivm.Callback, which
|
|
110
|
+
* copies them via the structured-clone algorithm — JSON-shaped values,
|
|
111
|
+
* not isolated-vm objects (`Reference`/`ExternalCopy`) or other
|
|
112
|
+
* non-cloneable values.
|
|
128
113
|
*
|
|
129
114
|
* @param data - Current workflow data
|
|
130
115
|
* @private
|
|
131
116
|
*/
|
|
132
117
|
private createCallHostRef;
|
|
133
|
-
/**
|
|
134
|
-
* Handlers for the `$('Foo').{first,last,all}` typed RPCs.
|
|
135
|
-
*
|
|
136
|
-
* Each handler reads a fixed literal property name off the host-side node
|
|
137
|
-
* proxy — the isolate cannot influence which property is dereferenced.
|
|
138
|
-
* Eliminating `data.$` as a host-callable entirely would require reaching
|
|
139
|
-
* the `WorkflowDataProxy` internals (e.g. `getNodeExecutionOrPinnedData`)
|
|
140
|
-
* rather than the public `$()` API; that's a follow-up.
|
|
141
|
-
*
|
|
142
|
-
* `data.$` is a host-wired function (`WorkflowDataProxy`'s `$`). If it
|
|
143
|
-
* ever isn't, optional chaining short-circuits to `undefined` — the same
|
|
144
|
-
* observable result the runtime's `E()` handler produces from any thrown
|
|
145
|
-
* error here.
|
|
146
|
-
*
|
|
147
|
-
* @private
|
|
148
|
-
*/
|
|
149
|
-
private handleGetNodeFirst;
|
|
150
|
-
private handleGetNodeLast;
|
|
151
|
-
private handleGetNodeAll;
|
|
152
|
-
/**
|
|
153
|
-
* Handlers for the `$input.{first,last,all}` typed RPCs.
|
|
154
|
-
*
|
|
155
|
-
* Each reads a fixed literal property name off `data.$input` (the host's
|
|
156
|
-
* `WorkflowDataProxy` input proxy). The host enforces zero arguments on
|
|
157
|
-
* these methods — the schemas have no fields besides `type`, so the
|
|
158
|
-
* isolate cannot pass anything that would trigger the "should have no
|
|
159
|
-
* arguments" error path on the host side.
|
|
160
|
-
*
|
|
161
|
-
* @private
|
|
162
|
-
*/
|
|
163
|
-
private handleGetInputFirst;
|
|
164
|
-
private handleGetInputLast;
|
|
165
|
-
private handleGetInputAll;
|
|
166
|
-
/**
|
|
167
|
-
* Handler for `$items(nodeName?, outputIndex?, runIndex?)` — the
|
|
168
|
-
* global accessor for a node's execution data. Reads the literal
|
|
169
|
-
* `$items` property off `data` (host-wired by `WorkflowDataProxy`)
|
|
170
|
-
* and forwards the validated args verbatim. The host applies its own
|
|
171
|
-
* defaults when fields are `undefined`.
|
|
172
|
-
*
|
|
173
|
-
* @private
|
|
174
|
-
*/
|
|
175
|
-
private handleGetItems;
|
|
176
|
-
/**
|
|
177
|
-
* Handler for `$fromAI(name, description?, type?, defaultValue?)` and its
|
|
178
|
-
* `$fromAi` / `$fromai` aliases. Reads the literal `$fromAI` property
|
|
179
|
-
* off `data` (host-wired) and forwards the args. The host validates
|
|
180
|
-
* `name` (required + regex) and applies its own resolution / fallback
|
|
181
|
-
* logic, so empty / invalid names surface as the host's structured
|
|
182
|
-
* `ExpressionError` rather than a generic zod parse error.
|
|
183
|
-
*
|
|
184
|
-
* Note: `msg.valueType` maps to the host's third positional parameter
|
|
185
|
-
* (`_type` in `WorkflowDataProxy.handleFromAi`). The bridge protocol
|
|
186
|
-
* renames it to avoid collision with the `type` discriminator on the
|
|
187
|
-
* envelope — the host parameter currently goes unused, but if it ever
|
|
188
|
-
* gains a name (`type`), this mapping should stay explicit.
|
|
189
|
-
*
|
|
190
|
-
* @private
|
|
191
|
-
*/
|
|
192
|
-
private handleFromAi;
|
|
193
|
-
/**
|
|
194
|
-
* Handlers for the `$('Foo').pairedItem(itemIndex?)` / `.itemMatching(...)` /
|
|
195
|
-
* `.item` cluster. Three separate typed RPCs, each reading exactly one
|
|
196
|
-
* literal property off the host node proxy.
|
|
197
|
-
*
|
|
198
|
-
* The split is load-bearing: the host's `pairedItemMethod` closure
|
|
199
|
-
* captures which property name the proxy `get` trap saw, and uses
|
|
200
|
-
* that to pick the right error message (e.g. "Missing item index for
|
|
201
|
-
* .itemMatching()") and to decide between method-call vs getter
|
|
202
|
-
* semantics for `.item`. Reading the matching property here lets
|
|
203
|
-
* those host-side branches fire exactly as they do in the legacy
|
|
204
|
-
* engine; no in-isolate validation needed.
|
|
205
|
-
*
|
|
206
|
-
* @private
|
|
207
|
-
*/
|
|
208
|
-
private handleGetNodePairedItem;
|
|
209
|
-
private handleGetNodeItemMatching;
|
|
210
|
-
private handleGetNodeItem;
|
|
211
|
-
/**
|
|
212
|
-
* Handler for `$evaluateExpression(expression, itemIndex?)`. Forwards
|
|
213
|
-
* the string to the host's nested-evaluation helper, which re-enters
|
|
214
|
-
* the expression engine on the inner expression. Under the VM engine
|
|
215
|
-
* this round-trips through the bridge again as a new evaluation on the
|
|
216
|
-
* enclosing call's time budget, which is the same shape the legacy
|
|
217
|
-
* engine supports.
|
|
218
|
-
*
|
|
219
|
-
* @private
|
|
220
|
-
*/
|
|
221
|
-
private handleEvaluateExpression;
|
|
222
|
-
/**
|
|
223
|
-
* Handler for `$getPairedItem(destinationNodeName, incomingSourceData,
|
|
224
|
-
* initialPairedItem)`. Forwards directly to the host binding, which
|
|
225
|
-
* walks the paired-item ancestry chain back to the named upstream node
|
|
226
|
-
* and returns the matching execution item.
|
|
227
|
-
*
|
|
228
|
-
* The two trailing host parameters — `usedMethodName` and
|
|
229
|
-
* `nodeBeforeLast` — are deliberately not part of the wire protocol:
|
|
230
|
-
* the host's default for `usedMethodName` is already `$getPairedItem`,
|
|
231
|
-
* and `nodeBeforeLast` is an internal recursion argument the host sets
|
|
232
|
-
* during traversal.
|
|
233
|
-
*
|
|
234
|
-
* @private
|
|
235
|
-
*/
|
|
236
|
-
private handleGetPairedItem;
|
|
237
118
|
/**
|
|
238
119
|
* Execute JavaScript code in the isolated context.
|
|
239
120
|
*
|
|
@@ -260,13 +141,6 @@ export declare class IsolatedVmBridge implements RuntimeBridge {
|
|
|
260
141
|
* ran on — reporting "timed out after 137ms" would misstate the limit.
|
|
261
142
|
*/
|
|
262
143
|
private timeoutError;
|
|
263
|
-
/**
|
|
264
|
-
* Reconstruct an error from serialized isolate data.
|
|
265
|
-
*
|
|
266
|
-
* Maps error names back to their host-side classes and restores
|
|
267
|
-
* custom properties that would otherwise be lost crossing the boundary.
|
|
268
|
-
*/
|
|
269
|
-
private reconstructError;
|
|
270
144
|
/**
|
|
271
145
|
* Dispose of the isolate and free resources.
|
|
272
146
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"isolated-vm-bridge.d.ts","sourceRoot":"","sources":["../../../src/bridge/isolated-vm-bridge.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"isolated-vm-bridge.d.ts","sourceRoot":"","sources":["../../../src/bridge/isolated-vm-bridge.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AA8G1F;;;;;;;;;;GAUG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IACrD,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,OAAO,CAAC,CAAc;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,MAAM,CAAmC;IAEjD,YAAY,MAAM,GAAE,YAAiB,EAUpC;IAED;;;;;;;;;;OAUG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAyBhC;IAED;;;;;;;;;;;OAWG;YACW,mBAAmB;IA8BjC;;;;;;;;;;;;;;;;;;;;;;OAsBG;YACW,kBAAkB;IAUhC;;;;;;OAMG;IACH,cAAc,IAAI,IAAI,CAgCrB;IAED;;;;;;;;;OASG;IACH,OAAO,CAAC,uBAAuB;IAU/B;;;;;;;;;OASG;IACH,OAAO,CAAC,wBAAwB;IAUhC;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,iBAAiB;IAUzB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CA8G3E;IAED;;;OAGG;IACH,OAAO,CAAC,YAAY;IASpB;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAc7B;IAED;;;;OAIG;IACH,UAAU,IAAI,OAAO,CAEpB;CACD"}
|