mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 06:57:44 +00:00
LibJS: Support for (x in obj)
iteration in bytecode VM
We were mistakenly treating these as `for (x of obj)`. By reorganizing the code a little bit, we actually support both kinds of iteration with less duplication. :^) Fixes 17 tests in test262.
This commit is contained in:
parent
249350a7a3
commit
29935fe943
1 changed files with 34 additions and 53 deletions
|
@ -2077,6 +2077,7 @@ static Bytecode::CodeGenerationErrorOr<ForInOfHeadEvaluationResult> for_in_of_he
|
||||||
{
|
{
|
||||||
ForInOfHeadEvaluationResult result {};
|
ForInOfHeadEvaluationResult result {};
|
||||||
|
|
||||||
|
bool entered_lexical_scope = false;
|
||||||
if (auto* ast_ptr = lhs.get_pointer<NonnullRefPtr<ASTNode>>(); ast_ptr && is<VariableDeclaration>(**ast_ptr)) {
|
if (auto* ast_ptr = lhs.get_pointer<NonnullRefPtr<ASTNode>>(); ast_ptr && is<VariableDeclaration>(**ast_ptr)) {
|
||||||
// Runtime Semantics: ForInOfLoopEvaluation, for any of:
|
// Runtime Semantics: ForInOfLoopEvaluation, for any of:
|
||||||
// ForInOfStatement : for ( var ForBinding in Expression ) Statement
|
// ForInOfStatement : for ( var ForBinding in Expression ) Statement
|
||||||
|
@ -2092,7 +2093,7 @@ static Bytecode::CodeGenerationErrorOr<ForInOfHeadEvaluationResult> for_in_of_he
|
||||||
|
|
||||||
// NOTE: 'uninitializedBoundNames' refers to the lexical bindings (i.e. Const/Let) present in the second and last form.
|
// NOTE: 'uninitializedBoundNames' refers to the lexical bindings (i.e. Const/Let) present in the second and last form.
|
||||||
// 2. If uninitializedBoundNames is not an empty List, then
|
// 2. If uninitializedBoundNames is not an empty List, then
|
||||||
bool entered_lexical_scope = false;
|
|
||||||
if (variable_declaration.declaration_kind() != DeclarationKind::Var) {
|
if (variable_declaration.declaration_kind() != DeclarationKind::Var) {
|
||||||
entered_lexical_scope = true;
|
entered_lexical_scope = true;
|
||||||
// a. Assert: uninitializedBoundNames has no duplicate entries.
|
// a. Assert: uninitializedBoundNames has no duplicate entries.
|
||||||
|
@ -2108,6 +2109,13 @@ static Bytecode::CodeGenerationErrorOr<ForInOfHeadEvaluationResult> for_in_of_he
|
||||||
// d. Set the running execution context's LexicalEnvironment to newEnv.
|
// d. Set the running execution context's LexicalEnvironment to newEnv.
|
||||||
// NOTE: Done by CreateEnvironment.
|
// NOTE: Done by CreateEnvironment.
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Runtime Semantics: ForInOfLoopEvaluation, for any of:
|
||||||
|
// ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement
|
||||||
|
// ForInOfStatement : for ( LeftHandSideExpression of AssignmentExpression ) Statement
|
||||||
|
result.lhs_kind = LHSKind::Assignment;
|
||||||
|
}
|
||||||
|
|
||||||
// 3. Let exprRef be the result of evaluating expr.
|
// 3. Let exprRef be the result of evaluating expr.
|
||||||
TRY(rhs->generate_bytecode(generator));
|
TRY(rhs->generate_bytecode(generator));
|
||||||
|
|
||||||
|
@ -2154,33 +2162,6 @@ static Bytecode::CodeGenerationErrorOr<ForInOfHeadEvaluationResult> for_in_of_he
|
||||||
// d. Return ? GetIterator(exprValue, iteratorHint).
|
// d. Return ? GetIterator(exprValue, iteratorHint).
|
||||||
generator.emit<Bytecode::Op::GetIterator>();
|
generator.emit<Bytecode::Op::GetIterator>();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Runtime Semantics: ForInOfLoopEvaluation, for any of:
|
|
||||||
// ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement
|
|
||||||
// ForInOfStatement : for ( LeftHandSideExpression of AssignmentExpression ) Statement
|
|
||||||
|
|
||||||
// Skip everything except steps 3, 5 and 7 (see above true branch for listing).
|
|
||||||
result.lhs_kind = LHSKind::Assignment;
|
|
||||||
|
|
||||||
// 3. Let exprRef be the result of evaluating expr.
|
|
||||||
TRY(rhs->generate_bytecode(generator));
|
|
||||||
|
|
||||||
// 5. Let exprValue be ? GetValue(exprRef).
|
|
||||||
// NOTE: No need to store this anywhere.
|
|
||||||
|
|
||||||
// a. Assert: iterationKind is iterate or async-iterate.
|
|
||||||
// b. If iterationKind is async-iterate, let iteratorHint be async.
|
|
||||||
if (iteration_kind == IterationKind::AsyncIterate) {
|
|
||||||
return Bytecode::CodeGenerationError {
|
|
||||||
rhs.ptr(),
|
|
||||||
"Unimplemented iteration mode: AsyncIterate"sv,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// c. Else, let iteratorHint be sync.
|
|
||||||
|
|
||||||
// d. Return ? GetIterator(exprValue, iteratorHint).
|
|
||||||
generator.emit<Bytecode::Op::GetIterator>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue