diff options
author | davidot <davidot@serenityos.org> | 2022-12-13 01:30:32 +0100 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-12-14 15:27:08 +0000 |
commit | 2bbea62176d05a7fa92e70f7de08306a9481e496 (patch) | |
tree | c34957765821e3f7b012ba9e8acfafe1e1ccada5 /Userland | |
parent | 897c7f7cc285b704e0240d2051a236ecc4e2e326 (diff) | |
download | serenity-2bbea62176d05a7fa92e70f7de08306a9481e496.zip |
LibJS: Don't update names of resulting functions in object expression
The only cases where the name should be set is if the function comes
from a direct anonymous function expression.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibJS/AST.cpp | 21 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Parser.cpp | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Tests/builtins/Object/Object.freeze.js | 8 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Tests/object-basic.js | 39 |
4 files changed, 63 insertions, 10 deletions
diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index 65fae457ad..c578678051 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -3095,18 +3095,21 @@ Completion ObjectExpression::execute(Interpreter& interpreter) const continue; } - if (value.is_function() && property.is_method()) + auto property_key = TRY(PropertyKey::from_value(vm, key)); + + if (property.is_method()) { + VERIFY(value.is_function()); static_cast<ECMAScriptFunctionObject&>(value.as_function()).set_home_object(object); - auto property_key = TRY(PropertyKey::from_value(vm, key)); - auto name = TRY(get_function_property_name(property_key)); - if (property.type() == ObjectProperty::Type::Getter) { - name = DeprecatedString::formatted("get {}", name); - } else if (property.type() == ObjectProperty::Type::Setter) { - name = DeprecatedString::formatted("set {}", name); - } + auto name = MUST(get_function_property_name(property_key)); + if (property.type() == ObjectProperty::Type::Getter) { + name = DeprecatedString::formatted("get {}", name); + } else if (property.type() == ObjectProperty::Type::Setter) { + name = DeprecatedString::formatted("set {}", name); + } - update_function_name(value, name); + update_function_name(value, name); + } switch (property.type()) { case ObjectProperty::Type::Getter: diff --git a/Userland/Libraries/LibJS/Parser.cpp b/Userland/Libraries/LibJS/Parser.cpp index daebf14732..d5d311afe2 100644 --- a/Userland/Libraries/LibJS/Parser.cpp +++ b/Userland/Libraries/LibJS/Parser.cpp @@ -1779,7 +1779,10 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression() } if (is_proto && property_type == ObjectProperty::Type::KeyValue) property_type = ObjectProperty::Type::ProtoSetter; - properties.append(create_ast_node<ObjectProperty>({ m_source_code, rule_start.position(), position() }, *property_key, parse_expression(2), property_type, false)); + + auto rhs_expression = parse_expression(2); + bool is_method = is<FunctionExpression>(*rhs_expression); + properties.append(create_ast_node<ObjectProperty>({ m_source_code, rule_start.position(), position() }, *property_key, move(rhs_expression), property_type, is_method)); } else if (property_key && property_value) { if (m_state.strict_mode && is<StringLiteral>(*property_key)) { auto& string_literal = static_cast<StringLiteral const&>(*property_key); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Object/Object.freeze.js b/Userland/Libraries/LibJS/Tests/builtins/Object/Object.freeze.js index 39d5720055..32f550548c 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Object/Object.freeze.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Object/Object.freeze.js @@ -67,3 +67,11 @@ describe("normal behavior", () => { expect(o.foo).toBe("bar"); }); }); + +test("does not override frozen function name", () => { + const func = Object.freeze(function () { + return 12; + }); + const obj = Object.freeze({ name: func }); + expect(obj.name()).toBe(12); +}); diff --git a/Userland/Libraries/LibJS/Tests/object-basic.js b/Userland/Libraries/LibJS/Tests/object-basic.js index 15b1906fbb..879a0a114a 100644 --- a/Userland/Libraries/LibJS/Tests/object-basic.js +++ b/Userland/Libraries/LibJS/Tests/object-basic.js @@ -215,3 +215,42 @@ describe("errors", () => { expect("({ ...foo: bar })").not.toEval(); }); }); + +describe("naming of anon functions", () => { + test("method has name", () => { + expect({ func() {} }.func.name).toBe("func"); + }); + + test("getter has name", () => { + expect(Object.getOwnPropertyDescriptor({ get func() {} }, "func").get.name).toBe( + "get func" + ); + }); + + test("setter has name", () => { + expect(Object.getOwnPropertyDescriptor({ set func(v) {} }, "func").set.name).toBe( + "set func" + ); + }); + + test("anon function property", () => { + expect({ func: function () {} }.func.name).toBe("func"); + }); + + test("anon function from within parenthesis", () => { + expect({ func: function () {} }.func.name).toBe("func"); + }); + + test("anon function from indirect expression", () => { + expect({ func: (0, function () {}) }.func.name).toBe(""); + }); + + test("function from function call does not get named", () => { + function f() { + return function () {}; + } + + expect(f().name).toBe(""); + expect({ func: f() }.func.name).toBe(""); + }); +}); |