Skip to content

$ref in $ref causes path hash to be repeated. #52

@supertong

Description

@supertong

Hey, first of all, thanks for the great library. I think I spot an edge case bug when using it.
Here is the JSON file that I have simplified a lot to demo the problem.

{
  "$ref": "#/definitions/doc_node",
  "definitions": {
    "top_level_node": {
      "type": "object"
    },
    "doc_node": {
      "type": "object",
      "properties": {
        "content": { "$ref": "#/definitions/top_level_node" }
      }
    }
  }
}

And when I tried to bundle it

const parser = new RefParser();
parser
  .bundle('./bug-schema.json')
  .then((s) => {
    console.log(JSON.stringify(s, null, 2))
  });

it generates output

{
  "$ref": "#/definitions/doc_node",
  "definitions": {
    "top_level_node": {
      "type": "object"
    },
    "doc_node": {
      "type": "object",
      "properties": {
        "content": {
          "$ref": "#/definitions/top_level_node/definitions/top_level_node"
        }
      }
    }
  }
}

As you can see, the 'definitions/top_level_node' is duplicated in doc_node. And I also did some debugging myself. It turns out that problem happens around here

Pointer.prototype.resolve = function(obj, options) {
  var tokens = Pointer.parse(this.path);

  // Crawl the object, one token at a time
  this.value = obj;
  for (var i = 0; i < tokens.length; i++) {
    if (resolveIf$Ref(this, options)) {
      // The $ref path has changed, so append the remaining tokens to the path
      this.path = Pointer.join(this.path, tokens.slice(i));  <== This line
    }

    var token = tokens[i];
    if (this.value[token] === undefined) {
      throw ono.syntax('Error resolving $ref pointer "%s". \nToken "%s" does not exist.', this.path, token);
    }
    else {
      this.value = this.value[token];
    }
  }

  // Resolve the final value
  resolveIf$Ref(this, options);
  return this;
};

I was trying to figure out what is the code doing here. My immature assumption is that resolveIf$Ref is checking if current object has a $ref and if it has one, it will be resolved. However, one thing I don't understand is the reason behind this path updating. May be it has something todo with line here ? Can we not update the path?

I understand you are busy and hope you could shed some light on this. I am happy to create a PR if you could understand the purpose of the path updating logic.

Cheers

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions