Skip to content

Commit

Permalink
Replace trace hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
hueniverse committed Sep 11, 2019
1 parent ba68201 commit ff0550e
Show file tree
Hide file tree
Showing 16 changed files with 202 additions and 159 deletions.
81 changes: 25 additions & 56 deletions lib/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ internals.Base = class {

this.$_temp = { // Runtime state (not cloned)
ruleset: null, // null: use last, false: error, number: start position
whens: {}, // Runtime cache of generated whens
whenSources: null, // The when schemas used to construct a runtime schema
whenId: null // Generated identifier used in nested generation
whens: {} // Runtime cache of generated whens
};
}

Expand Down Expand Up @@ -418,10 +416,10 @@ internals.Base = class {
obj.$_terms[key] = obj.$_terms[key].concat(terms);
}

// Temp
// Tracing

if (obj.$_temp.whenSources) {
obj.$_temp.whenSources.push(...source.$_temp.whenSources);
if (this.$_root._tracer) {
this.$_root._tracer._combine(obj, [this, source]);
}

// Rebuild
Expand Down Expand Up @@ -759,8 +757,6 @@ internals.Base = class {

target.$_temp = Object.assign({}, this.$_temp);
target.$_temp.whens = {};
target.$_temp.whenSources = this.$_temp.whenSources && this.$_temp.whenSources.slice();
target.$_temp.whenId = null;

target._ids = this._ids.clone();
target._preferences = this._preferences;
Expand Down Expand Up @@ -808,19 +804,15 @@ internals.Base = class {
_generate(value, state, prefs) {

if (!this.$_terms.whens) {
return this;
return { schema: this };
}

// Prepare base (debug)

const base = internals.debug(this, state);

// Collect matching whens

const whens = [];
const ids = [];
for (let i = 0; i < base.$_terms.whens.length; ++i) {
const when = base.$_terms.whens[i];
for (let i = 0; i < this.$_terms.whens.length; ++i) {
const when = this.$_terms.whens[i];

if (when.concat) {
whens.push(when.concat);
Expand All @@ -839,17 +831,17 @@ internals.Base = class {
if (is.$_match(input, state.nest(is, `${baseId}.is`), prefs)) {
if (then) {
const localState = state.localize([...state.path, `${baseId}.then`], state.ancestors, state.schemas);
const generated = then._generate(value, localState, prefs);
const { schema: generated, id } = then._generate(value, localState, prefs);
whens.push(generated);
ids.push(`${baseId}.then${generated.$_temp.whenId ? `(${generated.$_temp.whenId})` : ''}`);
ids.push(`${baseId}.then${id ? `(${id})` : ''}`);
break;
}
}
else if (otherwise) {
const localState = state.localize([...state.path, `${baseId}.otherwise`], state.ancestors, state.schemas);
const generated = otherwise._generate(value, localState, prefs);
const { schema: generated, id } = otherwise._generate(value, localState, prefs);
whens.push(generated);
ids.push(`${baseId}.otherwise${generated.$_temp.whenId ? `(${generated.$_temp.whenId})` : ''}`);
ids.push(`${baseId}.otherwise${id ? `(${id})` : ''}`);
break;
}
}
Expand All @@ -867,19 +859,20 @@ internals.Base = class {
state.mainstay.tracer.debug(state, 'rule', 'when', id);

if (!id) {
return this;
return { schema: this };
}

if (!state.mainstay.tracer.active &&
this.$_temp.whens[id]) {

return this.$_temp.whens[id];
return { schema: this.$_temp.whens[id], id };
}

let obj = base;
// Generate dynamic schema

let obj = this; // eslint-disable-line consistent-this
if (this._definition.generate) {
obj = this._definition.generate(this, value, state, prefs);
obj = internals.debug(obj, state);
}

// Apply whens
Expand All @@ -888,9 +881,16 @@ internals.Base = class {
obj = obj.concat(when);
}

obj.$_temp.whenId = id;
// Tracing

if (this.$_root._tracer) {
this.$_root._tracer._combine(obj, [this, ...whens]);
}

// Cache result

this.$_temp.whens[id] = obj;
return obj;
return { schema: obj, id };
}

_inner(type, values, options = {}) {
Expand Down Expand Up @@ -1024,34 +1024,3 @@ internals.Base.prototype.preferences = internals.Base.prototype.prefs;


module.exports = new internals.Base();


// Helpers

internals.debug = function (base, state) {

if (base.$_temp.whenSources ||
!state.mainstay.tracer.active) {

return base;
}

const each = (schema) => {

let clone = schema.$_modify({ each, ref: false });
if (clone === schema) {
clone = schema.clone();
}

clone.$_temp.whenSources = [schema];
return clone;
};

let obj = base.$_modify({ each, ref: false });
if (obj === base) {
obj = base.clone();
}

obj.$_temp.whenSources = [base];
return obj;
};
50 changes: 29 additions & 21 deletions lib/trace.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,6 @@ exports.location = function (schema) {
};


exports.debug = function (schema) {

return new internals.Store(schema);
};


internals.Tracer = class {

constructor() {
Expand All @@ -71,6 +65,13 @@ internals.Tracer = class {
return store;
}

_combine(merged, sources) {

for (const { store } of this._schemas.values()) {
store._combine(merged, sources);
}
}

report(file) {

const coverage = [];
Expand All @@ -89,7 +90,7 @@ internals.Tracer = class {
const missing = [];
const skipped = [];

for (const [sub, log] of store._logs) {
for (const [schema, log] of store._sources.entries()) {

// Check if sub schema parent skipped

Expand All @@ -112,7 +113,7 @@ internals.Tracer = class {
// Check values

for (const type of ['valid', 'invalid']) {
const set = sub[`_${type}s`];
const set = schema[`_${type}s`];
if (!set) {
continue;
}
Expand All @@ -136,9 +137,9 @@ internals.Tracer = class {

// Check rules status

const rules = sub._rules.map((rule) => rule.name);
const rules = schema._rules.map((rule) => rule.name);
for (const type of ['default', 'failover']) {
if (sub._flags[type] !== undefined) {
if (schema._flags[type] !== undefined) {
rules.push(type);
}
}
Expand Down Expand Up @@ -177,7 +178,8 @@ internals.Store = class {
constructor(schema) {

this.active = true;
this._logs = new Map();
this._sources = new Map(); // schema -> { paths, entry, rule, valid, invalid }
this._combos = new Map(); // merged -> [sources]
this._scan(schema);
}

Expand Down Expand Up @@ -245,22 +247,23 @@ internals.Store = class {

_record(schema, each) {

if (schema.$_temp.whenSources) {
for (const when of schema.$_temp.whenSources) {
this._record(when, each);
}

const log = this._sources.get(schema);
if (log) {
each(log);
return;
}

each(this._logs.get(schema));
const sources = this._combos.get(schema);
for (const source of sources) {
this._record(source, each);
}
}

_scan(schema, _path) {

const path = _path || [];

let log = this._logs.get(schema);
let log = this._sources.get(schema);
if (!log) {
log = {
paths: new Set(),
Expand All @@ -270,7 +273,7 @@ internals.Store = class {
invalid: new Set()
};

this._logs.set(schema, log);
this._sources.set(schema, log);
}

if (path.length) {
Expand All @@ -279,12 +282,17 @@ internals.Store = class {

const each = (sub, source) => {

const id = internals.id(sub, source);
this._scan(sub, path.concat(id));
const subId = internals.id(sub, source);
this._scan(sub, path.concat(subId));
};

schema.$_modify({ each, ref: false });
}

_combine(merged, sources) {

this._combos.set(merged, sources);
}
};


Expand Down
8 changes: 4 additions & 4 deletions lib/types/link.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ module.exports = Any.extend({

internals.generate = function (schema, value, state, prefs) {

let linked = schema.$_temp.resolved;
let linked = state.mainstay.links.get(schema);
if (linked) {
return linked._generate(value, state, prefs);
return linked._generate(value, state, prefs).schema;
}

const ref = schema.$_terms.link[0].ref;
Expand All @@ -122,10 +122,10 @@ internals.generate = function (schema, value, state, prefs) {
internals.assert(linked.type !== 'link', 'which is another link', ref, schema, state, prefs);

if (!schema._flags.relative) {
schema.$_temp.resolved = linked;
state.mainstay.links.set(schema, linked);
}

return linked._generate(value, state, prefs);
return linked._generate(value, state, prefs).schema;
};


Expand Down
21 changes: 13 additions & 8 deletions lib/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const Reach = require('@hapi/hoek/lib/reach');

const Common = require('./common');
const Errors = require('./errors');
const Trace = require('./trace');


const internals = {
Expand Down Expand Up @@ -120,9 +119,10 @@ internals.entry = function (value, schema, prefs) {

// Prepare state

const tracer = internals.tracer(schema, prefs);
const { tracer, cleanup } = internals.tracer(schema, prefs);
const debug = prefs.debug ? [] : null;
const mainstay = { externals: [], warnings: [], tracer, debug };
const links = schema._ids._schemaChain ? new Map() : null;
const mainstay = { externals: [], warnings: [], tracer, debug, links };
const schemas = schema._ids._schemaChain ? [{ schema }] : null;
const state = new Common.State([], [], { mainstay, schemas });

Expand All @@ -132,30 +132,35 @@ internals.entry = function (value, schema, prefs) {

// Process value and errors

if (cleanup) {
schema.$_root.untrace();
}

const error = Errors.process(result.errors, value, prefs);
return { value: result.value, error, mainstay };
};


internals.tracer = function (schema, prefs) {

Assert(schema.$_root.trace, 'Debug mode not supported');

if (schema.$_root._tracer) {
return schema.$_root._tracer._register(schema);
return { tracer: schema.$_root._tracer._register(schema) };
}

if (prefs.debug) {
Assert(Trace.debug, 'Debug mode not supported');
return Trace.debug(schema);
return { tracer: schema.$_root.trace()._register(schema), cleanup: true };
}

return internals.ignore;
return { tracer: internals.ignore };
};


exports.validate = function (value, schema, state, prefs, overrides = {}) {

if (schema.$_terms.whens) {
schema = schema._generate(value, state, prefs);
schema = schema._generate(value, state, prefs).schema;
}

// Setup state and settings
Expand Down
Loading

0 comments on commit ff0550e

Please sign in to comment.