From 784bb7390c19b4f5e8288b2d4043f22ba9bb74e5 Mon Sep 17 00:00:00 2001 From: Ryan Carniato Date: Fri, 14 Jun 2019 22:24:49 -0700 Subject: [PATCH] simplify when flows --- dom-expressions.config.js | 7 ++++- package-lock.json | 8 ++--- package.json | 4 +-- template/runtime.ejs | 63 +++++++++++++-------------------------- 4 files changed, 32 insertions(+), 50 deletions(-) diff --git a/dom-expressions.config.js b/dom-expressions.config.js index 87eef140..931c3759 100644 --- a/dom-expressions.config.js +++ b/dom-expressions.config.js @@ -3,9 +3,14 @@ module.exports = { variables: { imports: [ `import { comp as wrap, sample, root, cleanup, getContextOwner as currentContext, - setContext, makeDataNode + setContext, makeDataNode, value } from '@ryansolid/s-js'` ], declarations: { + memo: `(fn) => { + const s = value(fn()); + wrap(() => s(fn())); + return s; + }`, SuspenseContext: `{ id: 'suspense', initFn: () => { let counter = 0; diff --git a/package-lock.json b/package-lock.json index 4c6471e7..23f58ada 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "dom-expressions", - "version": "0.9.10", + "version": "0.10.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1260,9 +1260,9 @@ } }, "babel-plugin-jsx-dom-expressions": { - "version": "0.9.13", - "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.9.13.tgz", - "integrity": "sha512-424IzP5GnS4ndqiA4KZ6qHai7OKUsGjNGuA7ypuT2qr9YePc53OK2okDP9TIxCHXI56edu+rKe5R/GXt6cGI7Q==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.10.0.tgz", + "integrity": "sha512-qbfoW1sYsLlVtp46z4iODDsWESibcPqQzYFH1+Uv5N7IIQt1oQI6q3VDIfzRdz8zB0ozXhDSzq1E3r9kqS+p7w==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", diff --git a/package.json b/package.json index 3399686c..a6292ecd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "dom-expressions", "description": "A Fine-Grained Runtime for Performant DOM Rendering", - "version": "0.9.10", + "version": "0.10.0", "author": "Ryan Carniato", "license": "MIT", "repository": { @@ -24,7 +24,7 @@ "devDependencies": { "@babel/core": "7.4.5", "@babel/preset-env": "^7.4.5", - "babel-plugin-jsx-dom-expressions": "0.9.13", + "babel-plugin-jsx-dom-expressions": "0.10.0", "coveralls": "3.0.4", "jest": "24.8.0", "@ryansolid/s-js": "~0.4.14" diff --git a/template/runtime.ejs b/template/runtime.ejs index 5cbf9437..58dc0af2 100644 --- a/template/runtime.ejs +++ b/template/runtime.ejs @@ -250,74 +250,51 @@ export function spread(node, accessor) { export function when(parent, accessor, expr, options, marker) { let beforeNode, current, disposable; - const { afterRender, fallback } = options; + const { afterRender, fallback } = options, + condition = memo(accessor); if (marker !== undefined) beforeNode = marker ? marker.previousSibling : parent.lastChild; - cleanup(function dispose() { disposable && disposable(); }); - - wrap(cached => { - const value = accessor(); - if (value === cached) return cached; - return sample(() => { + wrap(() => { + const value = condition(); + sample(() => { parent = (marker && marker.parentNode) || (beforeNode && beforeNode.parentNode) || parent; - disposable && disposable(); clearAll(parent, current, marker, beforeNode && beforeNode.nextSibling); current = null; if (value == null || value === false) { afterRender && afterRender(current, marker); if (fallback) { - root(disposer => { - disposable = disposer; - addNode(parent, fallback(), marker, ++groupCounter, node => current = node); - }); + addNode(parent, fallback(), marker, ++groupCounter, node => current = node); } - } else { - root(disposer => { - disposable = disposer; - addNode(parent, expr(value), marker, ++groupCounter, node => current = node, afterRender && afterRender(node, marker)); - }); - } - return value; + } else addNode(parent, expr(value), marker, ++groupCounter, node => (current = node, afterRender && afterRender(node, marker))); }); }); } export function switchWhen(parent, conditions, _, options, marker) { let beforeNode, current, disposable; - const { fallback } = options; + const { fallback } = options, + evalConditions = memo(() => { + for (let i = 0; i < conditions.length; i++) { + if (conditions[i].condition()) return i; + } + return -1; + }); if (marker !== undefined) beforeNode = marker ? marker.previousSibling : parent.lastChild; - function evalConditions() { - for (let i = 0; i < conditions.length; i++) { - if (conditions[i].condition()) return {index: i, render: conditions[i].render, afterRender: conditions[i].options && conditions[i].options.afterRender}; - } - return {index: -1}; - } - cleanup(function dispose() { disposable && disposable(); }); - - wrap(cached => { - const {index, render, afterRender} = evalConditions(); - if (index === cached) return cached; - return sample(() => { + wrap(() => { + const index = evalConditions(); + sample(() => { parent = (marker && marker.parentNode) || (beforeNode && beforeNode.parentNode) || parent; - disposable && disposable(); clearAll(parent, current, marker, beforeNode && beforeNode.nextSibling); current = null; if (index < 0) { - afterRender && afterRender(null, marker); if (fallback) { - root(disposer => { - disposable = disposer; - addNode(parent, fallback(), marker, ++groupCounter, node => current = node); - }); + addNode(parent, fallback(), marker, ++groupCounter, node => current = node); } } else { - root(disposer => { - disposable = disposer; - addNode(parent, render(), marker, ++groupCounter, node => current = node, afterRender && afterRender(node, marker)); - }); + const afterRender = conditions[index].options && conditions[index].options.afterRender; + addNode(parent, conditions[index].render(), marker, ++groupCounter, node => current = node, afterRender && afterRender(node, marker)); } - return index; }); }); }