Skip to content

Commit

Permalink
Fix nondeterministic descent visitor
Browse files Browse the repository at this point in the history
  • Loading branch information
jg-rp committed Mar 15, 2024
1 parent 58bc819 commit ec50ecb
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 43 deletions.
75 changes: 33 additions & 42 deletions src/path/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -447,55 +447,46 @@ export class RecursiveDescentSegment extends JSONPathSelector {

// eslint-disable-next-line sonarjs/cognitive-complexity
protected nondeterministicVisitor(
node: JSONPathNode,
depth: number = 1,
root: JSONPathNode,
_: number = 1,

Check warning on line 451 in src/path/selectors.ts

View workflow job for this annotation

GitHub Actions / lint

'_' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 451 in src/path/selectors.ts

View workflow job for this annotation

GitHub Actions / lint

'_' is assigned a value but never used. Allowed unused vars must match /^_/u
): JSONPathNode[] {
if (depth >= this.environment.maxRecursionDepth) {
throw new JSONPathRecursionLimitError(
"recursion limit reached",
this.token,
);
}
const rv: JSONPathNode[] = [];
if (node.value instanceof String) return rv;
if (isArray(node.value)) {
const deferredChildren: JSONPathNode[] = [];
function children(node: JSONPathNode): JSONPathNode[] {
const _rv: JSONPathNode[] = [];
if (node.value instanceof String) return rv;
if (isArray(node.value)) {
for (let i = 0; i < node.value.length; i++) {
_rv.push(
new JSONPathNode(node.value[i], node.location.concat(i), node.root),
);
}
} else if (isObject(node.value)) {
for (const [key, value] of Object.entries(node.value)) {
_rv.push(
new JSONPathNode(value, node.location.concat(key), node.root),
);
}
}

for (let i = 0; i < node.value.length; i++) {
const _node = new JSONPathNode(
node.value[i],
node.location.concat(i),
node.root,
);
return _rv;
}

rv.push(_node);
const queue: JSONPathNode[] = children(root);
const rv: JSONPathNode[] = [];

for (const __node of this.nondeterministicVisitor(_node, depth + 1)) {
// Randomly choose to defer inclusion of this child node.
if (Math.random() < 0.5) {
deferredChildren.push(__node);
} else {
rv.push(__node);
while (queue.length) {
const node = queue.shift() as JSONPathNode;
rv.push(node);
for (const child of children(node)) {
// Queue the child node or visit now?
if (Math.random() < 0.5) {
queue.push(child);
} else {
rv.push(child);
for (const _child of children(child)) {
queue.push(_child);
}
}
}

// Include deferred children.
for (const child of deferredChildren) {
rv.push(child);
}
} else if (isObject(node.value)) {
for (const [key, value] of this.environment.entries(node.value)) {
const _node = new JSONPathNode(
value,
node.location.concat(key),
node.root,
);
rv.push(_node);
for (const __node of this.nondeterministicVisitor(_node, depth + 1)) {
rv.push(__node);
}
}
}

return rv;
Expand Down
2 changes: 1 addition & 1 deletion tests/path/cts
Submodule cts updated 3 files
+93 −0 cts.json
+9 −0 tests/basic.json
+17 −0 tests/filter.json

0 comments on commit ec50ecb

Please sign in to comment.