summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authordavidot <davidot@serenityos.org>2022-12-13 01:30:32 +0100
committerLinus Groh <mail@linusgroh.de>2022-12-14 15:27:08 +0000
commit2bbea62176d05a7fa92e70f7de08306a9481e496 (patch)
treec34957765821e3f7b012ba9e8acfafe1e1ccada5 /Userland
parent897c7f7cc285b704e0240d2051a236ecc4e2e326 (diff)
downloadserenity-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.cpp21
-rw-r--r--Userland/Libraries/LibJS/Parser.cpp5
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/Object/Object.freeze.js8
-rw-r--r--Userland/Libraries/LibJS/Tests/object-basic.js39
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("");
+ });
+});