ajv-validator/ajv

default values - RangeError: Maximum call stack size exceeded

fogine opened this issue · 4 comments

What version of Ajv are you using? Does the issue happen if you use the latest version?

6.5.0

Ajv options object

{useDefaults: false}

JSON Schema

function Default() {}
Default.prototype.toJSON = function toJSON() {
    return {};
};

const def = new Default;

def.prop = {
    Default: def // it fails because of this circular enumerable property
};

const schema = {
    type: 'object',
    properties: {
        prop: {
            type: 'object',
            default: def
        }
    }
};

Your code

ajv.addSchema(schema, 'test');

Validation result, data AFTER validation, error messages

RangeError: Maximum call stack size exceeded
    at _traverse (/path/to/project/node_modules/json-schema-traverse/index.js:58:5)
    at _traverse (/path/to/project/node_modules/json-schema-traverse/index.js:72:9)
    at _traverse (/path/to/project/node_modules/json-schema-traverse/index.js:72:9)
    at _traverse (/path/to/project/node_modules/json-schema-traverse/index.js:72:9)
    at _traverse (/path/to/project/node_modules/json-schema-traverse/index.js:72:9)
    at _traverse (/path/to/project/node_modules/json-schema-traverse/index.js:72:9)
    at _traverse (/path/to/project/node_modules/json-schema-traverse/index.js:72:9)
    at _traverse (/path/to/project/node_modules/json-schema-traverse/index.js:72:9)
    at _traverse (/path/to/project/node_modules/json-schema-traverse/index.js:72:9)
    at _traverse (/path/to/project/node_modules/json-schema-traverse/index.js:72:9)


What results did you expect?
When useDefaults=false I'd expect that ajv is gonna ignore default keyword and not traverse its enumerable properties.
Although it should not fail even with useDefaults=true when the default value object implements toJSON method.

Are you going to resolve the issue?
possible bugfix provided here:
epoberezkin/json-schema-traverse#5

In ajv library, used here:
https://github.com/epoberezkin/ajv/blob/master/lib/compile/resolve.js#L239

note: I see now that default property value is serialized because ajv option serialize is not set to false...

@fogine ajv indeed doesn't support schemas with recursive data structures - they need to be serialisable (unless you disable it, as you wrote, but they would still be used as keys - so unless you use WeakMap as a cache, nothing will work). I will release json-schema-traverse.

@epoberezkin
Evgeny,

ajv indeed doesn't support schemas with recursive data structures

Is it theoretically possible to change that? Пожалуйста?

Only theoretically, I am afraid... The cost would be prohibitive - it's a major design change.

Effectively, what you are asking is to detect cycles and translate them to $refs - this is a more complex operation than avoiding cycles in the first place...

It does seem though like some separate library could possibly do ref-ing, in the same way there is a library that does de-ref-ing, which means it doesn't need to be done as part of Ajv - it can be defined and solved as a relatively isolated CS problem on the level of tech interview questions...