elliptical-observe-inline
Version:
Dynamic sideways Data Loading for Elliptical
91 lines (77 loc) • 2.93 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = createProcessor;
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function createProcessor(register, processor) {
function observe(source) {
if (processor) {
source = processor(source);
}
return register(source);
}
function process(element) {
const newElement = _lodash2.default.assign({}, element, { observe });
// Don't worry about builtins, or Phrases with a visit
if (_lodash2.default.isString(element.type) || !element.type.describe) {
return newElement;
}
function describeAndTrackObserve() {
const sources = [];
const values = [];
function trackedObserve(source) {
if (processor) {
source = processor(source);
}
const value = register(source);
sources.push(source);
values.push(value);
return value;
}
const description = element.type.describe(_lodash2.default.assign({}, element, { observe: trackedObserve }));
return { description, sources, values };
}
const { description: firstDescription, sources: firstSources, values: firstValues } = describeAndTrackObserve();
let firstRun = true;
// If it never called observe, it never WILL call observe during
// a normal describe. It may with 'dynamic' or a child value,
// but we can't track and optimize that - so we'll just
// pass a naive observe
if (firstSources.length === 0) {
return newElement;
} else {
let oldValues = firstValues;
let oldSources = firstSources;
let oldDescription = firstDescription;
function visit(option, e, traverse) {
let sources, values, description;
if (firstRun) {
sources = firstSources;
values = firstValues;
description = firstDescription;
firstRun = false;
} else {
;({ sources, values, description } = describeAndTrackObserve());
}
if (oldDescription == null && description != null || values.length !== oldValues.length || // perf opt
_lodash2.default.some(_lodash2.default.unzip([values, oldValues]), ([a, b]) => a !== b) || _lodash2.default.some(_lodash2.default.unzip([sources, oldSources]), ([a, b]) => !_lodash2.default.isEqual(a, b))) {
oldValues = values;
oldSources = sources;
oldDescription = description;
}
return traverse(oldDescription, option);
}
const type = _lodash2.default.assign({}, element.type, {
visit,
_oldVisit: element.type.visit,
describe: undefined
});
return _lodash2.default.assign({}, newElement, { type });
}
}
process.observe = observe;
return process;
}