Skip to content

Commit

Permalink
Fix circular selector detection in t.like()
Browse files Browse the repository at this point in the history
The previous implementation tracked each object, even if not circular. Update to use a stack.

Fixes #3205.
  • Loading branch information
novemberborn committed Jun 16, 2023
1 parent c988e27 commit 2c67106
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 10 deletions.
22 changes: 12 additions & 10 deletions lib/like-selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,7 @@ export function isLikeSelector(selector) {

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

export function selectComparable(actual, selector, circular = new Set()) {
if (circular.has(selector)) {
throw CIRCULAR_SELECTOR;
}

circular.add(selector);

export function selectComparable(actual, selector, circular = [selector]) {
if (isPrimitive(actual)) {
return actual;
}
Expand All @@ -31,9 +25,17 @@ export function selectComparable(actual, selector, circular = new Set()) {
const enumerableKeys = Reflect.ownKeys(selector).filter(key => Reflect.getOwnPropertyDescriptor(selector, key).enumerable);
for (const key of enumerableKeys) {
const subselector = Reflect.get(selector, key);
comparable[key] = isLikeSelector(subselector)
? selectComparable(Reflect.get(actual, key), subselector, circular)
: Reflect.get(actual, key);
if (isLikeSelector(subselector)) {
if (circular.includes(subselector)) {
throw CIRCULAR_SELECTOR;
}

circular.push(subselector);
comparable[key] = selectComparable(Reflect.get(actual, key), subselector, circular);
circular.pop();
} else {
comparable[key] = Reflect.get(actual, key);
}
}

return comparable;
Expand Down
5 changes: 5 additions & 0 deletions test-tap/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,11 @@ test('.like()', t => {
return assertions.like(specimen, selector);
});

passes(t, () => {
const array = ['c1', 'c2'];
return assertions.like({a: 'a', b: 'b', c: ['c1', 'c2'], d: ['c1', 'c2']}, {b: 'b', d: array, c: array});
});

failsWith(t, () => {
const likePattern = {
a: 'a',
Expand Down

0 comments on commit 2c67106

Please sign in to comment.