@opencode/codemode 0.0.0-dev-19631 → 0.0.0-dev-19633
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/dist/codemode.js +1 -1
- package/dist/data.d.ts +3 -3
- package/dist/data.js +37 -31
- package/dist/interpreter/callback.d.ts +20 -0
- package/dist/interpreter/{runner.js → callback.js} +10 -10
- package/dist/interpreter/errors.d.ts +5 -5
- package/dist/interpreter/errors.js +21 -22
- package/dist/interpreter/execute.d.ts +2 -2
- package/dist/interpreter/execute.js +11 -11
- package/dist/interpreter/extensions.d.ts +2 -2
- package/dist/interpreter/extensions.js +42 -36
- package/dist/interpreter/generators.d.ts +2 -3
- package/dist/interpreter/generators.js +8 -8
- package/dist/interpreter/globals.d.ts +2 -12
- package/dist/interpreter/globals.js +41 -37
- package/dist/interpreter/interpreter.d.ts +31 -0
- package/dist/interpreter/{runtime.js → interpreter.js} +118 -117
- package/dist/interpreter/intrinsics.d.ts +5 -5
- package/dist/interpreter/intrinsics.js +16 -10
- package/dist/interpreter/model.d.ts +3 -3
- package/dist/interpreter/model.js +1 -1
- package/dist/interpreter/native.d.ts +9 -9
- package/dist/interpreter/native.js +9 -9
- package/dist/interpreter/objects.d.ts +51 -46
- package/dist/interpreter/objects.js +57 -40
- package/dist/interpreter/promises.d.ts +13 -13
- package/dist/interpreter/promises.js +70 -70
- package/dist/interpreter/references.js +17 -15
- package/dist/openapi/types.d.ts +1 -1
- package/dist/stdlib/array.d.ts +3 -3
- package/dist/stdlib/array.js +31 -31
- package/dist/stdlib/bytes.d.ts +10 -0
- package/dist/stdlib/bytes.js +228 -0
- package/dist/stdlib/collections.d.ts +4 -4
- package/dist/stdlib/collections.js +55 -55
- package/dist/stdlib/console.d.ts +3 -3
- package/dist/stdlib/console.js +24 -22
- package/dist/stdlib/date.d.ts +2 -2
- package/dist/stdlib/date.js +19 -19
- package/dist/stdlib/json.d.ts +3 -3
- package/dist/stdlib/json.js +24 -24
- package/dist/stdlib/math.d.ts +3 -3
- package/dist/stdlib/math.js +7 -7
- package/dist/stdlib/number.d.ts +3 -3
- package/dist/stdlib/number.js +11 -11
- package/dist/stdlib/object.d.ts +5 -5
- package/dist/stdlib/object.js +41 -39
- package/dist/stdlib/regexp.d.ts +6 -6
- package/dist/stdlib/regexp.js +24 -24
- package/dist/stdlib/string.d.ts +2 -2
- package/dist/stdlib/string.js +24 -24
- package/dist/stdlib/url.d.ts +6 -6
- package/dist/stdlib/url.js +39 -39
- package/dist/stdlib/value.d.ts +3 -3
- package/dist/stdlib/value.js +18 -14
- package/dist/stdlib/web.d.ts +4 -4
- package/dist/stdlib/web.js +19 -5
- package/dist/tool-runtime.d.ts +2 -2
- package/dist/tool-runtime.js +2 -2
- package/package.json +1 -1
- package/dist/interpreter/runner.d.ts +0 -27
- package/dist/interpreter/runtime.d.ts +0 -19
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Cause, Deferred, Effect, Exit } from "effect";
|
|
2
2
|
import { toProgram } from "../data.js";
|
|
3
3
|
import { ToolReference } from "../tool-runtime.js";
|
|
4
|
-
import { AsyncIteratorSymbol, CallSite, GeneratorReturn, IteratorSymbol, OptionalShortCircuit, invalidData,
|
|
4
|
+
import { AsyncIteratorSymbol, CallSite, GeneratorReturn, IteratorSymbol, OptionalShortCircuit, invalidData, Throw, rangeError, typeError, unsupportedSyntax, } from "./model.js";
|
|
5
5
|
import { checkStringLength } from "./limits.js";
|
|
6
6
|
import { locate, materialize } from "./errors.js";
|
|
7
7
|
import { globals } from "./globals.js";
|
|
8
|
-
import { assign, Callable, define, get, has, hasPrototype, keys,
|
|
9
|
-
import { preserveConsumerError } from "./
|
|
10
|
-
import {
|
|
8
|
+
import { assign, Callable, define, get, has, hasPrototype, keys, Native, parseArrayIndex, Arr, Bytes, DateObj, Fn, GeneratorObj, MapObj, Obj, PromiseObj, SetObj, URLSearchParamsObj, record, remove, set, } from "./objects.js";
|
|
9
|
+
import { preserveConsumerError } from "./callback.js";
|
|
10
|
+
import { Pending, resolvePromise, resolvePromiseValue } from "./promises.js";
|
|
11
11
|
import { containsOpaqueReference, describeValue, rejectCircularInsertion, typeofValue } from "./references.js";
|
|
12
12
|
import { ScopeStack } from "./scope.js";
|
|
13
13
|
import { constructRegExp } from "../stdlib/regexp.js";
|
|
@@ -49,7 +49,7 @@ const instanceofValue = (lhs, rhs, node) => {
|
|
|
49
49
|
throw typeError("The right-hand side of 'instanceof' is not callable.", node);
|
|
50
50
|
}
|
|
51
51
|
const prototype = get(rhs, "prototype");
|
|
52
|
-
if (!(prototype instanceof
|
|
52
|
+
if (!(prototype instanceof Obj)) {
|
|
53
53
|
throw typeError("The right-hand side of 'instanceof' has no 'prototype' object.", node);
|
|
54
54
|
}
|
|
55
55
|
return hasPrototype(lhs, prototype);
|
|
@@ -143,51 +143,49 @@ const loopDeclaration = (left, statement) => {
|
|
|
143
143
|
};
|
|
144
144
|
};
|
|
145
145
|
/** One program execution: the tool bridge, promise scheduler, captured logs, and the global scope built once. */
|
|
146
|
-
export class
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
promises;
|
|
151
|
-
prototypes;
|
|
146
|
+
export class Interpreter {
|
|
147
|
+
tools;
|
|
148
|
+
pending;
|
|
149
|
+
builtins;
|
|
152
150
|
logs;
|
|
153
|
-
runner;
|
|
154
151
|
root;
|
|
155
|
-
constructor(
|
|
156
|
-
this.
|
|
157
|
-
this.
|
|
158
|
-
this.
|
|
159
|
-
this.
|
|
160
|
-
this.prototypes = prototypes;
|
|
161
|
-
this.logs = logs;
|
|
152
|
+
constructor(options) {
|
|
153
|
+
this.tools = options.tools;
|
|
154
|
+
this.pending = options.pending;
|
|
155
|
+
this.builtins = options.builtins;
|
|
156
|
+
this.logs = options.logs ?? [];
|
|
162
157
|
const globalScope = new Map();
|
|
163
158
|
// Calling back into the program never reads frame state, so any frame serves; the root is always alive.
|
|
164
159
|
this.root = new Frame(this, new ScopeStack([globalScope]));
|
|
165
|
-
this.
|
|
166
|
-
invokeCallable: (callable, thisValue, args) => this.root.invokeCallable(callable, thisValue, args),
|
|
167
|
-
settlePromise: (promise) => this.root.settlePromise(promise),
|
|
168
|
-
syncIterator: (value) => this.root.syncIterator(value),
|
|
169
|
-
prototypes,
|
|
170
|
-
};
|
|
171
|
-
for (const [name, value] of [...globals(this), ...extraGlobals(this)]) {
|
|
160
|
+
for (const [name, value] of [...globals(this), ...(options.globals?.(this) ?? [])]) {
|
|
172
161
|
globalScope.set(name, { mutable: false, value });
|
|
173
162
|
}
|
|
174
163
|
}
|
|
175
164
|
run(program) {
|
|
176
165
|
return this.root.run(program);
|
|
177
166
|
}
|
|
167
|
+
call(callable, thisValue, args) {
|
|
168
|
+
return this.root.call(callable, thisValue, args);
|
|
169
|
+
}
|
|
170
|
+
await(promise) {
|
|
171
|
+
return this.root.await(promise);
|
|
172
|
+
}
|
|
173
|
+
iterate(value) {
|
|
174
|
+
return this.root.iterate(value);
|
|
175
|
+
}
|
|
178
176
|
}
|
|
179
177
|
const MAX_CALL_DEPTH = 10_000;
|
|
180
178
|
/** One activation: the top-level program or a single function call, evaluating against its own scope chain. */
|
|
181
179
|
class Frame {
|
|
182
|
-
|
|
180
|
+
ctx;
|
|
183
181
|
scopes;
|
|
184
182
|
depth;
|
|
185
183
|
generatorState;
|
|
186
184
|
generatorAsync = false;
|
|
187
|
-
constructor(
|
|
185
|
+
constructor(ctx, scopes,
|
|
188
186
|
/** Nested call depth; resets when an await resumes, since the continuation runs from the job queue. */
|
|
189
187
|
depth = 0) {
|
|
190
|
-
this.
|
|
188
|
+
this.ctx = ctx;
|
|
191
189
|
this.scopes = scopes;
|
|
192
190
|
this.depth = depth;
|
|
193
191
|
}
|
|
@@ -215,20 +213,20 @@ class Frame {
|
|
|
215
213
|
}
|
|
216
214
|
}
|
|
217
215
|
// The implicit async body adopts returned promises before copy-out.
|
|
218
|
-
value = yield* resolvePromiseValue(self.
|
|
216
|
+
value = yield* resolvePromiseValue(self.ctx, value);
|
|
219
217
|
return value;
|
|
220
218
|
}).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
|
|
221
219
|
}
|
|
222
220
|
// Fork at the call site so admission and hooks occur when the call is made.
|
|
223
221
|
createToolCallPromise(path, args) {
|
|
224
|
-
return this.
|
|
222
|
+
return this.ctx.pending.create(Effect.suspend(() => this.ctx.tools.execute(path, args)));
|
|
225
223
|
}
|
|
226
224
|
// Fiber exits make settlement idempotent; yielding prevents inline continuation.
|
|
227
|
-
|
|
228
|
-
const
|
|
225
|
+
await(promise) {
|
|
226
|
+
const pending = this.ctx.pending;
|
|
229
227
|
return Effect.suspend(() => {
|
|
230
|
-
|
|
231
|
-
return Effect.flatMap(
|
|
228
|
+
pending.markObserved(promise);
|
|
229
|
+
return Effect.flatMap(pending.await(promise), (exit) => Effect.andThen(Effect.yieldNow, exit));
|
|
232
230
|
});
|
|
233
231
|
}
|
|
234
232
|
evaluateStatement(node) {
|
|
@@ -294,7 +292,7 @@ class Frame {
|
|
|
294
292
|
}).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
|
|
295
293
|
}
|
|
296
294
|
createFunction(node, name = node.type === "ArrowFunctionExpression" ? "" : (node.id?.name ?? "")) {
|
|
297
|
-
return new
|
|
295
|
+
return new Fn(this.ctx.builtins.Function, name, node.params, node.body, this.scopes.capture(), node.async, node.generator);
|
|
298
296
|
}
|
|
299
297
|
// NamedEvaluation: an anonymous function definition takes the name of what it is assigned to.
|
|
300
298
|
evaluateNamed(node, name) {
|
|
@@ -472,7 +470,7 @@ class Frame {
|
|
|
472
470
|
self.predeclarePattern(declared.pattern, declared.mutable, left);
|
|
473
471
|
const right = yield* self.evaluateExpression(node.right);
|
|
474
472
|
const iterator = yield* self.customIterator(right, node, awaiting);
|
|
475
|
-
const cursor = iterator === undefined ? yield* self.
|
|
473
|
+
const cursor = iterator === undefined ? yield* self.iterate(right, node) : undefined;
|
|
476
474
|
if (iterator === undefined && cursor === undefined) {
|
|
477
475
|
throw invalidData(`${awaiting ? "for await...of" : "for...of"} requires an array, string, Map, Set, or URLSearchParams, or custom iterator value.`, node);
|
|
478
476
|
}
|
|
@@ -529,7 +527,7 @@ class Frame {
|
|
|
529
527
|
})));
|
|
530
528
|
}
|
|
531
529
|
awaitValue(value) {
|
|
532
|
-
return Effect.flatMap(resolvePromise(this.
|
|
530
|
+
return Effect.flatMap(resolvePromise(this.ctx, value), (promise) => Effect.ensuring(this.await(promise), Effect.sync(() => (this.depth = 0))));
|
|
533
531
|
}
|
|
534
532
|
awaitAsyncFromSyncValue(iterator, value, node, closeOnRejection) {
|
|
535
533
|
const self = this;
|
|
@@ -543,26 +541,28 @@ class Frame {
|
|
|
543
541
|
return yield* Effect.failCause(settled.cause);
|
|
544
542
|
});
|
|
545
543
|
}
|
|
546
|
-
|
|
547
|
-
const iterator = value instanceof
|
|
544
|
+
iterate(value, node) {
|
|
545
|
+
const iterator = value instanceof Arr
|
|
548
546
|
? value.items[Symbol.iterator]()
|
|
549
547
|
: typeof value === "string"
|
|
550
548
|
? value[Symbol.iterator]()
|
|
551
|
-
: value instanceof
|
|
549
|
+
: value instanceof MapObj
|
|
552
550
|
? value.map.entries()
|
|
553
|
-
: value instanceof
|
|
551
|
+
: value instanceof SetObj
|
|
554
552
|
? value.set.values()
|
|
555
|
-
: value instanceof
|
|
553
|
+
: value instanceof URLSearchParamsObj
|
|
556
554
|
? value.params.entries()
|
|
557
|
-
:
|
|
555
|
+
: value instanceof Bytes
|
|
556
|
+
? value.bytes.values()
|
|
557
|
+
: undefined;
|
|
558
558
|
if (iterator !== undefined) {
|
|
559
|
-
const proto = this.
|
|
559
|
+
const proto = this.ctx.builtins.Array;
|
|
560
560
|
return Effect.succeed({
|
|
561
561
|
next: Effect.sync(() => {
|
|
562
562
|
const step = iterator.next();
|
|
563
563
|
return {
|
|
564
564
|
done: Boolean(step.done),
|
|
565
|
-
value: Array.isArray(step.value) ? new
|
|
565
|
+
value: Array.isArray(step.value) ? new Arr(proto, step.value) : step.value,
|
|
566
566
|
};
|
|
567
567
|
}),
|
|
568
568
|
close: Effect.void,
|
|
@@ -577,14 +577,14 @@ class Frame {
|
|
|
577
577
|
});
|
|
578
578
|
}
|
|
579
579
|
customIterator(value, node, allowAsync = true) {
|
|
580
|
-
if (!(value instanceof
|
|
580
|
+
if (!(value instanceof Obj))
|
|
581
581
|
return Effect.undefined;
|
|
582
582
|
const asyncMethod = allowAsync ? get(value, AsyncIteratorSymbol) : undefined;
|
|
583
583
|
const method = asyncMethod ?? get(value, IteratorSymbol);
|
|
584
584
|
if (method === undefined || method === null)
|
|
585
585
|
return Effect.undefined;
|
|
586
586
|
const self = this;
|
|
587
|
-
return Effect.map(this.
|
|
587
|
+
return Effect.map(this.call(this.requireIteratorMethod(method, "Iterator method", node), value, [], node), (iterator) => {
|
|
588
588
|
const object = self.requireIteratorObject(iterator, "Iterator method result", node);
|
|
589
589
|
return {
|
|
590
590
|
iterator: object,
|
|
@@ -597,10 +597,10 @@ class Frame {
|
|
|
597
597
|
const self = this;
|
|
598
598
|
return Effect.gen(function* () {
|
|
599
599
|
if (iterator.asynchronous) {
|
|
600
|
-
const object = self.requireIteratorObject(yield* self.awaitValue(yield* self.
|
|
600
|
+
const object = self.requireIteratorObject(yield* self.awaitValue(yield* self.call(iterator.next, iterator.iterator, [], node)), "Iterator next() result", node);
|
|
601
601
|
return { done: Boolean(get(object, "done")), value: get(object, "value") };
|
|
602
602
|
}
|
|
603
|
-
const called = yield* Effect.exit(self.
|
|
603
|
+
const called = yield* Effect.exit(self.call(iterator.next, iterator.iterator, [], node));
|
|
604
604
|
if (!Exit.isSuccess(called)) {
|
|
605
605
|
if (awaiting)
|
|
606
606
|
yield* Effect.yieldNow;
|
|
@@ -631,10 +631,10 @@ class Frame {
|
|
|
631
631
|
return Effect.gen(function* () {
|
|
632
632
|
const method = self.requireIteratorMethod(close, "Iterator return", node);
|
|
633
633
|
if (iterator.asynchronous) {
|
|
634
|
-
self.requireIteratorObject(yield* self.awaitValue(yield* self.
|
|
634
|
+
self.requireIteratorObject(yield* self.awaitValue(yield* self.call(method, iterator.iterator, [], node)), "Iterator return() result", node);
|
|
635
635
|
return;
|
|
636
636
|
}
|
|
637
|
-
const called = yield* Effect.exit(self.
|
|
637
|
+
const called = yield* Effect.exit(self.call(method, iterator.iterator, [], node));
|
|
638
638
|
if (!Exit.isSuccess(called)) {
|
|
639
639
|
if (awaiting)
|
|
640
640
|
yield* Effect.yieldNow;
|
|
@@ -651,7 +651,7 @@ class Frame {
|
|
|
651
651
|
});
|
|
652
652
|
}
|
|
653
653
|
requireIteratorObject(value, context, node) {
|
|
654
|
-
if (value instanceof
|
|
654
|
+
if (value instanceof Obj)
|
|
655
655
|
return value;
|
|
656
656
|
throw typeError(`${context} must be an object.`, node);
|
|
657
657
|
}
|
|
@@ -663,10 +663,10 @@ class Frame {
|
|
|
663
663
|
// for...in over null/undefined iterates nothing, like JS.
|
|
664
664
|
enumerableKeys(value, node) {
|
|
665
665
|
if (value instanceof ToolReference)
|
|
666
|
-
return [...this.
|
|
666
|
+
return [...this.ctx.tools.keys(value.path)];
|
|
667
667
|
if (value === null || value === undefined)
|
|
668
668
|
return [];
|
|
669
|
-
return keys(enumerableSource(this.
|
|
669
|
+
return keys(enumerableSource(this.ctx, "for...in", value, node));
|
|
670
670
|
}
|
|
671
671
|
evaluateForInStatement(node, labels) {
|
|
672
672
|
const left = node.left;
|
|
@@ -742,7 +742,7 @@ class Frame {
|
|
|
742
742
|
: result);
|
|
743
743
|
}
|
|
744
744
|
evaluateThrowStatement(node) {
|
|
745
|
-
return Effect.flatMap(this.evaluateExpression(node.argument), (value) => Effect.fail(new
|
|
745
|
+
return Effect.flatMap(this.evaluateExpression(node.argument), (value) => Effect.fail(new Throw(value)));
|
|
746
746
|
}
|
|
747
747
|
evaluateTryStatement(node) {
|
|
748
748
|
const body = node.block;
|
|
@@ -754,7 +754,7 @@ class Frame {
|
|
|
754
754
|
if (cause.reasons.some(Cause.isInterruptReason) || Cause.squash(cause) instanceof GeneratorReturn || !handler) {
|
|
755
755
|
return Effect.failCause(cause);
|
|
756
756
|
}
|
|
757
|
-
const caught = materialize(self.
|
|
757
|
+
const caught = materialize(self.ctx, Cause.squash(cause));
|
|
758
758
|
const parameter = handler.param;
|
|
759
759
|
self.scopes.push();
|
|
760
760
|
return Effect.gen(function* () {
|
|
@@ -814,13 +814,13 @@ class Frame {
|
|
|
814
814
|
return;
|
|
815
815
|
}
|
|
816
816
|
if (pattern.type === "ObjectPattern") {
|
|
817
|
-
if (!(value instanceof
|
|
817
|
+
if (!(value instanceof Obj)) {
|
|
818
818
|
throw typeError(`Object destructuring requires a data object or array value, received ${describeValue(value)}.`, pattern);
|
|
819
819
|
}
|
|
820
820
|
const consumed = new Set();
|
|
821
821
|
for (const property of pattern.properties) {
|
|
822
822
|
if (property.type === "RestElement") {
|
|
823
|
-
const rest = new
|
|
823
|
+
const rest = new Obj(self.ctx.builtins.Object);
|
|
824
824
|
assign(rest, value, consumed);
|
|
825
825
|
yield* self.declarePattern(property.argument, rest, mutable, property, initialize);
|
|
826
826
|
continue;
|
|
@@ -854,13 +854,13 @@ class Frame {
|
|
|
854
854
|
return;
|
|
855
855
|
}
|
|
856
856
|
if (pattern.type === "ObjectPattern") {
|
|
857
|
-
if (!(value instanceof
|
|
857
|
+
if (!(value instanceof Obj)) {
|
|
858
858
|
throw invalidData(`Object destructuring requires a data object or array value, received ${describeValue(value)}.`, pattern);
|
|
859
859
|
}
|
|
860
860
|
const consumed = new Set();
|
|
861
861
|
for (const property of pattern.properties) {
|
|
862
862
|
if (property.type === "RestElement") {
|
|
863
|
-
const rest = new
|
|
863
|
+
const rest = new Obj(self.ctx.builtins.Object);
|
|
864
864
|
assign(rest, value, consumed);
|
|
865
865
|
yield* self.assignPattern(property.argument, rest, property);
|
|
866
866
|
continue;
|
|
@@ -885,7 +885,7 @@ class Frame {
|
|
|
885
885
|
destructureArrayPattern(pattern, value, consume) {
|
|
886
886
|
const self = this;
|
|
887
887
|
return Effect.gen(function* () {
|
|
888
|
-
const cursor = yield* self.
|
|
888
|
+
const cursor = yield* self.iterate(value, pattern);
|
|
889
889
|
if (cursor === undefined) {
|
|
890
890
|
throw typeError("Array destructuring requires a supported iterable value.", pattern);
|
|
891
891
|
}
|
|
@@ -894,7 +894,7 @@ class Frame {
|
|
|
894
894
|
if (done) {
|
|
895
895
|
if (element === null)
|
|
896
896
|
continue;
|
|
897
|
-
yield* consume(element.type === "RestElement" ? element.argument : element, element.type === "RestElement" ? new
|
|
897
|
+
yield* consume(element.type === "RestElement" ? element.argument : element, element.type === "RestElement" ? new Arr(self.ctx.builtins.Array) : undefined, element);
|
|
898
898
|
if (element.type === "RestElement")
|
|
899
899
|
return;
|
|
900
900
|
continue;
|
|
@@ -913,7 +913,7 @@ class Frame {
|
|
|
913
913
|
if (!done)
|
|
914
914
|
rest.push(next.value);
|
|
915
915
|
}
|
|
916
|
-
yield* consume(element.argument, new
|
|
916
|
+
yield* consume(element.argument, new Arr(self.ctx.builtins.Array, rest), element);
|
|
917
917
|
return;
|
|
918
918
|
}
|
|
919
919
|
const consumed = consume(element, step.done ? undefined : step.value, pattern);
|
|
@@ -942,8 +942,8 @@ class Frame {
|
|
|
942
942
|
case "Literal": {
|
|
943
943
|
const regex = node.regex;
|
|
944
944
|
if (regex)
|
|
945
|
-
return Effect.sync(() => constructRegExp(this.
|
|
946
|
-
return Effect.sync(() => toProgram(this.
|
|
945
|
+
return Effect.sync(() => constructRegExp(this.ctx.builtins, [regex.pattern, regex.flags]));
|
|
946
|
+
return Effect.sync(() => toProgram(this.ctx.builtins, node.value, "Literal"));
|
|
947
947
|
}
|
|
948
948
|
case "Identifier":
|
|
949
949
|
return Effect.sync(() => this.scopes.get(node.name, node));
|
|
@@ -1001,15 +1001,15 @@ class Frame {
|
|
|
1001
1001
|
return Effect.gen(function* () {
|
|
1002
1002
|
const callee = yield* self.evaluateExpression(node.callee);
|
|
1003
1003
|
// Globals are built with this interpreter's R; `instanceof` cannot recover the type argument.
|
|
1004
|
-
const construct = callee instanceof
|
|
1004
|
+
const construct = callee instanceof Native ? callee.construct : undefined;
|
|
1005
1005
|
if (construct === undefined) {
|
|
1006
1006
|
// `new` itself is supported, so a non-constructible callee is a TypeError like JS rather than
|
|
1007
1007
|
// unsupported syntax. Built-ins like Number are real constructors in JS, so do not claim
|
|
1008
1008
|
// otherwise; say `new` is unsupported for them and point at the plain call.
|
|
1009
1009
|
const name = calleeDescription(node.callee);
|
|
1010
|
-
const message = callee instanceof
|
|
1010
|
+
const message = callee instanceof Fn
|
|
1011
1011
|
? `${name} cannot be constructed: user-defined constructors and classes are not supported. Call it as a function that returns a plain object instead.`
|
|
1012
|
-
: callee instanceof
|
|
1012
|
+
: callee instanceof Native
|
|
1013
1013
|
? `new ${name}(...) is not supported; call ${name}(...) without new instead.`
|
|
1014
1014
|
: `${name} is not a constructor.`;
|
|
1015
1015
|
throw typeError(message, node);
|
|
@@ -1029,7 +1029,7 @@ class Frame {
|
|
|
1029
1029
|
const rhs = yield* self.evaluateExpression(node.right);
|
|
1030
1030
|
if (operator === "instanceof")
|
|
1031
1031
|
return instanceofValue(lhs, rhs, node);
|
|
1032
|
-
return toProgram(self.
|
|
1032
|
+
return toProgram(self.ctx.builtins, self.applyBinaryOperator(operator, lhs, rhs, node), "Binary expression result");
|
|
1033
1033
|
});
|
|
1034
1034
|
}
|
|
1035
1035
|
applyBinaryOperator(operator, lhs, rhs, node) {
|
|
@@ -1037,7 +1037,7 @@ class Frame {
|
|
|
1037
1037
|
return lhs === rhs;
|
|
1038
1038
|
if (operator === "!==")
|
|
1039
1039
|
return lhs !== rhs;
|
|
1040
|
-
if (operator === "in" && rhs instanceof
|
|
1040
|
+
if (operator === "in" && rhs instanceof Obj && !containsOpaqueReference(lhs)) {
|
|
1041
1041
|
return has(rhs, lhs !== null && typeof lhs === "object" ? coerceToString(lhs) : lhs);
|
|
1042
1042
|
}
|
|
1043
1043
|
if (containsOpaqueReference(lhs) || containsOpaqueReference(rhs)) {
|
|
@@ -1046,7 +1046,7 @@ class Frame {
|
|
|
1046
1046
|
// Null-prototype data needs explicit primitive coercion; identity and `in` retain raw objects.
|
|
1047
1047
|
// Dates use their default string hint for addition and loose equality, and epoch time elsewhere.
|
|
1048
1048
|
const coerceOperand = (operand) => {
|
|
1049
|
-
if (operand instanceof
|
|
1049
|
+
if (operand instanceof DateObj) {
|
|
1050
1050
|
return operator === "+" || operator === "==" || operator === "!=" ? coerceToString(operand) : operand.time;
|
|
1051
1051
|
}
|
|
1052
1052
|
return operand !== null && typeof operand === "object" ? coerceToString(operand) : operand;
|
|
@@ -1096,7 +1096,7 @@ class Frame {
|
|
|
1096
1096
|
case ">>>":
|
|
1097
1097
|
return l >>> r;
|
|
1098
1098
|
case "in":
|
|
1099
|
-
if (!(rhs instanceof
|
|
1099
|
+
if (!(rhs instanceof Obj)) {
|
|
1100
1100
|
throw typeError("The 'in' operator requires a data object on the right-hand side.", node);
|
|
1101
1101
|
}
|
|
1102
1102
|
return has(rhs, coerceOperand(lhs));
|
|
@@ -1135,7 +1135,7 @@ class Frame {
|
|
|
1135
1135
|
if (containsOpaqueReference(value)) {
|
|
1136
1136
|
throw invalidData("Unary operators require data values.", node);
|
|
1137
1137
|
}
|
|
1138
|
-
const operand = value instanceof
|
|
1138
|
+
const operand = value instanceof DateObj
|
|
1139
1139
|
? value.time
|
|
1140
1140
|
: value !== null && typeof value === "object"
|
|
1141
1141
|
? coerceToString(value)
|
|
@@ -1154,7 +1154,7 @@ class Frame {
|
|
|
1154
1154
|
default:
|
|
1155
1155
|
throw typeError(`Unsupported unary operator '${operator}'.`, node);
|
|
1156
1156
|
}
|
|
1157
|
-
return toProgram(this.
|
|
1157
|
+
return toProgram(this.ctx.builtins, result, "Unary expression result");
|
|
1158
1158
|
});
|
|
1159
1159
|
}
|
|
1160
1160
|
evaluateAssignmentExpression(node) {
|
|
@@ -1175,7 +1175,7 @@ class Frame {
|
|
|
1175
1175
|
if (operator !== "=") {
|
|
1176
1176
|
const current = self.scopes.get(name, left);
|
|
1177
1177
|
const rightValue = yield* self.evaluateExpression(node.right);
|
|
1178
|
-
const next = toProgram(self.
|
|
1178
|
+
const next = toProgram(self.ctx.builtins, self.applyCompoundAssignment(operator, current, rightValue, node), "Assignment result");
|
|
1179
1179
|
return self.scopes.set(name, next, left);
|
|
1180
1180
|
}
|
|
1181
1181
|
const rightValue = yield* self.evaluateNamed(node.right, name);
|
|
@@ -1185,7 +1185,7 @@ class Frame {
|
|
|
1185
1185
|
return yield* self.modifyMember(left, (current) => Effect.map(self.evaluateExpression(node.right), (rightValue) => {
|
|
1186
1186
|
if (operator === "=")
|
|
1187
1187
|
return { write: true, next: rightValue, result: rightValue };
|
|
1188
|
-
const next = toProgram(self.
|
|
1188
|
+
const next = toProgram(self.ctx.builtins, self.applyCompoundAssignment(operator, current, rightValue, node), "Assignment result");
|
|
1189
1189
|
return { write: true, next, result: next };
|
|
1190
1190
|
}));
|
|
1191
1191
|
}
|
|
@@ -1265,7 +1265,7 @@ class Frame {
|
|
|
1265
1265
|
if ((callable === null || callable === undefined) && node.optional)
|
|
1266
1266
|
return OptionalShortCircuit;
|
|
1267
1267
|
const args = yield* self.evaluateCallArguments(node.arguments);
|
|
1268
|
-
return yield* self.
|
|
1268
|
+
return yield* self.call(callable, thisValue, args, node, callee);
|
|
1269
1269
|
});
|
|
1270
1270
|
}
|
|
1271
1271
|
readMethod(node) {
|
|
@@ -1280,7 +1280,7 @@ class Frame {
|
|
|
1280
1280
|
});
|
|
1281
1281
|
}
|
|
1282
1282
|
// The single dispatch for every invocation: call expressions and callbacks share it.
|
|
1283
|
-
|
|
1283
|
+
call(callable, thisValue, args, node, callee) {
|
|
1284
1284
|
const self = this;
|
|
1285
1285
|
return Effect.gen(function* () {
|
|
1286
1286
|
if (callable instanceof ToolReference) {
|
|
@@ -1289,9 +1289,9 @@ class Frame {
|
|
|
1289
1289
|
}
|
|
1290
1290
|
return yield* self.createToolCallPromise(callable.path, args);
|
|
1291
1291
|
}
|
|
1292
|
-
if (callable instanceof
|
|
1292
|
+
if (callable instanceof Fn)
|
|
1293
1293
|
return yield* self.invokeFunction(callable, args, node);
|
|
1294
|
-
if (callable instanceof
|
|
1294
|
+
if (callable instanceof Native) {
|
|
1295
1295
|
return yield* self.native(() => callable.call(thisValue, args), node);
|
|
1296
1296
|
}
|
|
1297
1297
|
throw typeError(`${calleeDescription(callee)} is not a function.`, callee ?? node);
|
|
@@ -1308,7 +1308,7 @@ class Frame {
|
|
|
1308
1308
|
for (const argNode of argNodes) {
|
|
1309
1309
|
if (argNode.type === "SpreadElement") {
|
|
1310
1310
|
const spread = yield* self.evaluateExpression(argNode.argument);
|
|
1311
|
-
const cursor = yield* self.
|
|
1311
|
+
const cursor = yield* self.iterate(spread, argNode);
|
|
1312
1312
|
if (cursor === undefined)
|
|
1313
1313
|
throw typeError("Spread arguments require a synchronous iterable.", argNode);
|
|
1314
1314
|
while (true) {
|
|
@@ -1332,7 +1332,7 @@ class Frame {
|
|
|
1332
1332
|
const depth = Math.max(self.depth, site.depth) + 1;
|
|
1333
1333
|
if (depth > MAX_CALL_DEPTH)
|
|
1334
1334
|
throw rangeError("Maximum call stack size exceeded", node);
|
|
1335
|
-
const invocation = new Frame(this.
|
|
1335
|
+
const invocation = new Frame(this.ctx, new ScopeStack([...fn.capturedScopes, new Map()]), depth);
|
|
1336
1336
|
const run = Effect.gen(function* () {
|
|
1337
1337
|
// Seed all parameters first so defaults cannot fall through to same-named outer bindings.
|
|
1338
1338
|
const paramScope = invocation.scopes.current();
|
|
@@ -1343,7 +1343,7 @@ class Frame {
|
|
|
1343
1343
|
}
|
|
1344
1344
|
for (const [index, parameter] of fn.parameters.entries()) {
|
|
1345
1345
|
if (parameter.type === "RestElement") {
|
|
1346
|
-
yield* invocation.declarePattern(parameter.argument, new
|
|
1346
|
+
yield* invocation.declarePattern(parameter.argument, new Arr(self.ctx.builtins.Array, args.slice(index)), true, parameter, true);
|
|
1347
1347
|
break;
|
|
1348
1348
|
}
|
|
1349
1349
|
yield* invocation.declarePattern(parameter, args[index], true, parameter, true);
|
|
@@ -1360,15 +1360,15 @@ class Frame {
|
|
|
1360
1360
|
return Effect.succeed(this.createGenerator(invocation, run, fn.async));
|
|
1361
1361
|
if (!fn.async)
|
|
1362
1362
|
return run;
|
|
1363
|
-
return this.
|
|
1363
|
+
return this.ctx.pending.createWithSelf((self) => Effect.flatMap(run, (value) => resolvePromiseValue(invocation.ctx, value, self)));
|
|
1364
1364
|
});
|
|
1365
1365
|
}
|
|
1366
1366
|
createGenerator(invocation, run, asynchronous) {
|
|
1367
1367
|
const state = { started: false, completed: false, draining: false, pending: [], pendingIndex: 0 };
|
|
1368
1368
|
invocation.generatorState = state;
|
|
1369
1369
|
invocation.generatorAsync = asynchronous;
|
|
1370
|
-
const
|
|
1371
|
-
const result = (value, done) => record(
|
|
1370
|
+
const builtins = this.ctx.builtins;
|
|
1371
|
+
const result = (value, done) => record(builtins.Object, { value, done });
|
|
1372
1372
|
const request = (kind, value) => {
|
|
1373
1373
|
const request = { kind, value, response: Deferred.makeUnsafe() };
|
|
1374
1374
|
if (!asynchronous && state.active)
|
|
@@ -1380,19 +1380,19 @@ class Frame {
|
|
|
1380
1380
|
if (state.draining)
|
|
1381
1381
|
return Deferred.await(request.response);
|
|
1382
1382
|
state.draining = true;
|
|
1383
|
-
return Effect.andThen(this.
|
|
1383
|
+
return Effect.andThen(this.ctx.pending.fork(invocation
|
|
1384
1384
|
.completeGeneratorRequests(state, true)
|
|
1385
1385
|
.pipe(Effect.ensuring(Effect.sync(() => (state.draining = false))))), Deferred.await(request.response));
|
|
1386
1386
|
}
|
|
1387
1387
|
if (state.completed) {
|
|
1388
1388
|
if (kind === "throw")
|
|
1389
|
-
return Effect.fail(new
|
|
1389
|
+
return Effect.fail(new Throw(value));
|
|
1390
1390
|
return Effect.succeed(result(kind === "return" ? value : undefined, true));
|
|
1391
1391
|
}
|
|
1392
1392
|
if (!state.started && kind !== "next") {
|
|
1393
1393
|
state.completed = true;
|
|
1394
1394
|
if (kind === "throw")
|
|
1395
|
-
return Effect.fail(new
|
|
1395
|
+
return Effect.fail(new Throw(value));
|
|
1396
1396
|
return Effect.succeed(result(value, true));
|
|
1397
1397
|
}
|
|
1398
1398
|
state.pending.push(request);
|
|
@@ -1418,23 +1418,23 @@ class Frame {
|
|
|
1418
1418
|
yield* invocation.completeGeneratorRequests(state, asynchronous);
|
|
1419
1419
|
state.completed = true;
|
|
1420
1420
|
});
|
|
1421
|
-
return Effect.andThen(this.
|
|
1421
|
+
return Effect.andThen(this.ctx.pending.fork(body), Deferred.await(request.response));
|
|
1422
1422
|
}
|
|
1423
1423
|
return Deferred.await(request.response);
|
|
1424
1424
|
};
|
|
1425
|
-
const generator = new
|
|
1425
|
+
const generator = new GeneratorObj(asynchronous ? builtins.AsyncGenerator : builtins.Generator, asynchronous, request);
|
|
1426
1426
|
return generator;
|
|
1427
1427
|
}
|
|
1428
1428
|
completeGeneratorRequests(state, asynchronous) {
|
|
1429
1429
|
const self = this;
|
|
1430
|
-
const result = (value, done) => record(self.
|
|
1430
|
+
const result = (value, done) => record(self.ctx.builtins.Object, { value, done });
|
|
1431
1431
|
return Effect.gen(function* () {
|
|
1432
1432
|
while (true) {
|
|
1433
1433
|
const pending = self.dequeueGeneratorRequest(state);
|
|
1434
1434
|
if (!pending)
|
|
1435
1435
|
return;
|
|
1436
1436
|
if (pending.kind === "throw") {
|
|
1437
|
-
Deferred.doneUnsafe(pending.response, Exit.fail(new
|
|
1437
|
+
Deferred.doneUnsafe(pending.response, Exit.fail(new Throw(pending.value)));
|
|
1438
1438
|
continue;
|
|
1439
1439
|
}
|
|
1440
1440
|
if (asynchronous && pending.kind === "return") {
|
|
@@ -1483,14 +1483,14 @@ class Frame {
|
|
|
1483
1483
|
const state = this.generatorState;
|
|
1484
1484
|
if (!state?.active)
|
|
1485
1485
|
throw typeError("Generator has no active request.", node);
|
|
1486
|
-
Deferred.doneUnsafe(state.active.response, Exit.succeed(record(this.
|
|
1486
|
+
Deferred.doneUnsafe(state.active.response, Exit.succeed(record(this.ctx.builtins.Object, { value, done: false })));
|
|
1487
1487
|
state.active = undefined;
|
|
1488
1488
|
return Effect.flatMap(this.takeGeneratorRequest(state), (request) => {
|
|
1489
1489
|
state.active = request;
|
|
1490
1490
|
if (request.kind === "next")
|
|
1491
1491
|
return Effect.succeed(request.value);
|
|
1492
1492
|
if (request.kind === "throw")
|
|
1493
|
-
return Effect.fail(new
|
|
1493
|
+
return Effect.fail(new Throw(request.value));
|
|
1494
1494
|
return this.generatorAsync
|
|
1495
1495
|
? Effect.flatMap(this.awaitValue(request.value), (value) => Effect.fail(new GeneratorReturn(value)))
|
|
1496
1496
|
: Effect.fail(new GeneratorReturn(request.value));
|
|
@@ -1499,12 +1499,13 @@ class Frame {
|
|
|
1499
1499
|
delegateYield(value, node) {
|
|
1500
1500
|
const self = this;
|
|
1501
1501
|
return Effect.gen(function* () {
|
|
1502
|
-
if (value instanceof
|
|
1502
|
+
if (value instanceof Arr ||
|
|
1503
1503
|
typeof value === "string" ||
|
|
1504
|
-
value instanceof
|
|
1505
|
-
value instanceof
|
|
1506
|
-
value instanceof
|
|
1507
|
-
|
|
1504
|
+
value instanceof MapObj ||
|
|
1505
|
+
value instanceof SetObj ||
|
|
1506
|
+
value instanceof URLSearchParamsObj ||
|
|
1507
|
+
value instanceof Bytes) {
|
|
1508
|
+
const cursor = yield* self.iterate(value, node);
|
|
1508
1509
|
if (!cursor)
|
|
1509
1510
|
throw typeError("Built-in iterator is unavailable.", node);
|
|
1510
1511
|
while (true) {
|
|
@@ -1519,7 +1520,7 @@ class Frame {
|
|
|
1519
1520
|
yield* cursor.close;
|
|
1520
1521
|
return yield* Effect.fail(error);
|
|
1521
1522
|
}
|
|
1522
|
-
if (error instanceof
|
|
1523
|
+
if (error instanceof Throw) {
|
|
1523
1524
|
yield* cursor.close;
|
|
1524
1525
|
throw typeError("The delegated iterator does not provide a throw() method.", node);
|
|
1525
1526
|
}
|
|
@@ -1539,7 +1540,7 @@ class Frame {
|
|
|
1539
1540
|
yield* self.closeIterator(iterator, node, self.generatorAsync);
|
|
1540
1541
|
throw typeError("The delegated iterator does not provide a throw() method.", node);
|
|
1541
1542
|
}
|
|
1542
|
-
const called = yield* self.
|
|
1543
|
+
const called = yield* self.call(self.requireIteratorMethod(method, `Iterator ${kind}`, node), iterator.iterator, [input], node);
|
|
1543
1544
|
const result = self.requireIteratorObject(iterator.asynchronous ? yield* self.awaitValue(called) : called, `Iterator ${kind}() result`, node);
|
|
1544
1545
|
const done = Boolean(get(result, "done"));
|
|
1545
1546
|
const resultValue = self.generatorAsync && !iterator.asynchronous
|
|
@@ -1557,7 +1558,7 @@ class Frame {
|
|
|
1557
1558
|
continue;
|
|
1558
1559
|
}
|
|
1559
1560
|
const error = Cause.squash(resumed.cause);
|
|
1560
|
-
if (!(error instanceof GeneratorReturn) && !(error instanceof
|
|
1561
|
+
if (!(error instanceof GeneratorReturn) && !(error instanceof Throw)) {
|
|
1561
1562
|
return yield* Effect.failCause(resumed.cause);
|
|
1562
1563
|
}
|
|
1563
1564
|
kind = error instanceof GeneratorReturn ? "return" : "throw";
|
|
@@ -1566,7 +1567,7 @@ class Frame {
|
|
|
1566
1567
|
});
|
|
1567
1568
|
}
|
|
1568
1569
|
evaluateObjectExpression(node) {
|
|
1569
|
-
const objectValue = new
|
|
1570
|
+
const objectValue = new Obj(this.ctx.builtins.Object);
|
|
1570
1571
|
const self = this;
|
|
1571
1572
|
return Effect.gen(function* () {
|
|
1572
1573
|
for (const property of node.properties) {
|
|
@@ -1574,7 +1575,7 @@ class Frame {
|
|
|
1574
1575
|
const spread = yield* self.evaluateExpression(property.argument);
|
|
1575
1576
|
if (spread === null || spread === undefined)
|
|
1576
1577
|
continue;
|
|
1577
|
-
assign(objectValue, enumerableSource(self.
|
|
1578
|
+
assign(objectValue, enumerableSource(self.ctx, "Object spread", spread, property));
|
|
1578
1579
|
continue;
|
|
1579
1580
|
}
|
|
1580
1581
|
if (property.kind !== "init") {
|
|
@@ -1616,7 +1617,7 @@ class Frame {
|
|
|
1616
1617
|
}
|
|
1617
1618
|
if (element.type === "SpreadElement") {
|
|
1618
1619
|
const spread = yield* self.evaluateExpression(element.argument);
|
|
1619
|
-
const cursor = yield* self.
|
|
1620
|
+
const cursor = yield* self.iterate(spread, element);
|
|
1620
1621
|
if (cursor === undefined)
|
|
1621
1622
|
throw typeError("Array spread requires a synchronous iterable.", element);
|
|
1622
1623
|
while (true) {
|
|
@@ -1630,7 +1631,7 @@ class Frame {
|
|
|
1630
1631
|
values.push(yield* self.evaluateExpression(element));
|
|
1631
1632
|
}
|
|
1632
1633
|
}
|
|
1633
|
-
return new
|
|
1634
|
+
return new Arr(self.ctx.builtins.Array, values);
|
|
1634
1635
|
});
|
|
1635
1636
|
}
|
|
1636
1637
|
evaluateTemplateLiteral(node) {
|
|
@@ -1649,7 +1650,7 @@ class Frame {
|
|
|
1649
1650
|
checkStringLength(output.length);
|
|
1650
1651
|
if (index < expressions.length) {
|
|
1651
1652
|
const raw = yield* self.evaluateExpression(expressions[index]);
|
|
1652
|
-
output += coerceToString(toProgram(self.
|
|
1653
|
+
output += coerceToString(toProgram(self.ctx.builtins, raw, "Template interpolation"));
|
|
1653
1654
|
checkStringLength(output.length);
|
|
1654
1655
|
}
|
|
1655
1656
|
}
|
|
@@ -1690,22 +1691,22 @@ class Frame {
|
|
|
1690
1691
|
}
|
|
1691
1692
|
return new ToolReference([...objectValue.path, key]);
|
|
1692
1693
|
}
|
|
1693
|
-
if (objectValue instanceof
|
|
1694
|
+
if (objectValue instanceof Obj)
|
|
1694
1695
|
return { target: objectValue, key, receiver: objectValue };
|
|
1695
1696
|
// Primitives read through their wrapper prototype without being boxed; strings own length and indexes.
|
|
1696
|
-
const
|
|
1697
|
+
const builtins = self.ctx.builtins;
|
|
1697
1698
|
if (typeof objectValue === "string") {
|
|
1698
1699
|
if (key === "length")
|
|
1699
1700
|
return { value: objectValue.length };
|
|
1700
1701
|
const index = typeof key === "symbol" ? undefined : parseArrayIndex(key);
|
|
1701
1702
|
if (index !== undefined)
|
|
1702
1703
|
return { value: objectValue[index] };
|
|
1703
|
-
return { target:
|
|
1704
|
+
return { target: builtins.String, key, receiver: objectValue };
|
|
1704
1705
|
}
|
|
1705
1706
|
if (typeof objectValue === "number")
|
|
1706
|
-
return { target:
|
|
1707
|
+
return { target: builtins.Number, key, receiver: objectValue };
|
|
1707
1708
|
if (typeof objectValue === "boolean")
|
|
1708
|
-
return { target:
|
|
1709
|
+
return { target: builtins.Boolean, key, receiver: objectValue };
|
|
1709
1710
|
if (objectValue === null || objectValue === undefined) {
|
|
1710
1711
|
throw typeError(`Cannot read properties of ${objectValue} (reading '${String(key)}').`, objectNode);
|
|
1711
1712
|
}
|
|
@@ -1714,7 +1715,7 @@ class Frame {
|
|
|
1714
1715
|
}
|
|
1715
1716
|
readReference(reference, node) {
|
|
1716
1717
|
// Reject unknown promise properties so a missing await cannot hide.
|
|
1717
|
-
if (reference.target instanceof
|
|
1718
|
+
if (reference.target instanceof PromiseObj && !has(reference.target, reference.key)) {
|
|
1718
1719
|
throw invalidData("This value is an un-awaited Promise; await it first - e.g. `const result = await tools.ns.tool(...)`.", node.object);
|
|
1719
1720
|
}
|
|
1720
1721
|
return this.readProperty(reference.target, reference.key, node, reference.receiver);
|
|
@@ -1779,7 +1780,7 @@ class Frame {
|
|
|
1779
1780
|
assignToReference(target, key, next, node) {
|
|
1780
1781
|
const written = (() => {
|
|
1781
1782
|
try {
|
|
1782
|
-
rejectCircularInsertion(target, next, target instanceof
|
|
1783
|
+
rejectCircularInsertion(target, next, target instanceof Arr ? "Array assignment result" : "Object assignment result");
|
|
1783
1784
|
return set(target, key, next);
|
|
1784
1785
|
}
|
|
1785
1786
|
catch (error) {
|
|
@@ -1788,7 +1789,7 @@ class Frame {
|
|
|
1788
1789
|
})();
|
|
1789
1790
|
if (written)
|
|
1790
1791
|
return;
|
|
1791
|
-
if (target instanceof
|
|
1792
|
+
if (target instanceof Arr && key === "length")
|
|
1792
1793
|
throw rangeError("Invalid array length", node);
|
|
1793
1794
|
throw typeError(`Cannot assign to read only property '${String(key)}'.`, node);
|
|
1794
1795
|
}
|