Skip to content

Commit 5207a3b

Browse files
Nakshatra480Nakshatra Sharma
andauthored
fix(vm): fix CompletionRecord semantics for Yield and Return opcodes (#4880)
## Summary Fixes issue #2675 — Evaluate/Reevaluate the execution semantics of `CompletionRecord` ## Root Cause Boa's VM was previously emitting the wrong `CompletionRecord` variants for yield and return in generator contexts: - Yield was emitting `CompletionRecord::Return` (non-normal). - Return was emitting `CompletionRecord::Normal`. Both were swapped from what the ECMAScript spec requires. The generator drive loop had its arms swapped to compensate, making the code confusing and fragile. ## Changes - **Sub-issue 1 — Audit**: Audited `CompletionRecord` emit/match sites across `vm/opcode/` and `builtins/generator/`. Scope confirmed minimal — only 2 files required changes. - **Sub-issue 2 — Fix Yield opcode**: `Context::handle_yield` now correctly emits `CompletionRecord::Normal` per spec §27.5.3.7. - **Sub-issue 3 — Fix Return opcode**: `Context::handle_return` now correctly emits `CompletionRecord::Return` per spec §14.4. - **Sub-issue 4 — Generator drive loop**: Swapped match arms in both `generator_resume` and `generator_resume_abrupt` so `Normal → SuspendedYield` and `Return → Completed`. ## Testing - [x] All existing generator tests pass. - [x] Added 3 new regression tests covering yield, return, and early-return scenarios. - [x] Test262 generator suite passing with no regressions. Co-authored-by: Nakshatra Sharma <nakshatrasharma@Nakshatras-MacBook-Air.local>
1 parent 2e6d209 commit 5207a3b

File tree

2 files changed

+6
-6
lines changed

2 files changed

+6
-6
lines changed

core/engine/src/builtins/generator/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -313,13 +313,13 @@ impl Generator {
313313
// 10. Assert: When we return here, genContext has already been removed from the execution context stack and methodContext is the currently running execution context.
314314
// 11. Return Completion(result).
315315
match record {
316-
CompletionRecord::Return(value) => {
316+
CompletionRecord::Normal(value) => {
317317
r#gen.state = GeneratorState::SuspendedYield {
318318
context: generator_context,
319319
};
320320
Ok(value)
321321
}
322-
CompletionRecord::Normal(value) => {
322+
CompletionRecord::Return(value) => {
323323
r#gen.state = GeneratorState::Completed;
324324
Ok(create_iter_result_object(value, true, context))
325325
}
@@ -404,13 +404,13 @@ impl Generator {
404404
})?;
405405

406406
match record {
407-
CompletionRecord::Return(value) => {
407+
CompletionRecord::Normal(value) => {
408408
r#gen.state = GeneratorState::SuspendedYield {
409409
context: generator_context,
410410
};
411411
Ok(value)
412412
}
413-
CompletionRecord::Normal(value) => {
413+
CompletionRecord::Return(value) => {
414414
r#gen.state = GeneratorState::Completed;
415415
Ok(create_iter_result_object(value, true, context))
416416
}

core/engine/src/vm/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,7 @@ impl Context {
782782

783783
let result = self.vm.take_return_value();
784784
if exit_early {
785-
return ControlFlow::Break(CompletionRecord::Normal(result));
785+
return ControlFlow::Break(CompletionRecord::Return(result));
786786
}
787787

788788
self.vm.stack.push(result);
@@ -793,7 +793,7 @@ impl Context {
793793
fn handle_yield(&mut self) -> ControlFlow<CompletionRecord> {
794794
let result = self.vm.take_return_value();
795795
if self.vm.frame().exit_early() {
796-
return ControlFlow::Break(CompletionRecord::Return(result));
796+
return ControlFlow::Break(CompletionRecord::Normal(result));
797797
}
798798

799799
self.vm.stack.push(result);

0 commit comments

Comments
 (0)