Skip to content

Commit 7b94ae0

Browse files
committed
Merge remote-tracking branch 'upstream/master' into nested-extended
2 parents e432e6c + cdcfd4f commit 7b94ae0

File tree

9 files changed

+435
-186
lines changed

9 files changed

+435
-186
lines changed

.circleci/config.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ version: 2.1
22

33
orbs:
44
node: circleci/node@4.7.0
5-
browser-tools: circleci/browser-tools@1.2.4
5+
browser-tools: circleci/browser-tools@1.4.4
66

77
executors:
88
linux:
@@ -42,6 +42,7 @@ jobs:
4242
node-version: << parameters.node-version >>.0
4343
install-yarn: false
4444
install-npm: true
45+
npm-version: "9.7.1"
4546
- install
4647
- test-node
4748

.github/workflows/CI-CD.yaml

+16-16
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ jobs:
2828
- macos-latest
2929
- windows-latest
3030
node:
31-
- 10
32-
- 12
31+
- 14
32+
- 16
3333

3434
steps:
3535
- name: Checkout source
36-
uses: actions/checkout@v2
36+
uses: actions/checkout@v3
3737

3838
- name: Install Node ${{ matrix.node }}
39-
uses: actions/setup-node@v1
39+
uses: actions/setup-node@v3
4040
with:
4141
node-version: ${{ matrix.node }}
4242

@@ -53,30 +53,30 @@ jobs:
5353
run: npm run coverage:node
5454

5555
- name: Send code coverage results to Coveralls
56-
uses: coverallsapp/github-action@v1.0.1
56+
uses: coverallsapp/github-action@v1.1.0
5757
with:
5858
github-token: ${{ secrets.GITHUB_TOKEN }}
5959
parallel: true
6060

6161
browser_tests:
6262
name: Browser Tests
6363
runs-on: ${{ matrix.os }}
64-
timeout-minutes: 10
64+
timeout-minutes: 15
6565
strategy:
6666
fail-fast: true
6767
matrix:
6868
os:
69-
- ubuntu-latest # Chrome, Firefox, Safari (via SauceLabs), Edge (via SauceLabs)
70-
- windows-latest # Internet Explorer
69+
- ubuntu-latest # Chrome, Firefox
70+
- windows-latest # Internet Explorer
7171

7272
steps:
7373
- name: Checkout source
74-
uses: actions/checkout@v2
74+
uses: actions/checkout@v3
7575

7676
- name: Install Node
77-
uses: actions/setup-node@v1
77+
uses: actions/setup-node@v3
7878
with:
79-
node-version: 12
79+
node-version: 16
8080

8181
- name: Install dependencies
8282
run: npm ci
@@ -94,21 +94,21 @@ jobs:
9494
cat coverage/*/lcov.info > ./coverage/lcov.info
9595
9696
- name: Send code coverage results to Coveralls
97-
uses: coverallsapp/github-action@v1.0.1
97+
uses: coverallsapp/github-action@v1.1.0
9898
with:
9999
github-token: ${{ secrets.GITHUB_TOKEN }}
100100
parallel: true
101101

102102
coverage:
103103
name: Code Coverage
104104
runs-on: ubuntu-latest
105-
timeout-minutes: 10
105+
timeout-minutes: 5
106106
needs:
107107
- node_tests
108108
- browser_tests
109109
steps:
110110
- name: Let Coveralls know that all tests have finished
111-
uses: coverallsapp/github-action@v1.0.1
111+
uses: coverallsapp/github-action@v1.1.0
112112
with:
113113
github-token: ${{ secrets.GITHUB_TOKEN }}
114114
parallel-finished: true
@@ -124,10 +124,10 @@ jobs:
124124

125125
steps:
126126
- name: Checkout source
127-
uses: actions/checkout@v2
127+
uses: actions/checkout@v3
128128

129129
- name: Install Node
130-
uses: actions/setup-node@v1
130+
uses: actions/setup-node@v3
131131

132132
- name: Install dependencies
133133
run: npm ci

lib/bundle/util/key-generator.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const { safePointerToPath, parse } = require("../../util/url");
55
const { basename, extname } = require("@stoplight/path");
66
const { get } = require("./object");
77

8-
const MAX_ATTEMPTS = 20;
8+
const MAX_ATTEMPTS = 1000;
99

1010
function prettify (key) {
1111
return capitalize(key.replace(/(?:\.|[\\/]+)([a-z])?/g, (_, letter, i) => {

lib/resolve-external.js

+34-6
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ function resolveExternal (parser, options) {
2929

3030
try {
3131
// console.log('Resolving $ref pointers in %s', parser.$refs._root$Ref.path);
32-
let promises = crawl(parser.schema, parser.$refs._root$Ref.path + "#", parser.$refs, options);
32+
let promises = crawl(
33+
parser.schema,
34+
parser.$refs._root$Ref.path + "#",
35+
parser.$refs,
36+
options
37+
);
3338
return Promise.all(promises);
3439
}
3540
catch (e) {
@@ -44,24 +49,47 @@ function resolveExternal (parser, options) {
4449
* @param {string} path - The full path of `obj`, possibly with a JSON Pointer in the hash
4550
* @param {$Refs} $refs
4651
* @param {$RefParserOptions} options
52+
* @param {Set} seen - Internal.
4753
*
4854
* @returns {Promise[]}
4955
* Returns an array of promises. There will be one promise for each JSON reference in `obj`.
5056
* If `obj` does not contain any JSON references, then the array will be empty.
5157
* If any of the JSON references point to files that contain additional JSON references,
5258
* then the corresponding promise will internally reference an array of promises.
5359
*/
54-
function crawl (obj, path, $refs, options) {
60+
function crawl (obj, path, $refs, options, external, seen) {
61+
seen = seen || new Set();
5562
let promises = [];
5663

57-
if (obj && typeof obj === "object" && !ArrayBuffer.isView(obj)) {
64+
if (
65+
obj &&
66+
typeof obj === "object" &&
67+
!ArrayBuffer.isView(obj) &&
68+
!seen.has(obj)
69+
) {
70+
seen.add(obj); // Track previously seen objects to avoid infinite recursion
5871
if ($Ref.isExternal$Ref(obj)) {
5972
promises.push(resolve$Ref(obj, path, $refs, options));
6073
}
74+
else {
75+
if (external && $Ref.is$Ref(obj)) {
76+
/* Correct the reference in the external document so we can resolve it */
77+
let withoutHash = url.stripHash(path);
78+
if (url.isFileSystemPath(withoutHash)) {
79+
/* remove file:// from path */
80+
withoutHash = url.toFileSystemPath(withoutHash);
81+
}
82+
obj.$ref = withoutHash + obj.$ref;
83+
}
84+
}
85+
6186
for (let key of Object.keys(obj)) {
6287
let keyPath = Pointer.join(path, key);
6388
let value = obj[key];
64-
promises = promises.concat(crawl(value, keyPath, $refs, options));
89+
90+
promises = promises.concat(
91+
crawl(value, keyPath, $refs, options, external, seen)
92+
);
6593
}
6694
}
6795

@@ -99,7 +127,7 @@ async function resolve$Ref ($ref, path, $refs, options) {
99127

100128
// Crawl the parsed value
101129
// console.log('Resolving $ref pointers in %s', withoutHash);
102-
let promises = crawl(result, withoutHash + "#", $refs, options);
130+
let promises = crawl(result, withoutHash + "#", $refs, options, true);
103131

104132
return Promise.all(promises);
105133
}
@@ -109,7 +137,7 @@ async function resolve$Ref ($ref, path, $refs, options) {
109137
}
110138

111139
if ($refs._$refs[withoutHash]) {
112-
err.source = url.stripHash(path);
140+
err.source = decodeURI(url.stripHash(path));
113141
err.path = url.safePointerToPath(url.getHash(path));
114142
}
115143

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/specs/absolute-root/absolute-root.spec.js

+44-21
Original file line numberDiff line numberDiff line change
@@ -47,44 +47,65 @@ describe("When executed in the context of root directory", () => {
4747
process.cwd = originalProcessCwd; // already restored by the finally block above, but just in case
4848
});
4949

50-
5150
it("should parse successfully from an absolute path", async () => {
5251
let parser = new $RefParser();
53-
const schema = await parser.parse(path.abs("specs/absolute-root/absolute-root.yaml"));
52+
const schema = await parser.parse(
53+
path.abs("specs/absolute-root/absolute-root.yaml")
54+
);
5455
expect(schema).to.equal(parser.schema);
5556
expect(schema).to.deep.equal(parsedSchema.schema);
5657
expect(parser.$refs.paths()).to.deep.equal([
57-
path.abs("specs/absolute-root/absolute-root.yaml")
58+
path.abs("specs/absolute-root/absolute-root.yaml"),
5859
]);
5960
});
6061

6162
it("should parse successfully from a url", async () => {
6263
let parser = new $RefParser();
63-
const schema = await parser.parse(path.url("specs/absolute-root/absolute-root.yaml"));
64+
const schema = await parser.parse(
65+
path.url("specs/absolute-root/absolute-root.yaml")
66+
);
6467
expect(schema).to.equal(parser.schema);
6568
expect(schema).to.deep.equal(parsedSchema.schema);
66-
expect(parser.$refs.paths()).to.deep.equal([path.url("specs/absolute-root/absolute-root.yaml")]);
69+
expect(parser.$refs.paths()).to.deep.equal([
70+
path.url("specs/absolute-root/absolute-root.yaml"),
71+
]);
6772
});
6873

69-
it("should resolve successfully from an absolute path", helper.testResolve(
70-
path.abs("specs/absolute-root/absolute-root.yaml"),
71-
path.abs("specs/absolute-root/absolute-root.yaml"), parsedSchema.schema,
72-
path.abs("specs/absolute-root/definitions/definitions.json"), parsedSchema.definitions,
73-
path.abs("specs/absolute-root/definitions/name.yaml"), parsedSchema.name,
74-
path.abs("specs/absolute-root/definitions/required-string.yaml"), parsedSchema.requiredString
75-
));
74+
it(
75+
"should resolve successfully from an absolute path",
76+
helper.testResolve(
77+
path.abs("specs/absolute-root/absolute-root.yaml"),
78+
path.abs("specs/absolute-root/absolute-root.yaml"),
79+
parsedSchema.schema,
80+
path.abs("specs/absolute-root/definitions/definitions.json"),
81+
parsedSchema.definitions,
82+
path.abs("specs/absolute-root/definitions/name.yaml"),
83+
parsedSchema.name,
84+
path.abs("specs/absolute-root/definitions/required-string.yaml"),
85+
parsedSchema.requiredString
86+
)
87+
);
7688

77-
it("should resolve successfully from a url", helper.testResolve(
78-
path.url("specs/absolute-root/absolute-root.yaml"),
79-
path.url("specs/absolute-root/absolute-root.yaml"), parsedSchema.schema,
80-
path.url("specs/absolute-root/definitions/definitions.json"), parsedSchema.definitions,
81-
path.url("specs/absolute-root/definitions/name.yaml"), parsedSchema.name,
82-
path.url("specs/absolute-root/definitions/required-string.yaml"), parsedSchema.requiredString
83-
));
89+
it(
90+
"should resolve successfully from a url",
91+
helper.testResolve(
92+
path.url("specs/absolute-root/absolute-root.yaml"),
93+
path.url("specs/absolute-root/absolute-root.yaml"),
94+
parsedSchema.schema,
95+
path.url("specs/absolute-root/definitions/definitions.json"),
96+
parsedSchema.definitions,
97+
path.url("specs/absolute-root/definitions/name.yaml"),
98+
parsedSchema.name,
99+
path.url("specs/absolute-root/definitions/required-string.yaml"),
100+
parsedSchema.requiredString
101+
)
102+
);
84103

85104
it("should dereference successfully", async () => {
86105
let parser = new $RefParser();
87-
const schema = await parser.dereference(path.abs("specs/absolute-root/absolute-root.yaml"));
106+
const schema = await parser.dereference(
107+
path.abs("specs/absolute-root/absolute-root.yaml")
108+
);
88109
expect(schema).to.equal(parser.schema);
89110
expect(schema).to.deep.equal(dereferencedSchema);
90111
// Reference equality
@@ -100,7 +121,9 @@ describe("When executed in the context of root directory", () => {
100121

101122
it("should bundle successfully", async () => {
102123
let parser = new $RefParser();
103-
const schema = await parser.bundle(path.abs("specs/absolute-root/absolute-root.yaml"));
124+
const schema = await parser.bundle(
125+
path.abs("specs/absolute-root/absolute-root.yaml")
126+
);
104127
expect(schema).to.equal(parser.schema);
105128
expect(schema).to.deep.equal(bundledSchema);
106129
});

0 commit comments

Comments
 (0)