@opencode/codemode 0.0.0-dev-19959 → 0.0.0-dev-19961

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.
@@ -6,7 +6,7 @@ import { checkStringLength } from "./limits.js";
6
6
  import { locate, materialize } from "./errors.js";
7
7
  import { primitivePrototype } from "./intrinsics.js";
8
8
  import { globals } from "./globals.js";
9
- import { assign, Callable, define, get, hostCursor, IteratorObj, has, hasPrototype, keys, Native, parseArrayIndex, Arr, Fn, GeneratorObj, Obj, PromiseObj, record, remove, set, coerceToNumber, coerceToString, } from "./objects.js";
9
+ import { assign, Callable, define, get, hostCursor, IteratorObj, has, hidden, hasPrototype, keys, Native, parseArrayIndex, Arr, Fn, GeneratorObj, Obj, PromiseObj, record, remove, set, coerceToNumber, coerceToString, } from "./objects.js";
10
10
  import { preserveConsumerError } from "./callback.js";
11
11
  import { Pending, resolvePromise, resolvePromiseValue } from "./promises.js";
12
12
  import { containsOpaqueReference, describeValue, rejectCircularInsertion, typeofValue } from "./references.js";
@@ -318,7 +318,16 @@ class Frame {
318
318
  }).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
319
319
  }
320
320
  createFunction(node, name = node.type === "ArrowFunctionExpression" ? "" : (node.id?.name ?? "")) {
321
- return new Fn(this.ctx.builtins.Function, name, node.params, node.body, this.scopes.capture(), node.async, node.generator);
321
+ const builtins = this.ctx.builtins;
322
+ const fn = new Fn(builtins.Function, name, node.params, node.body, this.scopes.capture(), node.async, node.generator);
323
+ // Each generator function gets its own prototype, so `g() instanceof g` holds as in JS.
324
+ if (node.generator)
325
+ define(fn, "prototype", new Obj(node.async ? builtins.AsyncGenerator : builtins.Generator), hidden);
326
+ // The body of a named function expression sees its own name, read-only.
327
+ if (node.type === "FunctionExpression" && node.id) {
328
+ fn.capturedScopes.push(new Map([[node.id.name, { mutable: false, value: fn, initialized: true }]]));
329
+ }
330
+ return fn;
322
331
  }
323
332
  // NamedEvaluation: an anonymous function definition takes the name of what it is assigned to.
324
333
  evaluateNamed(node, name) {
@@ -327,11 +336,12 @@ class Frame {
327
336
  }
328
337
  return this.evaluateExpression(node);
329
338
  }
339
+ // Repeated `function` declarations and `var` clashes are legal: the last declaration wins.
330
340
  hoistFunctions(statements) {
331
341
  for (const node of statements) {
332
342
  if (node.type !== "FunctionDeclaration")
333
343
  continue;
334
- this.scopes.declare(node.id.name, this.createFunction(node), true, node);
344
+ this.scopes.current().set(node.id.name, { mutable: true, value: this.createFunction(node), initialized: true });
335
345
  }
336
346
  }
337
347
  // Hoisted `var` bindings start undefined, or copy a same-named parameter. Function bodies hoist
@@ -1373,13 +1383,14 @@ class Frame {
1373
1383
  return yield* invocation.evaluateExpression(fn.body);
1374
1384
  });
1375
1385
  if (fn.generator)
1376
- return Effect.succeed(this.createGenerator(invocation, run, fn.async));
1386
+ return Effect.succeed(this.createGenerator(invocation, run, fn));
1377
1387
  if (!fn.async)
1378
1388
  return run;
1379
1389
  return this.ctx.pending.createWithSelf((self) => Effect.flatMap(run, (value) => resolvePromiseValue(invocation.ctx, value, self)));
1380
1390
  });
1381
1391
  }
1382
- createGenerator(invocation, run, asynchronous) {
1392
+ createGenerator(invocation, run, fn) {
1393
+ const asynchronous = fn.async;
1383
1394
  const state = { started: false, completed: false, draining: false, pending: [], pendingIndex: 0 };
1384
1395
  invocation.generatorState = state;
1385
1396
  invocation.generatorAsync = asynchronous;
@@ -1438,8 +1449,8 @@ class Frame {
1438
1449
  }
1439
1450
  return Deferred.await(request.response);
1440
1451
  };
1441
- const generator = new GeneratorObj(asynchronous ? builtins.AsyncGenerator : builtins.Generator, asynchronous, request);
1442
- return generator;
1452
+ const proto = get(fn, "prototype");
1453
+ return new GeneratorObj(proto instanceof Obj ? proto : builtins.Generator, asynchronous, request);
1443
1454
  }
1444
1455
  completeGeneratorRequests(state, asynchronous) {
1445
1456
  const self = this;
@@ -1751,9 +1762,11 @@ class Frame {
1751
1762
  }
1752
1763
  evaluateDeleteExpression(argument) {
1753
1764
  const target = argument.type === "ChainExpression" ? argument.expression : argument;
1754
- if (target.type !== "MemberExpression") {
1765
+ if (target.type === "Identifier")
1755
1766
  throw typeError("Only data fields may be deleted.", argument);
1756
- }
1767
+ // `delete <non-reference>` evaluates the operand and is true, as in JS.
1768
+ if (target.type !== "MemberExpression")
1769
+ return Effect.map(this.evaluateExpression(target), () => true);
1757
1770
  return Effect.map(this.getMemberReference(target), (reference) => {
1758
1771
  if (reference === OptionalShortCircuit)
1759
1772
  return true;
@@ -87,10 +87,10 @@ export declare abstract class Callable extends Opaque {
87
87
  export declare class Fn extends Callable {
88
88
  readonly parameters: ReadonlyArray<Pattern>;
89
89
  readonly body: BlockStatement | Expression;
90
- readonly capturedScopes: ReadonlyArray<Map<string, Binding>>;
90
+ readonly capturedScopes: Array<Map<string, Binding>>;
91
91
  readonly async: boolean;
92
92
  readonly generator: boolean;
93
- constructor(proto: Obj, name: string, parameters: ReadonlyArray<Pattern>, body: BlockStatement | Expression, capturedScopes: ReadonlyArray<Map<string, Binding>>, async: boolean, generator: boolean);
93
+ constructor(proto: Obj, name: string, parameters: ReadonlyArray<Pattern>, body: BlockStatement | Expression, capturedScopes: Array<Map<string, Binding>>, async: boolean, generator: boolean);
94
94
  }
95
95
  export type NativeCall<R> = (thisValue: Value, args: Array<Value>) => Effect.Effect<Value, unknown, R>;
96
96
  export type NativeConstruct<R> = (args: Array<Value>, newTarget: Callable) => Effect.Effect<Value, unknown, R>;
@@ -166,7 +166,7 @@ export const mapGlobal = (ctx) => {
166
166
  const target = self(thisValue, "forEach");
167
167
  const apply = applyCollectionCallback(ctx, args[0], "Map.forEach");
168
168
  return Effect.gen(function* () {
169
- for (const [key, item] of Array.from(target.map.entries()))
169
+ for (const [key, item] of target.map.entries())
170
170
  yield* apply([item, key, target]);
171
171
  return undefined;
172
172
  });
@@ -356,7 +356,7 @@ export const setGlobal = (ctx) => {
356
356
  const target = self(thisValue, "forEach");
357
357
  const apply = applyCollectionCallback(ctx, args[0], "Set.forEach");
358
358
  return Effect.gen(function* () {
359
- for (const item of Array.from(target.set.values()))
359
+ for (const item of target.set.values())
360
360
  yield* apply([item, item, target]);
361
361
  return undefined;
362
362
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@opencode/codemode",
4
- "version": "0.0.0-dev-19959",
4
+ "version": "0.0.0-dev-19961",
5
5
  "description": "Effect-native confined code execution over schema-described tools",
6
6
  "type": "module",
7
7
  "license": "MIT",