Skip to content

fix: Fixed iterator state handling in for...of loops to properly update and advance through iterations#37

Merged
TheUncharted merged 2 commits intomasterfrom
develop
Mar 21, 2026
Merged

fix: Fixed iterator state handling in for...of loops to properly update and advance through iterations#37
TheUncharted merged 2 commits intomasterfrom
develop

Conversation

@TheUncharted
Copy link
Copy Markdown
Owner

@TheUncharted TheUncharted commented Mar 21, 2026

Summary

  • Bug Fixes

    • Fixed iterator state handling in for...of loops to properly update and advance through iterations.
  • Tests

    • Added comprehensive test suite for for...of loops covering synchronous iteration, async/await scenarios, and multiple external function calls within loop bodies.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 21, 2026

📝 Walkthrough

Walkthrough

Modified the Instruction::IteratorNext logic for 2-element array iterators to increment the index in the iterator state when at end-of-iteration, rather than pushing the original iterator unchanged. Added comprehensive Jest-style tests for for...of loop behavior in both synchronous and asynchronous execution contexts.

Changes

Cohort / File(s) Summary
VM Iterator State
crates/zapcode-core/src/vm/mod.rs
Updated IteratorNext instruction to push an incremented iterator state (with idx + 1) during the end-of-iteration path for 2-element array iterators, while maintaining the existing Value::Undefined push behavior.
For...of Loop Tests
crates/zapcode-core/tests/async_await.rs
Added four new test functions covering for...of behavior: two synchronous tests (sum accumulation and array mutation edge case) and two asynchronous tests (single and multiple external awaits per iteration).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description addresses the key sections but lacks critical details: no explicit list under Changes section, no verification of test execution status, and no linked issues. Provide a detailed list of changes, confirm test plan items (mark checkboxes), and link any related GitHub issues to complete the description.
✅ Passed checks (2 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The title directly addresses the main change: fixing iterator state handling in for...of loops to properly update and advance through iterations, which aligns with the core fix in the code changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can use TruffleHog to scan for secrets in your code with verification capabilities.

Add a TruffleHog config file (e.g. trufflehog-config.yml, trufflehog.yml) to your project to customize detectors and scanning behavior. The tool runs only when a config file is present.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/zapcode-core/src/vm/mod.rs (1)

1935-1947: ⚠️ Potential issue | 🟠 Major

Add resource-limit checks before building iterator state arrays.

Value::Array(vec![...]) allocates in VM dispatch without an explicit pre-allocation resource check. Please call track_allocation before constructing new_iter in both branches.

Suggested patch
                         if idx < arr.len() {
                             let value = arr[idx].clone();
+                            self.tracker.track_allocation(&self.limits)?;
                             // Update iterator
                             let new_iter =
                                 Value::Array(vec![items[0].clone(), Value::Int((idx + 1) as i64)]);
                             // Push updated iterator back, then the value
                             self.push(new_iter)?;
                             self.push(value)?;
                         } else {
                             // Done — increment index past the end so IteratorDone sees idx > len
+                            self.tracker.track_allocation(&self.limits)?;
                             let new_iter =
                                 Value::Array(vec![items[0].clone(), Value::Int((idx + 1) as i64)]);
                             self.push(new_iter)?;
                             self.push(Value::Undefined)?;
                         }

As per coding guidelines, "Resource limits (memory, time, stack depth, allocation count) must be enforced during execution. Check resource limits before allocations in the VM dispatcher."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/zapcode-core/src/vm/mod.rs` around lines 1935 - 1947, The VM is
constructing iterator state arrays with Value::Array without checking resource
limits; before creating new_iter in both branches (the "if idx < arr.len()" and
the "else" branch) call track_allocation with the anticipated allocation
size/count and/or check resource limits, then only construct
Value::Array(vec![...]) and call self.push(new_iter) if track_allocation
succeeded; update the code around the new_iter creation sites and ensure you
reference the track_allocation result (and abort/return the appropriate error)
before calling Value::Array and self.push.
🧹 Nitpick comments (1)
crates/zapcode-core/tests/async_await.rs (1)

1029-1183: Add an empty-iterable for...of suspend/resume boundary test.

Nice regression coverage for normal and multi-external flows. Please add one test for for (const x of []) asserting immediate VmState::Complete (no suspension), to lock boundary behavior.

As per coding guidelines, "Every language feature must have a positive test (correct execution), edge case tests (boundary conditions, empty inputs), and a sandbox escape test where applicable."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/zapcode-core/tests/async_await.rs` around lines 1029 - 1183, Add a new
unit test (e.g., test_for_of_empty_array_no_suspend) that uses
start_with_externals to run code with an empty iterable like `const items = [];
let count = 0; for (const x of items) { count = count + 1; } count;` (use
externals Vec::new()). After starting, assert the returned state is
VmState::Complete and that the value equals Value::Int(0); do not attempt any
resume calls. Reference start_with_externals, VmState::Complete, and Value::Int
in the new test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@crates/zapcode-core/src/vm/mod.rs`:
- Around line 1935-1947: The VM is constructing iterator state arrays with
Value::Array without checking resource limits; before creating new_iter in both
branches (the "if idx < arr.len()" and the "else" branch) call track_allocation
with the anticipated allocation size/count and/or check resource limits, then
only construct Value::Array(vec![...]) and call self.push(new_iter) if
track_allocation succeeded; update the code around the new_iter creation sites
and ensure you reference the track_allocation result (and abort/return the
appropriate error) before calling Value::Array and self.push.

---

Nitpick comments:
In `@crates/zapcode-core/tests/async_await.rs`:
- Around line 1029-1183: Add a new unit test (e.g.,
test_for_of_empty_array_no_suspend) that uses start_with_externals to run code
with an empty iterable like `const items = []; let count = 0; for (const x of
items) { count = count + 1; } count;` (use externals Vec::new()). After
starting, assert the returned state is VmState::Complete and that the value
equals Value::Int(0); do not attempt any resume calls. Reference
start_with_externals, VmState::Complete, and Value::Int in the new test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0c541ba2-ea7c-41fa-99ae-cfe317e764ce

📥 Commits

Reviewing files that changed from the base of the PR and between d205d26 and 6321317.

📒 Files selected for processing (2)
  • crates/zapcode-core/src/vm/mod.rs
  • crates/zapcode-core/tests/async_await.rs

@github-actions
Copy link
Copy Markdown
Contributor

Benchmark Results

    Updating crates.io index
 Downloading crates ...
  Downloaded allocator-api2 v0.2.21
  Downloaded cfg-if v1.0.4
  Downloaded byteorder v1.5.0
  Downloaded clap_lex v1.0.0
  Downloaded anstyle v1.0.13
  Downloaded autocfg v1.5.0
  Downloaded bitflags v2.11.0
  Downloaded oxc_str v0.117.0
  Downloaded castaway v0.2.4
  Downloaded hash32 v0.2.1
  Downloaded equivalent v1.0.2
  Downloaded phf_shared v0.13.1
  Downloaded clap v4.5.60
  Downloaded terminal_size v0.4.3
  Downloaded fastrand v2.3.0
  Downloaded seq-macro v0.3.6
  Downloaded smawk v0.3.2
  Downloaded oxc_estree v0.117.0
  Downloaded oxc-miette-derive v2.7.0
  Downloaded unicode-linebreak v0.1.5
  Downloaded phf_macros v0.13.1
  Downloaded thiserror v2.0.18
  Downloaded thiserror-impl v2.0.18
  Downloaded semver v1.0.27
  Downloaded tempfile v3.27.0
  Downloaded unicode-ident v1.0.24
  Downloaded regex-lite v0.1.9
  Downloaded unicode-segmentation v1.12.0
  Downloaded serde v1.0.228
  Downloaded hashbrown v0.16.1
  Downloaded oxc_parser v0.117.0
  Downloaded clap_builder v4.5.60
  Downloaded oxc_ast v0.117.0
  Downloaded insta v1.46.3
  Downloaded oxc_allocator v0.117.0
  Downloaded oxc-miette v2.7.0
  Downloaded num-bigint v0.4.6
  Downloaded unicode-width v0.2.2
  Downloaded syn v2.0.117
  Downloaded memchr v2.8.0
  Downloaded divan v0.1.21
  Downloaded indexmap v2.13.0
  Downloaded heapless v0.7.17
  Downloaded unicode-id-start v1.4.0
  Downloaded textwrap v0.16.2
  Downloaded serde_core v1.0.228
  Downloaded ryu v1.0.23
  Downloaded rustix v1.1.4
  Downloaded getrandom v0.4.2
  Downloaded console v0.15.11
  Downloaded compact_str v0.9.0
  Downloaded similar v2.7.0
  Downloaded serde_derive v1.0.228
  Downloaded proc-macro2 v1.0.106
  Downloaded oxc_regular_expression v0.117.0
  Downloaded postcard v1.1.3
  Downloaded oxc_span v0.117.0
  Downloaded oxc_ecmascript v0.117.0
  Downloaded once_cell v1.21.3
  Downloaded dragonbox_ecma v0.1.12
  Downloaded spin v0.9.8
  Downloaded rustversion v1.0.22
  Downloaded quote v1.0.45
  Downloaded oxc_index v4.1.0
  Downloaded num-traits v0.2.19
  Downloaded cobs v0.3.0
  Downloaded static_assertions v1.1.0
  Downloaded libc v0.2.183
  Downloaded phf v0.13.1
  Downloaded oxc_syntax v0.117.0
  Downloaded num-integer v0.1.46
  Downloaded stable_deref_trait v1.2.1
  Downloaded oxc_data_structures v0.117.0
  Downloaded owo-colors v4.3.0
  Downloaded lock_api v0.4.14
  Downloaded embedded-io v0.6.1
  Downloaded embedded-io v0.4.0
  Downloaded phf_generator v0.13.1
  Downloaded cow-utils v0.1.3
  Downloaded rustc_version v0.4.1
  Downloaded condtype v1.3.0
  Downloaded siphasher v1.0.2
  Downloaded scopeguard v1.2.0
  Downloaded rustc-hash v2.1.1
  Downloaded percent-encoding v2.3.2
  Downloaded oxc_diagnostics v0.117.0
  Downloaded oxc_ast_macros v0.117.0
  Downloaded nonmax v0.5.5
  Downloaded itoa v1.0.17
  Downloaded errno v0.3.14
  Downloaded divan-macros v0.1.21
  Downloaded linux-raw-sys v0.12.1
   Compiling proc-macro2 v1.0.106
   Compiling quote v1.0.45
   Compiling unicode-ident v1.0.24
   Compiling cfg-if v1.0.4
   Compiling serde_core v1.0.228
   Compiling thiserror v2.0.18
   Compiling bitflags v2.11.0
   Compiling siphasher v1.0.2
   Compiling phf_shared v0.13.1
   Compiling rustversion v1.0.22
   Compiling serde v1.0.228
   Compiling owo-colors v4.3.0
   Compiling allocator-api2 v0.2.21
   Compiling syn v2.0.117
   Compiling hashbrown v0.16.1
   Compiling unicode-linebreak v0.1.5
   Compiling unicode-width v0.2.2
   Compiling smawk v0.3.2
   Compiling castaway v0.2.4
   Compiling textwrap v0.16.2
   Compiling itoa v1.0.17
   Compiling oxc_data_structures v0.117.0
   Compiling rustc-hash v2.1.1
   Compiling ryu v1.0.23
   Compiling unicode-segmentation v1.12.0
   Compiling fastrand v2.3.0
   Compiling static_assertions v1.1.0
   Compiling compact_str v0.9.0
   Compiling phf_generator v0.13.1
   Compiling oxc_allocator v0.117.0
   Compiling phf v0.13.1
   Compiling autocfg v1.5.0
   Compiling rustix v1.1.4
   Compiling thiserror-impl v2.0.18
   Compiling serde_derive v1.0.228
   Compiling oxc-miette-derive v2.7.0
   Compiling oxc_estree v0.117.0
   Compiling oxc_str v0.117.0
   Compiling phf_macros v0.13.1
   Compiling oxc_ast_macros v0.117.0
   Compiling oxc-miette v2.7.0
   Compiling num-traits v0.2.19
   Compiling linux-raw-sys v0.12.1
   Compiling cow-utils v0.1.3
   Compiling dragonbox_ecma v0.1.12
   Compiling libc v0.2.183
   Compiling oxc_span v0.117.0
   Compiling semver v1.0.27
   Compiling unicode-id-start v1.4.0
   Compiling nonmax v0.5.5
   Compiling percent-encoding v2.3.2
   Compiling oxc_diagnostics v0.117.0
   Compiling oxc_index v4.1.0
   Compiling rustc_version v0.4.1
   Compiling scopeguard v1.2.0
   Compiling lock_api v0.4.14
   Compiling oxc_syntax v0.117.0
   Compiling num-integer v0.1.46
   Compiling heapless v0.7.17
   Compiling oxc_regular_expression v0.117.0
   Compiling getrandom v0.4.2
   Compiling byteorder v1.5.0
   Compiling hash32 v0.2.1
   Compiling num-bigint v0.4.6
   Compiling spin v0.9.8
   Compiling terminal_size v0.4.3
   Compiling oxc_ast v0.117.0
   Compiling clap_lex v1.0.0
   Compiling anstyle v1.0.13
   Compiling stable_deref_trait v1.2.1
   Compiling once_cell v1.21.3
   Compiling clap_builder v4.5.60
   Compiling cobs v0.3.0
   Compiling memchr v2.8.0
   Compiling equivalent v1.0.2
   Compiling seq-macro v0.3.6
   Compiling indexmap v2.13.0
   Compiling tempfile v3.27.0
   Compiling clap v4.5.60
   Compiling postcard v1.1.3
   Compiling oxc_ecmascript v0.117.0
   Compiling console v0.15.11
   Compiling oxc_parser v0.117.0
   Compiling divan-macros v0.1.21
   Compiling condtype v1.3.0
   Compiling similar v2.7.0
   Compiling regex-lite v0.1.9
   Compiling divan v0.1.21
   Compiling insta v1.46.3
   Compiling zapcode-core v1.5.0 (/home/runner/work/zapcode/zapcode/crates/zapcode-core)
    Finished `bench` profile [optimized] target(s) in 44.35s
     Running unittests src/lib.rs (target/release/deps/zapcode_core-55369acab5874560)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running benches/execution.rs (target/release/deps/execution-d5dd170ad24a0d97)
Timer precision: 20 ns
execution                  fastest       │ slowest       │ median        │ mean          │ samples │ iters
├─ array_creation          3.836 µs      │ 94.01 µs      │ 4.081 µs      │ 5.967 µs      │ 100     │ 100
├─ async_map_3             13.98 µs      │ 56.3 µs       │ 14.6 µs       │ 15.61 µs      │ 100     │ 100
├─ fibonacci_10            185.6 µs      │ 264.1 µs      │ 188.6 µs      │ 191.1 µs      │ 100     │ 100
├─ function_call           6.651 µs      │ 17.8 µs       │ 6.872 µs      │ 7.053 µs      │ 100     │ 100
├─ loop_100                104.7 µs      │ 132.9 µs      │ 105.3 µs      │ 106.7 µs      │ 100     │ 100
├─ object_creation         7.402 µs      │ 16.39 µs      │ 7.639 µs      │ 7.816 µs      │ 100     │ 100
├─ promise_all_3           9.818 µs      │ 23.59 µs      │ 10.33 µs      │ 10.64 µs      │ 100     │ 100
├─ promise_catch_resolved  6.451 µs      │ 18.87 µs      │ 6.647 µs      │ 6.862 µs      │ 100     │ 100
├─ promise_resolve_await   4.547 µs      │ 16.68 µs      │ 4.683 µs      │ 4.848 µs      │ 100     │ 100
├─ promise_then_chain_3    13.53 µs      │ 26.86 µs      │ 14.11 µs      │ 14.41 µs      │ 100     │ 100
├─ promise_then_single     8.144 µs      │ 20.08 µs      │ 8.31 µs       │ 8.568 µs      │ 100     │ 100
├─ simple_expression       3.506 µs      │ 6.21 µs       │ 3.616 µs      │ 3.67 µs       │ 100     │ 100
├─ string_concat           4.057 µs      │ 15.12 µs      │ 4.202 µs      │ 4.376 µs      │ 100     │ 100
├─ template_literal        4.507 µs      │ 10.73 µs      │ 4.633 µs      │ 4.724 µs      │ 100     │ 100
╰─ variable_arithmetic     4.567 µs      │ 15.08 µs      │ 4.758 µs      │ 4.912 µs      │ 100     │ 100


@TheUncharted TheUncharted changed the title Develop fix: Fixed iterator state handling in for...of loops to properly update and advance through iterations Mar 21, 2026
@TheUncharted TheUncharted merged commit ad287ae into master Mar 21, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant