`break` or `return` inside `for ... in` leaves the enumeration on the stack
まだ誰も着手していません。
評価
調査の方向性
Start in crates/rascal/src/internal/as2_codegen/statement.rs, especially gen_for_loop and StatementKind::Return, then inspect how loop cleanup and return values are emitted. Reproduce the nested for ... in cases from the issue and check related code generation tests. Done means both break and return leave enumeration values cleaned up, so the outer loop prints x and y once each.
索引モデルが issue の本文から書いたものです。
説明
for ... in keeps the enumerated names on the stack, terminated by null, and only consumes all of them when the loop runs to the end. Leaving the loop early with break or return jumps out without removing the rest. Any enclosing for ... in then picks up those leftover values: depending on what's left, it iterates over stale names, or it stops early on the inner loop's null. In the reproducers below, the outer loop gets b from every inner loop, so it never ends.
break:
var o = {a: 1, b: 2};
for (var k in {x: 1, y: 2}) {
trace(k);
for (var j in o) {
break;
}
}
return:
function first(o) {
for (var k in o) {
return k;
}
}
for (var k in {x: 1, y: 2}) {
trace(k);
first({a: 1, b: 2});
}
Expected for both: x and y, once each.
Actual, in Flash Player (Rascal 0.3.6, SWF 8), for both: x, then b repeated without end.
So the stack isn't reset when a function returns, which is why return is affected too.
gen_for_loop sets the break label to end_label, which is after the loop's cleanup.
https://github.com/Dinnerbone/Rascal/blob/3f1a80c85dcc657cf4a67b72754b9c7869a6d9c5/crates/rascal/src/internal/as2_codegen/statement.rs#L292-L302
StatementKind::Return emits Return directly. Before leaving a for ... in early, the remaining values need popping up to and including the null. Perhaps by emitting a small loop for that, similar to the loop header: Push null, Equals2, Not, If back to the start.
For a return from nested for ... in loops, each enclosing enumeration needs this, and the return value needs to be kept, for example in a register.
Real code hitting this: https://github.com/ruffle-rs/ruffle/blob/c7c2cc871c07d94f246d496e0b41479ba429085a/tests/tests/swfs/avm1/global_instance_decls/test.as#L46-L60
- 主要言語
- Rust
- スター
- 22
- フォーク
- 2
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
Dinnerbone/Rascal のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 79/100
Dinnerbone/Rascal#92 · コメント 1 件 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
Dinnerbone/Rascal#91 · リアクション 2 件 ·
-
難易度 5/5 1週間以上 初心者へのやさしさ 30/100
Dinnerbone/Rascal#88 ·
-
難易度 3/5 1〜2日 初心者へのやさしさ 55/100
Dinnerbone/Rascal#87 · コメント 1 件 ·
-
難易度 3/5 1〜2日 初心者へのやさしさ 58/100
Dinnerbone/Rascal#76 ·
Dinnerbone/Rascal の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
rubys/roundhouse#1917 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 2 日以内に返信
-
good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
pop-os/cosmic-applets#1619 ·
メンテナーはふだん 3 日以内に返信
-
binding:python bug
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
メンテナーはふだん 1 日以内に返信