From c43539a42849c9cac120b36b4234ed10c8172276 Mon Sep 17 00:00:00 2001 From: creampnx_x <73047992+creampnx-x@users.noreply.github.com> Date: Sun, 11 Sep 2022 16:23:50 +0000 Subject: [PATCH] fix computed property methods can call super methods (#2274) This Pull Request fixes: https://github.com/tc39/test262/blob/79e3bc5176b6f29a5aed3b7164a9c623a3a9a63b/test/language/computed-property-names/object/method/super.js This PR solves the bug of using the `super` keyword in the method attribute of object. When the environment is `None`, the `vm` gets the top element of `vm.stack` as `this`, such as: ```js var a = { f() { return super.m(); } }; var b = { m() { retrun "super"; } }; Object.setPrototypeOf(a, b); a.f(); // the top of stack is `a` let f = a.f; f(); // the top of stack is `global_this`, so `super` cannot be used ``` ### Can be improved What I think is that when I use `object.method()`, the engine should bind `this_object` to the `environment`, instead of using `vm.stack.last()...`. ### TODOS 1. `super` need to look for properties all the way to the end. Co-authored-by: creampnx_x <2270436024@qq.com> --- boa_engine/src/vm/mod.rs | 12 +++++++++- boa_engine/src/vm/tests.rs | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/boa_engine/src/vm/mod.rs b/boa_engine/src/vm/mod.rs index f17a0089281..3685570651e 100644 --- a/boa_engine/src/vm/mod.rs +++ b/boa_engine/src/vm/mod.rs @@ -1521,7 +1521,17 @@ impl Context { let function = function_object .as_function() .expect("must be function object"); - function.get_home_object().cloned() + let mut home_object = function.get_home_object().cloned(); + + if home_object.is_none() { + home_object = env + .get_this_binding() + .expect("can not get `this` object") + .as_object() + .cloned(); + } + + home_object } else { return self.throw_range_error("Must call super constructor in derived class before accessing 'this' or returning from derived constructor"); }; diff --git a/boa_engine/src/vm/tests.rs b/boa_engine/src/vm/tests.rs index 8a5fda7be06..cd1b1108c07 100644 --- a/boa_engine/src/vm/tests.rs +++ b/boa_engine/src/vm/tests.rs @@ -137,3 +137,48 @@ fn finally_block_binding_env() { Ok(JsValue::from("Hey hey people")) ); } + +#[test] +fn run_super_method_in_object() { + let source = r#" + let proto = { + m() { return "super"; } + }; + let obj = { + v() { return super.m(); } + }; + Object.setPrototypeOf(obj, proto); + obj.v(); + "#; + + assert_eq!( + Context::default().eval(source.as_bytes()), + Ok(JsValue::from("super")) + ) +} + +#[test] +fn get_reference_by_super() { + let source = r#" + var fromA, fromB; + var A = { fromA: 'a', fromB: 'a' }; + var B = { fromB: 'b' }; + Object.setPrototypeOf(B, A); + var obj = { + fromA: 'c', + fromB: 'c', + method() { + fromA = (() => { return super.fromA; })(); + fromB = (() => { return super.fromB; })(); + } + }; + Object.setPrototypeOf(obj, B); + obj.method(); + fromA + fromB + "#; + + assert_eq!( + Context::default().eval(source.as_bytes()), + Ok(JsValue::from("ab")) + ) +}