mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-19 08:41:53 +00:00
LibJS: Use correct this value for tagged template literals with members
Required by creepjs, which does Date().split` `[3] to get the current year.
This commit is contained in:
parent
5f33383a7b
commit
a588756105
Notes:
github-actions[bot]
2025-01-17 16:16:08 +00:00
Author: https://github.com/Lubrsi
Commit: a588756105
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3277
2 changed files with 119 additions and 3 deletions
|
@ -2469,10 +2469,24 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> TemplateLiteral::genera
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TagAndThisValue {
|
||||||
|
ScopedOperand tag;
|
||||||
|
ScopedOperand this_value;
|
||||||
|
};
|
||||||
|
|
||||||
Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> TaggedTemplateLiteral::generate_bytecode(Bytecode::Generator& generator, Optional<ScopedOperand> preferred_dst) const
|
Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> TaggedTemplateLiteral::generate_bytecode(Bytecode::Generator& generator, Optional<ScopedOperand> preferred_dst) const
|
||||||
{
|
{
|
||||||
Bytecode::Generator::SourceLocationScope scope(generator, *this);
|
Bytecode::Generator::SourceLocationScope scope(generator, *this);
|
||||||
|
auto [tag, this_value] = TRY([&]() -> CodeGenerationErrorOr<TagAndThisValue> {
|
||||||
|
if (is<MemberExpression>(*m_tag)) {
|
||||||
|
auto& member_expression = static_cast<MemberExpression const&>(*m_tag);
|
||||||
|
auto base_and_value = TRY(get_base_and_value_from_member_expression(generator, member_expression));
|
||||||
|
return TagAndThisValue { .tag = base_and_value.value, .this_value = base_and_value.base };
|
||||||
|
}
|
||||||
|
|
||||||
auto tag = TRY(m_tag->generate_bytecode(generator)).value();
|
auto tag = TRY(m_tag->generate_bytecode(generator)).value();
|
||||||
|
return TagAndThisValue { .tag = tag, .this_value = generator.add_constant(js_undefined()) };
|
||||||
|
}());
|
||||||
|
|
||||||
// FIXME: Follow
|
// FIXME: Follow
|
||||||
// 13.2.8.3 GetTemplateObject ( templateLiteral ), https://tc39.es/ecma262/#sec-gettemplateobject
|
// 13.2.8.3 GetTemplateObject ( templateLiteral ), https://tc39.es/ecma262/#sec-gettemplateobject
|
||||||
|
@ -2539,7 +2553,7 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> TaggedTemplateLiteral::
|
||||||
generator.emit<Bytecode::Op::NewArray>(arguments);
|
generator.emit<Bytecode::Op::NewArray>(arguments);
|
||||||
|
|
||||||
auto dst = choose_dst(generator, preferred_dst);
|
auto dst = choose_dst(generator, preferred_dst);
|
||||||
generator.emit<Bytecode::Op::CallWithArgumentArray>(Bytecode::Op::CallType::Call, dst, tag, generator.add_constant(js_undefined()), arguments);
|
generator.emit<Bytecode::Op::CallWithArgumentArray>(Bytecode::Op::CallType::Call, dst, tag, this_value, arguments);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,7 @@ describe("tagged template literal functionality", () => {
|
||||||
expect(firstResult).toBe(secondResult);
|
expect(firstResult).toBe(secondResult);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.xfail("this value of call comes from reference", () => {
|
test("this value of call comes from reference for non-computed, non-super property", () => {
|
||||||
let thisValue = null;
|
let thisValue = null;
|
||||||
const obj = {
|
const obj = {
|
||||||
func() {
|
func() {
|
||||||
|
@ -176,4 +176,106 @@ describe("tagged template literal functionality", () => {
|
||||||
|
|
||||||
expect(thisValue).toBe(obj);
|
expect(thisValue).toBe(obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("this value of call comes from reference for computed, non-super property", () => {
|
||||||
|
let thisValue = null;
|
||||||
|
const obj = {
|
||||||
|
func() {
|
||||||
|
thisValue = this;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
obj["func"]``;
|
||||||
|
|
||||||
|
expect(thisValue).toBe(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("this value of call comes from reference for private property", () => {
|
||||||
|
let thisValue = null;
|
||||||
|
const obj = new (class A {
|
||||||
|
#func = () => {
|
||||||
|
thisValue = this;
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.#func``;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
expect(thisValue).toBe(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("this value of call comes from reference for non-computed super call property", () => {
|
||||||
|
let thisValue = null;
|
||||||
|
|
||||||
|
class A {
|
||||||
|
func() {
|
||||||
|
thisValue = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const obj = new (class B extends A {
|
||||||
|
constructor() {
|
||||||
|
super().func``;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
expect(thisValue).toBe(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("this value of call comes from reference for computed super call property", () => {
|
||||||
|
let thisValue = null;
|
||||||
|
|
||||||
|
class A {
|
||||||
|
func() {
|
||||||
|
thisValue = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const obj = new (class B extends A {
|
||||||
|
constructor() {
|
||||||
|
super()["func"]``;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
expect(thisValue).toBe(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("this value of call comes from reference for non-computed super property", () => {
|
||||||
|
let thisValue = null;
|
||||||
|
|
||||||
|
class A {
|
||||||
|
func() {
|
||||||
|
thisValue = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const obj = new (class B extends A {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
super.func``;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
expect(thisValue).toBe(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("this value of call comes from reference for computed super property", () => {
|
||||||
|
let thisValue = null;
|
||||||
|
|
||||||
|
class A {
|
||||||
|
func() {
|
||||||
|
thisValue = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const obj = new (class B extends A {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
super["func"]``;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
expect(thisValue).toBe(obj);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue