LibJS: Use correct this value when callee is a with binding

If we're inside of a `with` statement scope, we have to take care to
extract the correct `this` value for use in calls when calling a method
on the binding object via an Identifier instead of a MemberExpression.

This makes Vue.js work way better in the bytecode VM. :^)

Also, 1 new pass on test262.
This commit is contained in:
Andreas Kling 2023-08-01 14:33:58 +02:00
parent e61fdd1dc6
commit e91bdedc93
Notes: sideshowbarker 2024-07-17 09:49:48 +09:00
4 changed files with 186 additions and 104 deletions

View file

@ -1526,6 +1526,19 @@ Bytecode::CodeGenerationErrorOr<void> CallExpression::generate_bytecode(Bytecode
} else if (is<OptionalChain>(*m_callee)) {
auto& optional_chain = static_cast<OptionalChain const&>(*m_callee);
TRY(generate_optional_chain(generator, optional_chain, callee_reg, this_reg));
} else if (is<Identifier>(*m_callee)) {
// If the callee is an identifier, we may need to extract a `this` value.
// This is important when we're inside a `with` statement and calling a method on
// the environment's binding object.
// NOTE: If the identifier refers to a known "local" or "global", we know it can't be
// a `with` binding, so we can skip this.
auto& identifier = static_cast<Identifier const&>(*m_callee);
if (!identifier.is_local() && !identifier.is_global()) {
generator.emit<Bytecode::Op::GetCalleeAndThisFromEnvironment>(generator.intern_identifier(identifier.string()), callee_reg, this_reg);
} else {
TRY(m_callee->generate_bytecode(generator));
generator.emit<Bytecode::Op::Store>(callee_reg);
}
} else {
// FIXME: this = global object in sloppy mode.
TRY(m_callee->generate_bytecode(generator));