mirror of
https://github.com/RGBCube/serenity
synced 2025-07-02 22:52:07 +00:00
LibJS: Only update anonymous function names when necessary
Previously we would generate function names for anonymous functions on every AssignmentExpression, even if we weren't assigning a function. We were also setting names of anonymous functions in arrays, which is apparently a SpiderMonkey specific behavior not supported by V8, JSC or required by ECMA262. This patch removes that behavior. This is a huge performance improvement on the CanvasCycle demo! :^)
This commit is contained in:
parent
f89c479358
commit
dc8817638e
2 changed files with 13 additions and 33 deletions
|
@ -80,30 +80,13 @@ String ASTNode::class_name() const
|
|||
return demangle(typeid(*this).name()).substring(4);
|
||||
}
|
||||
|
||||
static void update_function_name(Value value, const FlyString& name, HashTable<JS::Cell*>& visited)
|
||||
{
|
||||
if (!value.is_object())
|
||||
return;
|
||||
if (visited.contains(value.as_cell()))
|
||||
return;
|
||||
visited.set(value.as_cell());
|
||||
auto& object = value.as_object();
|
||||
if (object.is_function()) {
|
||||
auto& function = static_cast<Function&>(object);
|
||||
if (is<ScriptFunction>(function) && function.name().is_empty())
|
||||
static_cast<ScriptFunction&>(function).set_name(name);
|
||||
} else if (object.is_array()) {
|
||||
auto& array = static_cast<Array&>(object);
|
||||
array.indexed_properties().for_each_value([&](auto& array_element_value) {
|
||||
update_function_name(array_element_value, name, visited);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void update_function_name(Value value, const FlyString& name)
|
||||
{
|
||||
HashTable<JS::Cell*> visited;
|
||||
update_function_name(value, name, visited);
|
||||
if (!value.is_function())
|
||||
return;
|
||||
auto& function = value.as_function();
|
||||
if (is<ScriptFunction>(function) && function.name().is_empty())
|
||||
static_cast<ScriptFunction&>(function).set_name(name);
|
||||
}
|
||||
|
||||
static String get_function_name(GlobalObject& global_object, Value value)
|
||||
|
@ -1443,7 +1426,11 @@ Value AssignmentExpression::execute(Interpreter& interpreter, GlobalObject& glob
|
|||
interpreter.vm().throw_exception<ReferenceError>(global_object, ErrorType::InvalidLeftHandAssignment);
|
||||
return {};
|
||||
}
|
||||
|
||||
// FIXME: We should also check if the LHS is an identifier reference.
|
||||
if (rhs_result.is_function())
|
||||
update_function_name(rhs_result, get_function_name(global_object, reference.name().to_value(interpreter.vm())));
|
||||
|
||||
reference.put(global_object, rhs_result);
|
||||
|
||||
if (interpreter.exception())
|
||||
|
|
|
@ -21,9 +21,9 @@ test("function assigned to variable", () => {
|
|||
|
||||
test("functions in array assigned to variable", () => {
|
||||
const arr = [function () {}, function () {}, function () {}];
|
||||
expect(arr[0].name).toBe("arr");
|
||||
expect(arr[1].name).toBe("arr");
|
||||
expect(arr[2].name).toBe("arr");
|
||||
expect(arr[0].name).toBe("");
|
||||
expect(arr[1].name).toBe("");
|
||||
expect(arr[2].name).toBe("");
|
||||
});
|
||||
|
||||
test("functions in objects", () => {
|
||||
|
@ -48,10 +48,3 @@ test("names of native functions", () => {
|
|||
expect((console.debug.name = "warn")).toBe("warn");
|
||||
expect(console.debug.name).toBe("debug");
|
||||
});
|
||||
|
||||
test("cyclic members should not cause infinite recursion (#3471)", () => {
|
||||
let a = [() => 4];
|
||||
a[1] = a;
|
||||
a = a;
|
||||
expect(a[0].name).toBe("a");
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue