@speclynx/apidom-reference 3.1.0 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,30 @@
1
1
  {
2
2
  "name": "@speclynx/apidom-reference",
3
- "version": "3.1.0",
3
+ "version": "3.2.1",
4
4
  "description": "Advanced algorithms for semantic ApiDOM manipulations like dereferencing or resolution.",
5
+ "keywords": [
6
+ "apidom",
7
+ "api",
8
+ "$ref",
9
+ "dereference",
10
+ "reference",
11
+ "resolve",
12
+ "resolver",
13
+ "bundle",
14
+ "openapi",
15
+ "swagger",
16
+ "oas",
17
+ "asyncapi",
18
+ "arazzo",
19
+ "json-schema",
20
+ "json",
21
+ "yaml",
22
+ "spec",
23
+ "specification",
24
+ "parse",
25
+ "typescript",
26
+ "javascript"
27
+ ],
5
28
  "publishConfig": {
6
29
  "access": "public",
7
30
  "registry": "https://registry.npmjs.org",
@@ -231,29 +254,29 @@
231
254
  "license": "Apache-2.0",
232
255
  "dependencies": {
233
256
  "@babel/runtime-corejs3": "^7.28.4",
234
- "@speclynx/apidom-core": "3.1.0",
235
- "@speclynx/apidom-datamodel": "3.1.0",
236
- "@speclynx/apidom-error": "3.1.0",
237
- "@speclynx/apidom-json-pointer": "3.1.0",
238
- "@speclynx/apidom-ns-arazzo-1": "3.1.0",
239
- "@speclynx/apidom-ns-asyncapi-2": "3.1.0",
240
- "@speclynx/apidom-ns-json-schema-2020-12": "3.1.0",
241
- "@speclynx/apidom-ns-openapi-2": "3.1.0",
242
- "@speclynx/apidom-ns-openapi-3-0": "3.1.0",
243
- "@speclynx/apidom-ns-openapi-3-1": "3.1.0",
244
- "@speclynx/apidom-parser-adapter-arazzo-json-1": "3.1.0",
245
- "@speclynx/apidom-parser-adapter-arazzo-yaml-1": "3.1.0",
246
- "@speclynx/apidom-parser-adapter-asyncapi-json-2": "3.1.0",
247
- "@speclynx/apidom-parser-adapter-asyncapi-yaml-2": "3.1.0",
248
- "@speclynx/apidom-parser-adapter-json": "3.1.0",
249
- "@speclynx/apidom-parser-adapter-openapi-json-2": "3.1.0",
250
- "@speclynx/apidom-parser-adapter-openapi-json-3-0": "3.1.0",
251
- "@speclynx/apidom-parser-adapter-openapi-json-3-1": "3.1.0",
252
- "@speclynx/apidom-parser-adapter-openapi-yaml-2": "3.1.0",
253
- "@speclynx/apidom-parser-adapter-openapi-yaml-3-0": "3.1.0",
254
- "@speclynx/apidom-parser-adapter-openapi-yaml-3-1": "3.1.0",
255
- "@speclynx/apidom-parser-adapter-yaml-1-2": "3.1.0",
256
- "@speclynx/apidom-traverse": "3.1.0",
257
+ "@speclynx/apidom-core": "3.2.1",
258
+ "@speclynx/apidom-datamodel": "3.2.1",
259
+ "@speclynx/apidom-error": "3.2.1",
260
+ "@speclynx/apidom-json-pointer": "3.2.1",
261
+ "@speclynx/apidom-ns-arazzo-1": "3.2.1",
262
+ "@speclynx/apidom-ns-asyncapi-2": "3.2.1",
263
+ "@speclynx/apidom-ns-json-schema-2020-12": "3.2.1",
264
+ "@speclynx/apidom-ns-openapi-2": "3.2.1",
265
+ "@speclynx/apidom-ns-openapi-3-0": "3.2.1",
266
+ "@speclynx/apidom-ns-openapi-3-1": "3.2.1",
267
+ "@speclynx/apidom-parser-adapter-arazzo-json-1": "3.2.1",
268
+ "@speclynx/apidom-parser-adapter-arazzo-yaml-1": "3.2.1",
269
+ "@speclynx/apidom-parser-adapter-asyncapi-json-2": "3.2.1",
270
+ "@speclynx/apidom-parser-adapter-asyncapi-yaml-2": "3.2.1",
271
+ "@speclynx/apidom-parser-adapter-json": "3.2.1",
272
+ "@speclynx/apidom-parser-adapter-openapi-json-2": "3.2.1",
273
+ "@speclynx/apidom-parser-adapter-openapi-json-3-0": "3.2.1",
274
+ "@speclynx/apidom-parser-adapter-openapi-json-3-1": "3.2.1",
275
+ "@speclynx/apidom-parser-adapter-openapi-yaml-2": "3.2.1",
276
+ "@speclynx/apidom-parser-adapter-openapi-yaml-3-0": "3.2.1",
277
+ "@speclynx/apidom-parser-adapter-openapi-yaml-3-1": "3.2.1",
278
+ "@speclynx/apidom-parser-adapter-yaml-1-2": "3.2.1",
279
+ "@speclynx/apidom-traverse": "3.2.1",
257
280
  "@swaggerexpert/arazzo-runtime-expression": "^2.0.3",
258
281
  "axios": "^1.13.5",
259
282
  "picomatch": "^4.0.3",
@@ -275,5 +298,5 @@
275
298
  "README.md",
276
299
  "CHANGELOG.md"
277
300
  ],
278
- "gitHead": "c0807dd0b7770eaaf594bd0013be65e2c28c504a"
301
+ "gitHead": "83a1e97089ef29134e41ff7cacd351973114ea5b"
279
302
  }
@@ -106,15 +106,22 @@ class ApiDOMDereferenceVisitor {
106
106
  const isEntryDocument = url.stripHash(this.reference.refSet?.rootRef?.uri ?? '') === this.reference.uri;
107
107
  const uri = this.reference.uri;
108
108
  const type = referencingElement.element;
109
+ // find element location by identity in the document tree.
110
+ // guarded: this.reference.value may not be a ParseResultElement or may lack a result.
111
+ // falls back to visitorPath which may produce an incomplete path when
112
+ // dereferenceApiDOM is called with a fragment (cloneShallow creates a new root identity).
109
113
  let location;
110
- (0, _apidomTraverse.traverse)(this.reference.value.result, {
111
- enter(p) {
112
- if (p.node === referencingElement) {
113
- location = p.formatPath();
114
- p.stop();
114
+ const root = this.reference.value.result;
115
+ if ((0, _apidomDatamodel.isElement)(root)) {
116
+ (0, _apidomTraverse.traverse)(root, {
117
+ enter(p) {
118
+ if (p.node === referencingElement) {
119
+ location = p.formatPath();
120
+ p.stop();
121
+ }
115
122
  }
116
- }
117
- });
123
+ });
124
+ }
118
125
  location ??= visitorPath.formatPath();
119
126
  const codeFrame = (0, _apidomCore.toYAML)(referencingElement);
120
127
  const hop = {
@@ -99,15 +99,22 @@ class ApiDOMDereferenceVisitor {
99
99
  const isEntryDocument = url.stripHash(this.reference.refSet?.rootRef?.uri ?? '') === this.reference.uri;
100
100
  const uri = this.reference.uri;
101
101
  const type = referencingElement.element;
102
+ // find element location by identity in the document tree.
103
+ // guarded: this.reference.value may not be a ParseResultElement or may lack a result.
104
+ // falls back to visitorPath which may produce an incomplete path when
105
+ // dereferenceApiDOM is called with a fragment (cloneShallow creates a new root identity).
102
106
  let location;
103
- traverse(this.reference.value.result, {
104
- enter(p) {
105
- if (p.node === referencingElement) {
106
- location = p.formatPath();
107
- p.stop();
107
+ const root = this.reference.value.result;
108
+ if (isElement(root)) {
109
+ traverse(root, {
110
+ enter(p) {
111
+ if (p.node === referencingElement) {
112
+ location = p.formatPath();
113
+ p.stop();
114
+ }
108
115
  }
109
- }
110
- });
116
+ });
117
+ }
111
118
  location ??= visitorPath.formatPath();
112
119
  const codeFrame = toYAML(referencingElement);
113
120
  const hop = {
@@ -140,16 +140,22 @@ class Arazzo1DereferenceVisitor {
140
140
  const type = referencingElement.element;
141
141
  const codeFrame = (0, _apidomCore.toYAML)(referencingElement);
142
142
 
143
- // find element location: tree search for entry documents, visitor path for external
143
+ // find element location by identity in the document tree.
144
+ // guarded: this.reference.value may not be a ParseResultElement or may lack a result.
145
+ // falls back to visitorPath which may produce an incomplete path when
146
+ // dereferenceApiDOM is called with a fragment (cloneShallow creates a new root identity).
144
147
  let location;
145
- (0, _apidomTraverse.traverse)(this.reference.value.result, {
146
- enter: p => {
147
- if (p.node === referencingElement) {
148
- location = p.formatPath();
149
- p.stop();
148
+ const root = this.reference.value.result;
149
+ if ((0, _apidomDatamodel.isElement)(root)) {
150
+ (0, _apidomTraverse.traverse)(root, {
151
+ enter(p) {
152
+ if (p.node === referencingElement) {
153
+ location = p.formatPath();
154
+ p.stop();
155
+ }
150
156
  }
151
- }
152
- });
157
+ });
158
+ }
153
159
  location ??= visitorPath.formatPath();
154
160
  const hop = {
155
161
  uri,
@@ -274,6 +280,7 @@ class Arazzo1DereferenceVisitor {
274
280
  path.skip();
275
281
  return;
276
282
  }
283
+ const indirectionsSize = this.indirections.length;
277
284
  try {
278
285
  // compute baseURI using rules around $id and $ref keywords
279
286
  let reference = await this.toReference(url.unsanitize(this.reference.uri));
@@ -418,7 +425,6 @@ class Arazzo1DereferenceVisitor {
418
425
  });
419
426
  const replacer = this.options.dereference.strategyOpts['arazzo-1']?.circularReplacer ?? this.options.dereference.circularReplacer;
420
427
  const replacement = replacer(refElement);
421
- this.indirections.pop();
422
428
  path.replaceWith(replacement);
423
429
  return;
424
430
  }
@@ -451,7 +457,6 @@ class Arazzo1DereferenceVisitor {
451
457
  // remove referencing reference from ancestors lineage
452
458
  directAncestors.delete(referencingElement);
453
459
  }
454
- this.indirections.pop();
455
460
 
456
461
  // Boolean JSON Schemas
457
462
  if ((0, _apidomNsArazzo.isBooleanJSONSchemaElement)(referencedElement)) {
@@ -494,6 +499,8 @@ class Arazzo1DereferenceVisitor {
494
499
  } catch (error) {
495
500
  const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
496
501
  this.handleError(`Error while dereferencing Schema Object. Cannot resolve $ref "${$ref}": ${error.message}`, error, referencingElement, '$ref', $ref, path);
502
+ } finally {
503
+ if (this.indirections.length > indirectionsSize) this.indirections.pop();
497
504
  }
498
505
  }
499
506
  }
@@ -133,16 +133,22 @@ class Arazzo1DereferenceVisitor {
133
133
  const type = referencingElement.element;
134
134
  const codeFrame = toYAML(referencingElement);
135
135
 
136
- // find element location: tree search for entry documents, visitor path for external
136
+ // find element location by identity in the document tree.
137
+ // guarded: this.reference.value may not be a ParseResultElement or may lack a result.
138
+ // falls back to visitorPath which may produce an incomplete path when
139
+ // dereferenceApiDOM is called with a fragment (cloneShallow creates a new root identity).
137
140
  let location;
138
- traverse(this.reference.value.result, {
139
- enter: p => {
140
- if (p.node === referencingElement) {
141
- location = p.formatPath();
142
- p.stop();
141
+ const root = this.reference.value.result;
142
+ if (isElement(root)) {
143
+ traverse(root, {
144
+ enter(p) {
145
+ if (p.node === referencingElement) {
146
+ location = p.formatPath();
147
+ p.stop();
148
+ }
143
149
  }
144
- }
145
- });
150
+ });
151
+ }
146
152
  location ??= visitorPath.formatPath();
147
153
  const hop = {
148
154
  uri,
@@ -267,6 +273,7 @@ class Arazzo1DereferenceVisitor {
267
273
  path.skip();
268
274
  return;
269
275
  }
276
+ const indirectionsSize = this.indirections.length;
270
277
  try {
271
278
  // compute baseURI using rules around $id and $ref keywords
272
279
  let reference = await this.toReference(url.unsanitize(this.reference.uri));
@@ -411,7 +418,6 @@ class Arazzo1DereferenceVisitor {
411
418
  });
412
419
  const replacer = this.options.dereference.strategyOpts['arazzo-1']?.circularReplacer ?? this.options.dereference.circularReplacer;
413
420
  const replacement = replacer(refElement);
414
- this.indirections.pop();
415
421
  path.replaceWith(replacement);
416
422
  return;
417
423
  }
@@ -444,7 +450,6 @@ class Arazzo1DereferenceVisitor {
444
450
  // remove referencing reference from ancestors lineage
445
451
  directAncestors.delete(referencingElement);
446
452
  }
447
- this.indirections.pop();
448
453
 
449
454
  // Boolean JSON Schemas
450
455
  if (isBooleanJSONSchemaElement(referencedElement)) {
@@ -487,6 +492,8 @@ class Arazzo1DereferenceVisitor {
487
492
  } catch (error) {
488
493
  const $ref = toValue(referencingElement.$ref);
489
494
  this.handleError(`Error while dereferencing Schema Object. Cannot resolve $ref "${$ref}": ${error.message}`, error, referencingElement, '$ref', $ref, path);
495
+ } finally {
496
+ if (this.indirections.length > indirectionsSize) this.indirections.pop();
490
497
  }
491
498
  }
492
499
  }
@@ -136,16 +136,22 @@ class AsyncAPI2DereferenceVisitor {
136
136
  const type = referencingElement.element;
137
137
  const codeFrame = (0, _apidomCore.toYAML)(referencingElement);
138
138
 
139
- // find element location: tree search for entry documents, visitor path for external
139
+ // find element location by identity in the document tree.
140
+ // guarded: this.reference.value may not be a ParseResultElement or may lack a result.
141
+ // falls back to visitorPath which may produce an incomplete path when
142
+ // dereferenceApiDOM is called with a fragment (cloneShallow creates a new root identity).
140
143
  let location;
141
- (0, _apidomTraverse.traverse)(this.reference.value.result, {
142
- enter: p => {
143
- if (p.node === referencingElement || this.refractCache.get(p.node) === referencingElement) {
144
- location = p.formatPath();
145
- p.stop();
144
+ const root = this.reference.value.result;
145
+ if ((0, _apidomDatamodel.isElement)(root)) {
146
+ (0, _apidomTraverse.traverse)(root, {
147
+ enter: p => {
148
+ if (p.node === referencingElement || this.refractCache.get(p.node) === referencingElement) {
149
+ location = p.formatPath();
150
+ p.stop();
151
+ }
146
152
  }
147
- }
148
- });
153
+ });
154
+ }
149
155
  location ??= visitorPath.formatPath();
150
156
  const hop = {
151
157
  uri,
@@ -213,6 +219,7 @@ class AsyncAPI2DereferenceVisitor {
213
219
  return;
214
220
  }
215
221
  const $refBaseURI = url.resolve(retrievalURI, (0, _apidomCore.toValue)(referencingElement.$ref));
222
+ const indirectionsSize = this.indirections.length;
216
223
  try {
217
224
  const reference = await this.toReference((0, _apidomCore.toValue)(referencingElement.$ref));
218
225
  this.indirections.push(referencingElement);
@@ -273,7 +280,6 @@ class AsyncAPI2DereferenceVisitor {
273
280
  });
274
281
  const replacer = this.options.dereference.strategyOpts['asyncapi-2']?.circularReplacer ?? this.options.dereference.circularReplacer;
275
282
  const replacement = replacer(refElement);
276
- this.indirections.pop();
277
283
  path.replaceWith(replacement);
278
284
  return;
279
285
  }
@@ -307,7 +313,6 @@ class AsyncAPI2DereferenceVisitor {
307
313
  // remove referencing reference from ancestors lineage
308
314
  directAncestors.delete(referencingElement);
309
315
  }
310
- this.indirections.pop();
311
316
 
312
317
  // Boolean JSON Schemas
313
318
  if ((0, _apidomNsAsyncapi.isBooleanJSONSchemaElement)(referencedElement)) {
@@ -342,6 +347,8 @@ class AsyncAPI2DereferenceVisitor {
342
347
  } catch (error) {
343
348
  const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
344
349
  this.handleError(`Error while dereferencing Reference Object. Cannot resolve $ref "${$ref}": ${error.message}`, error, referencingElement, '$ref', $ref, path);
350
+ } finally {
351
+ if (this.indirections.length > indirectionsSize) this.indirections.pop();
345
352
  }
346
353
  }
347
354
  async ChannelItemElement(path) {
@@ -372,6 +379,7 @@ class AsyncAPI2DereferenceVisitor {
372
379
  return;
373
380
  }
374
381
  const $refBaseURI = url.resolve(retrievalURI, (0, _apidomCore.toValue)(referencingElement.$ref));
382
+ const indirectionsSize = this.indirections.length;
375
383
  try {
376
384
  const reference = await this.toReference((0, _apidomCore.toValue)(referencingElement.$ref));
377
385
  this.indirections.push(referencingElement);
@@ -422,7 +430,6 @@ class AsyncAPI2DereferenceVisitor {
422
430
  });
423
431
  const replacer = this.options.dereference.strategyOpts['asyncapi-2']?.circularReplacer ?? this.options.dereference.circularReplacer;
424
432
  const replacement = replacer(refElement);
425
- this.indirections.pop();
426
433
  path.replaceWith(replacement);
427
434
  return;
428
435
  }
@@ -456,7 +463,6 @@ class AsyncAPI2DereferenceVisitor {
456
463
  // remove referencing reference from ancestors lineage
457
464
  directAncestors.delete(referencingElement);
458
465
  }
459
- this.indirections.pop();
460
466
 
461
467
  /**
462
468
  * Creating a new version of Channel Item by merging fields from referenced Channel Item with referencing one.
@@ -487,6 +493,8 @@ class AsyncAPI2DereferenceVisitor {
487
493
  } catch (error) {
488
494
  const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
489
495
  this.handleError(`Error while dereferencing Channel Item Object. Cannot resolve $ref "${$ref}": ${error.message}`, error, referencingElement, '$ref', $ref, path);
496
+ } finally {
497
+ if (this.indirections.length > indirectionsSize) this.indirections.pop();
490
498
  }
491
499
  }
492
500
  }
@@ -129,16 +129,22 @@ class AsyncAPI2DereferenceVisitor {
129
129
  const type = referencingElement.element;
130
130
  const codeFrame = toYAML(referencingElement);
131
131
 
132
- // find element location: tree search for entry documents, visitor path for external
132
+ // find element location by identity in the document tree.
133
+ // guarded: this.reference.value may not be a ParseResultElement or may lack a result.
134
+ // falls back to visitorPath which may produce an incomplete path when
135
+ // dereferenceApiDOM is called with a fragment (cloneShallow creates a new root identity).
133
136
  let location;
134
- traverse(this.reference.value.result, {
135
- enter: p => {
136
- if (p.node === referencingElement || this.refractCache.get(p.node) === referencingElement) {
137
- location = p.formatPath();
138
- p.stop();
137
+ const root = this.reference.value.result;
138
+ if (isElement(root)) {
139
+ traverse(root, {
140
+ enter: p => {
141
+ if (p.node === referencingElement || this.refractCache.get(p.node) === referencingElement) {
142
+ location = p.formatPath();
143
+ p.stop();
144
+ }
139
145
  }
140
- }
141
- });
146
+ });
147
+ }
142
148
  location ??= visitorPath.formatPath();
143
149
  const hop = {
144
150
  uri,
@@ -206,6 +212,7 @@ class AsyncAPI2DereferenceVisitor {
206
212
  return;
207
213
  }
208
214
  const $refBaseURI = url.resolve(retrievalURI, toValue(referencingElement.$ref));
215
+ const indirectionsSize = this.indirections.length;
209
216
  try {
210
217
  const reference = await this.toReference(toValue(referencingElement.$ref));
211
218
  this.indirections.push(referencingElement);
@@ -266,7 +273,6 @@ class AsyncAPI2DereferenceVisitor {
266
273
  });
267
274
  const replacer = this.options.dereference.strategyOpts['asyncapi-2']?.circularReplacer ?? this.options.dereference.circularReplacer;
268
275
  const replacement = replacer(refElement);
269
- this.indirections.pop();
270
276
  path.replaceWith(replacement);
271
277
  return;
272
278
  }
@@ -300,7 +306,6 @@ class AsyncAPI2DereferenceVisitor {
300
306
  // remove referencing reference from ancestors lineage
301
307
  directAncestors.delete(referencingElement);
302
308
  }
303
- this.indirections.pop();
304
309
 
305
310
  // Boolean JSON Schemas
306
311
  if (isBooleanJSONSchemaElement(referencedElement)) {
@@ -335,6 +340,8 @@ class AsyncAPI2DereferenceVisitor {
335
340
  } catch (error) {
336
341
  const $ref = toValue(referencingElement.$ref);
337
342
  this.handleError(`Error while dereferencing Reference Object. Cannot resolve $ref "${$ref}": ${error.message}`, error, referencingElement, '$ref', $ref, path);
343
+ } finally {
344
+ if (this.indirections.length > indirectionsSize) this.indirections.pop();
338
345
  }
339
346
  }
340
347
  async ChannelItemElement(path) {
@@ -365,6 +372,7 @@ class AsyncAPI2DereferenceVisitor {
365
372
  return;
366
373
  }
367
374
  const $refBaseURI = url.resolve(retrievalURI, toValue(referencingElement.$ref));
375
+ const indirectionsSize = this.indirections.length;
368
376
  try {
369
377
  const reference = await this.toReference(toValue(referencingElement.$ref));
370
378
  this.indirections.push(referencingElement);
@@ -415,7 +423,6 @@ class AsyncAPI2DereferenceVisitor {
415
423
  });
416
424
  const replacer = this.options.dereference.strategyOpts['asyncapi-2']?.circularReplacer ?? this.options.dereference.circularReplacer;
417
425
  const replacement = replacer(refElement);
418
- this.indirections.pop();
419
426
  path.replaceWith(replacement);
420
427
  return;
421
428
  }
@@ -449,7 +456,6 @@ class AsyncAPI2DereferenceVisitor {
449
456
  // remove referencing reference from ancestors lineage
450
457
  directAncestors.delete(referencingElement);
451
458
  }
452
- this.indirections.pop();
453
459
 
454
460
  /**
455
461
  * Creating a new version of Channel Item by merging fields from referenced Channel Item with referencing one.
@@ -480,6 +486,8 @@ class AsyncAPI2DereferenceVisitor {
480
486
  } catch (error) {
481
487
  const $ref = toValue(referencingElement.$ref);
482
488
  this.handleError(`Error while dereferencing Channel Item Object. Cannot resolve $ref "${$ref}": ${error.message}`, error, referencingElement, '$ref', $ref, path);
489
+ } finally {
490
+ if (this.indirections.length > indirectionsSize) this.indirections.pop();
483
491
  }
484
492
  }
485
493
  }
@@ -136,16 +136,22 @@ class OpenAPI2DereferenceVisitor {
136
136
  const type = referencingElement.element;
137
137
  const codeFrame = (0, _apidomCore.toYAML)(referencingElement);
138
138
 
139
- // find element location: tree search for entry documents, visitor path for external
139
+ // find element location by identity in the document tree.
140
+ // guarded: this.reference.value may not be a ParseResultElement or may lack a result.
141
+ // falls back to visitorPath which may produce an incomplete path when
142
+ // dereferenceApiDOM is called with a fragment (cloneShallow creates a new root identity).
140
143
  let location;
141
- (0, _apidomTraverse.traverse)(this.reference.value.result, {
142
- enter: p => {
143
- if (p.node === referencingElement || this.refractCache.get(p.node) === referencingElement) {
144
- location = p.formatPath();
145
- p.stop();
144
+ const root = this.reference.value.result;
145
+ if ((0, _apidomDatamodel.isElement)(root)) {
146
+ (0, _apidomTraverse.traverse)(root, {
147
+ enter: p => {
148
+ if (p.node === referencingElement || this.refractCache.get(p.node) === referencingElement) {
149
+ location = p.formatPath();
150
+ p.stop();
151
+ }
146
152
  }
147
- }
148
- });
153
+ });
154
+ }
149
155
  location ??= visitorPath.formatPath();
150
156
  const hop = {
151
157
  uri,
@@ -213,6 +219,7 @@ class OpenAPI2DereferenceVisitor {
213
219
  return;
214
220
  }
215
221
  const $refBaseURI = url.resolve(retrievalURI, (0, _apidomCore.toValue)(referencingElement.$ref));
222
+ const indirectionsSize = this.indirections.length;
216
223
  try {
217
224
  const reference = await this.toReference((0, _apidomCore.toValue)(referencingElement.$ref));
218
225
  this.indirections.push(referencingElement);
@@ -273,7 +280,6 @@ class OpenAPI2DereferenceVisitor {
273
280
  });
274
281
  const replacer = this.options.dereference.strategyOpts['openapi-2']?.circularReplacer ?? this.options.dereference.circularReplacer;
275
282
  const replacement = replacer(refElement);
276
- this.indirections.pop();
277
283
  path.replaceWith(replacement);
278
284
  return;
279
285
  }
@@ -305,7 +311,6 @@ class OpenAPI2DereferenceVisitor {
305
311
  });
306
312
  directAncestors.delete(referencingElement);
307
313
  }
308
- this.indirections.pop();
309
314
 
310
315
  /**
311
316
  * Creating a new version of referenced element to avoid modifying the original one.
@@ -326,6 +331,8 @@ class OpenAPI2DereferenceVisitor {
326
331
  } catch (error) {
327
332
  const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
328
333
  this.handleError(`Error while dereferencing Reference Object. Cannot resolve $ref "${$ref}": ${error.message}`, error, referencingElement, '$ref', $ref, path);
334
+ } finally {
335
+ if (this.indirections.length > indirectionsSize) this.indirections.pop();
329
336
  }
330
337
  }
331
338
  async PathItemElement(path) {
@@ -356,6 +363,7 @@ class OpenAPI2DereferenceVisitor {
356
363
  return;
357
364
  }
358
365
  const $refBaseURI = url.resolve(retrievalURI, (0, _apidomCore.toValue)(referencingElement.$ref));
366
+ const indirectionsSize = this.indirections.length;
359
367
  try {
360
368
  const reference = await this.toReference((0, _apidomCore.toValue)(referencingElement.$ref));
361
369
  this.indirections.push(referencingElement);
@@ -406,7 +414,6 @@ class OpenAPI2DereferenceVisitor {
406
414
  });
407
415
  const replacer = this.options.dereference.strategyOpts['openapi-2']?.circularReplacer ?? this.options.dereference.circularReplacer;
408
416
  const replacement = replacer(refElement);
409
- this.indirections.pop();
410
417
  path.replaceWith(replacement);
411
418
  return;
412
419
  }
@@ -440,7 +447,6 @@ class OpenAPI2DereferenceVisitor {
440
447
  // remove referencing reference from ancestors lineage
441
448
  directAncestors.delete(referencingElement);
442
449
  }
443
- this.indirections.pop();
444
450
 
445
451
  /**
446
452
  * Creating a new version of Path Item by merging fields from referenced Path Item with referencing one.
@@ -472,6 +478,8 @@ class OpenAPI2DereferenceVisitor {
472
478
  } catch (error) {
473
479
  const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
474
480
  this.handleError(`Error while dereferencing Path Item Object. Cannot resolve $ref "${$ref}": ${error.message}`, error, referencingElement, '$ref', $ref, path);
481
+ } finally {
482
+ if (this.indirections.length > indirectionsSize) this.indirections.pop();
475
483
  }
476
484
  }
477
485
  async JSONReferenceElement(path) {
@@ -499,6 +507,7 @@ class OpenAPI2DereferenceVisitor {
499
507
  return;
500
508
  }
501
509
  const $refBaseURI = url.resolve(retrievalURI, (0, _apidomCore.toValue)(referencingElement.$ref));
510
+ const indirectionsSize = this.indirections.length;
502
511
  try {
503
512
  const reference = await this.toReference((0, _apidomCore.toValue)(referencingElement.$ref));
504
513
  this.indirections.push(referencingElement);
@@ -559,7 +568,6 @@ class OpenAPI2DereferenceVisitor {
559
568
  });
560
569
  const replacer = this.options.dereference.strategyOpts['openapi-2']?.circularReplacer ?? this.options.dereference.circularReplacer;
561
570
  const replacement = replacer(refElement);
562
- this.indirections.pop();
563
571
  path.replaceWith(replacement);
564
572
  return;
565
573
  }
@@ -593,7 +601,6 @@ class OpenAPI2DereferenceVisitor {
593
601
  // remove referencing reference from ancestors lineage
594
602
  directAncestors.delete(referencingElement);
595
603
  }
596
- this.indirections.pop();
597
604
 
598
605
  /**
599
606
  * Creating a new version of referenced element to avoid modifying the original one.
@@ -614,6 +621,8 @@ class OpenAPI2DereferenceVisitor {
614
621
  } catch (error) {
615
622
  const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
616
623
  this.handleError(`Error while dereferencing JSON Reference Object. Cannot resolve $ref "${$ref}": ${error.message}`, error, referencingElement, '$ref', $ref, path);
624
+ } finally {
625
+ if (this.indirections.length > indirectionsSize) this.indirections.pop();
617
626
  }
618
627
  }
619
628
  }