mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
LibJS: Make super() in catch block work
The TryStatement handler execution creates a new LexicalEnvironment without a current function set, which we were not accounting for when trying to get the super constructor while executing a SuperExpression. This makes it work but isn't pretty - this needs some refactoring to be close to the spec for that to happen. Fixes #7045.
This commit is contained in:
parent
d85b9fd5a0
commit
0a329d2d70
Notes:
sideshowbarker
2024-07-18 18:19:20 +09:00
2 changed files with 30 additions and 2 deletions
|
@ -220,7 +220,14 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj
|
|||
if (result.is_object())
|
||||
new_object = &result.as_object();
|
||||
} else if (is<SuperExpression>(*m_callee)) {
|
||||
auto* super_constructor = interpreter.current_environment()->current_function()->prototype();
|
||||
// FIXME: This is merely a band-aid to make super() inside catch {} work (which constructs
|
||||
// a new LexicalEnvironment without current function). Implement GetSuperConstructor()
|
||||
// and subsequently GetThisEnvironment() instead.
|
||||
auto* function_environment = interpreter.current_environment();
|
||||
if (!function_environment->current_function())
|
||||
function_environment = static_cast<LexicalEnvironment*>(function_environment->parent());
|
||||
|
||||
auto* super_constructor = function_environment->current_function()->prototype();
|
||||
// FIXME: Functions should track their constructor kind.
|
||||
if (!super_constructor || !super_constructor->is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAConstructor, "Super constructor");
|
||||
|
@ -230,7 +237,7 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj
|
|||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
interpreter.current_environment()->bind_this_value(global_object, result);
|
||||
function_environment->bind_this_value(global_object, result);
|
||||
} else {
|
||||
result = vm.call(function, this_value, move(arguments));
|
||||
}
|
||||
|
|
|
@ -131,3 +131,24 @@ test("super constructor call from child class with argument", () => {
|
|||
expect(p.x).toBe(3);
|
||||
expect(c.x).toBe(10);
|
||||
});
|
||||
|
||||
test("issue #7045, super constructor call from child class in catch {}", () => {
|
||||
class Parent {
|
||||
constructor(x) {
|
||||
this.x = x;
|
||||
}
|
||||
}
|
||||
|
||||
class Child extends Parent {
|
||||
constructor() {
|
||||
try {
|
||||
throw new Error("Error in Child constructor");
|
||||
} catch (e) {
|
||||
super(e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const c = new Child();
|
||||
expect(c.x).toBe("Error in Child constructor");
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue