1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 14:28:12 +00:00

LibJS: Handle circular references in Array.prototype.join()

This fixes Array.prototype.{join,toString}() crashing with arrays
containing themselves, i.e. circular references.

The spec is suspiciously silent about this, and indeed engine262, a
"100% spec compliant" ECMA-262 implementation, can't handle these cases.
I had a look at some major engines instead and they all seem to keep
track or check for circular references and return an empty string for
already seen objects.

- SpiderMonkey: "AutoCycleDetector detector(cx, obj)"
- V8: "CycleProtectedArrayJoin<JSArray>(...)"
- JavaScriptCore: "StringRecursionChecker checker(globalObject, thisObject)"
- ChakraCore: "scriptContext->CheckObject(thisArg)"

To keep things simple & consistent this uses the same pattern as
JSONObject, MarkupGenerator and js: simply putting each seen object in a
HashTable<Object*>.

Fixes #3929.
This commit is contained in:
Linus Groh 2020-11-04 09:44:57 +00:00 committed by Andreas Kling
parent e5845ba3a0
commit 0603402c80
2 changed files with 21 additions and 0 deletions

View file

@ -14,3 +14,11 @@ test("basic functionality", () => {
expect([1, null, 2, undefined, 3].join()).toBe("1,,2,,3");
expect(Array(3).join()).toBe(",,");
});
test("circular references", () => {
const a = ["foo", [], [1, 2, []], ["bar"]];
a[1] = a;
a[2][2] = a;
// [ "foo", <circular>, [ 1, 2, <circular> ], [ "bar" ] ]
expect(a.join()).toBe("foo,,1,2,,bar");
});