Skip to content

Commit d0b1445

Browse files
committed
Improved cache
1 parent 6377383 commit d0b1445

6 files changed

Lines changed: 40 additions & 32 deletions

File tree

esm/creator.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { PersistentFragment } from './persistent-fragment.js';
2-
import { detail } from './literals.js';
2+
import { detail, resolved } from './literals.js';
33
import { array, hole } from './handler.js';
44
import { empty } from './utils.js';
55
import { cache } from './literals.js';
@@ -26,14 +26,14 @@ export default parse => (
2626
const { p: path, u: update, n: name } = entries[i];
2727
const node = path === prev ? current : (current = find(root, (prev = path)));
2828
details[i] = detail(empty, update, node, name);
29-
stack[i] = update === array ? cache([]) : (update === hole ? cache(empty) : null);
29+
stack[i] = update === array ? [] : (update === hole ? cache() : null);
3030
}
3131
}
32-
return {
33-
t: template,
34-
n: direct ? root.firstChild : new PersistentFragment(root),
35-
d: details,
36-
s: stack,
37-
};
32+
return resolved(
33+
template,
34+
direct ? root.firstChild : new PersistentFragment(root),
35+
details,
36+
stack,
37+
);
3838
}
3939
);

esm/keyed.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { Hole } from './rabbit.js';
33
import { attr } from './handler.js';
44
import { cache } from './literals.js';
5-
import { empty, set } from './utils.js';
5+
import { set } from './utils.js';
66
import { html, svg } from './index.js';
77

88
import render from './render/keyed.js';
@@ -28,7 +28,7 @@ const createRef = svg => /** @type {Bound} */ (ref, key) => {
2828
}
2929

3030
const memo = keyed.get(ref) || set(keyed, ref, new Map);
31-
return memo.get(key) || set(memo, key, tag.bind(cache(empty)));
31+
return memo.get(key) || set(memo, key, tag.bind(cache()));
3232
};
3333

3434
/** @type {Bound} Returns a bound tag to render HTML content. */

esm/literals.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@ export const cel = (f, e, d) => ({ f, e, d });
2828
* @param {function} u the callback to update the value
2929
* @param {Node} t the target comment node or element
3030
* @param {string | null} n the attribute name, if any, or `null`
31+
* @param {Cache | null} c the cache value for this detail
3132
* @returns {Detail}
3233
*/
33-
export const detail = (v, u, t, n) => ({ v, u, t, n });
34+
export const detail = (v, u, t, n, c) => ({ v, u, t, n, c });
3435

3536
/**
3637
* @typedef {Object} Entry
@@ -56,10 +57,18 @@ export const entry = (p, u, n) => ({ p, u, n });
5657
*/
5758

5859
/**
59-
* @param {Cache[]} s the cache stack
6060
* @returns {Cache}
6161
*/
62-
export const cache = s => ({ t: null, n: null, d: empty, s });
62+
export const cache = () => resolved(null, null, empty, empty);
63+
64+
/**
65+
* @property {null | TemplateStringsArray} t the cached template
66+
* @property {null | Node | PersistentFragment} n the node returned when parsing the template
67+
* @property {Detail[]} d the list of updates to perform
68+
* @property {Cache[]} s the stack of caches per each interpolation / hole
69+
* @returns {Cache}
70+
*/
71+
export const resolved = (t, n, d, s) => ({ t, n, d, s });
6372

6473
/**
6574
* @typedef {Object} Parsed

esm/rabbit.js

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { array, hole } from './handler.js';
2-
import { cache as newCache } from './literals.js';
3-
import { empty } from './utils.js';
2+
import { cache } from './literals.js';
43
import create from './creator.js';
54
import parser from './parser.js';
65

@@ -10,14 +9,14 @@ const parseHTML = create(parser(false));
109
const parseSVG = create(parser(true));
1110

1211
/**
13-
* @param {import("./literals.js").Cache} cache
12+
* @param {import("./literals.js").Cache} info
1413
* @param {Hole} hole
1514
* @returns {Node}
1615
*/
17-
const unroll = (cache, { s, t, v }) => {
18-
if (cache.t !== t)
19-
assign(cache, (s ? parseSVG : parseHTML)(t, v));
20-
for (let { d, s } = cache, i = 0; i < d.length; i++) {
16+
const unroll = (info, { s, t, v }) => {
17+
if (info.t !== t)
18+
assign(info, (s ? parseSVG : parseHTML)(t, v));
19+
for (let { d, s } = info, i = 0; i < d.length; i++) {
2120
const value = v[i];
2221
const detail = d[i];
2322
const { v: previous, u: update, t: target, n: name } = detail;
@@ -31,7 +30,7 @@ const unroll = (cache, { s, t, v }) => {
3130
break;
3231
case hole:
3332
const current = value instanceof Hole ?
34-
unroll(s[i] || (s[i] = newCache(empty)), value) :
33+
unroll(s[i] || (s[i] = cache()), value) :
3534
(s[i] = null, value)
3635
;
3736
if (current !== previous)
@@ -43,22 +42,22 @@ const unroll = (cache, { s, t, v }) => {
4342
break;
4443
}
4544
}
46-
return cache.n;
45+
return info.n;
4746
};
4847

4948
/**
5049
* @param {Cache} cache
5150
* @param {any[]} values
5251
* @returns {number}
5352
*/
54-
const unrollValues = ({ s: stack }, values) => {
53+
const unrollValues = (stack, values) => {
5554
let i = 0, { length } = values;
5655
if (length < stack.length) stack.splice(length);
5756
for (; i < length; i++) {
5857
const value = values[i];
59-
const asHole = value instanceof Hole;
60-
const cache = stack[i] || (stack[i] = asHole ? newCache(empty) : null);
61-
if (asHole) values[i] = unroll(cache, value);
58+
if (value instanceof Hole)
59+
values[i] = unroll(stack[i] || (stack[i] = cache()), value);
60+
else stack[i] = null;
6261
}
6362
return values;
6463
};
@@ -76,7 +75,7 @@ export class Hole {
7675
this.t = template;
7776
this.v = values;
7877
}
79-
toDOM(cache = newCache(empty)) {
80-
return unroll(cache, this);
78+
toDOM(info = cache()) {
79+
return unroll(info, this);
8180
}
8281
};

esm/render/hole.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { cache } from '../literals.js';
2-
import { empty, set } from '../utils.js';
2+
import { set } from '../utils.js';
33

44
/** @typedef {import("../rabbit.js").Hole} Hole */
55

@@ -14,7 +14,7 @@ const known = new WeakMap;
1414
* @returns
1515
*/
1616
export default (where, what) => {
17-
const info = known.get(where) || set(known, where, cache(empty));
17+
const info = known.get(where) || set(known, where, cache());
1818
if (info.n !== (typeof what === 'function' ? what() : what).toDOM(info))
1919
where.replaceChildren(info.n.valueOf());
2020
return where;

esm/render/shared.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Hole } from '../rabbit.js';
22
import { cache } from '../literals.js';
3-
import { empty, set } from '../utils.js';
3+
import { set } from '../utils.js';
44

55
/** @type {WeakMap<Element | DocumentFragment, import("../literals.js").Cache>} */
66
const known = new WeakMap;
@@ -13,7 +13,7 @@ const known = new WeakMap;
1313
* @returns
1414
*/
1515
export default (where, what, check) => {
16-
const info = known.get(where) || set(known, where, cache(empty));
16+
const info = known.get(where) || set(known, where, cache());
1717
const hole = (check && typeof what === 'function') ? what() : what;
1818
const { n } = info;
1919
const node = hole instanceof Hole ? hole.toDOM(info) : hole;

0 commit comments

Comments
 (0)