All checks were successful
ci / fast (linux) (push) Successful in 7m9s
Create comprehensive implementation-ready story files for the remaining Epic 3 (JavaScript Engine Maturity) stories and update sprint status from backlog to ready-for-dev: - 3.5: Built-in Completeness (Array/String/Object) - 3.6: Built-in Completeness (Date/RegExp/Map/Set) - 3.7: WeakRef, FinalizationRegistry & Strict Mode Edge Cases - 3.8: DOM Bindings via web_api - 3.9: Event Dispatch Completeness - 3.10: Web API Exposure (fetch, Math, setInterval, rAF) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
331 lines
23 KiB
Markdown
331 lines
23 KiB
Markdown
# Story 3.5: Built-in Completeness -- Array/String/Object
|
|
|
|
Status: ready-for-dev
|
|
|
|
<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
|
|
|
|
## Story
|
|
|
|
As a web developer using JavaScript,
|
|
I want all standard Array, String, and Object methods to be available,
|
|
So that common JavaScript patterns and library code work correctly.
|
|
|
|
## Acceptance Criteria
|
|
|
|
1. **Array methods complete:** `splice`, `flat`, `flatMap`, `fill`, `copyWithin`, `at`, `from`, `of`, `entries`/`keys`/`values`, `toReversed`, `toSorted`, `toSpliced`, `with`, `toLocaleString` all behave per their ECMAScript specifications. Existing methods (`push`, `pop`, `shift`, `unshift`, `slice`, `concat`, `join`, `indexOf`, `lastIndexOf`, `includes`, `reverse`, `toString`, `sort`, `forEach`, `map`, `filter`, `find`, `findIndex`, `some`, `every`, `reduce`, `reduceRight`, `isArray`) continue to pass.
|
|
|
|
2. **String methods complete:** `padStart`, `padEnd`, `replaceAll`, `matchAll`, `at`, `codePointAt`, `normalize`, `String.fromCharCode`, `String.fromCodePoint`, `String.raw` all behave per their ECMAScript specifications. Existing methods (28 already implemented) continue to pass.
|
|
|
|
3. **Object methods complete:** `Object.defineProperty`, `Object.defineProperties`, `Object.getOwnPropertyDescriptor`, `Object.getOwnPropertyDescriptors`, `Object.getOwnPropertyNames`, `Object.setPrototypeOf`, `Object.freeze`, `Object.isFrozen`, `Object.seal`, `Object.isSealed`, `Object.preventExtensions`, `Object.isExtensible`, `Object.is`, `Object.fromEntries`, `Object.hasOwn`, `Object.prototype.isPrototypeOf` all behave per their ECMAScript specifications. Existing methods (11 already implemented) continue to pass.
|
|
|
|
4. **Callback error propagation:** Methods accepting callbacks (`map`, `filter`, `reduce`, `sort`, `flat`, `flatMap`, `from`, etc.) correctly propagate thrown errors without corrupting internal state.
|
|
|
|
5. **Property descriptor system:** `Object.defineProperty` enforces `writable`, `enumerable`, `configurable` flags. Accessor properties (get/set) work. `Object.freeze`/`Object.seal`/`Object.preventExtensions` enforce their respective constraints on subsequent operations.
|
|
|
|
6. **Iterator protocol for Array:** `Array.prototype.entries()`, `.keys()`, `.values()`, and `Array.prototype[Symbol.iterator]` return spec-compliant iterators usable with `for...of` (depends on generator/iterator protocol from Story 3.2).
|
|
|
|
7. **Test262 tests promoted:** All relevant vendored and full-suite Test262 tests for Array, String, and Object built-ins are promoted from `known_fail` to `pass`. `docs/JavaScript_Implementation_Checklist.md` and `docs/js_feature_matrix.md` are updated. `just ci` passes.
|
|
|
|
## What NOT to Implement
|
|
|
|
- **No `Intl` / locale-sensitive methods** -- `toLocaleString`, `toLocaleLowerCase`, `toLocaleUpperCase`, `localeCompare` are out of scope (would require ICU/locale data).
|
|
- **No `String.prototype.normalize` with full Unicode normalization** -- stub returning input unchanged is acceptable if full NFC/NFD/NFKC/NFKD is too complex.
|
|
- **No `Proxy` or `Reflect`** -- property descriptor enforcement is internal, not through Proxy traps.
|
|
- **No typed arrays** -- `Int8Array`, `Uint8Array`, etc. are separate built-ins for a future story.
|
|
- **No `structuredClone`** -- not a built-in method on these prototypes.
|
|
- **No `Array.prototype.group` / `groupToMap`** -- Stage 3, not yet standard at time of implementation.
|
|
|
|
## Files to Modify
|
|
|
|
| File | Change |
|
|
|------|--------|
|
|
| `crates/js_vm/src/interpreter/builtins.rs` | Add `splice`, `fill`, `copyWithin`, `at`, `flat`, `toReversed`, `toSorted`, `toSpliced`, `with`, `toLocaleString` to `eval_array_method()`. Add `padStart`, `padEnd`, `replaceAll`, `at`, `codePointAt` to `eval_string_method()`. |
|
|
| `crates/js_vm/src/interpreter/array_builtins.rs` | Add `flatMap` to `eval_array_callback_method()`. Add `Array.from(iterable, mapFn)` support. |
|
|
| `crates/js_vm/src/interpreter/mod.rs` | Extend `setup_builtins()` with new Object static methods and prototype methods. Add `String.fromCharCode`, `String.fromCodePoint`, `String.raw` as static methods on String constructor. Add `Array.of` as static method. Wire `entries()`/`keys()`/`values()` iterator methods. |
|
|
| `crates/js_vm/src/interpreter/primitive_builtins.rs` | Add String static methods (`fromCharCode`, `fromCodePoint`, `raw`) if String constructor setup lives here. |
|
|
| `crates/js_vm/src/interpreter/object_builtins.rs` | **New file** -- `Object.defineProperty`, `Object.defineProperties`, `Object.getOwnPropertyDescriptor`, `Object.getOwnPropertyDescriptors`, `Object.getOwnPropertyNames`, `Object.setPrototypeOf`, `Object.freeze`/`isFrozen`, `Object.seal`/`isSealed`, `Object.preventExtensions`/`isExtensible`, `Object.is`, `Object.fromEntries`, `Object.hasOwn`, `Object.prototype.isPrototypeOf`. |
|
|
| `crates/js_vm/src/value.rs` | Add property descriptor support: `PropertyDescriptor` struct (value, writable, enumerable, configurable, get, set), `PropertyFlags` bitflags, update `JsObject` property storage to support descriptors. |
|
|
| `crates/js_vm/src/interpreter/bytecode_exec.rs` | Update property access to respect descriptors (getter/setter calls, writable checks). |
|
|
| `crates/js_vm/src/interpreter/tests/array_tests.rs` | Add tests for all new Array methods. |
|
|
| `crates/js_vm/src/interpreter/tests/string_tests.rs` | Add tests for all new String methods. |
|
|
| `crates/js_vm/src/interpreter/tests/object_tests.rs` | Add tests for all new Object methods and property descriptors. |
|
|
| `tests/external/js262/js262_manifest.toml` | Promote passing tests. |
|
|
| `docs/JavaScript_Implementation_Checklist.md` | Check off completed built-in items. |
|
|
| `docs/old/js_feature_matrix.md` | Update built-in coverage. |
|
|
| `Cargo.toml` | No new dependencies expected. |
|
|
|
|
## Tasks / Subtasks
|
|
|
|
- [ ] Task 1: Property descriptor infrastructure (AC: #5)
|
|
- [ ] 1.1 Add `PropertyDescriptor` to `crates/js_vm/src/value.rs`:
|
|
- `PropertyDescriptor { value: Option<JsValue>, writable: Option<bool>, enumerable: Option<bool>, configurable: Option<bool>, get: Option<JsValue>, set: Option<JsValue> }`
|
|
- `PropertyFlags` bitflags: `WRITABLE`, `ENUMERABLE`, `CONFIGURABLE`, defaults to all-true for existing properties
|
|
- Accessor vs data descriptor detection: accessor has get/set, data has value/writable
|
|
- [ ] 1.2 Update `JsObject` property storage to support descriptors:
|
|
- Current: `HashMap<String, JsValue>` for properties
|
|
- New: `HashMap<String, Property>` where `Property { value: JsValue, flags: PropertyFlags, getter: Option<JsValue>, setter: Option<JsValue> }`
|
|
- **CRITICAL**: Existing `.set()` and `.get()` must continue working unchanged -- all existing properties default to `WRITABLE | ENUMERABLE | CONFIGURABLE`
|
|
- Update `.get()` to call getter function if property is accessor
|
|
- Update `.set()` to call setter function if property is accessor, respect `WRITABLE` flag
|
|
- Update `.delete()` to respect `CONFIGURABLE` flag
|
|
- [ ] 1.3 Add internal `[[DefineOwnProperty]]` helper on `JsObject`:
|
|
- Follows ECMAScript §10.1.6.3 -- validates descriptor, merges with existing, rejects invalid changes to non-configurable properties
|
|
- Used by `Object.defineProperty` and property assignment
|
|
- [ ] 1.4 Update `Object.keys()`, `Object.values()`, `Object.entries()` to filter by `ENUMERABLE` flag
|
|
- [ ] 1.5 Update `for...in` enumeration to respect `ENUMERABLE` flag
|
|
- [ ] 1.6 Add unit tests for property descriptor behavior: writable rejection, enumerable filtering, configurable deletion prevention, accessor get/set invocation
|
|
|
|
- [ ] Task 2: Object static methods (AC: #3, #5)
|
|
- [ ] 2.1 Create `crates/js_vm/src/interpreter/object_builtins.rs` with:
|
|
- `eval_object_static_method(method: &str, args: &[JsValue]) -> Option<Result<JsValue, RuntimeError>>`
|
|
- [ ] 2.2 Implement `Object.defineProperty(obj, prop, descriptor)` (ECMAScript §20.1.2.4):
|
|
- Parse descriptor object into `PropertyDescriptor`
|
|
- Call internal `[[DefineOwnProperty]]`
|
|
- Return the object
|
|
- [ ] 2.3 Implement `Object.defineProperties(obj, props)` (ECMAScript §20.1.2.3):
|
|
- For each enumerable own property of `props`, call `defineProperty`
|
|
- [ ] 2.4 Implement `Object.getOwnPropertyDescriptor(obj, prop)` (ECMAScript §20.1.2.6):
|
|
- Return descriptor object `{ value, writable, enumerable, configurable }` or `{ get, set, enumerable, configurable }`
|
|
- [ ] 2.5 Implement `Object.getOwnPropertyDescriptors(obj)` (ECMAScript §20.1.2.8):
|
|
- Return object mapping all own properties to their descriptors
|
|
- [ ] 2.6 Implement `Object.getOwnPropertyNames(obj)` (ECMAScript §20.1.2.7):
|
|
- Return all own string property names (enumerable and non-enumerable)
|
|
- [ ] 2.7 Implement `Object.setPrototypeOf(obj, proto)` (ECMAScript §20.1.2.23):
|
|
- Set prototype, check for circular prototype chains, return obj
|
|
- [ ] 2.8 Implement `Object.freeze(obj)` / `Object.isFrozen(obj)` (ECMAScript §20.1.2.5/§20.1.2.11):
|
|
- Freeze: set all properties non-writable + non-configurable, mark object non-extensible
|
|
- isFrozen: check all conditions
|
|
- [ ] 2.9 Implement `Object.seal(obj)` / `Object.isSealed(obj)` (ECMAScript §20.1.2.20/§20.1.2.12):
|
|
- Seal: set all properties non-configurable, mark object non-extensible
|
|
- isSealed: check conditions
|
|
- [ ] 2.10 Implement `Object.preventExtensions(obj)` / `Object.isExtensible(obj)` (ECMAScript §20.1.2.15/§20.1.2.10):
|
|
- Add `extensible: bool` flag to `JsObject` (defaults to true)
|
|
- Check flag when adding new properties
|
|
- [ ] 2.11 Implement `Object.is(a, b)` (ECMAScript §20.1.2.9):
|
|
- SameValue: `NaN === NaN` is true, `+0 === -0` is false
|
|
- [ ] 2.12 Implement `Object.fromEntries(iterable)` (ECMAScript §20.1.2.9):
|
|
- Accept array of `[key, value]` pairs, create object
|
|
- [ ] 2.13 Implement `Object.hasOwn(obj, prop)` (ECMAScript §20.1.2.16):
|
|
- Static version of `hasOwnProperty` (ES2022)
|
|
- [ ] 2.14 Implement `Object.prototype.isPrototypeOf(obj)` (ECMAScript §20.1.3.6):
|
|
- Walk prototype chain of `obj` checking for `this`
|
|
- [ ] 2.15 Wire all Object static methods into `setup_builtins()` in `crates/js_vm/src/interpreter/mod.rs`
|
|
- [ ] 2.16 Add unit tests in `crates/js_vm/src/interpreter/tests/object_tests.rs`
|
|
|
|
- [ ] Task 3: Array methods -- non-callback (AC: #1)
|
|
- [ ] 3.1 Implement `Array.prototype.splice(start, deleteCount, ...items)` in `eval_array_method()` (ECMAScript §22.1.3.26):
|
|
- Remove `deleteCount` elements starting at `start`, insert `items` in their place
|
|
- Return array of deleted elements
|
|
- Adjust `.length` and shift elements as needed
|
|
- [ ] 3.2 Implement `Array.prototype.fill(value, start, end)` (ECMAScript §22.1.3.10):
|
|
- Fill elements from `start` to `end` with `value`
|
|
- Returns the modified array
|
|
- [ ] 3.3 Implement `Array.prototype.copyWithin(target, start, end)` (ECMAScript §22.1.3.5):
|
|
- Copy elements within array, handle overlapping regions
|
|
- [ ] 3.4 Implement `Array.prototype.at(index)` (ECMAScript §22.1.3.2):
|
|
- Negative indices count from end (`-1` = last element)
|
|
- Also add to `String.prototype.at(index)` (ECMAScript §21.1.3.1) in `eval_string_method()`
|
|
- [ ] 3.5 Implement `Array.prototype.flat(depth)` (ECMAScript §22.1.3.13):
|
|
- Flatten nested arrays up to `depth` (default 1, Infinity for full flatten)
|
|
- Recursive flattening with depth tracking
|
|
- [ ] 3.6 Implement `Array.prototype.toReversed()` (ECMAScript §22.1.3.30):
|
|
- Return new reversed array (non-mutating copy of `reverse()`)
|
|
- [ ] 3.7 Implement `Array.prototype.toSorted(compareFn)` (ECMAScript §22.1.3.31):
|
|
- Return new sorted array (non-mutating copy of `sort()`)
|
|
- [ ] 3.8 Implement `Array.prototype.toSpliced(start, deleteCount, ...items)` (ECMAScript §22.1.3.32):
|
|
- Return new array with splice applied (non-mutating)
|
|
- [ ] 3.9 Implement `Array.prototype.with(index, value)` (ECMAScript §22.1.3.36):
|
|
- Return new array with element at `index` replaced by `value`
|
|
- [ ] 3.10 Add unit tests in `crates/js_vm/src/interpreter/tests/array_tests.rs`
|
|
|
|
- [ ] Task 4: Array methods -- callback and static (AC: #1, #4, #6)
|
|
- [ ] 4.1 Implement `Array.prototype.flatMap(callback, thisArg)` in `eval_array_callback_method()` (ECMAScript §22.1.3.14):
|
|
- Map each element, then flatten one level
|
|
- Callback receives `(element, index, array)`
|
|
- [ ] 4.2 Implement `Array.from(arrayLike, mapFn, thisArg)` (ECMAScript §22.1.2.1):
|
|
- Handle array-like objects (with `.length` property)
|
|
- Handle iterables (objects with `Symbol.iterator`) -- use iterator protocol from Story 3.2
|
|
- Handle strings (iterate characters)
|
|
- Apply `mapFn` to each element if provided
|
|
- Wire as static method on `Array` constructor in `setup_builtins()`
|
|
- [ ] 4.3 Implement `Array.of(...items)` (ECMAScript §22.1.2.3):
|
|
- Create array from arguments (unlike `Array(n)` which creates sparse array of length n)
|
|
- [ ] 4.4 Implement `Array.prototype.entries()`, `.keys()`, `.values()` (ECMAScript §22.1.3.6/§22.1.3.15/§22.1.3.33):
|
|
- Return iterator objects (reuse iterator protocol from Story 3.2 generators)
|
|
- `entries()` yields `[index, value]` pairs
|
|
- `keys()` yields indices
|
|
- `values()` yields values
|
|
- Wire `Array.prototype[Symbol.iterator]` = `Array.prototype.values`
|
|
- [ ] 4.5 Verify callback error propagation in `flatMap` and `Array.from` with `mapFn`
|
|
- [ ] 4.6 Add unit tests in `crates/js_vm/src/interpreter/tests/array_tests.rs`
|
|
|
|
- [ ] Task 5: String methods (AC: #2)
|
|
- [ ] 5.1 Implement `String.prototype.padStart(targetLength, padString)` in `eval_string_method()` (ECMAScript §21.1.3.16):
|
|
- Pad start of string to reach `targetLength`; padString defaults to " "
|
|
- [ ] 5.2 Implement `String.prototype.padEnd(targetLength, padString)` (ECMAScript §21.1.3.17):
|
|
- Pad end of string
|
|
- [ ] 5.3 Implement `String.prototype.replaceAll(searchValue, replaceValue)` (ECMAScript §21.1.3.19):
|
|
- If `searchValue` is string: replace all occurrences (NOT regex)
|
|
- If `searchValue` is regex: must have global flag, otherwise TypeError
|
|
- **Reuse existing `replace` logic** from `eval_string_method()` but apply globally for string pattern
|
|
- [ ] 5.4 Implement `String.prototype.matchAll(regexp)` (ECMAScript §21.1.3.11):
|
|
- Returns iterator of all matches (requires global or sticky flag)
|
|
- Each match includes capture groups, index, input
|
|
- Return iterator object (use iterator protocol from Story 3.2)
|
|
- [ ] 5.5 Implement `String.prototype.at(index)` (ECMAScript §21.1.3.1):
|
|
- Negative indices count from end
|
|
- Returns single-character string or undefined
|
|
- [ ] 5.6 Implement `String.prototype.codePointAt(index)` (ECMAScript §21.1.3.3):
|
|
- Returns full Unicode code point (handles surrogate pairs)
|
|
- [ ] 5.7 Implement `String.fromCharCode(...codes)` (ECMAScript §21.1.2.1):
|
|
- Static method on String constructor
|
|
- Creates string from UTF-16 code units
|
|
- [ ] 5.8 Implement `String.fromCodePoint(...codes)` (ECMAScript §21.1.2.2):
|
|
- Static method on String constructor
|
|
- Creates string from Unicode code points (handles > 0xFFFF)
|
|
- [ ] 5.9 Implement `String.raw(template, ...substitutions)` (ECMAScript §21.1.2.4):
|
|
- Template tag function that returns raw string without escape processing
|
|
- [ ] 5.10 Implement `String.prototype.normalize(form)` -- **STUB ONLY**:
|
|
- Accept "NFC", "NFD", "NFKC", "NFKD" forms
|
|
- Return input string unchanged (full Unicode normalization deferred)
|
|
- Log warning on first call
|
|
- [ ] 5.11 Add unit tests in `crates/js_vm/src/interpreter/tests/string_tests.rs`
|
|
|
|
- [ ] Task 6: Testing and validation (AC: #7)
|
|
- [ ] 6.1 Run vendored Test262 suite and promote passing tests:
|
|
- `cargo test -p rust_browser --test js262_harness js262_suite_matches_manifest_expectations -- --nocapture`
|
|
- `just js262-status promote --id <test-id>` for each newly passing test
|
|
- [ ] 6.2 Run full Test262 suite and triage built-in tests:
|
|
- `just test262-full`
|
|
- `just triage-test262-full`
|
|
- [ ] 6.3 Run all existing JS test suites to verify no regressions:
|
|
- `cargo test -p js_vm` (unit tests including existing array/string/object tests)
|
|
- `cargo test -p rust_browser --test js_tests`
|
|
- `cargo test -p rust_browser --test js_dom_tests`
|
|
- `cargo test -p rust_browser --test js_events`
|
|
- `cargo test -p rust_browser --test js_scheduling`
|
|
- `cargo test -p rust_browser --test js_async`
|
|
- `cargo test -p rust_browser --test js_modules`
|
|
- [ ] 6.4 Update `docs/JavaScript_Implementation_Checklist.md`:
|
|
- Check off all newly implemented built-in methods
|
|
- [ ] 6.5 Update `docs/old/js_feature_matrix.md` with expanded built-in coverage
|
|
- [ ] 6.6 Run `just ci` -- full validation pass
|
|
|
|
## Dev Notes
|
|
|
|
### Key Architecture Decisions
|
|
|
|
**Property descriptor system is the foundation.** Task 1 must land first -- it changes the internal property storage model in `JsObject`. All subsequent Object methods (`defineProperty`, `freeze`, `seal`, etc.) depend on it. Array and String methods do NOT depend on property descriptors, so Tasks 3-5 can proceed in parallel after Task 1.
|
|
|
|
**No new crate dependencies.** All built-in methods are pure Rust using existing infrastructure. The `regress` crate (already a dependency) handles regex for `matchAll`/`replaceAll`. The `url` crate is not needed here.
|
|
|
|
**Iterator methods reuse Story 3.2 generator protocol.** `Array.prototype.entries()`, `.keys()`, `.values()`, and `String.prototype.matchAll()` return iterator objects. These should reuse the `IteratorRecord` / `GeneratorObject` infrastructure from Story 3.2 (generators and iterator protocol). Check `crates/js_vm/src/interpreter/` for existing iterator patterns.
|
|
|
|
### Implementation Patterns from Existing Code
|
|
|
|
**Array method dispatch** (in `builtins.rs:eval_array_method()`):
|
|
```rust
|
|
// Non-callback methods return Option<Result<JsValue, RuntimeError>>
|
|
// Return None if method not found -> falls through to prototype chain
|
|
"splice" => { /* implementation */ Some(Ok(result)) }
|
|
```
|
|
|
|
**Callback array methods** (in `array_builtins.rs:eval_array_callback_method()`):
|
|
```rust
|
|
// Callback methods need &mut self (interpreter) for function invocation
|
|
// Use self.invoke_array_callback(&callback, &[elem, idx, arr], this_arg)?
|
|
```
|
|
|
|
**Object static methods** (in `mod.rs:setup_builtins()`):
|
|
```rust
|
|
// Object static methods are NativeFunction values on the Object constructor
|
|
let obj_constructor = JsValue::NativeFunction {
|
|
name: "Object".into(),
|
|
func: /* ... */
|
|
};
|
|
// Then obj_constructor.set("keys", JsValue::NativeFunction { ... });
|
|
```
|
|
|
|
### Critical Compatibility Concerns
|
|
|
|
**Changing JsObject property storage is high-risk.** The `JsObject` type is used everywhere in the VM. Changing from `HashMap<String, JsValue>` to `HashMap<String, Property>` must be done carefully:
|
|
- All existing `.set()` calls must default to `WRITABLE | ENUMERABLE | CONFIGURABLE`
|
|
- All existing `.get()` calls must transparently handle both data and accessor properties
|
|
- `mark_all_non_enumerable()` already exists -- it should now set the `ENUMERABLE` flag to false
|
|
- Run `just ci` after property descriptor changes before proceeding
|
|
|
|
**ES2023 immutable array methods (`toReversed`, `toSorted`, `toSpliced`, `with`)** return new arrays. They must NOT modify the original array. This is a common LLM mistake -- double-check each implementation.
|
|
|
|
**`Array.from` with iterables** depends on the iterator protocol from Story 3.2. Verify that `Symbol.iterator` dispatch works correctly for strings, arrays, and custom iterables before implementing.
|
|
|
|
**`String.prototype.replaceAll` with regex** requires the global flag -- throw `TypeError` if regex without `/g` flag is passed. This is a common spec compliance detail.
|
|
|
|
### Previous Story Intelligence
|
|
|
|
From Story 3.4 (ES modules) review findings:
|
|
- **Opcode stubs as dead code**: Avoid creating infrastructure that isn't wired into execution. If adding opcodes, make sure they're actually emitted by the compiler and handled by the VM.
|
|
- **Integration tests must test the right function**: Tests that call `execute_script()` instead of `execute_module()` were caught in review. Similarly, ensure built-in method tests actually exercise the new code paths.
|
|
- **Run `just ci` frequently**: The 3-4 story had 3 rounds of code review. Run CI after each task, not just at the end.
|
|
|
|
From Story 3.2 (generators/iterator protocol):
|
|
- Iterator objects are `JsObject` instances with `next()` method returning `{ value, done }`
|
|
- `Symbol.iterator` is used for `for...of` dispatch
|
|
- Array iterator methods should follow this same pattern
|
|
|
|
### Risk Assessment
|
|
|
|
**HIGH: Property descriptor changes to JsObject.** This is a foundational change affecting all property access in the VM. Must maintain backwards compatibility with existing `.set()`/`.get()` API. Risk of subtle breakage in existing tests.
|
|
|
|
**MEDIUM: Array.from with iterator protocol.** Depends on Story 3.2's iterator infrastructure. If `Symbol.iterator` dispatch has issues, this will surface them.
|
|
|
|
**MEDIUM: String.matchAll returning iterator.** Combines regex engine (regress crate) with iterator protocol. Each match object needs `index`, `input`, and capture groups.
|
|
|
|
**LOW: Simple methods (at, padStart, padEnd, fill, splice).** Well-defined, self-contained. Straightforward to implement and test.
|
|
|
|
### Phased Implementation Strategy
|
|
|
|
**Phase A -- Property Descriptors (Task 1):** Foundation for everything in Object methods. Must land first and pass `just ci` before proceeding.
|
|
|
|
**Phase B -- Object Methods (Task 2):** Depends on Phase A. All Object static methods.
|
|
|
|
**Phase C -- Array Non-Callback (Task 3):** Independent of Phases A/B. Can start in parallel with Phase B.
|
|
|
|
**Phase D -- Array Callback + Static (Task 4):** Depends on iterator protocol (Story 3.2). Can start after Phase C.
|
|
|
|
**Phase E -- String Methods (Task 5):** Largely independent. Can start in parallel with Phases C/D.
|
|
|
|
**Phase F -- Testing + Validation (Task 6):** After all methods implemented.
|
|
|
|
### Project Structure Notes
|
|
|
|
- All implementation in `crates/js_vm/src/interpreter/` (Layer 1) -- no layer violations
|
|
- New file: `crates/js_vm/src/interpreter/object_builtins.rs` for Object static methods
|
|
- Property descriptor changes in `crates/js_vm/src/value.rs` (Layer 1)
|
|
- No `unsafe` code needed
|
|
- No new external dependencies
|
|
|
|
### References
|
|
|
|
- [ECMAScript §22.1 -- Array Objects](https://tc39.es/ecma262/#sec-array-objects) -- Array prototype methods
|
|
- [ECMAScript §21.1 -- String Objects](https://tc39.es/ecma262/#sec-string-objects) -- String prototype methods
|
|
- [ECMAScript §20.1 -- Object Objects](https://tc39.es/ecma262/#sec-object-objects) -- Object constructor and prototype
|
|
- [ECMAScript §10.1.6.3 -- OrdinaryDefineOwnProperty](https://tc39.es/ecma262/#sec-ordinarydefineownproperty) -- Property descriptor semantics
|
|
- [ECMAScript §6.2.6 -- Property Descriptor](https://tc39.es/ecma262/#sec-property-descriptor-specification-type) -- Descriptor type specification
|
|
- [Source: _bmad-output/planning-artifacts/architecture.md#JS Feature Implementation Order] -- Parser -> pipeline -> tests -> docs
|
|
- [Source: _bmad-output/planning-artifacts/epics.md#Story 3.5] -- Story requirements and acceptance criteria
|
|
- [Source: crates/js_vm/src/interpreter/builtins.rs] -- Existing Array/String method dispatch
|
|
- [Source: crates/js_vm/src/interpreter/array_builtins.rs] -- Existing callback-based Array methods
|
|
- [Source: crates/js_vm/src/interpreter/mod.rs:90-494] -- setup_builtins() initialization
|
|
|
|
## Dev Agent Record
|
|
|
|
### Agent Model Used
|
|
|
|
{{agent_model_name_version}}
|
|
|
|
### Debug Log References
|
|
|
|
### Completion Notes List
|
|
|
|
### File List
|