UNPKG

synks

Version:
817 lines (789 loc) 38.7 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var SCOPE = Symbol(); var SCOPE_CHILDREN = Symbol(); var UPDATE_CONTEXT = Symbol(); var Context = /** @class */ (function () { function Context() { var _this = this; var keys = Object.getOwnPropertyNames(Object.getPrototypeOf(this)); keys.forEach(function (key) { var value = _this[key]; if (value instanceof Function) { _this[key] = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var output = value.apply(_this, args); _this[UPDATE_CONTEXT](); return output; }; } }); } Context.prototype[UPDATE_CONTEXT] = function () { }; return Context; }()); function h(type, props) { var children = []; for (var _i = 2; _i < arguments.length; _i++) { children[_i - 2] = arguments[_i]; } var key = props && props.key; return { type: type, props: props, children: children, key: key === undefined ? null : key, }; } /*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } } function arrayUnique(array) { var a = array.slice(); for (var i = 0; i < a.length; ++i) { for (var j = i + 1; j < a.length; ++j) { if (a[i] === a[j]) { a.splice(j--, 1); } } } return a; } function getChildNodes(node) { return Array.prototype.slice.call(node.childNodes); } function build(currentNode, previousNode, container) { if (previousNode === void 0) { previousNode = {}; } return __awaiter(this, void 0, void 0, function () { var underSameParent, p, type; return __generator(this, function (_a) { if (currentNode.target) { return [2 /*return*/, currentNode.target]; } underSameParent = container ? !!getChildNodes(container) .find(function (child) { return child === previousNode.target; }) : false; // Text node if (currentNode.type === '') { p = currentNode.props; if (p === undefined || p === null || typeof p === 'boolean') { currentNode.props = ''; } // Patch text node if (underSameParent && previousNode && previousNode.type === '' && previousNode.target) { // Patch node content if (currentNode.props !== previousNode.props) { previousNode.target.nodeValue = String(currentNode.props); } return [2 /*return*/, previousNode.target]; } // New text node return [2 /*return*/, new Text(String(currentNode.props))]; } if (!underSameParent) { previousNode.props = {}; previousNode.key = null; } // Patch node if (underSameParent && previousNode && previousNode.target && currentNode.type === previousNode.type) { return [2 /*return*/, previousNode.target]; } type = String(currentNode.type); if (currentNode.type === 'svg' || container instanceof SVGElement) { return [2 /*return*/, document.createElementNS('http://www.w3.org/2000/svg', type)]; } // New node return [2 /*return*/, document.createElement(String(type))]; }); }); } function isContext(value) { return !!value && Object.getPrototypeOf(value) === Context; } function handleContext(generator, scope, context, node, contextRoot) { return __awaiter(this, void 0, void 0, function () { var contextName, currentContext; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!isContext(contextRoot)) return [2 /*return*/, contextRoot]; contextName = contextRoot && contextRoot.name; currentContext = context[contextName]; if (!currentContext) { throw new Error(contextName + " was called in <" + node.type.name + "> before it was defined"); } if (currentContext[1].indexOf(scope) === -1) { currentContext[1].push(scope); } return [4 /*yield*/, generator.next(currentContext[0])]; case 1: return [2 /*return*/, (_a.sent()).value]; } }); }); } function isGenerator(value) { return !!value && typeof value.next === 'function' && typeof value.throw === 'function'; } function handleHooks(generator, scope, context, node, hook) { return __awaiter(this, void 0, void 0, function () { var value, contextName, currentContext; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!isGenerator(hook)) return [2 /*return*/, hook]; return [4 /*yield*/, hook.next()]; case 1: value = _a.sent(); _a.label = 2; case 2: if (!(isContext(value.value) || value.value === SCOPE)) return [3 /*break*/, 7]; if (!isContext(value.value)) return [3 /*break*/, 4]; contextName = value.value && value.value.name; currentContext = context[contextName]; if (!currentContext) { throw new Error(contextName + " was called from hook in <" + node.type.name + "> before it was defined"); } if (currentContext[1].indexOf(scope) === -1) { currentContext[1].push(scope); } return [4 /*yield*/, hook.next(currentContext[0])]; case 3: value = _a.sent(); _a.label = 4; case 4: if (!(value.value === SCOPE)) return [3 /*break*/, 6]; return [4 /*yield*/, hook.next(__assign(__assign({}, scope), { next: function () { return __awaiter(this, void 0, void 0, function () { var _a, _b, _c; return __generator(this, function (_d) { switch (_d.label) { case 0: if (!(value !== undefined)) return [3 /*break*/, 2]; _b = (_a = Object).assign; _c = [value]; return [4 /*yield*/, hook.next()]; case 1: _b.apply(_a, _c.concat([_d.sent()])); _d.label = 2; case 2: return [4 /*yield*/, scope.next()]; case 3: return [2 /*return*/, _d.sent()]; } }); }); } }))]; case 5: value = _a.sent(); _a.label = 6; case 6: return [3 /*break*/, 2]; case 7: return [4 /*yield*/, generator.next(value)]; case 8: return [2 /*return*/, (_a.sent()).value]; } }); }); } function handleCustomYields(generator, output, scope, node, context) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, generator.next()]; case 1: output = (_a.sent()).value; _a.label = 2; case 2: if (!(isGenerator(output) || isContext(output))) return [3 /*break*/, 5]; return [4 /*yield*/, handleHooks(generator, scope, context, node, output)]; case 3: output = _a.sent(); return [4 /*yield*/, handleContext(generator, scope, context, node, output)]; case 4: output = _a.sent(); return [3 /*break*/, 2]; case 5: return [2 /*return*/, output]; } }); }); } var PROPS; (function (PROPS) { PROPS["innerHTML"] = "innerHTML"; PROPS["style"] = "style"; })(PROPS || (PROPS = {})); function patchStyle(currentNode, previousNode) { var target = currentNode.target; if (!currentNode.type || (target instanceof Text) || !target) return; var styleA = (currentNode.props || {}).style || {}; var styleB = (previousNode.props || {}).style || {}; Object.keys(styleA).forEach(function (name) { var value = styleA[name]; var oldValue = styleB[name]; if (value === oldValue) return; if (value === null || value === false || value === undefined) { return delete target[name]; } return target.style[name] = String(value); }); if (!previousNode) return; Object.keys(styleB).forEach(function (name) { if (styleA && (styleA[name] !== null && styleA[name] !== false && styleA[name] !== undefined)) return; return delete target.style[name]; }); } function patchProps(currentNode, previousNode) { var target = currentNode.target; if (!currentNode.type || (target instanceof Text) || !target) return; var propsA = currentNode.props || {}; var propsB = previousNode.props || {}; Object.keys(propsA).forEach(function (name) { if (name === PROPS.style) return; var value = propsA[name]; var oldValue = propsB[name]; if (value === oldValue) return; if (value instanceof Function) { if (value === target[name]) return; return (target[name] = value); } else { if (value === null || value === false || value === undefined) { return target.removeAttribute(name); } var newValue = String(value); if (name === PROPS.innerHTML) { return target[name] = newValue; } return target.setAttribute(name, newValue); } }); if (!previousNode) return; Object.keys(propsB).forEach(function (name) { if (name === PROPS.style) return; if (propsA && (propsA[name] !== null && propsA[name] !== false && propsA[name] !== undefined)) return; if (name === PROPS.innerHTML) { return delete target[name]; } return target.removeAttribute(name); }); patchStyle(currentNode, previousNode); } function checkEquality(a, b, keys) { for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { var key = keys_1[_i]; if (typeof a[key] === 'function' && String(a[key]) !== String(b[key])) { return false; } if (JSON.stringify(a[key]) !== JSON.stringify(b[key]) && a[key] !== b[key]) { return false; } } return true; } function quickEqual(a, b) { if (a === b) return true; if (!(a instanceof Object && a)) return false; if (!(b instanceof Object && b)) return false; var ai = Object.keys(a); var bi = Object.keys(b); if (ai.length !== bi.length) return false; return checkEquality(a, b, ai); } function removeNode(node) { if (node instanceof Array) { node.map(removeNode); return; } if (!(node && node.target && node.target.parentNode)) return; node.target.parentNode.removeChild(node.target); if (node.scope) { node.scope.destroy(); } } function removeStranglers(previous) { if (previous instanceof Array) { previous.forEach(function (prev) { var instance = (prev.instance || prev); if (instance.target !== null) { removeNode(prev); } }); } } function asyncMap(value, fn) { return __awaiter(this, void 0, void 0, function () { var output, _a, _b, _i, i, _c, _d; return __generator(this, function (_e) { switch (_e.label) { case 0: output = []; _a = []; for (_b in value) _a.push(_b); _i = 0; _e.label = 1; case 1: if (!(_i < _a.length)) return [3 /*break*/, 4]; i = _a[_i]; _d = (_c = output).push; return [4 /*yield*/, fn(value[i], parseInt(i, 10))]; case 2: _d.apply(_c, [_e.sent()]); _e.label = 3; case 3: _i++; return [3 /*break*/, 1]; case 4: return [2 /*return*/, output]; } }); }); } function renderChildren(currentChildren, previousChildren, container, parentIndex, context) { return __awaiter(this, void 0, void 0, function () { var offset, renderedData; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: offset = parentIndex; return [4 /*yield*/, asyncMap(currentChildren, function (child, index) { return __awaiter(_this, void 0, void 0, function () { var previousNode, renderedData_1, keyElement, output; return __generator(this, function (_a) { switch (_a.label) { case 0: previousNode = previousChildren && previousChildren[index]; if (!(child instanceof Array)) return [3 /*break*/, 2]; return [4 /*yield*/, renderChildren(child, previousNode, container, offset + parseInt(index, 10), context)]; case 1: renderedData_1 = _a.sent(); removeStranglers(previousNode); offset += Math.max([].concat.apply([], renderedData_1).length - 1, 0); return [2 /*return*/, renderedData_1]; case 2: // Handle keyed children if (child && child.key !== null && child.key !== undefined && previousNode && previousChildren instanceof Array) { if (previousNode.key === child.key) { child.target = previousNode.target; previousNode.target = null; patchProps(child, previousNode); return [2 /*return*/, child]; } keyElement = previousChildren.find(function (p) { return p.key === child.key; }); if (previousNode.key !== child.key && keyElement) { child.target = keyElement.target; keyElement.target = null; } } return [4 /*yield*/, render(child, previousNode, container, parseInt(index, 10) + offset, context)]; case 3: output = _a.sent(); if (output instanceof Array) { offset += Math.max([].concat.apply([], output).length - 1, 0); } if (!(output instanceof Array) && output.instance instanceof Array) { offset += Math.max([].concat.apply([], output.instance).length - 1, 0); } return [2 /*return*/, output]; } }); }); })]; case 1: renderedData = _a.sent(); removeStranglers(previousChildren); return [2 /*return*/, renderedData]; } }); }); } function isVnode(value) { return value && value instanceof Object; } function transformNode(node) { if (node instanceof Array) { return Object.assign(node, node.map(transformNode)); } if (isVnode(node)) { if (node.children instanceof Array) { node.children = node.children.map(transformNode); } return Object.assign(node, { type: node.type, props: node.props, key: node.key === undefined ? null : node.key, children: node.children, target: null, instance: null, scope: null, }); } return { type: '', props: node, key: null, children: undefined, }; } var updateQueue = []; var cleanupQueue = []; function startCleanup() { var cleanup = cleanupQueue.slice(); cleanupQueue = []; cleanup.forEach(function (d) { return d(); }); } function render(currentNode, previousNode, container, childIndex, context) { if (previousNode === void 0) { previousNode = currentNode && currentNode.constructor(); } return __awaiter(this, void 0, void 0, function () { var prevNodes, cachedTarget_1, fn_1, currentContext_1, name_1, events_1, nextFn_1, props1, props2, key1, key2, output_1, originalProps_1, scope_1, newContext_1, generator_1, renderSelf_1, isKeyMoved, _a; var _b; var _this = this; return __generator(this, function (_c) { switch (_c.label) { case 0: if (currentNode === undefined || currentNode === null) { return [2 /*return*/, transformNode()]; } if (!(currentNode instanceof Array)) return [3 /*break*/, 2]; prevNodes = previousNode instanceof Array ? previousNode : [previousNode]; return [4 /*yield*/, renderChildren(currentNode.map(transformNode), prevNodes, container, childIndex, context)]; case 1: return [2 /*return*/, _c.sent()]; case 2: currentNode = transformNode(currentNode); if (!(previousNode && previousNode.type instanceof Function && currentNode && currentNode.type !== previousNode.type)) return [3 /*break*/, 5]; cachedTarget_1 = previousNode && Object.assign({}, previousNode.instance); if (!previousNode.scope) return [3 /*break*/, 4]; return [4 /*yield*/, previousNode.scope.destroy()]; case 3: _c.sent(); _c.label = 4; case 4: if (cachedTarget_1) { cleanupQueue.push(function () { removeNode(cachedTarget_1); }); } _c.label = 5; case 5: if (!(currentNode.type instanceof Function)) return [3 /*break*/, 9]; fn_1 = currentNode.type; if (!isContext(fn_1)) return [3 /*break*/, 7]; currentContext_1 = new fn_1(currentNode.props); name_1 = fn_1.name; events_1 = []; nextFn_1 = function (newContext) { return __awaiter(_this, void 0, void 0, function () { var cache, _i, cache_1, event_1; return __generator(this, function (_a) { switch (_a.label) { case 0: updateQueue = arrayUnique(events_1.concat(updateQueue)); // Update context state Object.assign(currentContext_1, newContext); cache = updateQueue.slice().filter(function (d) { return d.mounted && !d.rendering; }); updateQueue = []; _i = 0, cache_1 = cache; _a.label = 1; case 1: if (!(_i < cache_1.length)) return [3 /*break*/, 4]; event_1 = cache_1[_i]; if (!(event_1.mounted && !event_1.rendering)) return [3 /*break*/, 3]; return [4 /*yield*/, event_1.next()]; case 2: _a.sent(); _a.label = 3; case 3: _i++; return [3 /*break*/, 1]; case 4: return [2 /*return*/]; } }); }); }; currentContext_1[UPDATE_CONTEXT] = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, nextFn_1.call(currentContext_1)]; case 1: return [2 /*return*/, _a.sent()]; } }); }); }; context[name_1] = [currentContext_1, events_1]; return [4 /*yield*/, render(currentNode.children, previousNode.children, container, childIndex, context)]; case 6: // Render children return [2 /*return*/, _c.sent()]; case 7: // Component update if (currentNode.type === previousNode.type && !!previousNode.instance) { props1 = Object.assign({}, currentNode.props, { children: currentNode.children, }); props2 = Object.assign({}, previousNode.props, { children: previousNode.children, }); key1 = currentNode.key; key2 = previousNode.key; // Don't update component as props are the same (in shallow level) if (quickEqual(props1, props2) || (key1 !== null && key1 === key2)) { return [2 /*return*/, Object.assign(currentNode, previousNode)]; } } originalProps_1 = Object.assign({}, currentNode.props, { children: currentNode.children, }); scope_1 = (_b = { mounted: true, rendering: false }, _b[SCOPE_CHILDREN] = [], _b.onMount = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/]; }); }); }, _b.onDestroy = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/]; }); }); }, _b.next = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: if (!scope_1.mounted || scope_1.rendering) { return [2 /*return*/]; } return [4 /*yield*/, this.nextProps(originalProps_1)]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }, _b.nextProps = function (props) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: if (!scope_1.mounted || scope_1.rendering) { return [2 /*return*/]; } scope_1.rendering = true; // eslint-disable-next-line @typescript-eslint/no-use-before-define return [4 /*yield*/, renderSelf_1(currentNode.instance, props)]; case 1: // eslint-disable-next-line @typescript-eslint/no-use-before-define _a.sent(); scope_1.rendering = false; return [2 /*return*/]; } }); }); }, _b.destroy = function () { return __awaiter(this, void 0, void 0, function () { var parentScopes; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!scope_1.mounted) { return [2 /*return*/]; } scope_1.mounted = false; return [4 /*yield*/, scope_1.onDestroy()]; case 1: _a.sent(); scope_1[SCOPE_CHILDREN].forEach(function (s) { s.destroy(); }); scope_1[SCOPE_CHILDREN] = []; parentScopes = context.scope && context.scope[SCOPE_CHILDREN]; if (parentScopes) { context.scope[SCOPE_CHILDREN] = parentScopes.filter(function (s) { return s.mounted; }); } return [2 /*return*/]; } }); }); }, _b); if (context.scope) { context.scope[SCOPE_CHILDREN].push(scope_1); } newContext_1 = Object.assign({}, context, { scope: scope_1, }); currentNode.scope = scope_1; renderSelf_1 = function (previousTree, props) { return __awaiter(_this, void 0, void 0, function () { var rendered; return __generator(this, function (_a) { switch (_a.label) { case 0: Object.assign(originalProps_1, props); if (!(typeof fn_1 === 'function')) return [3 /*break*/, 3]; return [4 /*yield*/, fn_1.call(scope_1, props)]; case 1: output_1 = _a.sent(); if (!isGenerator(output_1)) return [3 /*break*/, 3]; if (!generator_1) { generator_1 = output_1; } return [4 /*yield*/, handleCustomYields(generator_1, output_1, scope_1, currentNode, context)]; case 2: output_1 = _a.sent(); _a.label = 3; case 3: return [4 /*yield*/, render(output_1, previousTree, container, childIndex, newContext_1)]; case 4: rendered = _a.sent(); startCleanup(); if (!(currentNode instanceof Array)) { currentNode.instance = output_1; } Object.assign(previousNode, currentNode); if (previousTree) { Object.assign(previousTree, rendered); } previousNode.target = null; return [2 /*return*/, rendered]; } }); }); }; return [4 /*yield*/, renderSelf_1(previousNode, originalProps_1)]; case 8: _c.sent(); scope_1.onMount(); return [2 /*return*/, currentNode]; case 9: isKeyMoved = currentNode.target && previousNode.key !== undefined && previousNode.key !== null; _a = currentNode; return [4 /*yield*/, build(currentNode, previousNode, container)]; case 10: _a.target = _c.sent(); // Patch props patchProps(currentNode, previousNode); if (isKeyMoved) { container.insertBefore(currentNode.target, container.childNodes[childIndex + 1]); return [2 /*return*/, currentNode]; } if (currentNode.target === previousNode.target || (previousNode.instance && previousNode.target === container)) { previousNode.target = null; } if (!(currentNode.children instanceof Array)) return [3 /*break*/, 12]; return [4 /*yield*/, renderChildren(currentNode.children, previousNode.children, currentNode.target, 0, context)]; case 11: _c.sent(); _c.label = 12; case 12: // Remove stranglers if (previousNode.target && previousNode.target.parentNode && previousNode.target !== currentNode.target && previousNode.target !== container) { removeNode(previousNode); } if (previousNode && previousNode.children) { removeStranglers(previousNode.children); } // Add element to dom if (!currentNode.target.parentNode) { container.insertBefore(currentNode.target, container.childNodes[childIndex]); } return [2 /*return*/, currentNode]; } }); }); } function mount(node, container, previousNode) { if (container === void 0) { container = document.body; } if (previousNode === void 0) { previousNode = node.constructor(); } return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: if (!(container instanceof HTMLElement)) { throw new Error('[Synks] Container should be valid HTMLElement'); } if (!(node instanceof Array)) { node = [node]; } return [4 /*yield*/, render(node, previousNode, container, 0, {})]; case 1: return [2 /*return*/, _a.sent()]; } }); }); } exports.Context = Context; exports.SCOPE = SCOPE; exports.h = h; exports.mount = mount;