mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-27 01:50:24 +00:00
LibJS: Use correct this value for tagged template calls
This has to get quite messy because we currently do evaluation to value and reference separately meaning we have to deal with a lot of edge cases here.
This commit is contained in:
parent
b3edd94869
commit
385c2f2eb8
Notes:
sideshowbarker
2024-07-17 18:23:22 +09:00
Author: https://github.com/davidot Commit: https://github.com/SerenityOS/serenity/commit/385c2f2eb8 Pull-request: https://github.com/SerenityOS/serenity/pull/16073 Issue: https://github.com/SerenityOS/serenity/issues/16044 Reviewed-by: https://github.com/linusg
2 changed files with 36 additions and 4 deletions
|
@ -3627,13 +3627,32 @@ Completion TaggedTemplateLiteral::execute(Interpreter& interpreter) const
|
|||
// NOTE: This is both
|
||||
// MemberExpression : MemberExpression TemplateLiteral
|
||||
// CallExpression : CallExpression TemplateLiteral
|
||||
// As the only difference is the first step.
|
||||
|
||||
// 1. Let tagRef be ? Evaluation of MemberExpression.
|
||||
// 1. Let tagRef be ? Evaluation of CallExpression.
|
||||
|
||||
// 2. Let tagFunc be ? GetValue(tagRef).
|
||||
auto tag = TRY(m_tag->execute(interpreter)).release_value();
|
||||
// NOTE: This is much more complicated than the spec because we have to
|
||||
// handle every type of reference. If we handle evaluation closer
|
||||
// to the spec this could be improved.
|
||||
Value tag_this_value;
|
||||
Value tag;
|
||||
if (auto tag_reference = TRY(m_tag->to_reference(interpreter)); tag_reference.is_valid_reference()) {
|
||||
tag = TRY(tag_reference.get_value(vm));
|
||||
if (tag_reference.is_environment_reference()) {
|
||||
auto& environment = tag_reference.base_environment();
|
||||
if (environment.has_this_binding())
|
||||
tag_this_value = TRY(environment.get_this_binding(vm));
|
||||
else
|
||||
tag_this_value = js_undefined();
|
||||
} else {
|
||||
tag_this_value = tag_reference.get_this_value();
|
||||
}
|
||||
} else {
|
||||
auto result = TRY(m_tag->execute(interpreter));
|
||||
VERIFY(result.has_value());
|
||||
tag = result.release_value();
|
||||
tag_this_value = js_undefined();
|
||||
}
|
||||
|
||||
// 3. Let thisCall be this CallExpression.
|
||||
// 3. Let thisCall be this MemberExpression.
|
||||
|
@ -3655,7 +3674,7 @@ Completion TaggedTemplateLiteral::execute(Interpreter& interpreter) const
|
|||
arguments.append(TRY(expressions[i].execute(interpreter)).release_value());
|
||||
|
||||
// 5. Return ? EvaluateCall(tagFunc, tagRef, TemplateLiteral, tailCall).
|
||||
return call(vm, tag, js_undefined(), move(arguments));
|
||||
return call(vm, tag, tag_this_value, move(arguments));
|
||||
}
|
||||
|
||||
// 13.2.8.3 GetTemplateObject ( templateLiteral ), https://tc39.es/ecma262/#sec-gettemplateobject
|
||||
|
|
|
@ -163,4 +163,17 @@ describe("tagged template literal functionality", () => {
|
|||
let secondResult = call(value => value, 2);
|
||||
expect(firstResult).toBe(secondResult);
|
||||
});
|
||||
|
||||
test("this value of call comes from reference", () => {
|
||||
let thisValue = null;
|
||||
const obj = {
|
||||
func() {
|
||||
thisValue = this;
|
||||
},
|
||||
};
|
||||
|
||||
obj.func``;
|
||||
|
||||
expect(thisValue).toBe(obj);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue