Skip to content

Commit 659befc

Browse files
authored
refactor: deep clone elements before assigning to structured errrors (#3328)
Refs #3209
1 parent 15ab4b7 commit 659befc

File tree

13 files changed

+82
-90
lines changed

13 files changed

+82
-90
lines changed

packages/apidom-ast/src/traversal/visitor.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ApiDOMError } from '@swagger-api/apidom-error';
1+
import { ApiDOMStructuredError } from '@swagger-api/apidom-error';
22

33
/**
44
* SPDX-FileCopyrightText: Copyright (c) GraphQL Contributors
@@ -281,7 +281,9 @@ export const visit = (
281281
let result;
282282
if (!Array.isArray(node)) {
283283
if (!nodePredicate(node)) {
284-
throw new ApiDOMError(`Invalid AST Node: ${JSON.stringify(node)}`);
284+
throw new ApiDOMStructuredError(`Invalid AST Node: ${String(node)}`, {
285+
node,
286+
});
285287
}
286288

287289
// cycle detected; skipping over a sub-tree to avoid recursion
@@ -436,7 +438,9 @@ visit[Symbol.for('nodejs.util.promisify.custom')] = async (
436438
let result;
437439
if (!Array.isArray(node)) {
438440
if (!nodePredicate(node)) {
439-
throw new ApiDOMError(`Invalid AST Node: ${JSON.stringify(node)}`);
441+
throw new ApiDOMStructuredError(`Invalid AST Node: ${String(node)}`, {
442+
node,
443+
});
440444
}
441445

442446
// cycle detected; skipping over a sub-tree to avoid recursion

packages/apidom-ast/src/yaml/errors/YamlTagError.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import { ApiDOMErrorOptions } from '@swagger-api/apidom-error';
22

33
import YamlSchemaError from './YamlSchemaError';
44
import Position from '../../Position';
5+
import Node from '../../Node';
56

6-
export interface YamlTagErrorOptions extends ApiDOMErrorOptions {
7+
export interface YamlTagErrorOptions<T extends Node = Node> extends ApiDOMErrorOptions {
78
readonly specificTagName: string;
89
readonly explicitTagName: string;
910
readonly tagKind: string;
1011
readonly tagPosition?: Position;
1112
readonly nodeCanonicalContent?: string;
13+
readonly node?: T;
1214
}
1315

1416
class YamlTagError extends YamlSchemaError {
@@ -22,6 +24,8 @@ class YamlTagError extends YamlSchemaError {
2224

2325
public readonly nodeCanonicalContent?: string;
2426

27+
public readonly node?: unknown;
28+
2529
constructor(message?: string, structuredOptions?: YamlTagErrorOptions) {
2630
super(message, structuredOptions);
2731

@@ -31,6 +35,7 @@ class YamlTagError extends YamlSchemaError {
3135
this.tagKind = structuredOptions.tagKind;
3236
this.tagPosition = structuredOptions.tagPosition;
3337
this.nodeCanonicalContent = structuredOptions.nodeCanonicalContent;
38+
this.node = structuredOptions.node;
3439
}
3540
}
3641
}

packages/apidom-ast/src/yaml/schemas/failsafe/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ const FailsafeSchema = stampit({
9494
explicitTagName: node.tag.explicitName,
9595
tagKind: node.tag.kind,
9696
tagPosition: clone(node.tag.position),
97+
node: node.clone(),
9798
});
9899
}
99100

@@ -105,6 +106,7 @@ const FailsafeSchema = stampit({
105106
tagKind: node.tag.kind,
106107
tagPosition: clone(node.tag.position),
107108
nodeCanonicalContent: canonicalNode.content,
109+
node: node.clone(),
108110
});
109111
}
110112

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
import { ApiDOMStructuredError } from '@swagger-api/apidom-error';
2+
import type { ApiDOMErrorOptions } from '@swagger-api/apidom-error';
23

3-
class CloneError extends ApiDOMStructuredError {}
4+
interface CloneErrorOptions extends ApiDOMErrorOptions {
5+
readonly value: unknown;
6+
}
7+
8+
class CloneError extends ApiDOMStructuredError {
9+
public readonly value: unknown;
10+
11+
constructor(message?: string, structuredOptions?: CloneErrorOptions) {
12+
super(message, structuredOptions);
13+
14+
if (typeof structuredOptions !== 'undefined') {
15+
this.value = structuredOptions.source;
16+
}
17+
}
18+
}
419

520
export default CloneError;

packages/apidom-core/src/deepmerge.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ export default function deepmerge(
158158

159159
deepmerge.all = (list: ObjectOrArrayElement[], options?: DeepMergeOptions) => {
160160
if (!Array.isArray(list)) {
161-
throw new TypeError('First argument should be an array.');
161+
throw new TypeError('First argument of deepmerge should be an array.');
162162
}
163163
if (list.length === 0) {
164164
return new ObjectElement();

packages/apidom-json-path/src/errors/EvaluationJsonPathError.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Element, hasElementSourceMap, toValue } from '@swagger-api/apidom-core';
1+
import { Element } from '@swagger-api/apidom-core';
22
import { ApiDOMErrorOptions } from '@swagger-api/apidom-error';
33

44
import JsonPathError from './JsonPathError';
@@ -11,19 +11,14 @@ export interface EvaluationJsonPathErrorOptions<T extends Element> extends ApiDO
1111
class EvaluationJsonPathError<T extends Element> extends JsonPathError {
1212
public readonly path!: string | string[];
1313

14-
public readonly element!: string;
15-
16-
public readonly elementSourceMap?: [[number, number, number], [number, number, number]];
14+
public readonly element!: T;
1715

1816
constructor(message?: string, structuredOptions?: EvaluationJsonPathErrorOptions<T>) {
1917
super(message, structuredOptions);
2018

2119
if (typeof structuredOptions !== 'undefined') {
2220
this.path = structuredOptions.path;
23-
this.element = structuredOptions.element.element;
24-
if (hasElementSourceMap(structuredOptions.element)) {
25-
this.elementSourceMap = toValue(structuredOptions.element.getMetaProperty('sourceMap'));
26-
}
21+
this.element = structuredOptions.element;
2722
}
2823
}
2924
}

packages/apidom-json-path/src/errors/MultiEvaluationJsonPathError.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Element, hasElementSourceMap, toValue } from '@swagger-api/apidom-core';
1+
import { Element } from '@swagger-api/apidom-core';
22
import { ApiDOMErrorOptions } from '@swagger-api/apidom-error';
33

44
import JsonPathError from './JsonPathError';
@@ -11,19 +11,14 @@ export interface MultiEvaluationJsonPathErrorOptions<T extends Element> extends
1111
class MultiEvaluationJsonPathError<T extends Element> extends JsonPathError {
1212
public readonly paths!: string[] | string[][];
1313

14-
public readonly element!: string;
15-
16-
public readonly elementSourceMap?: [[number, number, number], [number, number, number]];
14+
public readonly element!: T;
1715

1816
constructor(message?: string, structuredOptions?: MultiEvaluationJsonPathErrorOptions<T>) {
1917
super(message, structuredOptions);
2018

2119
if (typeof structuredOptions !== 'undefined') {
2220
this.paths = structuredOptions.paths;
23-
this.element = structuredOptions.element.element;
24-
if (hasElementSourceMap(structuredOptions.element)) {
25-
this.elementSourceMap = toValue(structuredOptions.element.getMetaProperty('sourceMap'));
26-
}
21+
this.element = structuredOptions.element;
2722
}
2823
}
2924
}

packages/apidom-json-path/src/evaluate-multi.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { JSONPath } from 'jsonpath-plus';
2-
import { Element, toValue } from '@swagger-api/apidom-core';
2+
import { Element, toValue, cloneDeep } from '@swagger-api/apidom-core';
33
import { evaluate as jsonPointerEvaluate } from '@swagger-api/apidom-json-pointer';
44

55
import MultiEvaluationJsonPathError from './errors/MultiEvaluationJsonPathError';
@@ -45,7 +45,7 @@ const evaluateMulti: EvaluateMulti = (paths, element) => {
4545
`JSON Path evaluation failed while multi-evaluating "${String(paths)}".`,
4646
{
4747
paths,
48-
element,
48+
element: cloneDeep(element),
4949
cause: error,
5050
},
5151
);

packages/apidom-json-path/src/evaluate.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { JSONPath } from 'jsonpath-plus';
2-
import { Element, toValue } from '@swagger-api/apidom-core';
2+
import { Element, toValue, cloneDeep } from '@swagger-api/apidom-core';
33
import { evaluate as jsonPointerEvaluate } from '@swagger-api/apidom-json-pointer';
44

55
import EvaluationJsonPathError from './errors/EvaluationJsonPathError';
@@ -25,7 +25,7 @@ const evaluate: Evaluate = (path, element) => {
2525
} catch (error: unknown) {
2626
throw new EvaluationJsonPathError(
2727
`JSON Path evaluation failed while evaluating "${String(path)}".`,
28-
{ path, element, cause: error },
28+
{ path, element: cloneDeep(element), cause: error },
2929
);
3030
}
3131
};

packages/apidom-json-pointer-relative/src/errors/EvaluationRelativeJsonPointerError.ts

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Element, hasElementSourceMap, toValue } from '@swagger-api/apidom-core';
1+
import { Element } from '@swagger-api/apidom-core';
22
import { ApiDOMErrorOptions } from '@swagger-api/apidom-error';
33

44
import RelativeJsonPointerError from './RelativeJsonPointerError';
@@ -21,17 +21,11 @@ class EvaluationRelativeJsonPointerError<
2121
> extends RelativeJsonPointerError {
2222
public readonly relativePointer!: string;
2323

24-
public readonly currentElement!: string;
24+
public readonly currentElement!: T;
2525

26-
public readonly currentElementSourceMap?: [[number, number, number], [number, number, number]];
26+
public readonly rootElement!: U;
2727

28-
public readonly rootElement!: string;
29-
30-
public readonly rootElementSourceMap?: [[number, number, number], [number, number, number]];
31-
32-
public readonly cursorElement?: string;
33-
34-
public readonly cursorElementSourceMap?: [[number, number, number], [number, number, number]];
28+
public readonly cursorElement?: V;
3529

3630
constructor(
3731
message?: string,
@@ -41,29 +35,9 @@ class EvaluationRelativeJsonPointerError<
4135

4236
if (typeof structuredOptions !== 'undefined') {
4337
this.relativePointer = structuredOptions.relativePointer;
44-
45-
this.currentElement = structuredOptions.currentElement.element;
46-
if (hasElementSourceMap(structuredOptions.currentElement)) {
47-
this.currentElementSourceMap = toValue(
48-
structuredOptions.currentElement.getMetaProperty('sourceMap'),
49-
);
50-
}
51-
52-
this.rootElement = structuredOptions.rootElement.element;
53-
if (hasElementSourceMap(structuredOptions.rootElement)) {
54-
this.rootElementSourceMap = toValue(
55-
structuredOptions.rootElement.getMetaProperty('sourceMap'),
56-
);
57-
}
58-
59-
if (typeof structuredOptions.cursorElement !== 'undefined') {
60-
this.cursorElement = structuredOptions.cursorElement.element;
61-
if (hasElementSourceMap(structuredOptions.cursorElement)) {
62-
this.cursorElementSourceMap = toValue(
63-
structuredOptions.cursorElement.getMetaProperty('sourceMap'),
64-
);
65-
}
66-
}
38+
this.currentElement = structuredOptions.currentElement;
39+
this.rootElement = structuredOptions.rootElement;
40+
this.cursorElement = structuredOptions.cursorElement;
6741
}
6842
}
6943
}

0 commit comments

Comments
 (0)