fix: pass previousRealm to AsyncGeneratorCompleteStep in AsyncGeneratorYield#5106
fix: pass previousRealm to AsyncGeneratorCompleteStep in AsyncGeneratorYield#5106xcb3d wants to merge 7 commits intoboa-dev:mainfrom
Conversation
28155e6 to
df7b5a7
Compare
Test262 conformance changes
Tested main commit: |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5106 +/- ##
===========================================
+ Coverage 47.24% 59.31% +12.06%
===========================================
Files 476 563 +87
Lines 46892 62800 +15908
===========================================
+ Hits 22154 37248 +15094
- Misses 24738 25552 +814 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| } | ||
|
|
||
| #[test] | ||
| fn cross_realm_async_generator_yield() { |
There was a problem hiding this comment.
You also might want to test if the generator is really using the caller's realm to create the iter object. A simple way to do this would be to check that the prototype of the async generator's returned object is equal to the Object.prototype in old_realm.
|
Updated the The key challenge was that Boa's native function mechanism doesn't use a spec-compliant execution context stack, so "second to top element" doesn't map directly. Here's the approach:
The |
core/engine/src/vm/mod.rs
Outdated
| /// The caller's realm before a native function's `swap_realm`. | ||
| /// Used by `GeneratorContext::resume()` to capture `previousRealm` | ||
| /// for `AsyncGeneratorYield`. | ||
| pub(crate) native_caller_realm: Option<Realm>, | ||
|
|
If this is the case, it's a bug. We shouldn't hack around bugs. |
|
Hi @jedel1043, reverted to the One question: you mentioned checking the prototype against |
|
Then |
|
Thanks for the clarification! You're right — Would you like me to fix |
|
I see two possible approaches to fix the
What do you think? Do you have a recommendation on which direction to go? |
|
Hi @jedel1043, can you check my comment pls ?. Thanks |
|
Lightweight frame seems like a good solution |
This Pull Request closes #N/A (no existing issue — this is a spec compliance improvement discovered through code audit).
It changes the following:
AsyncGeneratorYieldsteps 6-8 by capturing the caller's realm (previousRealm) and passing it toAsyncGeneratorCompleteStepviacomplete_step().caller_realm: Option<Realm>toCallFrameto carry the caller's realm through the generator resume/yield cycle.context.realm().clone()inGeneratorContext::resume()before the stack swap, storing it in the generator'sCallFrame.previous_realmtoAsyncGenerator::complete_step()in theAsyncGeneratorYieldopcode instead of always passingNone.Background:
Previously,
AsyncGeneratorYieldalways passedNoneas therealmargument tocomplete_step(), causing iterator result objects ({value, done}) to always be created in the generator's own realm. Per the spec, they should be created inpreviousRealm— the realm of the execution context that was active before the generator resumed. Thecomplete_step()function already handled theSome(realm)case correctly (switching realms viaenter_realmbefore callingcreate_iter_result_object), but was never given a realm to switch to.This fix captures the caller's realm at the correct point (in
GeneratorContext::resume(), before the stack swap) and threads it through theCallFrameso theAsyncGeneratorYieldopcode can read it and pass it tocomplete_step().