@ball-lang/compiler 1.68.4 → 1.68.6

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.
@@ -174,8 +174,20 @@ export declare class BallCompiler {
174
174
  private filterCtorBody;
175
175
  /**
176
176
  * Builds a named constructor as a static factory method.
177
- * Named constructors (e.g., Point.origin, Point.fromList) create instances
178
- * from field initializers in metadata.
177
+ *
178
+ * Every named constructor that is not a Dart `factory` CONSTRUCTS a real
179
+ * instance — whether it carries an initializer list (`Point.origin() : x =
180
+ * 0`), `this.`-formals (`Box.of(this.value)`), a plain body
181
+ * (`Bar.named(int x) { print(x); }`), or any combination. The instance comes
182
+ * from `Object.create(C.prototype)` so no user constructor runs, which means
183
+ * the class's inline field initializers do not run either: every declared
184
+ * field is seeded with its own default FIRST (Dart's ordering — inline field
185
+ * initializers, then the initializer list, then the body), and only then do
186
+ * the constructor-specific writes land on top (#564).
187
+ *
188
+ * A `factory` named constructor is the one exception: by definition it
189
+ * returns some other object, so its body runs as the static method's own
190
+ * statements and its value is the method's result.
179
191
  */
180
192
  private buildNamedCtor;
181
193
  private buildMethod;
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"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"}
package/dist/compiler.js CHANGED
@@ -2259,8 +2259,11 @@ function __isUnknownFnError(e: any): boolean {
2259
2259
  }
2260
2260
  else {
2261
2261
  // Named constructors are static factory methods that return a new
2262
- // instance. Build them by creating an instance from initializers.
2263
- methods.push(this.buildNamedCtor(fn, mMeta, fieldNames, tsName));
2262
+ // instance. The class's own (non-static) field declarations go with
2263
+ // them: the instance is built with `Object.create`, which runs no
2264
+ // field initializer, so the builder has to seed each default itself
2265
+ // (#564).
2266
+ methods.push(this.buildNamedCtor(fn, mMeta, fieldNames, tsName, properties.filter((p) => !p.isStatic)));
2264
2267
  }
2265
2268
  }
2266
2269
  else if (mMeta["is_getter"] === true) {
@@ -2402,8 +2405,15 @@ function __isUnknownFnError(e: any): boolean {
2402
2405
  }
2403
2406
  }
2404
2407
  else {
2408
+ // ONLY a `this.`-formal writes a constructor parameter into the field of
2409
+ // the same name. A plain parameter that merely happens to share a
2410
+ // field's name is an ordinary local and must never clobber that field's
2411
+ // initializer — `class Foo { int x = 5; Foo(int x) { print(x); } }`
2412
+ // leaves `x` at 5 in Dart (#539/#564, conformance 453). The old
2413
+ // `|| classFields.has(p.name)` disjunct is the byte-identical defect the
2414
+ // Dart engine carried until #563.
2405
2415
  for (const p of rawParams) {
2406
- if (p.isThis || classFields.has(p.name)) {
2416
+ if (p.isThis) {
2407
2417
  prologueParts.push(`this.${p.name} = ${sanitize(p.name)};`);
2408
2418
  }
2409
2419
  }
@@ -2469,53 +2479,48 @@ function __isUnknownFnError(e: any): boolean {
2469
2479
  }
2470
2480
  /**
2471
2481
  * Builds a named constructor as a static factory method.
2472
- * Named constructors (e.g., Point.origin, Point.fromList) create instances
2473
- * from field initializers in metadata.
2482
+ *
2483
+ * Every named constructor that is not a Dart `factory` CONSTRUCTS a real
2484
+ * instance — whether it carries an initializer list (`Point.origin() : x =
2485
+ * 0`), `this.`-formals (`Box.of(this.value)`), a plain body
2486
+ * (`Bar.named(int x) { print(x); }`), or any combination. The instance comes
2487
+ * from `Object.create(C.prototype)` so no user constructor runs, which means
2488
+ * the class's inline field initializers do not run either: every declared
2489
+ * field is seeded with its own default FIRST (Dart's ordering — inline field
2490
+ * initializers, then the initializer list, then the body), and only then do
2491
+ * the constructor-specific writes land on top (#564).
2492
+ *
2493
+ * A `factory` named constructor is the one exception: by definition it
2494
+ * returns some other object, so its body runs as the static method's own
2495
+ * statements and its value is the method's result.
2474
2496
  */
2475
- buildNamedCtor(fn, meta, classFields, className) {
2497
+ buildNamedCtor(fn, meta, classFields, className, classProperties = []) {
2476
2498
  const params = extractParams(fn);
2477
2499
  const ctorParams = extractCtorParams(meta);
2478
2500
  const initializers = Array.isArray(meta["initializers"]) ? meta["initializers"] : [];
2479
2501
  // Build the body: resolve field initializers and create a new instance.
2480
2502
  const bodyParts = [];
2481
- const ctorArgs = [];
2482
- // Extract field initializers to build constructor arguments
2483
- for (const init of initializers) {
2484
- if (init?.kind === "field" && typeof init.name === "string") {
2485
- const valueStr = typeof init.value === "string" ? init.value : "null";
2486
- // Resolve the value: could be a param reference, literal, or expression
2487
- let resolvedValue;
2488
- if (params.includes(valueStr)) {
2489
- resolvedValue = sanitize(valueStr);
2490
- }
2491
- else if (/^-?\d+(\.\d+)?$/.test(valueStr)) {
2492
- // Numeric literal — wrap in BallDouble if it has a decimal point
2493
- resolvedValue = valueStr.includes(".") ? `new BallDouble(${valueStr})` : valueStr;
2494
- }
2495
- else if (valueStr.startsWith("'") || valueStr.startsWith('"')) {
2496
- resolvedValue = valueStr;
2497
- }
2498
- else {
2499
- // Try to parse indexed access like "coords[0]"
2500
- const idxMatch = /^(\w+)\[(\d+)\]$/.exec(valueStr);
2501
- if (idxMatch && params.includes(idxMatch[1])) {
2502
- resolvedValue = `${sanitize(idxMatch[1])}[${idxMatch[2]}]`;
2503
- }
2504
- else {
2505
- resolvedValue = valueStr;
2506
- }
2507
- }
2508
- ctorArgs.push(resolvedValue);
2509
- }
2510
- }
2511
- // Also check for is_this params — they pass directly to the constructor
2503
+ // Does the ctor have any field write of its own? Only WHETHER matters
2504
+ // here; each value is resolved where the assignment is emitted, by
2505
+ // `resolveInitializerValue`. (A `this.`-formal counts only when there is
2506
+ // no initializer list at all, preserving the historical branch selection
2507
+ // for the `Foo.named(this.x) : super(...)` shape, which still falls
2508
+ // through to `return new Foo()`.)
2512
2509
  const thisParams = ctorParams.filter(p => p.isThis);
2513
- if (ctorArgs.length === 0 && initializers.length === 0 && thisParams.length > 0) {
2514
- for (const p of thisParams) {
2515
- ctorArgs.push(sanitize(p.name));
2516
- }
2517
- }
2518
- if (ctorArgs.length > 0 || (initializers.length > 0 && ctorArgs.length > 0)) {
2510
+ const hasFieldInitializers = initializers.some((i) => i?.kind === "field" && typeof i.name === "string");
2511
+ const hasCtorFieldWrites = hasFieldInitializers || (initializers.length === 0 && thisParams.length > 0);
2512
+ // A Dart `factory` returns some other object, so it is the ONE named
2513
+ // constructor that must not synthesize an instance of its own class.
2514
+ const isFactory = meta["is_factory"] === true;
2515
+ // Everything else constructs: an initializer list / `this.`-formal, or a
2516
+ // plain body, or both. A body-only named constructor
2517
+ // (`Bar.named(int x) { print(x); }`) used to fall through to the
2518
+ // run-the-body-as-a-static-method branch below, so it created no instance
2519
+ // at all — `this` inside it was the CLASS and the method returned the
2520
+ // body's value, i.e. `undefined` for a `print` (#564, conformance
2521
+ // 453/454).
2522
+ const constructsInstance = hasCtorFieldWrites || (fn.body !== undefined && !isFactory);
2523
+ if (constructsInstance) {
2519
2524
  // Use Object.create to avoid calling the constructor (which might be a factory).
2520
2525
  // This directly instantiates with fields set.
2521
2526
  const assignments = initializers
@@ -2525,16 +2530,29 @@ function __isUnknownFnError(e: any): boolean {
2525
2530
  const thisAssignments = thisParams.map(p => `__inst.${p.name} = ${sanitize(p.name)};`);
2526
2531
  const allAssignments = [...assignments, ...thisAssignments];
2527
2532
  bodyParts.push(`const __inst = Object.create(${className}.prototype);`);
2533
+ // `Object.create` deliberately runs no constructor — which also means it
2534
+ // runs none of the class's inline field initializers. Seed every
2535
+ // declared field with the SAME default the class declaration emits,
2536
+ // before any constructor-specific write, exactly as Dart orders them
2537
+ // (inline initializers, then the initializer list, then the body).
2538
+ // Without this a field the named constructor never mentions stayed
2539
+ // `undefined` forever (#564: `Init.viaList`'s `w`, `Baz.bare`'s `v`).
2540
+ for (const p of classProperties) {
2541
+ const def = dartInitializerToTs(p.dartInitializer, p.type, p.rawDartType);
2542
+ if (def !== undefined)
2543
+ bodyParts.push(`__inst.${p.name} = ${def};`);
2544
+ }
2528
2545
  for (const a of allAssignments)
2529
2546
  bodyParts.push(a);
2530
- // A named constructor may have BOTH an initializer list / `this.`-params
2531
- // AND a body (`Countdown.pair(int s) : value = s { tail = …; }`, or
2532
- // `Countdown.from(this.value) { … }`). Dart runs the list first, then the
2533
- // body; the body used to be dropped entirely by this branch, so every
2534
- // field the body set stayed unset (conformance 436/438). `.call(__inst)`
2535
- // — a real `function`, not an arrow — gives the compiled body the
2536
- // instance as `this`, so its `this.<field>` writes land on `__inst`,
2537
- // while the constructor's parameters stay in scope by closure.
2547
+ // A named constructor may have an initializer list / `this.`-params, a
2548
+ // body, or both (`Countdown.pair(int s) : value = s { tail = …; }`,
2549
+ // `Countdown.from(this.value) { … }`, `Bar.named(int x) { print(x); }`).
2550
+ // Dart runs the list first, then the body; the body used to be dropped
2551
+ // entirely by this branch, so every field the body set stayed unset
2552
+ // (conformance 436/438). `.call(__inst)` — a real `function`, not an
2553
+ // arrow — gives the compiled body the instance as `this`, so its
2554
+ // `this.<field>` writes land on `__inst`, while the constructor's
2555
+ // parameters stay in scope by closure.
2538
2556
  if (fn.body) {
2539
2557
  const captured = this.withMethodContext(new Set(params), classFields, () => this.captureInto(() => {
2540
2558
  this.emitStatementOrExpression(fn.body, false);
@@ -2546,13 +2564,18 @@ function __isUnknownFnError(e: any): boolean {
2546
2564
  bodyParts.push(`return __inst;`);
2547
2565
  }
2548
2566
  else if (fn.body) {
2549
- // Has an actual body — use it
2567
+ // A `factory` named constructor: its body IS the method whatever it
2568
+ // evaluates to is what the caller gets, and no instance of this class is
2569
+ // synthesized. This is the only body-bearing shape that reaches here
2570
+ // (every non-factory body constructs, above).
2550
2571
  const captured = this.withMethodContext(new Set(params), classFields, () => this.captureInto(() => {
2551
2572
  this.emitStatementOrExpression(fn.body, true);
2552
2573
  }));
2553
2574
  bodyParts.push(captured);
2554
2575
  }
2555
2576
  else {
2577
+ // Nothing to run and nothing to assign: let the real constructor build
2578
+ // it (which runs the class's inline field initializers itself).
2556
2579
  bodyParts.push(`return new ${className}();`);
2557
2580
  }
2558
2581
  return {