mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 02:08:11 +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 {};
|
||||
|
||||
bool entered_lexical_scope = false;
|
||||
if (auto* ast_ptr = lhs.get_pointer<NonnullRefPtr<ASTNode>>(); ast_ptr && is<VariableDeclaration>(**ast_ptr)) {
|
||||
// Runtime Semantics: ForInOfLoopEvaluation, for any of:
|
||||
// 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.
|
||||
// 2. If uninitializedBoundNames is not an empty List, then
|
||||
bool entered_lexical_scope = false;
|
||||
|
||||
if (variable_declaration.declaration_kind() != DeclarationKind::Var) {
|
||||
entered_lexical_scope = true;
|
||||
// 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.
|
||||
// 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.
|
||||
TRY(rhs->generate_bytecode(generator));
|
||||
|
||||
|
@ -2154,33 +2162,6 @@ static Bytecode::CodeGenerationErrorOr<ForInOfHeadEvaluationResult> for_in_of_he
|
|||
// d. Return ? GetIterator(exprValue, iteratorHint).
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue