mirror of
https://github.com/RGBCube/serenity
synced 2025-05-22 19:35:06 +00:00
LibJS: Do not revisit already visited values in update_function_name()
Fixes #3471, adds a test.
This commit is contained in:
parent
e317ee7541
commit
21f513fe0f
2 changed files with 19 additions and 2 deletions
|
@ -26,6 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
|
#include <AK/HashTable.h>
|
||||||
#include <AK/ScopeGuard.h>
|
#include <AK/ScopeGuard.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
#include <LibCrypto/BigInt/SignedBigInteger.h>
|
#include <LibCrypto/BigInt/SignedBigInteger.h>
|
||||||
|
@ -49,10 +50,13 @@
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
static void update_function_name(Value& value, const FlyString& name)
|
static void update_function_name(Value& value, const FlyString& name, HashTable<const JS::Cell*>& visited)
|
||||||
{
|
{
|
||||||
if (!value.is_object())
|
if (!value.is_object())
|
||||||
return;
|
return;
|
||||||
|
if (visited.contains(value.as_cell()))
|
||||||
|
return;
|
||||||
|
visited.set(value.as_cell());
|
||||||
auto& object = value.as_object();
|
auto& object = value.as_object();
|
||||||
if (object.is_function()) {
|
if (object.is_function()) {
|
||||||
auto& function = static_cast<Function&>(object);
|
auto& function = static_cast<Function&>(object);
|
||||||
|
@ -61,10 +65,16 @@ static void update_function_name(Value& value, const FlyString& name)
|
||||||
} else if (object.is_array()) {
|
} else if (object.is_array()) {
|
||||||
auto& array = static_cast<Array&>(object);
|
auto& array = static_cast<Array&>(object);
|
||||||
for (auto& entry : array.indexed_properties().values_unordered())
|
for (auto& entry : array.indexed_properties().values_unordered())
|
||||||
update_function_name(entry.value, name);
|
update_function_name(entry.value, name, visited);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void update_function_name(Value& value, const FlyString& name)
|
||||||
|
{
|
||||||
|
HashTable<const JS::Cell*> visited;
|
||||||
|
update_function_name(value, name, visited);
|
||||||
|
}
|
||||||
|
|
||||||
static String get_function_name(Interpreter& interpreter, Value value)
|
static String get_function_name(Interpreter& interpreter, Value value)
|
||||||
{
|
{
|
||||||
if (value.is_symbol())
|
if (value.is_symbol())
|
||||||
|
|
|
@ -48,3 +48,10 @@ test("names of native functions", () => {
|
||||||
expect((console.debug.name = "warn")).toBe("warn");
|
expect((console.debug.name = "warn")).toBe("warn");
|
||||||
expect(console.debug.name).toBe("debug");
|
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