Fix circular selector detection in t.like()

The previous implementation tracked each object, even if not circular. Update to use a stack.

Fixes #3205.
This commit is contained in:
Mark Wubben 2023-06-16 18:23:54 +02:00 committed by GitHub
parent c988e27400
commit 6398772595
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 10 deletions

View file

@ -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;
}
@ -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;

View file

@ -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',