@@ -978,13 +978,19 @@ function crawl (obj, path, pathFromRoot, parents, $refs, options) {
978
978
if ($Ref.isAllowed$Ref(value, options)) {
979
979
dereferenced = dereference$Ref(value, keyPath, keyPathFromRoot, parents, $refs, options);
980
980
circular = dereferenced.circular;
981
- obj[key] = dereferenced.value;
981
+ // Avoid pointless mutations; breaks frozen objects to no profit
982
+ if (obj[key] !== dereferenced.value) {
983
+ obj[key] = dereferenced.value;
984
+ }
982
985
}
983
986
else {
984
987
if (parents.indexOf(value) === -1) {
985
988
dereferenced = crawl(value, keyPath, keyPathFromRoot, parents, $refs, options);
986
989
circular = dereferenced.circular;
987
- obj[key] = dereferenced.value;
990
+ // Avoid pointless mutations; breaks frozen objects to no profit
991
+ if (obj[key] !== dereferenced.value) {
992
+ obj[key] = dereferenced.value;
993
+ }
988
994
}
989
995
else {
990
996
circular = foundCircularReference(keyPath, $refs, options);
@@ -2041,14 +2047,15 @@ function Pointer ($ref, path, friendlyPath) {
2041
2047
*
2042
2048
* @param {*} obj - The object that will be crawled
2043
2049
* @param {$RefParserOptions} options
2050
+ * @param {string} pathFromRoot - the path of place that initiated resolving
2044
2051
*
2045
2052
* @returns {Pointer}
2046
2053
* Returns a JSON pointer whose {@link Pointer#value} is the resolved value.
2047
2054
* If resolving this value required resolving other JSON references, then
2048
2055
* the {@link Pointer#$ref} and {@link Pointer#path} will reflect the resolution path
2049
2056
* of the resolved value.
2050
2057
*/
2051
- Pointer.prototype.resolve = function (obj, options) {
2058
+ Pointer.prototype.resolve = function (obj, options, pathFromRoot ) {
2052
2059
let tokens = Pointer.parse(this.path, this.originalPath);
2053
2060
2054
2061
// Crawl the object, one token at a time
@@ -2060,6 +2067,10 @@ Pointer.prototype.resolve = function (obj, options) {
2060
2067
this.path = Pointer.join(this.path, tokens.slice(i));
2061
2068
}
2062
2069
2070
+ if (typeof this.value === "object" && this.value !== null && "$ref" in this.value) {
2071
+ return this;
2072
+ }
2073
+
2063
2074
let token = tokens[i];
2064
2075
if (this.value[token] === undefined || this.value[token] === null) {
2065
2076
this.value = null;
@@ -2071,7 +2082,10 @@ Pointer.prototype.resolve = function (obj, options) {
2071
2082
}
2072
2083
2073
2084
// Resolve the final value
2074
- resolveIf$Ref(this, options);
2085
+ if (!this.value || this.value.$ref && url.resolve(this.path, this.value.$ref) !== pathFromRoot) {
2086
+ resolveIf$Ref(this, options);
2087
+ }
2088
+
2075
2089
return this;
2076
2090
};
2077
2091
@@ -2203,7 +2217,7 @@ function resolveIf$Ref (pointer, options) {
2203
2217
pointer.circular = true;
2204
2218
}
2205
2219
else {
2206
- let resolved = pointer.$ref.$refs._resolve($refPath, url.getHash( pointer.path) , options);
2220
+ let resolved = pointer.$ref.$refs._resolve($refPath, pointer.path, options);
2207
2221
pointer.indirections += resolved.indirections + 1;
2208
2222
2209
2223
if ($Ref.isExtended$Ref(pointer.value)) {
@@ -2374,7 +2388,7 @@ $Ref.prototype.get = function (path, options) {
2374
2388
$Ref.prototype.resolve = function (path, options, friendlyPath, pathFromRoot) {
2375
2389
let pointer = new Pointer(this, path, friendlyPath);
2376
2390
try {
2377
- return pointer.resolve(this.value, options);
2391
+ return pointer.resolve(this.value, options, pathFromRoot );
2378
2392
}
2379
2393
catch (err) {
2380
2394
if (!options || !options.continueOnError || !isHandledError(err)) {
0 commit comments