@ball-lang/engine 1.4.5 → 1.5.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ball-lang/engine",
3
- "version": "1.4.5",
3
+ "version": "1.5.1",
4
4
  "description": "Ball language engine — interprets Ball programs in TypeScript/JavaScript. Runs in Node.js and browsers.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -3726,7 +3726,7 @@ export class BallEngine {
3726
3726
  }
3727
3727
  else if ((__sw === 'reversed')) {
3728
3728
  if (!__ball_eq(rawList, null)) {
3729
- return [...rawList.reversed];
3729
+ return this._manualReverse(rawList);
3730
3730
  }
3731
3731
  }
3732
3732
  else if ((__sw === 'keys')) {
@@ -6078,7 +6078,7 @@ export class BallEngine {
6078
6078
  return _wrapList(self.slice(this._toInt(arg0), (!__ball_eq(end, null) ? this._toInt(end) : null)));
6079
6079
  }
6080
6080
  else if ((__sw === 'reversed')) {
6081
- return _wrapList([...self.reversed]);
6081
+ return _wrapList(this._manualReverse(self));
6082
6082
  }
6083
6083
  else if ((__sw === 'sort')) {
6084
6084
  if ((typeof arg0 === 'function')) {
@@ -7223,7 +7223,7 @@ export class BallEngine {
7223
7223
  return (() => { const __r: any[] = []; for (const idx of indices) { __r.push(__ball_index(list, idx)); } return __r; })();
7224
7224
  }), ['list_reverse']: ((i) => {
7225
7225
  const input = i;
7226
- return this._trackListCopy([...this._stdAsList(__ball_index(this._stdAsMap(i), 'list')).reversed]);
7226
+ return this._trackListCopy(this._manualReverse(this._stdAsList(__ball_index(this._stdAsMap(i), 'list'))));
7227
7227
  }), ['list_slice']: ((i) => {
7228
7228
  const input = i;
7229
7229
  let m = this._stdAsMap(i);
@@ -8168,6 +8168,15 @@ export class BallEngine {
8168
8168
  return list;
8169
8169
  }
8170
8170
 
8171
+ _manualReverse(list: any): any {
8172
+ const input = list;
8173
+ let result = [];
8174
+ for (let i = __ball_sub(list.length, 1); (i >= 0); (i--)) {
8175
+ result = (result.push(__ball_index(list, i)), result);
8176
+ }
8177
+ return result;
8178
+ }
8179
+
8171
8180
  _resolveMethod(typeName: any, methodName: any): any {
8172
8181
  let colonIdx = typeName.indexOf(':');
8173
8182
  let modPart = ((colonIdx >= 0) ? typeName.substring(0, colonIdx) : this._currentModule);
@@ -786,8 +786,19 @@ export function createEngineSetup(mod: EngineModule) {
786
786
  _r('list_add', (i: any) => { const m = _m(i); const l = m['list'] ?? m['collection']; const v = m['value'] ?? m['element']; if (l instanceof Set) { l.add(v); return null; } if (Array.isArray(l)) l.push(v); return null; });
787
787
  _r('list_add_all', (i: any) => { const m = _m(i); const l = m['list'] ?? m['collection']; const o = m['other'] ?? m['elements'] ?? []; if (Array.isArray(l) && Array.isArray(o)) l.push(...o); return null; });
788
788
  _r('list_remove_at', (i: any) => { const m = _m(i); const l = m['list'] ?? m['collection']; const idx = Number(m['index'] ?? 0); return Array.isArray(l) ? l.splice(idx, 1)[0] : null; });
789
- _r('list_insert', (i: any) => { const m = _m(i); const l = m['list'] ?? m['collection']; const idx = Number(m['index'] ?? 0); const v = m['value'] ?? m['element']; if (Array.isArray(l)) l.splice(idx, 0, v); return null; });
790
- _r('list_clear', (i: any) => { const m = _m(i); const l = m['list'] ?? m['collection']; if (Array.isArray(l)) l.length = 0; return null; });
789
+ // Both mutate in place AND return the (mutated) list: the encoder wraps
790
+ // `list.insert(...)` / `list.clear()` statements in
791
+ // `assign(target: list, value: list_insert(...)/list_clear(...))`
792
+ // (`mutatingMethods` in encoder.dart), so returning `null` here — as a
793
+ // literal Dart-`void`-return translation would — reassigns the variable
794
+ // to `null` instead of the mutated list (issue #64 std-coverage gap:
795
+ // `385_list_insert_at_index` was the first fixture to actually exercise
796
+ // the non-cascade `list_insert` path on the TS self-host and caught
797
+ // this). `list_clear` has the identical bug shape but was previously
798
+ // only exercised via a cascade (`111_cascade_operator.dart`), which
799
+ // discards the mutating call's return value and never surfaced it.
800
+ _r('list_insert', (i: any) => { const m = _m(i); const l = m['list'] ?? m['collection']; const idx = Number(m['index'] ?? 0); const v = m['value'] ?? m['element']; if (Array.isArray(l)) l.splice(idx, 0, v); return l; });
801
+ _r('list_clear', (i: any) => { const m = _m(i); const l = m['list'] ?? m['collection']; if (Array.isArray(l)) l.length = 0; return l; });
791
802
  _r('list_contains', (i: any) => {
792
803
  const m = _m(i); const l = m['list'] ?? m['collection'] ?? []; const v = m['value'] ?? m['element'];
793
804
  if (l instanceof Set) { if (l.has(v)) return true; if (typeof v === 'number') return l.has(String(v)); if (typeof v === 'string') { const n = Number(v); if (!isNaN(n)) return l.has(n); } return false; }