UNPKG

dash-renderer

Version:

render dash components in react

252 lines (238 loc) 20.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _ramda = require("ramda"); var _callbacks = require("../actions/callbacks"); var _dependencies = require("../actions/dependencies"); var _dependencies_ts = require("../actions/dependencies_ts"); var _wait = _interopRequireDefault(require("./../utils/wait")); var _callbacks2 = require("../utils/callbacks"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _regeneratorValues(e) { if (null != e) { var t = e["function" == typeof Symbol && Symbol.iterator || "@@iterator"], r = 0; if (t) return t.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) return { next: function next() { return e && r >= e.length && (e = void 0), { value: e && e[r++], done: !e }; } }; } throw new TypeError(typeof e + " is not iterable"); } function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); } function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); } function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; } var observer = { observer: function () { var _observer = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(_ref) { var dispatch, getState, _getState, callbacks, _getState$callbacks, prioritized, blocked, executing, watched, stored, paths, graphs, _getState2, requested, initialRequested, pendingCallbacks, rCirculars, rDuplicates, rMergedDuplicates, pDuplicates, bDuplicates, eDuplicates, wDuplicates, _pruneCallbacks, rAdded, rRemoved, _pruneCallbacks2, pAdded, pRemoved, _pruneCallbacks3, bAdded, bRemoved, _pruneCallbacks4, eAdded, eRemoved, _pruneCallbacks5, wAdded, wRemoved, readyCallbacks, oldBlocked, newBlocked, candidates, _loop, pendingGroups, dropped, added, removed; return _regenerator().w(function (_context2) { while (1) switch (_context2.n) { case 0: dispatch = _ref.dispatch, getState = _ref.getState; _context2.n = 1; return (0, _wait.default)(0); case 1: _getState = getState(), callbacks = _getState.callbacks, _getState$callbacks = _getState.callbacks, prioritized = _getState$callbacks.prioritized, blocked = _getState$callbacks.blocked, executing = _getState$callbacks.executing, watched = _getState$callbacks.watched, stored = _getState$callbacks.stored, paths = _getState.paths, graphs = _getState.graphs; _getState2 = getState(), requested = _getState2.callbacks.requested; initialRequested = requested.slice(0); pendingCallbacks = (0, _callbacks2.getPendingCallbacks)(callbacks); /* 0. Prune circular callbacks that have completed the loop - cb.callback included in cb.predecessors */ rCirculars = (0, _ramda.filter)(cb => { var _cb$predecessors; return (0, _ramda.includes)(cb.callback, (_cb$predecessors = cb.predecessors) !== null && _cb$predecessors !== void 0 ? _cb$predecessors : []); }, requested); /* TODO? Clean up the `requested` list - during the dispatch phase, circulars will be removed for real */ requested = (0, _ramda.difference)(requested, rCirculars); /* 1. Remove duplicated `requested` callbacks - give precedence to newer callbacks over older ones */ rDuplicates = []; rMergedDuplicates = []; (0, _ramda.values)((0, _ramda.groupBy)(_dependencies_ts.getUniqueIdentifier, requested)).forEach(group => { if (group.length === 1) { // keep callback if its the only one of its kind rMergedDuplicates.push(group[0]); } else { var initial = group.find(cb => cb.initialCall); if (initial) { // drop the initial callback if it's not alone rDuplicates.push(initial); } var groupWithoutInitial = group.filter(cb => cb !== initial); if (groupWithoutInitial.length === 1) { // if there's only one callback beside the initial one, keep that callback rMergedDuplicates.push(groupWithoutInitial[0]); } else { // otherwise merge all remaining callbacks together rDuplicates = (0, _ramda.concat)(rDuplicates, groupWithoutInitial); rMergedDuplicates.push((0, _ramda.mergeLeft)({ changedPropIds: (0, _ramda.reduce)((0, _ramda.mergeWith)(Math.max), {}, (0, _ramda.pluck)('changedPropIds', groupWithoutInitial)), executionGroup: (0, _ramda.filter)(exg => Boolean(exg), (0, _ramda.pluck)('executionGroup', groupWithoutInitial)).slice(-1)[0] }, groupWithoutInitial.slice(-1)[0])); } } }); /* TODO? Clean up the `requested` list - during the dispatch phase, duplicates will be removed for real */ requested = rMergedDuplicates; /* 2. Remove duplicated `prioritized`, `executing` and `watching` callbacks */ /* Extract all but the first callback from each IOS-key group these callbacks are `prioritized` and duplicates. */ pDuplicates = (0, _ramda.flatten)((0, _ramda.map)(group => group.slice(0, -1), (0, _ramda.values)((0, _ramda.groupBy)(_dependencies_ts.getUniqueIdentifier, (0, _ramda.concat)(prioritized, requested))))); bDuplicates = (0, _ramda.flatten)((0, _ramda.map)(group => group.slice(0, -1), (0, _ramda.values)((0, _ramda.groupBy)(_dependencies_ts.getUniqueIdentifier, (0, _ramda.concat)(blocked, requested))))); eDuplicates = (0, _ramda.flatten)((0, _ramda.map)(group => group.slice(0, -1), (0, _ramda.values)((0, _ramda.groupBy)(_dependencies_ts.getUniqueIdentifier, (0, _ramda.concat)(executing, requested))))); wDuplicates = (0, _ramda.flatten)((0, _ramda.map)(group => group.slice(0, -1), (0, _ramda.values)((0, _ramda.groupBy)(_dependencies_ts.getUniqueIdentifier, (0, _ramda.concat)(watched, requested))))); /* 3. Modify or remove callbacks that are outputting to non-existing layout `id`. */ _pruneCallbacks = (0, _dependencies_ts.pruneCallbacks)(requested, paths), rAdded = _pruneCallbacks.added, rRemoved = _pruneCallbacks.removed; _pruneCallbacks2 = (0, _dependencies_ts.pruneCallbacks)(prioritized, paths), pAdded = _pruneCallbacks2.added, pRemoved = _pruneCallbacks2.removed; _pruneCallbacks3 = (0, _dependencies_ts.pruneCallbacks)(blocked, paths), bAdded = _pruneCallbacks3.added, bRemoved = _pruneCallbacks3.removed; _pruneCallbacks4 = (0, _dependencies_ts.pruneCallbacks)(executing, paths), eAdded = _pruneCallbacks4.added, eRemoved = _pruneCallbacks4.removed; _pruneCallbacks5 = (0, _dependencies_ts.pruneCallbacks)(watched, paths), wAdded = _pruneCallbacks5.added, wRemoved = _pruneCallbacks5.removed; /* TODO? Clean up the `requested` list - during the dispatch phase, it will be updated for real */ requested = (0, _ramda.concat)((0, _ramda.difference)(requested, rRemoved), rAdded); /* 4. Find `requested` callbacks that do not depend on a outstanding output (as either input or state) */ readyCallbacks = (0, _dependencies_ts.getReadyCallbacks)(paths, requested, pendingCallbacks, graphs); oldBlocked = []; newBlocked = []; /** * If there is : * - no ready callbacks * - at least one requested callback * - no additional pending callbacks * * can assume: * - the requested callbacks are part of a circular dependency loop * * then recursively: * - assume the first callback in the list is ready (the entry point for the loop) * - check what callbacks are blocked / ready with the assumption * - update the missing predecessors based on assumptions * - continue until there are no remaining candidates * */ if (!(!readyCallbacks.length && requested.length && requested.length === pendingCallbacks.length)) { _context2.n = 4; break; } candidates = requested.slice(0); _loop = /*#__PURE__*/_regenerator().m(function _loop() { var readyCallback, blockedByAssumptions, modified; return _regenerator().w(function (_context) { while (1) switch (_context.n) { case 0: // Assume 1st callback is ready and // update candidates / readyCallbacks accordingly readyCallback = candidates[0]; readyCallbacks.push(readyCallback); candidates = candidates.slice(1); // Remaining candidates are not blocked by current assumptions candidates = (0, _dependencies_ts.getReadyCallbacks)(paths, candidates, readyCallbacks); // Blocked requests need to make sure they have the callback as a predecessor blockedByAssumptions = (0, _ramda.difference)(candidates, candidates); modified = (0, _ramda.filter)(cb => !cb.predecessors || !(0, _ramda.includes)(readyCallback.callback, cb.predecessors), blockedByAssumptions); oldBlocked = (0, _ramda.concat)(oldBlocked, modified); newBlocked = (0, _ramda.concat)(newBlocked, modified.map(cb => { var _cb$predecessors2; return _objectSpread(_objectSpread({}, cb), {}, { predecessors: (0, _ramda.concat)((_cb$predecessors2 = cb.predecessors) !== null && _cb$predecessors2 !== void 0 ? _cb$predecessors2 : [], [readyCallback.callback]) }); })); case 1: return _context.a(2); } }, _loop); }); case 2: if (!candidates.length) { _context2.n = 4; break; } return _context2.d(_regeneratorValues(_loop()), 3); case 3: _context2.n = 2; break; case 4: /* TODO? Clean up the `requested` list - during the dispatch phase, it will be updated for real */ requested = (0, _ramda.concat)((0, _ramda.difference)(requested, oldBlocked), newBlocked); /* 5. Prune callbacks that became irrelevant in their `executionGroup` */ // Group by executionGroup, drop non-executionGroup callbacks // those were not triggered by layout changes and don't have "strong" interdependency for // callback chain completion pendingGroups = (0, _ramda.groupBy)(cb => cb.executionGroup, (0, _ramda.filter)(cb => !(0, _ramda.isNil)(cb.executionGroup), stored)); dropped = (0, _ramda.filter)(cb => { // If there is no `stored` callback for the group, no outputs were dropped -> `cb` is kept if (!cb.executionGroup || !pendingGroups[cb.executionGroup] || !pendingGroups[cb.executionGroup].length) { return false; } // Get all inputs for `cb` var inputs = (0, _ramda.map)(_dependencies_ts.combineIdAndProp, (0, _ramda.flatten)(cb.getInputs(paths))); // Get all the potentially updated props for the group so far var allProps = (0, _ramda.flatten)((0, _ramda.map)(gcb => gcb.executionMeta.allProps, pendingGroups[cb.executionGroup])); // Get all the updated props for the group so far var updated = (0, _ramda.flatten)((0, _ramda.map)(gcb => gcb.executionMeta.updatedProps, pendingGroups[cb.executionGroup])); // If there's no overlap between the updated props and the inputs, // + there's no props that aren't covered by the potentially updated props, // and not all inputs are multi valued // -> drop `cb` var res = (0, _ramda.isEmpty)((0, _ramda.intersection)(inputs, updated)) && (0, _ramda.isEmpty)((0, _ramda.difference)(inputs, allProps)) && !(0, _ramda.all)(_dependencies.isMultiValued, cb.callback.inputs); return res; }, readyCallbacks); /* TODO? Clean up the `requested` list - during the dispatch phase, it will be updated for real */ requested = (0, _ramda.difference)(requested, dropped); readyCallbacks = (0, _ramda.difference)(readyCallbacks, dropped); requested = (0, _ramda.difference)(requested, readyCallbacks); added = (0, _ramda.difference)(requested, initialRequested); removed = (0, _ramda.difference)(initialRequested, requested); dispatch((0, _callbacks.aggregateCallbacks)([ // Clean up requested callbacks added.length ? (0, _callbacks.addRequestedCallbacks)(added) : null, removed.length ? (0, _callbacks.removeRequestedCallbacks)(removed) : null, // Clean up duplicated callbacks pDuplicates.length ? (0, _callbacks.removePrioritizedCallbacks)(pDuplicates) : null, bDuplicates.length ? (0, _callbacks.removeBlockedCallbacks)(bDuplicates) : null, eDuplicates.length ? (0, _callbacks.removeExecutingCallbacks)(eDuplicates) : null, wDuplicates.length ? (0, _callbacks.removeWatchedCallbacks)(wDuplicates) : null, // Prune callbacks pRemoved.length ? (0, _callbacks.removePrioritizedCallbacks)(pRemoved) : null, pAdded.length ? (0, _callbacks.addPrioritizedCallbacks)(pAdded) : null, bRemoved.length ? (0, _callbacks.removeBlockedCallbacks)(bRemoved) : null, bAdded.length ? (0, _callbacks.addBlockedCallbacks)(bAdded) : null, eRemoved.length ? (0, _callbacks.removeExecutingCallbacks)(eRemoved) : null, eAdded.length ? (0, _callbacks.addExecutingCallbacks)(eAdded) : null, wRemoved.length ? (0, _callbacks.removeWatchedCallbacks)(wRemoved) : null, wAdded.length ? (0, _callbacks.addWatchedCallbacks)(wAdded) : null, // Promote callbacks readyCallbacks.length ? (0, _callbacks.addPrioritizedCallbacks)(readyCallbacks) : null])); case 5: return _context2.a(2); } }, _callee); })); function observer(_x) { return _observer.apply(this, arguments); } return observer; }(), inputs: ['callbacks.requested', 'callbacks.completed'] }; var _default = exports.default = observer;