Skip to content

Commit 6398772

Browse files
authored
Fix circular selector detection in t.like()
The previous implementation tracked each object, even if not circular. Update to use a stack. Fixes #3205.
1 parent c988e27 commit 6398772

File tree

2 files changed

+17
-10
lines changed

2 files changed

+17
-10
lines changed

lib/like-selector.js

+12-10
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,7 @@ export function isLikeSelector(selector) {
1616

1717
export const CIRCULAR_SELECTOR = new Error('Encountered a circular selector');
1818

19-
export function selectComparable(actual, selector, circular = new Set()) {
20-
if (circular.has(selector)) {
21-
throw CIRCULAR_SELECTOR;
22-
}
23-
24-
circular.add(selector);
25-
19+
export function selectComparable(actual, selector, circular = [selector]) {
2620
if (isPrimitive(actual)) {
2721
return actual;
2822
}
@@ -31,9 +25,17 @@ export function selectComparable(actual, selector, circular = new Set()) {
3125
const enumerableKeys = Reflect.ownKeys(selector).filter(key => Reflect.getOwnPropertyDescriptor(selector, key).enumerable);
3226
for (const key of enumerableKeys) {
3327
const subselector = Reflect.get(selector, key);
34-
comparable[key] = isLikeSelector(subselector)
35-
? selectComparable(Reflect.get(actual, key), subselector, circular)
36-
: Reflect.get(actual, key);
28+
if (isLikeSelector(subselector)) {
29+
if (circular.includes(subselector)) {
30+
throw CIRCULAR_SELECTOR;
31+
}
32+
33+
circular.push(subselector);
34+
comparable[key] = selectComparable(Reflect.get(actual, key), subselector, circular);
35+
circular.pop();
36+
} else {
37+
comparable[key] = Reflect.get(actual, key);
38+
}
3739
}
3840

3941
return comparable;

test-tap/assert.js

+5
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,11 @@ test('.like()', t => {
741741
return assertions.like(specimen, selector);
742742
});
743743

744+
passes(t, () => {
745+
const array = ['c1', 'c2'];
746+
return assertions.like({a: 'a', b: 'b', c: ['c1', 'c2'], d: ['c1', 'c2']}, {b: 'b', d: array, c: array});
747+
});
748+
744749
failsWith(t, () => {
745750
const likePattern = {
746751
a: 'a',

0 commit comments

Comments
 (0)