@n8n/expression-runtime 0.21.0 → 0.23.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.
Files changed (115) hide show
  1. package/dist/cjs/bridge/bridge-messages.d.ts +8 -8
  2. package/dist/cjs/bridge/bridge-messages.js +234 -244
  3. package/dist/cjs/bridge/bridge-messages.js.map +1 -1
  4. package/dist/cjs/bridge/isolated-vm-bridge.d.ts.map +1 -1
  5. package/dist/cjs/bridge/isolated-vm-bridge.js +633 -643
  6. package/dist/cjs/bridge/isolated-vm-bridge.js.map +1 -1
  7. package/dist/cjs/build.tsbuildinfo +1 -1
  8. package/dist/cjs/evaluator/error-classification.js +15 -25
  9. package/dist/cjs/evaluator/error-classification.js.map +1 -1
  10. package/dist/cjs/evaluator/expression-evaluator.d.ts +7 -1
  11. package/dist/cjs/evaluator/expression-evaluator.d.ts.map +1 -1
  12. package/dist/cjs/evaluator/expression-evaluator.js +152 -155
  13. package/dist/cjs/evaluator/expression-evaluator.js.map +1 -1
  14. package/dist/cjs/evaluator/lru-cache.d.ts.map +1 -1
  15. package/dist/cjs/evaluator/lru-cache.js +35 -45
  16. package/dist/cjs/evaluator/lru-cache.js.map +1 -1
  17. package/dist/cjs/extensions/array-extensions.js +589 -599
  18. package/dist/cjs/extensions/array-extensions.js.map +1 -1
  19. package/dist/cjs/extensions/boolean-extensions.js +38 -48
  20. package/dist/cjs/extensions/boolean-extensions.js.map +1 -1
  21. package/dist/cjs/extensions/date-extensions.js +500 -510
  22. package/dist/cjs/extensions/date-extensions.js.map +1 -1
  23. package/dist/cjs/extensions/expression-extension-error.d.ts.map +1 -1
  24. package/dist/cjs/extensions/expression-extension-error.js +12 -22
  25. package/dist/cjs/extensions/expression-extension-error.js.map +1 -1
  26. package/dist/cjs/extensions/extend.js +162 -172
  27. package/dist/cjs/extensions/extend.js.map +1 -1
  28. package/dist/cjs/extensions/extensions.js +2 -12
  29. package/dist/cjs/extensions/function-extensions.d.ts +10 -18
  30. package/dist/cjs/extensions/function-extensions.d.ts.map +1 -1
  31. package/dist/cjs/extensions/function-extensions.js +78 -88
  32. package/dist/cjs/extensions/function-extensions.js.map +1 -1
  33. package/dist/cjs/extensions/number-extensions.js +225 -235
  34. package/dist/cjs/extensions/number-extensions.js.map +1 -1
  35. package/dist/cjs/extensions/object-extensions.js +286 -296
  36. package/dist/cjs/extensions/object-extensions.js.map +1 -1
  37. package/dist/cjs/extensions/string-extensions.d.ts +1 -1
  38. package/dist/cjs/extensions/string-extensions.d.ts.map +1 -1
  39. package/dist/cjs/extensions/string-extensions.js +758 -768
  40. package/dist/cjs/extensions/string-extensions.js.map +1 -1
  41. package/dist/cjs/extensions/utils.d.ts.map +1 -1
  42. package/dist/cjs/extensions/utils.js +28 -38
  43. package/dist/cjs/extensions/utils.js.map +1 -1
  44. package/dist/cjs/index.js +32 -42
  45. package/dist/cjs/index.js.map +1 -1
  46. package/dist/cjs/observability/metrics.d.ts +27 -27
  47. package/dist/cjs/observability/metrics.d.ts.map +1 -1
  48. package/dist/cjs/observability/metrics.js +59 -69
  49. package/dist/cjs/observability/metrics.js.map +1 -1
  50. package/dist/cjs/observability/noop-provider.js +28 -38
  51. package/dist/cjs/observability/noop-provider.js.map +1 -1
  52. package/dist/cjs/pool/idle-scaling-pool.d.ts.map +1 -1
  53. package/dist/cjs/pool/idle-scaling-pool.js +134 -144
  54. package/dist/cjs/pool/idle-scaling-pool.js.map +1 -1
  55. package/dist/cjs/pool/isolate-pool.d.ts.map +1 -1
  56. package/dist/cjs/pool/isolate-pool.js +101 -111
  57. package/dist/cjs/pool/isolate-pool.js.map +1 -1
  58. package/dist/cjs/runtime/context.js +418 -428
  59. package/dist/cjs/runtime/context.js.map +1 -1
  60. package/dist/cjs/runtime/index.js +26 -36
  61. package/dist/cjs/runtime/index.js.map +1 -1
  62. package/dist/cjs/runtime/jmespath.js +72 -82
  63. package/dist/cjs/runtime/jmespath.js.map +1 -1
  64. package/dist/cjs/runtime/lazy-proxy.js +238 -248
  65. package/dist/cjs/runtime/lazy-proxy.js.map +1 -1
  66. package/dist/cjs/runtime/safe-globals.d.ts.map +1 -1
  67. package/dist/cjs/runtime/safe-globals.js +134 -144
  68. package/dist/cjs/runtime/safe-globals.js.map +1 -1
  69. package/dist/cjs/runtime/serialize.js +54 -64
  70. package/dist/cjs/runtime/serialize.js.map +1 -1
  71. package/dist/cjs/runtime/utils.js +20 -30
  72. package/dist/cjs/runtime/utils.js.map +1 -1
  73. package/dist/cjs/types/bridge.js +15 -25
  74. package/dist/cjs/types/bridge.js.map +1 -1
  75. package/dist/cjs/types/evaluator.d.ts +5 -1
  76. package/dist/cjs/types/evaluator.d.ts.map +1 -1
  77. package/dist/cjs/types/evaluator.js +35 -45
  78. package/dist/cjs/types/evaluator.js.map +1 -1
  79. package/dist/cjs/types/index.js +14 -24
  80. package/dist/cjs/types/index.js.map +1 -1
  81. package/dist/cjs/types/runtime.d.ts.map +1 -1
  82. package/dist/cjs/types/runtime.js +27 -37
  83. package/dist/cjs/types/runtime.js.map +1 -1
  84. package/dist/esm/bridge/bridge-messages.d.ts +8 -8
  85. package/dist/esm/bridge/isolated-vm-bridge.d.ts.map +1 -1
  86. package/dist/esm/bridge/isolated-vm-bridge.js.map +1 -1
  87. package/dist/esm/build.tsbuildinfo +1 -1
  88. package/dist/esm/evaluator/expression-evaluator.d.ts +7 -1
  89. package/dist/esm/evaluator/expression-evaluator.d.ts.map +1 -1
  90. package/dist/esm/evaluator/expression-evaluator.js +8 -1
  91. package/dist/esm/evaluator/expression-evaluator.js.map +1 -1
  92. package/dist/esm/evaluator/lru-cache.d.ts.map +1 -1
  93. package/dist/esm/evaluator/lru-cache.js.map +1 -1
  94. package/dist/esm/extensions/expression-extension-error.d.ts.map +1 -1
  95. package/dist/esm/extensions/function-extensions.d.ts +10 -18
  96. package/dist/esm/extensions/function-extensions.d.ts.map +1 -1
  97. package/dist/esm/extensions/number-extensions.js.map +1 -1
  98. package/dist/esm/extensions/string-extensions.d.ts +1 -1
  99. package/dist/esm/extensions/string-extensions.d.ts.map +1 -1
  100. package/dist/esm/extensions/string-extensions.js.map +1 -1
  101. package/dist/esm/extensions/utils.d.ts.map +1 -1
  102. package/dist/esm/observability/metrics.d.ts +27 -27
  103. package/dist/esm/observability/metrics.d.ts.map +1 -1
  104. package/dist/esm/pool/idle-scaling-pool.d.ts.map +1 -1
  105. package/dist/esm/pool/idle-scaling-pool.js.map +1 -1
  106. package/dist/esm/pool/isolate-pool.d.ts.map +1 -1
  107. package/dist/esm/pool/isolate-pool.js.map +1 -1
  108. package/dist/esm/runtime/lazy-proxy.js.map +1 -1
  109. package/dist/esm/runtime/safe-globals.d.ts.map +1 -1
  110. package/dist/esm/types/evaluator.d.ts +5 -1
  111. package/dist/esm/types/evaluator.d.ts.map +1 -1
  112. package/dist/esm/types/evaluator.js.map +1 -1
  113. package/dist/esm/types/runtime.d.ts.map +1 -1
  114. package/dist/esm/types/runtime.js.map +1 -1
  115. package/package.json +7 -6
@@ -1,449 +1,439 @@
1
- (function (factory) {
2
- if (typeof module === "object" && typeof module.exports === "object") {
3
- var v = factory(require, exports);
4
- if (v !== undefined) module.exports = v;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildContext = buildContext;
4
+ const luxon_1 = require("luxon");
5
+ const extend_1 = require("../extensions/extend");
6
+ const function_extensions_1 = require("../extensions/function-extensions");
7
+ const safe_globals_1 = require("./safe-globals");
8
+ const lazy_proxy_1 = require("./lazy-proxy");
9
+ const jmespath_1 = require("./jmespath");
10
+ const utils_1 = require("./utils");
11
+ // Pre-create safe error subclass wrappers (reused across evaluations)
12
+ const SafeTypeError = (0, safe_globals_1.createSafeErrorSubclass)(TypeError);
13
+ const SafeSyntaxError = (0, safe_globals_1.createSafeErrorSubclass)(SyntaxError);
14
+ const SafeEvalError = (0, safe_globals_1.createSafeErrorSubclass)(EvalError);
15
+ const SafeRangeError = (0, safe_globals_1.createSafeErrorSubclass)(RangeError);
16
+ const SafeReferenceError = (0, safe_globals_1.createSafeErrorSubclass)(ReferenceError);
17
+ const SafeURIError = (0, safe_globals_1.createSafeErrorSubclass)(URIError);
18
+ /**
19
+ * Maps proxy property names on `$('NodeName')` to the typed-RPC discriminator
20
+ * the bridge dispatches on. Single source of truth for the synthetic proxy's
21
+ * `get`/`has` traps and the `sendNodeMethod` envelope builder. Adding a new
22
+ * `getNode*` schema to `BridgeMessage` lets you wire a new method here in
23
+ * one place; `satisfies` catches typos in the discriminator string.
24
+ */
25
+ const NODE_RPC_TYPES = {
26
+ first: 'getNodeFirst',
27
+ last: 'getNodeLast',
28
+ all: 'getNodeAll',
29
+ };
30
+ /**
31
+ * Same shape as `NODE_RPC_TYPES`, for the current node's `$input` proxy.
32
+ * Discriminators are `getInput*` and the host enforces zero-arg invocation.
33
+ */
34
+ const INPUT_RPC_TYPES = {
35
+ first: 'getInputFirst',
36
+ last: 'getInputLast',
37
+ all: 'getInputAll',
38
+ };
39
+ /**
40
+ * Build a fresh, closure-scoped evaluation context.
41
+ *
42
+ * This function creates a context object that contains everything needed to
43
+ * evaluate an expression, without touching any global mutable state
44
+ * (except luxon's Settings.defaultZone which is process-wide).
45
+ *
46
+ * The returned object is used as tournament's `this` context in the
47
+ * evalClosureSync wrapper.
48
+ *
49
+ * @param callbacks - Bridge callbacks (data-access primitives + typed RPCs)
50
+ * @param timezone - Optional IANA timezone string
51
+ * @returns A context object with all workflow data, proxies, and builtins
52
+ */
53
+ function buildContext(callbacks, timezone) {
54
+ if (timezone && !luxon_1.IANAZone.isValidZone(timezone)) {
55
+ throw new Error(`Invalid timezone: "${timezone}"`);
5
56
  }
6
- else if (typeof define === "function" && define.amd) {
7
- define(["require", "exports", "luxon", "../extensions/extend", "../extensions/function-extensions", "./safe-globals", "./lazy-proxy", "./jmespath", "./utils"], factory);
8
- }
9
- })(function (require, exports) {
10
- "use strict";
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.buildContext = buildContext;
13
- const luxon_1 = require("luxon");
14
- const extend_1 = require("../extensions/extend");
15
- const function_extensions_1 = require("../extensions/function-extensions");
16
- const safe_globals_1 = require("./safe-globals");
17
- const lazy_proxy_1 = require("./lazy-proxy");
18
- const jmespath_1 = require("./jmespath");
19
- const utils_1 = require("./utils");
20
- // Pre-create safe error subclass wrappers (reused across evaluations)
21
- const SafeTypeError = (0, safe_globals_1.createSafeErrorSubclass)(TypeError);
22
- const SafeSyntaxError = (0, safe_globals_1.createSafeErrorSubclass)(SyntaxError);
23
- const SafeEvalError = (0, safe_globals_1.createSafeErrorSubclass)(EvalError);
24
- const SafeRangeError = (0, safe_globals_1.createSafeErrorSubclass)(RangeError);
25
- const SafeReferenceError = (0, safe_globals_1.createSafeErrorSubclass)(ReferenceError);
26
- const SafeURIError = (0, safe_globals_1.createSafeErrorSubclass)(URIError);
27
- /**
28
- * Maps proxy property names on `$('NodeName')` to the typed-RPC discriminator
29
- * the bridge dispatches on. Single source of truth for the synthetic proxy's
30
- * `get`/`has` traps and the `sendNodeMethod` envelope builder. Adding a new
31
- * `getNode*` schema to `BridgeMessage` lets you wire a new method here in
32
- * one place; `satisfies` catches typos in the discriminator string.
33
- */
34
- const NODE_RPC_TYPES = {
35
- first: 'getNodeFirst',
36
- last: 'getNodeLast',
37
- all: 'getNodeAll',
38
- };
39
- /**
40
- * Same shape as `NODE_RPC_TYPES`, for the current node's `$input` proxy.
41
- * Discriminators are `getInput*` and the host enforces zero-arg invocation.
42
- */
43
- const INPUT_RPC_TYPES = {
44
- first: 'getInputFirst',
45
- last: 'getInputLast',
46
- all: 'getInputAll',
57
+ luxon_1.Settings.defaultZone = timezone ?? 'system';
58
+ const target = {};
59
+ // __sanitize must be on the context because PrototypeSanitizer generates:
60
+ // obj[this.__sanitize(expr)] where 'this' is the context (via .call(ctx) wrapping)
61
+ // Use a non-writable property descriptor so override attempts throw instead of silently succeeding.
62
+ Object.defineProperty(target, '__sanitize', {
63
+ get: () => safe_globals_1.__sanitize,
64
+ set: () => {
65
+ throw new safe_globals_1.ExpressionError('Cannot override "__sanitize" due to security concerns');
66
+ },
67
+ enumerable: false,
68
+ configurable: false,
69
+ });
70
+ // -------------------------------------------------------------------------
71
+ // Create DateTime values inside the isolate (not lazy-loaded from host,
72
+ // because host-side DateTime objects lose their prototype crossing the
73
+ // boundary). The isolate has its own luxon with the correct timezone
74
+ // already set via Settings.defaultZone above.
75
+ // -------------------------------------------------------------------------
76
+ target.$now = luxon_1.DateTime.now();
77
+ target.$today = luxon_1.DateTime.now().set({ hour: 0, minute: 0, second: 0, millisecond: 0 });
78
+ // -------------------------------------------------------------------------
79
+ // Expose standalone functions (min, max, average, numberList, zip, $ifEmpty, etc.)
80
+ // -------------------------------------------------------------------------
81
+ Object.assign(target, function_extensions_1.extendedFunctions);
82
+ // -------------------------------------------------------------------------
83
+ // Expose globals on target so tournament's "x in this ? this.x : global.x"
84
+ // pattern resolves them correctly (tournament checks ctx before global)
85
+ // -------------------------------------------------------------------------
86
+ target.DateTime = globalThis.DateTime;
87
+ target.Duration = globalThis.Duration;
88
+ target.Interval = globalThis.Interval;
89
+ // Expose extend/extendOptional on target so tournament's "x in this ? this.x : global.x"
90
+ // pattern resolves them correctly when the VM checks ctx first
91
+ target.extend = extend_1.extend;
92
+ target.extendOptional = extend_1.extendOptional;
93
+ // Expose jmespath helpers in-isolate so they shadow the host-side
94
+ // `data.$jmesPath` / `data.$jmespath` from WorkflowDataProxy. Same rationale
95
+ // as extend / extendOptional above: keeping these in-isolate removes them
96
+ // from the bridge's reachable host-callable surface.
97
+ target.$jmesPath = jmespath_1.jmesPath;
98
+ target.$jmespath = jmespath_1.jmesPath;
99
+ // Wire builtins so tournament's VariablePolyfill resolves them from ctx
100
+ initializeBuiltins(target);
101
+ // $item(i) → single lazy proxy at ['$item', i]; the host bridge navigates
102
+ // data.$item(i).<rest> safely (see isolated-vm-bridge getValueAtPath),
103
+ // exposing the full accessor surface ($json, $binary, $node, $nodeId, ...).
104
+ target.$item = function (itemIndex) {
105
+ return (0, lazy_proxy_1.createDeepLazyProxy)(['$item', String(itemIndex)], undefined, callbacks);
47
106
  };
48
- /**
49
- * Build a fresh, closure-scoped evaluation context.
50
- *
51
- * This function creates a context object that contains everything needed to
52
- * evaluate an expression, without touching any global mutable state
53
- * (except luxon's Settings.defaultZone which is process-wide).
54
- *
55
- * The returned object is used as tournament's `this` context in the
56
- * evalClosureSync wrapper.
57
- *
58
- * @param callbacks - Bridge callbacks (data-access primitives + typed RPCs)
59
- * @param timezone - Optional IANA timezone string
60
- * @returns A context object with all workflow data, proxies, and builtins
61
- */
62
- function buildContext(callbacks, timezone) {
63
- if (timezone && !luxon_1.IANAZone.isValidZone(timezone)) {
64
- throw new Error(`Invalid timezone: "${timezone}"`);
65
- }
66
- luxon_1.Settings.defaultZone = timezone ?? 'system';
67
- const target = {};
68
- // __sanitize must be on the context because PrototypeSanitizer generates:
69
- // obj[this.__sanitize(expr)] where 'this' is the context (via .call(ctx) wrapping)
70
- // Use a non-writable property descriptor so override attempts throw instead of silently succeeding.
71
- Object.defineProperty(target, '__sanitize', {
72
- get: () => safe_globals_1.__sanitize,
73
- set: () => {
74
- throw new safe_globals_1.ExpressionError('Cannot override "__sanitize" due to security concerns');
75
- },
76
- enumerable: false,
77
- configurable: false,
78
- });
79
- // -------------------------------------------------------------------------
80
- // Create DateTime values inside the isolate (not lazy-loaded from host,
81
- // because host-side DateTime objects lose their prototype crossing the
82
- // boundary). The isolate has its own luxon with the correct timezone
83
- // already set via Settings.defaultZone above.
84
- // -------------------------------------------------------------------------
85
- target.$now = luxon_1.DateTime.now();
86
- target.$today = luxon_1.DateTime.now().set({ hour: 0, minute: 0, second: 0, millisecond: 0 });
87
- // -------------------------------------------------------------------------
88
- // Expose standalone functions (min, max, average, numberList, zip, $ifEmpty, etc.)
89
- // -------------------------------------------------------------------------
90
- Object.assign(target, function_extensions_1.extendedFunctions);
91
- // -------------------------------------------------------------------------
92
- // Expose globals on target so tournament's "x in this ? this.x : global.x"
93
- // pattern resolves them correctly (tournament checks ctx before global)
94
- // -------------------------------------------------------------------------
95
- target.DateTime = globalThis.DateTime;
96
- target.Duration = globalThis.Duration;
97
- target.Interval = globalThis.Interval;
98
- // Expose extend/extendOptional on target so tournament's "x in this ? this.x : global.x"
99
- // pattern resolves them correctly when the VM checks ctx first
100
- target.extend = extend_1.extend;
101
- target.extendOptional = extend_1.extendOptional;
102
- // Expose jmespath helpers in-isolate so they shadow the host-side
103
- // `data.$jmesPath` / `data.$jmespath` from WorkflowDataProxy. Same rationale
104
- // as extend / extendOptional above: keeping these in-isolate removes them
105
- // from the bridge's reachable host-callable surface.
106
- target.$jmesPath = jmespath_1.jmesPath;
107
- target.$jmespath = jmespath_1.jmesPath;
108
- // Wire builtins so tournament's VariablePolyfill resolves them from ctx
109
- initializeBuiltins(target);
110
- // $item(i) → single lazy proxy at ['$item', i]; the host bridge navigates
111
- // data.$item(i).<rest> safely (see isolated-vm-bridge getValueAtPath),
112
- // exposing the full accessor surface ($json, $binary, $node, $nodeId, ...).
113
- target.$item = function (itemIndex) {
114
- return (0, lazy_proxy_1.createDeepLazyProxy)(['$item', String(itemIndex)], undefined, callbacks);
115
- };
116
- // $() function for accessing other nodes.
117
- //
118
- // The returned object is a Proxy whose `get` trap intercepts properties
119
- // that have a typed RPC (e.g. `.first` → `getNodeFirst`) and routes them
120
- // through the `callHost` envelope. Everything else (properties like
121
- // `.params`, `.json`, and methods that don't yet have a typed RPC) is
122
- // read from an underlying lazy proxy via explicit delegation.
123
- //
124
- // Important: the synthetic Proxy's *target* is a plain `{}` rather than
125
- // the lazy proxy itself. Nesting one Proxy inside another causes V8 to
126
- // run invariant checks (`[[OwnPropertyKeys]]`, descriptor consistency)
127
- // against the inner target, which would trigger the lazy proxy's
128
- // `ownKeys` trap and an unnecessary `getValueAtPath` round-trip for the
129
- // whole node's keys. Using `{}` as the target keeps those checks cheap;
130
- // the lazy proxy lives in closure and is only consulted on demand.
131
- //
132
- // As more typed RPCs are added, more cases land in this trap.
133
- // The `has` trap mirrors the `get` trap for typed-RPC names so that
134
- // tournament's `"first" in this.$('Foo')` check resolves true even though
135
- // the inner target is empty.
136
- target.$ = function (nodeName) {
137
- const lazyProxy = (0, lazy_proxy_1.createDeepLazyProxy)(['$', nodeName], undefined, callbacks);
138
- const sendNodeMethod = (type) => {
139
- return (branchIndex, runIndex) => {
140
- const result = callbacks.callHost.applySync(null, [{ type, nodeName, branchIndex, runIndex }], { arguments: { copy: true }, result: { copy: true } });
141
- (0, lazy_proxy_1.throwIfErrorSentinel)(result);
142
- return result;
143
- };
144
- };
145
- // Paired-item cluster: `.pairedItem(idx?)`, `.itemMatching(idx)`,
146
- // `.item`. Each surface form has its own typed-RPC discriminator
147
- // (`getNodePairedItem` / `getNodeItemMatching` / `getNodeItem`)
148
- // because the host's resolver closes over the literal property
149
- // name to pick error messages and getter-vs-method semantics.
150
- // The bridge handler for each reads the matching property name.
151
- const sendPairedRpc = (type, itemIndex) => {
152
- const result = callbacks.callHost.applySync(null, [{ type, nodeName, itemIndex }], {
153
- arguments: { copy: true },
154
- result: { copy: true },
155
- });
107
+ // $() function for accessing other nodes.
108
+ //
109
+ // The returned object is a Proxy whose `get` trap intercepts properties
110
+ // that have a typed RPC (e.g. `.first` `getNodeFirst`) and routes them
111
+ // through the `callHost` envelope. Everything else (properties like
112
+ // `.params`, `.json`, and methods that don't yet have a typed RPC) is
113
+ // read from an underlying lazy proxy via explicit delegation.
114
+ //
115
+ // Important: the synthetic Proxy's *target* is a plain `{}` rather than
116
+ // the lazy proxy itself. Nesting one Proxy inside another causes V8 to
117
+ // run invariant checks (`[[OwnPropertyKeys]]`, descriptor consistency)
118
+ // against the inner target, which would trigger the lazy proxy's
119
+ // `ownKeys` trap and an unnecessary `getValueAtPath` round-trip for the
120
+ // whole node's keys. Using `{}` as the target keeps those checks cheap;
121
+ // the lazy proxy lives in closure and is only consulted on demand.
122
+ //
123
+ // As more typed RPCs are added, more cases land in this trap.
124
+ // The `has` trap mirrors the `get` trap for typed-RPC names so that
125
+ // tournament's `"first" in this.$('Foo')` check resolves true even though
126
+ // the inner target is empty.
127
+ target.$ = function (nodeName) {
128
+ const lazyProxy = (0, lazy_proxy_1.createDeepLazyProxy)(['$', nodeName], undefined, callbacks);
129
+ const sendNodeMethod = (type) => {
130
+ return (branchIndex, runIndex) => {
131
+ const result = callbacks.callHost.applySync(null, [{ type, nodeName, branchIndex, runIndex }], { arguments: { copy: true }, result: { copy: true } });
156
132
  (0, lazy_proxy_1.throwIfErrorSentinel)(result);
157
133
  return result;
158
134
  };
159
- const sendGetNodeItem = () => {
160
- const result = callbacks.callHost.applySync(null, [{ type: 'getNodeItem', nodeName }], {
161
- arguments: { copy: true },
162
- result: { copy: true },
163
- });
164
- (0, lazy_proxy_1.throwIfErrorSentinel)(result);
165
- return result;
166
- };
167
- return new Proxy({}, {
168
- get(_emptyTarget, prop) {
169
- if ((0, utils_1.isKeyOf)(NODE_RPC_TYPES, prop)) {
170
- return sendNodeMethod(NODE_RPC_TYPES[prop]);
171
- }
172
- if (prop === 'pairedItem') {
173
- return (itemIndex) => sendPairedRpc('getNodePairedItem', itemIndex);
174
- }
175
- if (prop === 'itemMatching') {
176
- return (itemIndex) => sendPairedRpc('getNodeItemMatching', itemIndex);
177
- }
178
- if (prop === 'item') {
179
- // Getter form: invoke immediately, return the value.
180
- return sendGetNodeItem();
181
- }
182
- // Everything else: delegate to the lazy proxy. The lazy proxy's
183
- // own `get` trap handles caching, host fetching, and metadata.
184
- return lazyProxy[prop];
185
- },
186
- has(_emptyTarget, prop) {
187
- return ((0, utils_1.isKeyOf)(NODE_RPC_TYPES, prop) ||
188
- prop === 'pairedItem' ||
189
- prop === 'itemMatching' ||
190
- prop === 'item' ||
191
- prop in lazyProxy);
192
- },
135
+ };
136
+ // Paired-item cluster: `.pairedItem(idx?)`, `.itemMatching(idx)`,
137
+ // `.item`. Each surface form has its own typed-RPC discriminator
138
+ // (`getNodePairedItem` / `getNodeItemMatching` / `getNodeItem`)
139
+ // because the host's resolver closes over the literal property
140
+ // name to pick error messages and getter-vs-method semantics.
141
+ // The bridge handler for each reads the matching property name.
142
+ const sendPairedRpc = (type, itemIndex) => {
143
+ const result = callbacks.callHost.applySync(null, [{ type, nodeName, itemIndex }], {
144
+ arguments: { copy: true },
145
+ result: { copy: true },
193
146
  });
147
+ (0, lazy_proxy_1.throwIfErrorSentinel)(result);
148
+ return result;
194
149
  };
195
- // $input current-node input proxy. Same synthetic-Proxy pattern as
196
- // `target.$()`: intercept the typed-RPC method names (`first`, `last`,
197
- // `all`, all zero-arg per the host's `WorkflowDataProxy`), delegate
198
- // everything else (notably the `.item` getter and `.params` / `.context`
199
- // properties) to a lazy proxy on `$input`.
200
- const lazyInputProxy = (0, lazy_proxy_1.createDeepLazyProxy)(['$input'], undefined, callbacks);
201
- const sendInputMethod = (type) => {
202
- return () => {
203
- const result = callbacks.callHost.applySync(null, [{ type }], {
204
- arguments: { copy: true },
205
- result: { copy: true },
206
- });
207
- (0, lazy_proxy_1.throwIfErrorSentinel)(result);
208
- return result;
209
- };
150
+ const sendGetNodeItem = () => {
151
+ const result = callbacks.callHost.applySync(null, [{ type: 'getNodeItem', nodeName }], {
152
+ arguments: { copy: true },
153
+ result: { copy: true },
154
+ });
155
+ (0, lazy_proxy_1.throwIfErrorSentinel)(result);
156
+ return result;
210
157
  };
211
- target.$input = new Proxy({}, {
158
+ return new Proxy({}, {
212
159
  get(_emptyTarget, prop) {
213
- if ((0, utils_1.isKeyOf)(INPUT_RPC_TYPES, prop))
214
- return sendInputMethod(INPUT_RPC_TYPES[prop]);
215
- return lazyInputProxy[prop];
160
+ if ((0, utils_1.isKeyOf)(NODE_RPC_TYPES, prop)) {
161
+ return sendNodeMethod(NODE_RPC_TYPES[prop]);
162
+ }
163
+ if (prop === 'pairedItem') {
164
+ return (itemIndex) => sendPairedRpc('getNodePairedItem', itemIndex);
165
+ }
166
+ if (prop === 'itemMatching') {
167
+ return (itemIndex) => sendPairedRpc('getNodeItemMatching', itemIndex);
168
+ }
169
+ if (prop === 'item') {
170
+ // Getter form: invoke immediately, return the value.
171
+ return sendGetNodeItem();
172
+ }
173
+ // Everything else: delegate to the lazy proxy. The lazy proxy's
174
+ // own `get` trap handles caching, host fetching, and metadata.
175
+ return lazyProxy[prop];
216
176
  },
217
177
  has(_emptyTarget, prop) {
218
- return (0, utils_1.isKeyOf)(INPUT_RPC_TYPES, prop) || prop in lazyInputProxy;
178
+ return ((0, utils_1.isKeyOf)(NODE_RPC_TYPES, prop) ||
179
+ prop === 'pairedItem' ||
180
+ prop === 'itemMatching' ||
181
+ prop === 'item' ||
182
+ prop in lazyProxy);
219
183
  },
220
184
  });
221
- // $items — global accessor for a node's execution data. Unlike $() and
222
- // $input this is a plain typed-RPC function (not a synthetic Proxy):
223
- // the host enforces nothing structural here, the schema validates the
224
- // args, and the host's `WorkflowDataProxy.$items` applies its own
225
- // defaults when fields are undefined.
226
- target.$items = (nodeName, outputIndex, runIndex) => {
227
- const result = callbacks.callHost.applySync(null, [{ type: 'getItems', nodeName, outputIndex, runIndex }], { arguments: { copy: true }, result: { copy: true } });
228
- (0, lazy_proxy_1.throwIfErrorSentinel)(result);
229
- return result;
230
- };
231
- // $fromAI / $fromAi / $fromai — AI-builder placeholder accessor.
232
- // All three host aliases route to the same `handleFromAi` callback;
233
- // the typed-RPC envelope is identical regardless of which name the
234
- // expression used. `name` is forwarded as-is — host validates it
235
- // (required, regex-restricted) and emits a structured `ExpressionError`
236
- // on bad input.
237
- const sendFromAi = (name, description, valueType, defaultValue) => {
238
- const result = callbacks.callHost.applySync(null, [{ type: 'fromAi', name, description, valueType, defaultValue }], { arguments: { copy: true }, result: { copy: true } });
239
- (0, lazy_proxy_1.throwIfErrorSentinel)(result);
240
- return result;
241
- };
242
- target.$fromAI = sendFromAi;
243
- target.$fromAi = sendFromAi;
244
- target.$fromai = sendFromAi;
245
- // $evaluateExpression — recursive expression evaluator. Forwards the
246
- // inner expression string to the host, which re-invokes the engine.
247
- // Under the VM engine this re-enters the bridge on a fresh evaluation;
248
- // the legacy engine handles it inline.
249
- target.$evaluateExpression = (expression, itemIndex) => {
250
- const result = callbacks.callHost.applySync(null, [{ type: 'evaluateExpression', expression, itemIndex }], { arguments: { copy: true }, result: { copy: true } });
251
- (0, lazy_proxy_1.throwIfErrorSentinel)(result);
252
- return result;
253
- };
254
- // $getPairedItem — walks the paired-item ancestry chain back to the
255
- // named upstream node. The host validates the structural shape of
256
- // `incomingSourceData` and `initialPairedItem` via the typed-RPC
257
- // schema; bad input surfaces as a schema-parse error sentinel rather
258
- // than a host throw, keeping the protocol surface tight.
259
- target.$getPairedItem = (destinationNodeName, incomingSourceData, initialPairedItem) => {
260
- const result = callbacks.callHost.applySync(null, [
261
- {
262
- type: 'getPairedItem',
263
- destinationNodeName,
264
- incomingSourceData,
265
- initialPairedItem,
266
- },
267
- ], { arguments: { copy: true }, result: { copy: true } });
185
+ };
186
+ // $input current-node input proxy. Same synthetic-Proxy pattern as
187
+ // `target.$()`: intercept the typed-RPC method names (`first`, `last`,
188
+ // `all`, all zero-arg per the host's `WorkflowDataProxy`), delegate
189
+ // everything else (notably the `.item` getter and `.params` / `.context`
190
+ // properties) to a lazy proxy on `$input`.
191
+ const lazyInputProxy = (0, lazy_proxy_1.createDeepLazyProxy)(['$input'], undefined, callbacks);
192
+ const sendInputMethod = (type) => {
193
+ return () => {
194
+ const result = callbacks.callHost.applySync(null, [{ type }], {
195
+ arguments: { copy: true },
196
+ result: { copy: true },
197
+ });
268
198
  (0, lazy_proxy_1.throwIfErrorSentinel)(result);
269
199
  return result;
270
200
  };
271
- // -------------------------------------------------------------------------
272
- // Resolve an unknown key from the host. Called by the proxy's has/get traps
273
- // for keys not already on the target. The resolved value is cached on target
274
- // so each key is fetched at most once per evaluation.
275
- // -------------------------------------------------------------------------
276
- // Track keys we've already probed so we never call applySync twice
277
- // for the same key — even if the host returned undefined.
278
- const probedKeys = new Set();
279
- function resolveFromHost(key) {
280
- if (probedKeys.has(key))
281
- return false;
282
- let value;
283
- try {
284
- value = callbacks.getValueAtPath.applySync(null, [[key]], {
285
- arguments: { copy: true },
286
- result: { copy: true },
287
- });
288
- }
289
- catch {
290
- // Don't mark as probed — the throw may be transient
291
- // (e.g. host data not yet available) and a retry should be allowed.
292
- return false;
293
- }
294
- // Mark as probed only after a definitive answer from the host.
295
- probedKeys.add(key);
296
- if (value === undefined)
297
- return false;
298
- (0, lazy_proxy_1.throwIfErrorSentinel)(value);
299
- // Object / array metadata create a shape-matched lazy proxy for deep access
300
- if ((0, lazy_proxy_1.isArrayMetadata)(value)) {
301
- target[key] = (0, lazy_proxy_1.createDeepLazyProxy)([key], { kind: 'array', length: value.__length }, callbacks);
302
- return true;
303
- }
304
- if ((0, lazy_proxy_1.isObjectMetadata)(value)) {
305
- target[key] = (0, lazy_proxy_1.createDeepLazyProxy)([key], { kind: 'object', keys: value.__keys }, callbacks);
306
- return true;
307
- }
308
- // Primitive or null store directly
309
- target[key] = value;
201
+ };
202
+ target.$input = new Proxy({}, {
203
+ get(_emptyTarget, prop) {
204
+ if ((0, utils_1.isKeyOf)(INPUT_RPC_TYPES, prop))
205
+ return sendInputMethod(INPUT_RPC_TYPES[prop]);
206
+ return lazyInputProxy[prop];
207
+ },
208
+ has(_emptyTarget, prop) {
209
+ return (0, utils_1.isKeyOf)(INPUT_RPC_TYPES, prop) || prop in lazyInputProxy;
210
+ },
211
+ });
212
+ // $items — global accessor for a node's execution data. Unlike $() and
213
+ // $input this is a plain typed-RPC function (not a synthetic Proxy):
214
+ // the host enforces nothing structural here, the schema validates the
215
+ // args, and the host's `WorkflowDataProxy.$items` applies its own
216
+ // defaults when fields are undefined.
217
+ target.$items = (nodeName, outputIndex, runIndex) => {
218
+ const result = callbacks.callHost.applySync(null, [{ type: 'getItems', nodeName, outputIndex, runIndex }], { arguments: { copy: true }, result: { copy: true } });
219
+ (0, lazy_proxy_1.throwIfErrorSentinel)(result);
220
+ return result;
221
+ };
222
+ // $fromAI / $fromAi / $fromai — AI-builder placeholder accessor.
223
+ // All three host aliases route to the same `handleFromAi` callback;
224
+ // the typed-RPC envelope is identical regardless of which name the
225
+ // expression used. `name` is forwarded as-is — host validates it
226
+ // (required, regex-restricted) and emits a structured `ExpressionError`
227
+ // on bad input.
228
+ const sendFromAi = (name, description, valueType, defaultValue) => {
229
+ const result = callbacks.callHost.applySync(null, [{ type: 'fromAi', name, description, valueType, defaultValue }], { arguments: { copy: true }, result: { copy: true } });
230
+ (0, lazy_proxy_1.throwIfErrorSentinel)(result);
231
+ return result;
232
+ };
233
+ target.$fromAI = sendFromAi;
234
+ target.$fromAi = sendFromAi;
235
+ target.$fromai = sendFromAi;
236
+ // $evaluateExpression — recursive expression evaluator. Forwards the
237
+ // inner expression string to the host, which re-invokes the engine.
238
+ // Under the VM engine this re-enters the bridge on a fresh evaluation;
239
+ // the legacy engine handles it inline.
240
+ target.$evaluateExpression = (expression, itemIndex) => {
241
+ const result = callbacks.callHost.applySync(null, [{ type: 'evaluateExpression', expression, itemIndex }], { arguments: { copy: true }, result: { copy: true } });
242
+ (0, lazy_proxy_1.throwIfErrorSentinel)(result);
243
+ return result;
244
+ };
245
+ // $getPairedItem — walks the paired-item ancestry chain back to the
246
+ // named upstream node. The host validates the structural shape of
247
+ // `incomingSourceData` and `initialPairedItem` via the typed-RPC
248
+ // schema; bad input surfaces as a schema-parse error sentinel rather
249
+ // than a host throw, keeping the protocol surface tight.
250
+ target.$getPairedItem = (destinationNodeName, incomingSourceData, initialPairedItem) => {
251
+ const result = callbacks.callHost.applySync(null, [
252
+ {
253
+ type: 'getPairedItem',
254
+ destinationNodeName,
255
+ incomingSourceData,
256
+ initialPairedItem,
257
+ },
258
+ ], { arguments: { copy: true }, result: { copy: true } });
259
+ (0, lazy_proxy_1.throwIfErrorSentinel)(result);
260
+ return result;
261
+ };
262
+ // -------------------------------------------------------------------------
263
+ // Resolve an unknown key from the host. Called by the proxy's has/get traps
264
+ // for keys not already on the target. The resolved value is cached on target
265
+ // so each key is fetched at most once per evaluation.
266
+ // -------------------------------------------------------------------------
267
+ // Track keys we've already probed so we never call applySync twice
268
+ // for the same key — even if the host returned undefined.
269
+ const probedKeys = new Set();
270
+ function resolveFromHost(key) {
271
+ if (probedKeys.has(key))
272
+ return false;
273
+ let value;
274
+ try {
275
+ value = callbacks.getValueAtPath.applySync(null, [[key]], {
276
+ arguments: { copy: true },
277
+ result: { copy: true },
278
+ });
279
+ }
280
+ catch {
281
+ // Don't mark as probed — the throw may be transient
282
+ // (e.g. host data not yet available) and a retry should be allowed.
283
+ return false;
284
+ }
285
+ // Mark as probed only after a definitive answer from the host.
286
+ probedKeys.add(key);
287
+ if (value === undefined)
288
+ return false;
289
+ (0, lazy_proxy_1.throwIfErrorSentinel)(value);
290
+ // Object / array metadata — create a shape-matched lazy proxy for deep access
291
+ if ((0, lazy_proxy_1.isArrayMetadata)(value)) {
292
+ target[key] = (0, lazy_proxy_1.createDeepLazyProxy)([key], { kind: 'array', length: value.__length }, callbacks);
310
293
  return true;
311
294
  }
312
- // -------------------------------------------------------------------------
313
- // Wrap target in a Proxy so unknown keys are resolved lazily from the host.
314
- // Tournament's VariablePolyfill transforms identifiers to:
315
- // ("x" in this ? this : global).x
316
- // The has trap intercepts the "in" check, resolves the key on demand, and
317
- // caches it on target. The get trap then finds it cached.
318
- // -------------------------------------------------------------------------
319
- return new Proxy(target, {
320
- has(_target, prop) {
321
- if (typeof prop === 'symbol')
322
- return prop in target;
323
- if (prop in target)
324
- return true;
325
- return resolveFromHost(prop);
326
- },
327
- get(_target, prop) {
328
- if (typeof prop === 'symbol')
329
- return undefined;
330
- if (prop in target)
331
- return target[prop];
332
- // has() should have resolved it, but handle direct get() too
333
- resolveFromHost(prop);
334
- return target[prop];
335
- },
336
- });
337
- }
338
- // Matches initializeGlobalContext() lines 262-318 in packages/workflow/src/expression.ts
339
- const DENYLISTED_GLOBALS = [
340
- 'document',
341
- 'global',
342
- 'window',
343
- 'Window',
344
- 'globalThis',
345
- 'self',
346
- 'alert',
347
- 'prompt',
348
- 'confirm',
349
- 'eval',
350
- 'uneval',
351
- 'setTimeout',
352
- 'setInterval',
353
- 'setImmediate',
354
- 'clearImmediate',
355
- 'queueMicrotask',
356
- 'Function',
357
- 'require',
358
- 'module',
359
- 'Buffer',
360
- '__dirname',
361
- '__filename',
362
- 'fetch',
363
- 'XMLHttpRequest',
364
- 'Promise',
365
- 'Generator',
366
- 'GeneratorFunction',
367
- 'AsyncFunction',
368
- 'AsyncGenerator',
369
- 'AsyncGeneratorFunction',
370
- 'WebAssembly',
371
- 'Reflect',
372
- 'Proxy',
373
- 'escape',
374
- 'unescape',
375
- ];
376
- /**
377
- * Wire builtins onto a context object so tournament's VariablePolyfill resolves them.
378
- *
379
- * Tournament transforms `Object` → `("Object" in this ? this : window).Object`.
380
- * `this` = ctx. Without these entries on ctx, builtins fall through to
381
- * `window` which doesn't exist in the isolate, causing a ReferenceError.
382
- *
383
- * Mirrors Expression.initializeGlobalContext() in packages/workflow/src/expression.ts.
384
- */
385
- function initializeBuiltins(data) {
386
- // ── Denylist: dangerous globals → empty objects ──
387
- for (const key of DENYLISTED_GLOBALS) {
388
- data[key] = {};
295
+ if ((0, lazy_proxy_1.isObjectMetadata)(value)) {
296
+ target[key] = (0, lazy_proxy_1.createDeepLazyProxy)([key], { kind: 'object', keys: value.__keys }, callbacks);
297
+ return true;
389
298
  }
390
- data.__lookupGetter__ = undefined;
391
- data.__lookupSetter__ = undefined;
392
- data.__defineGetter__ = undefined;
393
- data.__defineSetter__ = undefined;
394
- // ── Allowlist: safe versions of builtins ──
395
- // Object use SafeObject wrapper from the runtime bundle
396
- data.Object = globalThis.SafeObject;
397
- // Error types use SafeError and safe subclass wrappers
398
- data.Error = globalThis.SafeError;
399
- data.TypeError = SafeTypeError;
400
- data.SyntaxError = SafeSyntaxError;
401
- data.EvalError = SafeEvalError;
402
- data.RangeError = SafeRangeError;
403
- data.ReferenceError = SafeReferenceError;
404
- data.URIError = SafeURIError;
405
- // Arrays
406
- data.Array = Array;
407
- data.Int8Array = Int8Array;
408
- data.Uint8Array = Uint8Array;
409
- data.Uint8ClampedArray = Uint8ClampedArray;
410
- data.Int16Array = Int16Array;
411
- data.Uint16Array = Uint16Array;
412
- data.Int32Array = Int32Array;
413
- data.Uint32Array = Uint32Array;
414
- data.Float32Array = Float32Array;
415
- data.Float64Array = Float64Array;
416
- data.BigInt64Array = typeof BigInt64Array !== 'undefined' ? BigInt64Array : {};
417
- data.BigUint64Array = typeof BigUint64Array !== 'undefined' ? BigUint64Array : {};
418
- // Collections
419
- data.Map = Map;
420
- data.WeakMap = WeakMap;
421
- data.Set = Set;
422
- data.WeakSet = WeakSet;
423
- // Internationalization
424
- data.Intl = typeof Intl !== 'undefined' ? Intl : {};
425
- // Text
426
- data.String = String;
427
- // Numbers
428
- data.Number = Number;
429
- data.BigInt = typeof BigInt !== 'undefined' ? BigInt : {};
430
- data.Infinity = Infinity;
431
- data.parseFloat = parseFloat;
432
- data.parseInt = parseInt;
433
- // Structured data
434
- data.JSON = JSON;
435
- data.ArrayBuffer = typeof ArrayBuffer !== 'undefined' ? ArrayBuffer : {};
436
- data.SharedArrayBuffer = typeof SharedArrayBuffer !== 'undefined' ? SharedArrayBuffer : {};
437
- data.Atomics = typeof Atomics !== 'undefined' ? Atomics : {};
438
- data.DataView = typeof DataView !== 'undefined' ? DataView : {};
439
- // Encoding
440
- data.encodeURI = encodeURI;
441
- data.encodeURIComponent = encodeURIComponent;
442
- data.decodeURI = decodeURI;
443
- data.decodeURIComponent = decodeURIComponent;
444
- // Other
445
- data.Boolean = Boolean;
446
- data.Symbol = Symbol;
299
+ // Primitive or null — store directly
300
+ target[key] = value;
301
+ return true;
302
+ }
303
+ // -------------------------------------------------------------------------
304
+ // Wrap target in a Proxy so unknown keys are resolved lazily from the host.
305
+ // Tournament's VariablePolyfill transforms identifiers to:
306
+ // ("x" in this ? this : global).x
307
+ // The has trap intercepts the "in" check, resolves the key on demand, and
308
+ // caches it on target. The get trap then finds it cached.
309
+ // -------------------------------------------------------------------------
310
+ return new Proxy(target, {
311
+ has(_target, prop) {
312
+ if (typeof prop === 'symbol')
313
+ return prop in target;
314
+ if (prop in target)
315
+ return true;
316
+ return resolveFromHost(prop);
317
+ },
318
+ get(_target, prop) {
319
+ if (typeof prop === 'symbol')
320
+ return undefined;
321
+ if (prop in target)
322
+ return target[prop];
323
+ // has() should have resolved it, but handle direct get() too
324
+ resolveFromHost(prop);
325
+ return target[prop];
326
+ },
327
+ });
328
+ }
329
+ // Matches initializeGlobalContext() lines 262-318 in packages/workflow/src/expression.ts
330
+ const DENYLISTED_GLOBALS = [
331
+ 'document',
332
+ 'global',
333
+ 'window',
334
+ 'Window',
335
+ 'globalThis',
336
+ 'self',
337
+ 'alert',
338
+ 'prompt',
339
+ 'confirm',
340
+ 'eval',
341
+ 'uneval',
342
+ 'setTimeout',
343
+ 'setInterval',
344
+ 'setImmediate',
345
+ 'clearImmediate',
346
+ 'queueMicrotask',
347
+ 'Function',
348
+ 'require',
349
+ 'module',
350
+ 'Buffer',
351
+ '__dirname',
352
+ '__filename',
353
+ 'fetch',
354
+ 'XMLHttpRequest',
355
+ 'Promise',
356
+ 'Generator',
357
+ 'GeneratorFunction',
358
+ 'AsyncFunction',
359
+ 'AsyncGenerator',
360
+ 'AsyncGeneratorFunction',
361
+ 'WebAssembly',
362
+ 'Reflect',
363
+ 'Proxy',
364
+ 'escape',
365
+ 'unescape',
366
+ ];
367
+ /**
368
+ * Wire builtins onto a context object so tournament's VariablePolyfill resolves them.
369
+ *
370
+ * Tournament transforms `Object` → `("Object" in this ? this : window).Object`.
371
+ * `this` = ctx. Without these entries on ctx, builtins fall through to
372
+ * `window` which doesn't exist in the isolate, causing a ReferenceError.
373
+ *
374
+ * Mirrors Expression.initializeGlobalContext() in packages/workflow/src/expression.ts.
375
+ */
376
+ function initializeBuiltins(data) {
377
+ // ── Denylist: dangerous globals → empty objects ──
378
+ for (const key of DENYLISTED_GLOBALS) {
379
+ data[key] = {};
447
380
  }
448
- });
381
+ data.__lookupGetter__ = undefined;
382
+ data.__lookupSetter__ = undefined;
383
+ data.__defineGetter__ = undefined;
384
+ data.__defineSetter__ = undefined;
385
+ // ── Allowlist: safe versions of builtins ──
386
+ // Object — use SafeObject wrapper from the runtime bundle
387
+ data.Object = globalThis.SafeObject;
388
+ // Error types — use SafeError and safe subclass wrappers
389
+ data.Error = globalThis.SafeError;
390
+ data.TypeError = SafeTypeError;
391
+ data.SyntaxError = SafeSyntaxError;
392
+ data.EvalError = SafeEvalError;
393
+ data.RangeError = SafeRangeError;
394
+ data.ReferenceError = SafeReferenceError;
395
+ data.URIError = SafeURIError;
396
+ // Arrays
397
+ data.Array = Array;
398
+ data.Int8Array = Int8Array;
399
+ data.Uint8Array = Uint8Array;
400
+ data.Uint8ClampedArray = Uint8ClampedArray;
401
+ data.Int16Array = Int16Array;
402
+ data.Uint16Array = Uint16Array;
403
+ data.Int32Array = Int32Array;
404
+ data.Uint32Array = Uint32Array;
405
+ data.Float32Array = Float32Array;
406
+ data.Float64Array = Float64Array;
407
+ data.BigInt64Array = typeof BigInt64Array !== 'undefined' ? BigInt64Array : {};
408
+ data.BigUint64Array = typeof BigUint64Array !== 'undefined' ? BigUint64Array : {};
409
+ // Collections
410
+ data.Map = Map;
411
+ data.WeakMap = WeakMap;
412
+ data.Set = Set;
413
+ data.WeakSet = WeakSet;
414
+ // Internationalization
415
+ data.Intl = typeof Intl !== 'undefined' ? Intl : {};
416
+ // Text
417
+ data.String = String;
418
+ // Numbers
419
+ data.Number = Number;
420
+ data.BigInt = typeof BigInt !== 'undefined' ? BigInt : {};
421
+ data.Infinity = Infinity;
422
+ data.parseFloat = parseFloat;
423
+ data.parseInt = parseInt;
424
+ // Structured data
425
+ data.JSON = JSON;
426
+ data.ArrayBuffer = typeof ArrayBuffer !== 'undefined' ? ArrayBuffer : {};
427
+ data.SharedArrayBuffer = typeof SharedArrayBuffer !== 'undefined' ? SharedArrayBuffer : {};
428
+ data.Atomics = typeof Atomics !== 'undefined' ? Atomics : {};
429
+ data.DataView = typeof DataView !== 'undefined' ? DataView : {};
430
+ // Encoding
431
+ data.encodeURI = encodeURI;
432
+ data.encodeURIComponent = encodeURIComponent;
433
+ data.decodeURI = decodeURI;
434
+ data.decodeURIComponent = decodeURIComponent;
435
+ // Other
436
+ data.Boolean = Boolean;
437
+ data.Symbol = Symbol;
438
+ }
449
439
  //# sourceMappingURL=context.js.map