Skip to content

Commit dc11625

Browse files
detect cycles in JS Arrays as well
1 parent 0712859 commit dc11625

File tree

1 file changed

+18
-7
lines changed

1 file changed

+18
-7
lines changed

src/JSArrayProxy.cc

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -511,17 +511,26 @@ PyObject *JSArrayProxyMethodDefinitions::JSArrayProxy_richcompare(JSArrayProxy *
511511
}
512512

513513
PyObject *JSArrayProxyMethodDefinitions::JSArrayProxy_repr(JSArrayProxy *self) {
514+
// Detect cyclic objects
515+
PyObject *objPtr = PyLong_FromVoidPtr(self->jsArray->get());
516+
// For `Py_ReprEnter`, we must get a same PyObject when visiting the same JSObject.
517+
// We cannot simply use the object returned by `PyLong_FromVoidPtr` because it won't reuse the PyLongObjects for ints not between -5 and 256.
518+
// Instead, we store this PyLongObject in a global dict, using itself as the hashable key, effectively interning the PyLongObject.
519+
PyObject *tsDict = PyThreadState_GetDict();
520+
PyObject *cyclicKey = PyDict_SetDefault(tsDict, /*key*/ objPtr, /*value*/ objPtr); // cyclicKey = (tsDict[objPtr] ??= objPtr)
521+
int i = Py_ReprEnter(cyclicKey);
522+
if (i != 0) {
523+
return i > 0 ? PyUnicode_FromString("[...]") : NULL;
524+
}
525+
514526
Py_ssize_t selfLength = JSArrayProxy_length(self);
515527

516528
if (selfLength == 0) {
529+
Py_ReprLeave(cyclicKey);
530+
PyDict_DelItem(tsDict, cyclicKey);
517531
return PyUnicode_FromString("[]");
518532
}
519533

520-
Py_ssize_t i = Py_ReprEnter((PyObject *)self);
521-
if (i != 0) {
522-
return i > 0 ? PyUnicode_FromString("[...]") : NULL;
523-
}
524-
525534
_PyUnicodeWriter writer;
526535

527536
_PyUnicodeWriter_Init(&writer);
@@ -569,12 +578,14 @@ PyObject *JSArrayProxyMethodDefinitions::JSArrayProxy_repr(JSArrayProxy *self) {
569578
goto error;
570579
}
571580

572-
Py_ReprLeave((PyObject *)self);
581+
Py_ReprLeave(cyclicKey);
582+
PyDict_DelItem(tsDict, cyclicKey);
573583
return _PyUnicodeWriter_Finish(&writer);
574584

575585
error:
576586
_PyUnicodeWriter_Dealloc(&writer);
577-
Py_ReprLeave((PyObject *)self);
587+
Py_ReprLeave(cyclicKey);
588+
PyDict_DelItem(tsDict, cyclicKey);
578589
return NULL;
579590
}
580591

0 commit comments

Comments
 (0)