@gyral/core 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -0
- package/README.md +7 -5
- package/dist/children.d.ts +5 -2
- package/dist/children.js +8 -3
- package/dist/children.js.map +1 -1
- package/dist/command.js +6 -0
- package/dist/command.js.map +1 -1
- package/dist/compiler/ast.d.ts +21 -0
- package/dist/compiler/ast.js +145 -0
- package/dist/compiler/ast.js.map +1 -0
- package/dist/compiler/compile.d.ts +38 -0
- package/dist/compiler/compile.js +129 -0
- package/dist/compiler/compile.js.map +1 -0
- package/dist/compiler/hooks.d.ts +18 -0
- package/dist/compiler/hooks.js +186 -0
- package/dist/compiler/hooks.js.map +1 -0
- package/dist/compiler/parse5-check.d.ts +21 -0
- package/dist/compiler/parse5-check.js +55 -0
- package/dist/compiler/parse5-check.js.map +1 -0
- package/dist/compiler/scan.d.ts +31 -0
- package/dist/compiler/scan.js +152 -0
- package/dist/compiler/scan.js.map +1 -0
- package/dist/compiler/source.d.ts +34 -0
- package/dist/compiler/source.js +114 -0
- package/dist/compiler/source.js.map +1 -0
- package/dist/define.d.ts +2 -2
- package/dist/define.js +35 -327
- package/dist/define.js.map +1 -1
- package/dist/devtools-events.d.ts +5 -0
- package/dist/devtools-events.js.map +1 -1
- package/dist/devtools-off.d.ts +1 -0
- package/dist/devtools-off.js +1 -0
- package/dist/devtools-off.js.map +1 -1
- package/dist/devtools.d.ts +1 -0
- package/dist/devtools.js +3 -2
- package/dist/devtools.js.map +1 -1
- package/dist/drivers-scope.d.ts +1 -1
- package/dist/drivers-scope.js +1 -8
- package/dist/drivers-scope.js.map +1 -1
- package/dist/element-types.d.ts +5 -3
- package/dist/element-types.js.map +1 -1
- package/dist/element.d.ts +3 -0
- package/dist/element.js +269 -0
- package/dist/element.js.map +1 -0
- package/dist/eslint/imports.d.ts +24 -0
- package/dist/eslint/imports.js +78 -0
- package/dist/eslint/imports.js.map +1 -0
- package/dist/eslint/index.d.ts +15 -0
- package/dist/eslint/index.js +15 -0
- package/dist/eslint/index.js.map +1 -0
- package/dist/eslint/locate.d.ts +33 -0
- package/dist/eslint/locate.js +132 -0
- package/dist/eslint/locate.js.map +1 -0
- package/dist/eslint/row-purity-rule.d.ts +2 -0
- package/dist/eslint/row-purity-rule.js +103 -0
- package/dist/eslint/row-purity-rule.js.map +1 -0
- package/dist/eslint/template-rule.d.ts +5 -0
- package/dist/eslint/template-rule.js +66 -0
- package/dist/eslint/template-rule.js.map +1 -0
- package/dist/features.d.ts +39 -0
- package/dist/features.js +2 -0
- package/dist/features.js.map +1 -0
- package/dist/focus.d.ts +7 -12
- package/dist/focus.js +13 -10
- package/dist/focus.js.map +1 -1
- package/dist/hooks/invalid.d.ts +14 -0
- package/dist/hooks/invalid.js +72 -0
- package/dist/hooks/invalid.js.map +1 -0
- package/dist/hooks/labelled-by.d.ts +13 -0
- package/dist/hooks/labelled-by.js +51 -0
- package/dist/hooks/labelled-by.js.map +1 -0
- package/dist/host-model.d.ts +48 -0
- package/dist/host-model.js +155 -0
- package/dist/host-model.js.map +1 -0
- package/dist/hydration-client.d.ts +9 -0
- package/dist/hydration-client.js +35 -0
- package/dist/hydration-client.js.map +1 -0
- package/dist/hydration.d.ts +13 -19
- package/dist/hydration.js +45 -45
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +9 -17
- package/dist/index.js +9 -18
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +31 -8
- package/dist/intent.js +82 -27
- package/dist/intent.js.map +1 -1
- package/dist/internal/interpreter.d.ts +7 -1
- package/dist/internal/interpreter.js +11 -4
- package/dist/internal/interpreter.js.map +1 -1
- package/dist/invokers-shim.d.ts +6 -0
- package/dist/invokers-shim.js +32 -0
- package/dist/invokers-shim.js.map +1 -0
- package/dist/invokers.d.ts +3 -5
- package/dist/invokers.js +11 -51
- package/dist/invokers.js.map +1 -1
- package/dist/islands.d.ts +0 -2
- package/dist/islands.js +4 -11
- package/dist/islands.js.map +1 -1
- package/dist/light-dom.d.ts +3 -52
- package/dist/light-dom.js +5 -100
- package/dist/light-dom.js.map +1 -1
- package/dist/prop.d.ts +66 -0
- package/dist/prop.js +22 -0
- package/dist/prop.js.map +1 -0
- package/dist/props.d.ts +52 -21
- package/dist/props.js +150 -34
- package/dist/props.js.map +1 -1
- package/dist/scheduler.d.ts +39 -0
- package/dist/scheduler.js +230 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/server-component.d.ts +10 -0
- package/dist/server-component.js +102 -0
- package/dist/server-component.js.map +1 -0
- package/dist/server-specs.d.ts +6 -0
- package/dist/server-specs.js +13 -0
- package/dist/server-specs.js.map +1 -0
- package/dist/server.d.ts +28 -0
- package/dist/server.js +50 -0
- package/dist/server.js.map +1 -0
- package/dist/settled.d.ts +10 -0
- package/dist/settled.js +40 -0
- package/dist/settled.js.map +1 -0
- package/dist/states.d.ts +3 -3
- package/dist/states.js +4 -7
- package/dist/states.js.map +1 -1
- package/dist/store-binding.d.ts +6 -3
- package/dist/store-binding.js +5 -6
- package/dist/store-binding.js.map +1 -1
- package/dist/store-scope.d.ts +6 -7
- package/dist/store-scope.js +11 -26
- package/dist/store-scope.js.map +1 -1
- package/dist/store.d.ts +3 -0
- package/dist/store.js +9 -2
- package/dist/store.js.map +1 -1
- package/dist/stores-provider.d.ts +2 -6
- package/dist/stores-provider.js +21 -55
- package/dist/stores-provider.js.map +1 -1
- package/dist/transitions.d.ts +5 -6
- package/dist/transitions.js +11 -20
- package/dist/transitions.js.map +1 -1
- package/dist/types.d.ts +19 -23
- package/dist/types.js.map +1 -1
- package/dist/view/attributes.d.ts +6 -0
- package/dist/view/attributes.js +10 -0
- package/dist/view/attributes.js.map +1 -0
- package/dist/view/compiled.d.ts +1 -0
- package/dist/view/compiled.js +6 -0
- package/dist/view/compiled.js.map +1 -0
- package/dist/view/dev-off.d.ts +1 -0
- package/dist/view/dev-off.js +4 -0
- package/dist/view/dev-off.js.map +1 -0
- package/dist/view/dev.d.ts +1 -0
- package/dist/view/dev.js +5 -0
- package/dist/view/dev.js.map +1 -0
- package/dist/view/flags.d.ts +1 -0
- package/dist/view/flags.js +4 -0
- package/dist/view/flags.js.map +1 -0
- package/dist/view/index.d.ts +21 -0
- package/dist/view/index.js +21 -0
- package/dist/view/index.js.map +1 -0
- package/dist/view/normalize/check.d.ts +20 -0
- package/dist/view/normalize/check.js +78 -0
- package/dist/view/normalize/check.js.map +1 -0
- package/dist/view/normalize/emit.d.ts +13 -0
- package/dist/view/normalize/emit.js +136 -0
- package/dist/view/normalize/emit.js.map +1 -0
- package/dist/view/normalize/entities.d.ts +4 -0
- package/dist/view/normalize/entities.js +38 -0
- package/dist/view/normalize/entities.js.map +1 -0
- package/dist/view/normalize/errors.d.ts +9 -0
- package/dist/view/normalize/errors.js +19 -0
- package/dist/view/normalize/errors.js.map +1 -0
- package/dist/view/normalize/id.d.ts +7 -0
- package/dist/view/normalize/id.js +48 -0
- package/dist/view/normalize/id.js.map +1 -0
- package/dist/view/normalize/normalize.d.ts +15 -0
- package/dist/view/normalize/normalize.js +36 -0
- package/dist/view/normalize/normalize.js.map +1 -0
- package/dist/view/normalize/repairs.d.ts +24 -0
- package/dist/view/normalize/repairs.js +166 -0
- package/dist/view/normalize/repairs.js.map +1 -0
- package/dist/view/normalize/rules.d.ts +30 -0
- package/dist/view/normalize/rules.js +90 -0
- package/dist/view/normalize/rules.js.map +1 -0
- package/dist/view/normalize/shape.d.ts +5 -0
- package/dist/view/normalize/shape.js +38 -0
- package/dist/view/normalize/shape.js.map +1 -0
- package/dist/view/normalize/source.d.ts +13 -0
- package/dist/view/normalize/source.js +34 -0
- package/dist/view/normalize/source.js.map +1 -0
- package/dist/view/normalize/tag-states.d.ts +23 -0
- package/dist/view/normalize/tag-states.js +192 -0
- package/dist/view/normalize/tag-states.js.map +1 -0
- package/dist/view/normalize/tokenizer.d.ts +5 -0
- package/dist/view/normalize/tokenizer.js +233 -0
- package/dist/view/normalize/tokenizer.js.map +1 -0
- package/dist/view/normalize/tokens.d.ts +51 -0
- package/dist/view/normalize/tokens.js +24 -0
- package/dist/view/normalize/tokens.js.map +1 -0
- package/dist/view/normalize/tree.d.ts +59 -0
- package/dist/view/normalize/tree.js +190 -0
- package/dist/view/normalize/tree.js.map +1 -0
- package/dist/view/normalize/types.d.ts +126 -0
- package/dist/view/normalize/types.js +26 -0
- package/dist/view/normalize/types.js.map +1 -0
- package/dist/view/normalize/whitespace.d.ts +2 -0
- package/dist/{template-whitespace.js → view/normalize/whitespace.js} +24 -34
- package/dist/view/normalize/whitespace.js.map +1 -0
- package/dist/view/prepare-stub.d.ts +3 -0
- package/dist/view/prepare-stub.js +7 -0
- package/dist/view/prepare-stub.js.map +1 -0
- package/dist/view/prepare.d.ts +8 -0
- package/dist/view/prepare.js +57 -0
- package/dist/view/prepare.js.map +1 -0
- package/dist/view/registry.d.ts +63 -0
- package/dist/view/registry.js +19 -0
- package/dist/view/registry.js.map +1 -0
- package/dist/view/render/adopt-attr.d.ts +14 -0
- package/dist/view/render/adopt-attr.js +77 -0
- package/dist/view/render/adopt-attr.js.map +1 -0
- package/dist/view/render/adopt-plan.d.ts +10 -0
- package/dist/view/render/adopt-plan.js +26 -0
- package/dist/view/render/adopt-plan.js.map +1 -0
- package/dist/view/render/adopt.d.ts +3 -0
- package/dist/view/render/adopt.js +269 -0
- package/dist/view/render/adopt.js.map +1 -0
- package/dist/view/render/attr-parts.d.ts +61 -0
- package/dist/view/render/attr-parts.js +229 -0
- package/dist/view/render/attr-parts.js.map +1 -0
- package/dist/view/render/child-part.d.ts +51 -0
- package/dist/view/render/child-part.js +170 -0
- package/dist/view/render/child-part.js.map +1 -0
- package/dist/view/render/dev-check.d.ts +12 -0
- package/dist/view/render/dev-check.js +122 -0
- package/dist/view/render/dev-check.js.map +1 -0
- package/dist/view/render/hook-part.d.ts +3 -0
- package/dist/view/render/hook-part.js +20 -0
- package/dist/view/render/hook-part.js.map +1 -0
- package/dist/view/render/hooks.d.ts +40 -0
- package/dist/view/render/hooks.js +46 -0
- package/dist/view/render/hooks.js.map +1 -0
- package/dist/view/render/hydrate.d.ts +10 -0
- package/dist/view/render/hydrate.js +33 -0
- package/dist/view/render/hydrate.js.map +1 -0
- package/dist/view/render/instance.d.ts +33 -0
- package/dist/view/render/instance.js +107 -0
- package/dist/view/render/instance.js.map +1 -0
- package/dist/view/render/list.d.ts +20 -0
- package/dist/view/render/list.js +156 -0
- package/dist/view/render/list.js.map +1 -0
- package/dist/view/render/mismatch.d.ts +10 -0
- package/dist/view/render/mismatch.js +53 -0
- package/dist/view/render/mismatch.js.map +1 -0
- package/dist/view/render/nodes.d.ts +10 -0
- package/dist/view/render/nodes.js +37 -0
- package/dist/view/render/nodes.js.map +1 -0
- package/dist/view/render/place.d.ts +18 -0
- package/dist/view/render/place.js +69 -0
- package/dist/view/render/place.js.map +1 -0
- package/dist/view/render/plan.d.ts +26 -0
- package/dist/view/render/plan.js +124 -0
- package/dist/view/render/plan.js.map +1 -0
- package/dist/view/render/raw.d.ts +18 -0
- package/dist/view/render/raw.js +68 -0
- package/dist/view/render/raw.js.map +1 -0
- package/dist/view/render/render.d.ts +12 -0
- package/dist/view/render/render.js +60 -0
- package/dist/view/render/render.js.map +1 -0
- package/dist/view/render/reorder.d.ts +4 -0
- package/dist/view/render/reorder.js +101 -0
- package/dist/view/render/reorder.js.map +1 -0
- package/dist/view/render/rows.d.ts +23 -0
- package/dist/view/render/rows.js +95 -0
- package/dist/view/render/rows.js.map +1 -0
- package/dist/view/render/seen.d.ts +11 -0
- package/dist/view/render/seen.js +17 -0
- package/dist/view/render/seen.js.map +1 -0
- package/dist/view/render/values.d.ts +29 -0
- package/dist/view/render/values.js +13 -0
- package/dist/view/render/values.js.map +1 -0
- package/dist/view/render/warn.d.ts +14 -0
- package/dist/view/render/warn.js +69 -0
- package/dist/view/render/warn.js.map +1 -0
- package/dist/view/server/component.d.ts +9 -0
- package/dist/view/server/component.js +42 -0
- package/dist/view/server/component.js.map +1 -0
- package/dist/view/server/escape.d.ts +10 -0
- package/dist/view/server/escape.js +34 -0
- package/dist/view/server/escape.js.map +1 -0
- package/dist/view/server/index.d.ts +28 -0
- package/dist/view/server/index.js +72 -0
- package/dist/view/server/index.js.map +1 -0
- package/dist/view/server/sha256.d.ts +2 -0
- package/dist/view/server/sha256.js +75 -0
- package/dist/view/server/sha256.js.map +1 -0
- package/dist/view/server/tags.d.ts +57 -0
- package/dist/view/server/tags.js +121 -0
- package/dist/view/server/tags.js.map +1 -0
- package/dist/view/server/values.d.ts +16 -0
- package/dist/view/server/values.js +86 -0
- package/dist/view/server/values.js.map +1 -0
- package/dist/view/server/writer.d.ts +16 -0
- package/dist/view/server/writer.js +155 -0
- package/dist/view/server/writer.js.map +1 -0
- package/dist/view/styles.d.ts +25 -0
- package/dist/view/styles.js +58 -0
- package/dist/view/styles.js.map +1 -0
- package/dist/view/template-element.d.ts +3 -0
- package/dist/view/template-element.js +25 -0
- package/dist/view/template-element.js.map +1 -0
- package/dist/view/template.d.ts +21 -0
- package/dist/view/template.js +30 -0
- package/dist/view/template.js.map +1 -0
- package/dist/vite.d.ts +45 -6
- package/dist/vite.js +150 -25
- package/dist/vite.js.map +1 -1
- package/package.json +39 -4
- package/dist/accessible-name.d.ts +0 -19
- package/dist/accessible-name.js +0 -56
- package/dist/accessible-name.js.map +0 -1
- package/dist/element-directive.d.ts +0 -20
- package/dist/element-directive.js +0 -31
- package/dist/element-directive.js.map +0 -1
- package/dist/invalid.d.ts +0 -21
- package/dist/invalid.js +0 -70
- package/dist/invalid.js.map +0 -1
- package/dist/lit-html-check.d.ts +0 -6
- package/dist/lit-html-check.js +0 -48
- package/dist/lit-html-check.js.map +0 -1
- package/dist/live-boolean.d.ts +0 -22
- package/dist/live-boolean.js +0 -34
- package/dist/live-boolean.js.map +0 -1
- package/dist/styles.d.ts +0 -12
- package/dist/styles.js +0 -11
- package/dist/styles.js.map +0 -1
- package/dist/template-whitespace.d.ts +0 -7
- package/dist/template-whitespace.js.map +0 -1
- package/dist/templates.d.ts +0 -5
- package/dist/templates.js +0 -15
- package/dist/templates.js.map +0 -1
- package/dist/textarea.d.ts +0 -26
- package/dist/textarea.js +0 -85
- package/dist/textarea.js.map +0 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { TemplateObject } from '../normalize/types.js';
|
|
2
|
+
import { type Part } from './attr-parts.js';
|
|
3
|
+
import { ChildPart, type Owner } from './child-part.js';
|
|
4
|
+
/** The DOM cloned from one template, plus its parts. */
|
|
5
|
+
export declare class Instance implements Owner {
|
|
6
|
+
readonly template: TemplateObject;
|
|
7
|
+
/** The result source last rendered (strings array or compiled object), for a fast compare. */
|
|
8
|
+
source: unknown;
|
|
9
|
+
/** The child part whose content this instance is. */
|
|
10
|
+
readonly holder: ChildPart;
|
|
11
|
+
readonly parts: Part[];
|
|
12
|
+
/** First and last static root nodes; null when the template is a single hole. */
|
|
13
|
+
start: Node | null;
|
|
14
|
+
end: Node | null;
|
|
15
|
+
/** Root-level child parts before the first / after the last static root node. */
|
|
16
|
+
head: ChildPart | null;
|
|
17
|
+
tail: ChildPart | null;
|
|
18
|
+
/** The clone, until it is inserted. */
|
|
19
|
+
frag: DocumentFragment | null;
|
|
20
|
+
/** `adopt`: hydration (adopt.ts) fills the parts and root nodes from server DOM instead. */
|
|
21
|
+
constructor(template: TemplateObject, source: unknown, holder: ChildPart, adopt?: boolean);
|
|
22
|
+
private build;
|
|
23
|
+
/** Commits this render's values, part by part in document order. */
|
|
24
|
+
update(values: readonly unknown[]): void;
|
|
25
|
+
/** Inserts the (committed) clone; afterwards root-level parts resolve through the holder. */
|
|
26
|
+
insert(parent: Node, before: Node | null): void;
|
|
27
|
+
first(): Node | null;
|
|
28
|
+
last(): Node | null;
|
|
29
|
+
remove(): void;
|
|
30
|
+
/** Owner of root-level open parts: the clone while building, then the holder's parent. */
|
|
31
|
+
parentFor(): Node;
|
|
32
|
+
endFor(): Node | null;
|
|
33
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { attrPart } from './attr-parts.js';
|
|
2
|
+
import { ChildPart } from './child-part.js';
|
|
3
|
+
import { removeRange } from './nodes.js';
|
|
4
|
+
import { report } from './seen.js';
|
|
5
|
+
import { CHILD, nodes, planOf, ROOT, stack, walk } from './plan.js';
|
|
6
|
+
/** The DOM cloned from one template, plus its parts. */
|
|
7
|
+
export class Instance {
|
|
8
|
+
/** `adopt`: hydration (adopt.ts) fills the parts and root nodes from server DOM instead. */
|
|
9
|
+
constructor(template, source, holder, adopt) {
|
|
10
|
+
this.template = template;
|
|
11
|
+
this.source = source;
|
|
12
|
+
this.holder = holder;
|
|
13
|
+
this.parts = [];
|
|
14
|
+
this.head = null;
|
|
15
|
+
this.tail = null;
|
|
16
|
+
this.frag = this.start = this.end = null;
|
|
17
|
+
report(template);
|
|
18
|
+
if (adopt === true)
|
|
19
|
+
return;
|
|
20
|
+
const plan = planOf(template);
|
|
21
|
+
if (plan.single) {
|
|
22
|
+
const root = document.importNode(plan.content.firstChild, true);
|
|
23
|
+
stack[1] = root;
|
|
24
|
+
this.start = this.end = root;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
const frag = document.importNode(plan.content, true);
|
|
28
|
+
stack[0] = frag;
|
|
29
|
+
this.frag = frag;
|
|
30
|
+
this.start = frag.firstChild;
|
|
31
|
+
this.end = frag.lastChild;
|
|
32
|
+
}
|
|
33
|
+
walk(plan);
|
|
34
|
+
this.build(plan);
|
|
35
|
+
}
|
|
36
|
+
build(plan) {
|
|
37
|
+
const { a, b, at, kinds } = plan;
|
|
38
|
+
const specs = this.template.parts;
|
|
39
|
+
for (let i = 0; i < kinds.length; i++) {
|
|
40
|
+
const kind = kinds[i];
|
|
41
|
+
const node = nodes[a[i]];
|
|
42
|
+
if (kind >= 0) {
|
|
43
|
+
this.parts.push(attrPart(node, kind, specs[i], at[i]));
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const r = b[i];
|
|
47
|
+
const ref = r >= 0 ? nodes[r] : null;
|
|
48
|
+
if (kind !== ROOT) {
|
|
49
|
+
this.parts.push(new ChildPart(node, ref, null, 0, kind !== CHILD, at[i]));
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const part = new ChildPart(null, ref, ref === null ? this : null, 0, false, at[i]);
|
|
53
|
+
if (ref === null)
|
|
54
|
+
this.tail = part;
|
|
55
|
+
else if (ref === this.start)
|
|
56
|
+
this.head = part;
|
|
57
|
+
this.parts.push(part);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Commits this render's values, part by part in document order. */
|
|
61
|
+
update(values) {
|
|
62
|
+
const parts = this.parts;
|
|
63
|
+
for (let i = 0; i < parts.length; i++)
|
|
64
|
+
parts[i].set(values);
|
|
65
|
+
}
|
|
66
|
+
/** Inserts the (committed) clone; afterwards root-level parts resolve through the holder. */
|
|
67
|
+
insert(parent, before) {
|
|
68
|
+
parent.insertBefore(this.frag ?? this.start, before);
|
|
69
|
+
this.frag = null;
|
|
70
|
+
}
|
|
71
|
+
first() {
|
|
72
|
+
const head = this.head !== null ? this.head.first() : null;
|
|
73
|
+
if (head !== null)
|
|
74
|
+
return head;
|
|
75
|
+
if (this.start !== null)
|
|
76
|
+
return this.start;
|
|
77
|
+
return this.tail !== null ? this.tail.first() : null;
|
|
78
|
+
}
|
|
79
|
+
last() {
|
|
80
|
+
const tail = this.tail !== null ? this.tail.last() : null;
|
|
81
|
+
if (tail !== null)
|
|
82
|
+
return tail;
|
|
83
|
+
if (this.end !== null)
|
|
84
|
+
return this.end;
|
|
85
|
+
return this.head !== null ? this.head.last() : null;
|
|
86
|
+
}
|
|
87
|
+
remove() {
|
|
88
|
+
const first = this.first();
|
|
89
|
+
if (first === null)
|
|
90
|
+
return;
|
|
91
|
+
const last = this.last();
|
|
92
|
+
if (first === last)
|
|
93
|
+
first.remove();
|
|
94
|
+
else
|
|
95
|
+
removeRange(first, last);
|
|
96
|
+
}
|
|
97
|
+
/** Owner of root-level open parts: the clone while building, then the holder's parent. */
|
|
98
|
+
parentFor() {
|
|
99
|
+
if (this.frag !== null)
|
|
100
|
+
return this.frag;
|
|
101
|
+
return this.start !== null ? this.start.parentNode : this.holder.parent();
|
|
102
|
+
}
|
|
103
|
+
endFor() {
|
|
104
|
+
return this.frag !== null ? null : this.holder.end();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=instance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance.js","sourceRoot":"","sources":["../../../src/view/render/instance.ts"],"names":[],"mappings":"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","sourcesContent":["// Template instances (view/01-templates.md \"Instantiation\", view/02-bindings.md \"Commit order\").\n// An instance is cloned with `document.importNode` (nested custom elements upgrade at once),\n// every part's nodes are resolved from the clone first by child-index paths (firstChild/\n// nextSibling, sharing prefixes; no TreeWalker, no marker search), then the values commit while\n// the clone is still detached, and only then is it inserted, so child components connect with\n// their props set. A template with one root node and no root-level holes clones just that node.\n// How to reach the nodes, and what each part is, comes from the template's plan (plan.ts).\n// Hydration (adopt.ts) creates instances with `adopt` set and fills them from server DOM.\nimport type { PartSpec, TemplateObject } from '../normalize/types.js';\nimport { attrPart, type Part } from './attr-parts.js';\nimport { ChildPart, type Owner } from './child-part.js';\nimport { removeRange } from './nodes.js';\nimport { report } from './seen.js';\nimport { CHILD, nodes, planOf, ROOT, stack, walk, type Plan } from './plan.js';\n\n/** The DOM cloned from one template, plus its parts. */\nexport class Instance implements Owner {\n readonly template: TemplateObject;\n /** The result source last rendered (strings array or compiled object), for a fast compare. */\n source: unknown;\n /** The child part whose content this instance is. */\n readonly holder: ChildPart;\n readonly parts: Part[];\n /** First and last static root nodes; null when the template is a single hole. */\n start: Node | null;\n end: Node | null;\n /** Root-level child parts before the first / after the last static root node. */\n head: ChildPart | null;\n tail: ChildPart | null;\n /** The clone, until it is inserted. */\n frag: DocumentFragment | null;\n\n /** `adopt`: hydration (adopt.ts) fills the parts and root nodes from server DOM instead. */\n constructor(template: TemplateObject, source: unknown, holder: ChildPart, adopt?: boolean) {\n this.template = template;\n this.source = source;\n this.holder = holder;\n this.parts = [];\n this.head = null;\n this.tail = null;\n this.frag = this.start = this.end = null;\n report(template);\n if (adopt === true) return;\n const plan = planOf(template);\n if (plan.single) {\n const root = document.importNode(plan.content.firstChild as Node, true);\n stack[1] = root;\n this.start = this.end = root;\n } else {\n const frag = document.importNode(plan.content, true);\n stack[0] = frag;\n this.frag = frag;\n this.start = frag.firstChild;\n this.end = frag.lastChild;\n }\n walk(plan);\n this.build(plan);\n }\n\n private build(plan: Plan): void {\n const { a, b, at, kinds } = plan;\n const specs = this.template.parts;\n for (let i = 0; i < kinds.length; i++) {\n const kind = kinds[i] as number;\n const node = nodes[a[i] as number] as Element;\n if (kind >= 0) {\n this.parts.push(attrPart(node, kind, specs[i] as PartSpec, at[i] as number));\n continue;\n }\n const r = b[i] as number;\n const ref = r >= 0 ? (nodes[r] as Node) : null;\n if (kind !== ROOT) {\n this.parts.push(new ChildPart(node, ref, null, 0, kind !== CHILD, at[i] as number));\n continue;\n }\n const part = new ChildPart(null, ref, ref === null ? this : null, 0, false, at[i] as number);\n if (ref === null) this.tail = part;\n else if (ref === this.start) this.head = part;\n this.parts.push(part);\n }\n }\n\n /** Commits this render's values, part by part in document order. */\n update(values: readonly unknown[]): void {\n const parts = this.parts;\n for (let i = 0; i < parts.length; i++) (parts[i] as Part).set(values);\n }\n\n /** Inserts the (committed) clone; afterwards root-level parts resolve through the holder. */\n insert(parent: Node, before: Node | null): void {\n parent.insertBefore(this.frag ?? (this.start as Node), before);\n this.frag = null;\n }\n\n first(): Node | null {\n const head = this.head !== null ? this.head.first() : null;\n if (head !== null) return head;\n if (this.start !== null) return this.start;\n return this.tail !== null ? this.tail.first() : null;\n }\n\n last(): Node | null {\n const tail = this.tail !== null ? this.tail.last() : null;\n if (tail !== null) return tail;\n if (this.end !== null) return this.end;\n return this.head !== null ? this.head.last() : null;\n }\n\n remove(): void {\n const first = this.first();\n if (first === null) return;\n const last = this.last() as Node;\n if (first === last) (first as ChildNode).remove();\n else removeRange(first, last);\n }\n\n /** Owner of root-level open parts: the clone while building, then the holder's parent. */\n parentFor(): Node {\n if (this.frag !== null) return this.frag;\n return this.start !== null ? (this.start.parentNode as Node) : this.holder.parent();\n }\n\n endFor(): Node | null {\n return this.frag !== null ? null : this.holder.end();\n }\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ChildPart } from './child-part.js';
|
|
2
|
+
import { List } from './rows.js';
|
|
3
|
+
import { type ChildValue, type ListResult } from './values.js';
|
|
4
|
+
export { List } from './rows.js';
|
|
5
|
+
/** Removes every row; the list's part keeps its (now empty) list. */
|
|
6
|
+
export declare function clearList(part: ChildPart, list: List): void;
|
|
7
|
+
/**
|
|
8
|
+
* Creates rows for `l.items[from…to]` (keys from `keys[i - from]` when given) into one
|
|
9
|
+
* fragment, pushes them onto `rows` and inserts the fragment before `end`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createRows(part: ChildPart, list: List, l: ListResult, rows: ChildPart[], from: number, to: number, end: Node | null, keys?: readonly unknown[]): void;
|
|
12
|
+
/**
|
|
13
|
+
* A keyed list (view/03-lists.md). `key` must give each item a unique string or number; `row`
|
|
14
|
+
* must depend only on its arguments: a row re-renders only when its item object or its `pick`
|
|
15
|
+
* result changes.
|
|
16
|
+
*/
|
|
17
|
+
export declare function each<T>(items: readonly T[], key: (item: T) => string | number, row: (item: T) => ChildValue): ListResult;
|
|
18
|
+
export declare function each<T, P>(items: readonly T[], key: (item: T) => string | number, row: (item: T, picked: P) => ChildValue, pick: (item: T) => P): ListResult;
|
|
19
|
+
/** A positional array: items reused by index (view/02-bindings.md "Child values"). */
|
|
20
|
+
export declare function commitItems(part: ChildPart, values: readonly unknown[]): void;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// Lists in child holes: `each` (view/03-lists.md "Reconciliation", "Fast paths") and
|
|
2
|
+
// positional arrays (view/02-bindings.md "Child values"). Rows are child parts tracked by their
|
|
3
|
+
// node range, with no markers. Fast paths: create into empty (one fragment), clear
|
|
4
|
+
// (replaceChildren when the list is its parent's only content), the common prefix and suffix,
|
|
5
|
+
// insert-only (append, prepend, insert) and remove-only. What remains is reordered by
|
|
6
|
+
// reorder.ts. Rows commit in document order. `each` is here: its result carries `commitList`,
|
|
7
|
+
// so the keyed path (this, rows.ts, reorder.ts, place.ts) is bundled only by apps that call it.
|
|
8
|
+
import { DEV } from '#view-dev';
|
|
9
|
+
import { ChildPart, EMPTY, ITEMS, LIST } from './child-part.js';
|
|
10
|
+
import { checkKeys, recheckRows } from './dev-check.js';
|
|
11
|
+
import { reorder } from './reorder.js';
|
|
12
|
+
import { firstFrom, List, newRow, updateRow } from './rows.js';
|
|
13
|
+
import { EACH } from './values.js';
|
|
14
|
+
export { List } from './rows.js';
|
|
15
|
+
function listOf(part, kind) {
|
|
16
|
+
if (part.kind === kind)
|
|
17
|
+
return part.content;
|
|
18
|
+
if (part.kind !== EMPTY)
|
|
19
|
+
part.clear();
|
|
20
|
+
const list = new List(part);
|
|
21
|
+
part.kind = kind;
|
|
22
|
+
part.content = list;
|
|
23
|
+
return list;
|
|
24
|
+
}
|
|
25
|
+
/** Removes every row; the list's part keeps its (now empty) list. */
|
|
26
|
+
export function clearList(part, list) {
|
|
27
|
+
if (part.sole && part.parentNode !== null)
|
|
28
|
+
part.parentNode.replaceChildren();
|
|
29
|
+
else
|
|
30
|
+
for (const row of list.rows)
|
|
31
|
+
row.clear();
|
|
32
|
+
list.rows = [];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Creates rows for `l.items[from…to]` (keys from `keys[i - from]` when given) into one
|
|
36
|
+
* fragment, pushes them onto `rows` and inserts the fragment before `end`.
|
|
37
|
+
*/
|
|
38
|
+
export function createRows(part, list, l, rows, from, to, end, keys) {
|
|
39
|
+
const frag = document.createDocumentFragment();
|
|
40
|
+
list.building = frag;
|
|
41
|
+
try {
|
|
42
|
+
for (let i = from; i <= to; i++) {
|
|
43
|
+
const item = l.items[i];
|
|
44
|
+
const key = keys === undefined ? l.key(item) : keys[i - from];
|
|
45
|
+
rows.push(newRow(list, null, l, item, key, i));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
list.building = null;
|
|
50
|
+
}
|
|
51
|
+
part.parent().insertBefore(frag, end);
|
|
52
|
+
}
|
|
53
|
+
export function each(items, key, row, pick) {
|
|
54
|
+
if (DEV && typeof key !== 'function') {
|
|
55
|
+
throw new TypeError('gyral: each() needs a key function as its second argument: ' +
|
|
56
|
+
'each(items, (x) => x.id, Row) (docs/design-docs/view/03-lists.md "Keys", rule 9).');
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
[EACH]: commitList,
|
|
60
|
+
items,
|
|
61
|
+
key: key,
|
|
62
|
+
row: row,
|
|
63
|
+
pick: pick,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function commitList(part, l) {
|
|
67
|
+
const list = listOf(part, LIST);
|
|
68
|
+
const n = l.items.length;
|
|
69
|
+
if (DEV)
|
|
70
|
+
checkKeys(l.items, l.key);
|
|
71
|
+
if (list.rows.length === 0) {
|
|
72
|
+
if (n > 0) {
|
|
73
|
+
const rows = [];
|
|
74
|
+
createRows(part, list, l, rows, 0, n - 1, part.end());
|
|
75
|
+
list.rows = rows;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else if (n === 0)
|
|
79
|
+
clearList(part, list);
|
|
80
|
+
else
|
|
81
|
+
reconcile(part, list, l);
|
|
82
|
+
if (DEV)
|
|
83
|
+
recheckRows(list, l);
|
|
84
|
+
}
|
|
85
|
+
function reconcile(part, list, l) {
|
|
86
|
+
const { items, key } = l;
|
|
87
|
+
const old = list.rows;
|
|
88
|
+
const n = items.length;
|
|
89
|
+
const on = old.length;
|
|
90
|
+
const m = n < on ? n : on;
|
|
91
|
+
let s = 0;
|
|
92
|
+
for (; s < m; s++) {
|
|
93
|
+
const item = items[s];
|
|
94
|
+
const row = old[s];
|
|
95
|
+
if (key(item) !== row.key)
|
|
96
|
+
break;
|
|
97
|
+
updateRow(row, item, l);
|
|
98
|
+
}
|
|
99
|
+
if (s === n && s === on)
|
|
100
|
+
return;
|
|
101
|
+
let oe = on - 1;
|
|
102
|
+
let ne = n - 1;
|
|
103
|
+
while (oe >= s && ne >= s && key(items[ne]) === old[oe].key) {
|
|
104
|
+
oe--;
|
|
105
|
+
ne--;
|
|
106
|
+
}
|
|
107
|
+
const rows = old.slice(0, s);
|
|
108
|
+
if (s > oe)
|
|
109
|
+
createRows(part, list, l, rows, s, ne, firstFrom(old, oe + 1, part));
|
|
110
|
+
else if (s > ne)
|
|
111
|
+
for (let j = s; j <= oe; j++)
|
|
112
|
+
old[j].clear();
|
|
113
|
+
else
|
|
114
|
+
reorder(part, list, l, rows, s, oe, ne);
|
|
115
|
+
for (let j = oe + 1; j < on; j++)
|
|
116
|
+
rows.push(old[j]);
|
|
117
|
+
list.rows = rows;
|
|
118
|
+
for (let i = s; i < n; i++)
|
|
119
|
+
rows[i].index = i;
|
|
120
|
+
for (let i = ne + 1; i < n; i++)
|
|
121
|
+
updateRow(rows[i], items[i], l);
|
|
122
|
+
}
|
|
123
|
+
/** A positional array: items reused by index (view/02-bindings.md "Child values"). */
|
|
124
|
+
export function commitItems(part, values) {
|
|
125
|
+
const list = listOf(part, ITEMS);
|
|
126
|
+
const rows = list.rows;
|
|
127
|
+
const n = values.length;
|
|
128
|
+
if (n === 0) {
|
|
129
|
+
if (rows.length > 0)
|
|
130
|
+
clearList(part, list);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const common = n < rows.length ? n : rows.length;
|
|
134
|
+
for (let i = 0; i < common; i++)
|
|
135
|
+
rows[i].commit(values[i]);
|
|
136
|
+
if (n > rows.length) {
|
|
137
|
+
const end = part.end();
|
|
138
|
+
const frag = document.createDocumentFragment();
|
|
139
|
+
list.building = frag;
|
|
140
|
+
try {
|
|
141
|
+
for (let i = rows.length; i < n; i++) {
|
|
142
|
+
const row = new ChildPart(null, null, list, i, false, -1);
|
|
143
|
+
rows.push(row);
|
|
144
|
+
row.commit(values[i]);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
list.building = null;
|
|
149
|
+
}
|
|
150
|
+
part.parent().insertBefore(frag, end);
|
|
151
|
+
}
|
|
152
|
+
else
|
|
153
|
+
while (rows.length > n)
|
|
154
|
+
rows.pop().clear();
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/view/render/list.ts"],"names":[],"mappings":"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","sourcesContent":["// Lists in child holes: `each` (view/03-lists.md \"Reconciliation\", \"Fast paths\") and\n// positional arrays (view/02-bindings.md \"Child values\"). Rows are child parts tracked by their\n// node range, with no markers. Fast paths: create into empty (one fragment), clear\n// (replaceChildren when the list is its parent's only content), the common prefix and suffix,\n// insert-only (append, prepend, insert) and remove-only. What remains is reordered by\n// reorder.ts. Rows commit in document order. `each` is here: its result carries `commitList`,\n// so the keyed path (this, rows.ts, reorder.ts, place.ts) is bundled only by apps that call it.\nimport { DEV } from '#view-dev';\nimport { ChildPart, EMPTY, ITEMS, LIST } from './child-part.js';\nimport { checkKeys, recheckRows } from './dev-check.js';\nimport { reorder } from './reorder.js';\nimport { firstFrom, List, newRow, updateRow } from './rows.js';\nimport { EACH, type ChildValue, type ListResult } from './values.js';\n\nexport { List } from './rows.js';\n\nfunction listOf(part: ChildPart, kind: number): List {\n if (part.kind === kind) return part.content as List;\n if (part.kind !== EMPTY) part.clear();\n const list = new List(part);\n part.kind = kind;\n part.content = list;\n return list;\n}\n\n/** Removes every row; the list's part keeps its (now empty) list. */\nexport function clearList(part: ChildPart, list: List): void {\n if (part.sole && part.parentNode !== null) (part.parentNode as Element).replaceChildren();\n else for (const row of list.rows) row.clear();\n list.rows = [];\n}\n\n/**\n * Creates rows for `l.items[from…to]` (keys from `keys[i - from]` when given) into one\n * fragment, pushes them onto `rows` and inserts the fragment before `end`.\n */\nexport function createRows(\n part: ChildPart,\n list: List,\n l: ListResult,\n rows: ChildPart[],\n from: number,\n to: number,\n end: Node | null,\n keys?: readonly unknown[],\n): void {\n const frag = document.createDocumentFragment();\n list.building = frag;\n try {\n for (let i = from; i <= to; i++) {\n const item = l.items[i];\n const key = keys === undefined ? l.key(item) : keys[i - from];\n rows.push(newRow(list, null, l, item, key, i));\n }\n } finally {\n list.building = null;\n }\n part.parent().insertBefore(frag, end);\n}\n\n/**\n * A keyed list (view/03-lists.md). `key` must give each item a unique string or number; `row`\n * must depend only on its arguments: a row re-renders only when its item object or its `pick`\n * result changes.\n */\nexport function each<T>(\n items: readonly T[],\n key: (item: T) => string | number,\n row: (item: T) => ChildValue,\n): ListResult;\nexport function each<T, P>(\n items: readonly T[],\n key: (item: T) => string | number,\n row: (item: T, picked: P) => ChildValue,\n pick: (item: T) => P,\n): ListResult;\nexport function each<T, P>(\n items: readonly T[],\n key: (item: T) => string | number,\n row: (item: T, picked: P) => ChildValue,\n pick?: (item: T) => P,\n): ListResult {\n if (DEV && typeof key !== 'function') {\n throw new TypeError(\n 'gyral: each() needs a key function as its second argument: ' +\n 'each(items, (x) => x.id, Row) (docs/design-docs/view/03-lists.md \"Keys\", rule 9).',\n );\n }\n return {\n [EACH]: commitList,\n items,\n key: key as (item: unknown) => unknown,\n row: row as (item: unknown, picked: unknown) => unknown,\n pick: pick as ((item: unknown) => unknown) | undefined,\n };\n}\n\nfunction commitList(part: ChildPart, l: ListResult): void {\n const list = listOf(part, LIST);\n const n = l.items.length;\n if (DEV) checkKeys(l.items, l.key);\n if (list.rows.length === 0) {\n if (n > 0) {\n const rows: ChildPart[] = [];\n createRows(part, list, l, rows, 0, n - 1, part.end());\n list.rows = rows;\n }\n } else if (n === 0) clearList(part, list);\n else reconcile(part, list, l);\n if (DEV) recheckRows(list, l);\n}\n\nfunction reconcile(part: ChildPart, list: List, l: ListResult): void {\n const { items, key } = l;\n const old = list.rows;\n const n = items.length;\n const on = old.length;\n const m = n < on ? n : on;\n let s = 0;\n for (; s < m; s++) {\n const item = items[s];\n const row = old[s] as ChildPart;\n if (key(item) !== row.key) break;\n updateRow(row, item, l);\n }\n if (s === n && s === on) return;\n let oe = on - 1;\n let ne = n - 1;\n while (oe >= s && ne >= s && key(items[ne]) === (old[oe] as ChildPart).key) {\n oe--;\n ne--;\n }\n const rows = old.slice(0, s);\n if (s > oe) createRows(part, list, l, rows, s, ne, firstFrom(old, oe + 1, part));\n else if (s > ne) for (let j = s; j <= oe; j++) (old[j] as ChildPart).clear();\n else reorder(part, list, l, rows, s, oe, ne);\n for (let j = oe + 1; j < on; j++) rows.push(old[j] as ChildPart);\n list.rows = rows;\n for (let i = s; i < n; i++) (rows[i] as ChildPart).index = i;\n for (let i = ne + 1; i < n; i++) updateRow(rows[i] as ChildPart, items[i], l);\n}\n\n/** A positional array: items reused by index (view/02-bindings.md \"Child values\"). */\nexport function commitItems(part: ChildPart, values: readonly unknown[]): void {\n const list = listOf(part, ITEMS);\n const rows = list.rows;\n const n = values.length;\n if (n === 0) {\n if (rows.length > 0) clearList(part, list);\n return;\n }\n const common = n < rows.length ? n : rows.length;\n for (let i = 0; i < common; i++) (rows[i] as ChildPart).commit(values[i]);\n if (n > rows.length) {\n const end = part.end();\n const frag = document.createDocumentFragment();\n list.building = frag;\n try {\n for (let i = rows.length; i < n; i++) {\n const row = new ChildPart(null, null, list, i, false, -1);\n rows.push(row);\n row.commit(values[i]);\n }\n } finally {\n list.building = null;\n }\n part.parent().insertBefore(frag, end);\n } else while (rows.length > n) (rows.pop() as ChildPart).clear();\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** The server's DOM doesn't match the component's first client render. */
|
|
2
|
+
export declare class HydrationMismatch extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Throws a mismatch. `expected` describes what the walk needed; `found` is the DOM node there,
|
|
7
|
+
* a description, or null when `at` (the parent) had no more children. `host` names the
|
|
8
|
+
* component and `loc` the template's call site.
|
|
9
|
+
*/
|
|
10
|
+
export declare function mismatch(expected: string, found: Node | string | null, at: Node, root: Node, host: string, loc: string | undefined): never;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Hydration mismatches (view/07-hydration.md "Mismatches"): the server DOM differs from what
|
|
2
|
+
// the first client render needs. The message names the component, the template's call site
|
|
3
|
+
// (development builds know it), the path from the root to the node, and what was expected
|
|
4
|
+
// and found. Development throws it; production recovers the one component (core's caller).
|
|
5
|
+
import { DEV } from '#view-dev';
|
|
6
|
+
/** The server's DOM doesn't match the component's first client render. */
|
|
7
|
+
export class HydrationMismatch extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = 'HydrationMismatch';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** A short description of a DOM node. */
|
|
14
|
+
function describe(node) {
|
|
15
|
+
if (node.nodeType === 3)
|
|
16
|
+
return `text ${JSON.stringify(node.data.slice(0, 40))}`;
|
|
17
|
+
if (node.nodeType === 8)
|
|
18
|
+
return `<!--${node.data}-->`;
|
|
19
|
+
return node.nodeType === 1 ? `<${node.localName}>` : 'the root';
|
|
20
|
+
}
|
|
21
|
+
/** `div[0] › ul[2] › li[1]`: local names and child indexes from `root` down to `node`. */
|
|
22
|
+
function pathOf(node, root) {
|
|
23
|
+
const steps = [];
|
|
24
|
+
for (let n = node; n !== null && n !== root; n = n.parentNode) {
|
|
25
|
+
let index = 0;
|
|
26
|
+
for (let s = n.previousSibling; s !== null; s = s.previousSibling)
|
|
27
|
+
index++;
|
|
28
|
+
steps.unshift(`${n.nodeType === 1 ? n.localName : n.nodeName}[${String(index)}]`);
|
|
29
|
+
}
|
|
30
|
+
return steps.length === 0 ? 'the root' : steps.join(' › ');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Throws a mismatch. `expected` describes what the walk needed; `found` is the DOM node there,
|
|
34
|
+
* a description, or null when `at` (the parent) had no more children. `host` names the
|
|
35
|
+
* component and `loc` the template's call site.
|
|
36
|
+
*/
|
|
37
|
+
export function mismatch(expected, found, at, root, host, loc) {
|
|
38
|
+
const where = typeof found === 'object' && found !== null ? found : at;
|
|
39
|
+
const what = found === null
|
|
40
|
+
? `the end of ${describe(at)}`
|
|
41
|
+
: typeof found === 'string'
|
|
42
|
+
? found
|
|
43
|
+
: describe(found);
|
|
44
|
+
throw new HydrationMismatch(`gyral: hydration mismatch in ${host}${loc === undefined ? '' : ` (template at ${loc})`} ` +
|
|
45
|
+
`at ${pathOf(where, root)}: expected ${expected}, found ${what}.` +
|
|
46
|
+
(DEV
|
|
47
|
+
? " The server's HTML differs from the first client render: a view that isn't " +
|
|
48
|
+
'deterministic (Date.now(), locale), a third party that changed the DOM before ' +
|
|
49
|
+
'scripts ran, or a stale cached page (docs/design-docs/view/07-hydration.md ' +
|
|
50
|
+
'"Mismatches").'
|
|
51
|
+
: ''));
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=mismatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mismatch.js","sourceRoot":"","sources":["../../../src/view/render/mismatch.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,2FAA2F;AAC3F,0FAA0F;AAC1F,2FAA2F;AAC3F,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEhC,0EAA0E;AAC1E,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,yCAAyC;AACzC,SAAS,QAAQ,CAAC,IAAU;IAC1B,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,QAAQ,IAAI,CAAC,SAAS,CAAE,IAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;IAC3F,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,OAAQ,IAAgB,CAAC,IAAI,KAAK,CAAC;IACnE,OAAO,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,IAAK,IAAgB,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC;AAC/E,CAAC;AAED,0FAA0F;AAC1F,SAAS,MAAM,CAAC,IAAU,EAAE,IAAU;IACpC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAgB,IAAI,EAAE,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC;QAC3E,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC,eAAe,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,eAAe;YAAE,KAAK,EAAE,CAAC;QAC3E,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAE,CAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjG,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC7D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CACtB,QAAgB,EAChB,KAA2B,EAC3B,EAAQ,EACR,IAAU,EACV,IAAY,EACZ,GAAuB;IAEvB,MAAM,KAAK,GAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,MAAM,IAAI,GACR,KAAK,KAAK,IAAI;QACZ,CAAC,CAAC,cAAc,QAAQ,CAAC,EAAE,CAAC,EAAE;QAC9B,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;YACzB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxB,MAAM,IAAI,iBAAiB,CACzB,gCAAgC,IAAI,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,GAAG,GAAG,GAAG;QACxF,MAAM,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,QAAQ,WAAW,IAAI,GAAG;QACjE,CAAC,GAAG;YACF,CAAC,CAAC,6EAA6E;gBAC7E,gFAAgF;gBAChF,6EAA6E;gBAC7E,gBAAgB;YAClB,CAAC,CAAC,EAAE,CAAC,CACV,CAAC;AACJ,CAAC","sourcesContent":["// Hydration mismatches (view/07-hydration.md \"Mismatches\"): the server DOM differs from what\n// the first client render needs. The message names the component, the template's call site\n// (development builds know it), the path from the root to the node, and what was expected\n// and found. Development throws it; production recovers the one component (core's caller).\nimport { DEV } from '#view-dev';\n\n/** The server's DOM doesn't match the component's first client render. */\nexport class HydrationMismatch extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'HydrationMismatch';\n }\n}\n\n/** A short description of a DOM node. */\nfunction describe(node: Node): string {\n if (node.nodeType === 3) return `text ${JSON.stringify((node as Text).data.slice(0, 40))}`;\n if (node.nodeType === 8) return `<!--${(node as Comment).data}-->`;\n return node.nodeType === 1 ? `<${(node as Element).localName}>` : 'the root';\n}\n\n/** `div[0] › ul[2] › li[1]`: local names and child indexes from `root` down to `node`. */\nfunction pathOf(node: Node, root: Node): string {\n const steps: string[] = [];\n for (let n: Node | null = node; n !== null && n !== root; n = n.parentNode) {\n let index = 0;\n for (let s = n.previousSibling; s !== null; s = s.previousSibling) index++;\n steps.unshift(`${n.nodeType === 1 ? (n as Element).localName : n.nodeName}[${String(index)}]`);\n }\n return steps.length === 0 ? 'the root' : steps.join(' › ');\n}\n\n/**\n * Throws a mismatch. `expected` describes what the walk needed; `found` is the DOM node there,\n * a description, or null when `at` (the parent) had no more children. `host` names the\n * component and `loc` the template's call site.\n */\nexport function mismatch(\n expected: string,\n found: Node | string | null,\n at: Node,\n root: Node,\n host: string,\n loc: string | undefined,\n): never {\n const where = typeof found === 'object' && found !== null ? found : at;\n const what =\n found === null\n ? `the end of ${describe(at)}`\n : typeof found === 'string'\n ? found\n : describe(found);\n throw new HydrationMismatch(\n `gyral: hydration mismatch in ${host}${loc === undefined ? '' : ` (template at ${loc})`} ` +\n `at ${pathOf(where, root)}: expected ${expected}, found ${what}.` +\n (DEV\n ? \" The server's HTML differs from the first client render: a view that isn't \" +\n 'deterministic (Date.now(), locale), a third party that changed the DOM before ' +\n 'scripts ran, or a stale cached page (docs/design-docs/view/07-hydration.md ' +\n '\"Mismatches\").'\n : ''),\n );\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether moves into `parent` can use `moveBefore` (not Baseline yet: detected on the parent,
|
|
3
|
+
* once per reorder): the browser has it and the parent is in a document (state worth keeping
|
|
4
|
+
* only exists there, and both ends share a root).
|
|
5
|
+
*/
|
|
6
|
+
export declare const canMove: (parent: Node) => boolean;
|
|
7
|
+
/** Moves the nodes `first`…`last` (siblings, in order) before `ref` in `parent`. */
|
|
8
|
+
export declare function moveRange(parent: Node, first: Node, last: Node, ref: Node | null, move: boolean): void;
|
|
9
|
+
/** Removes the nodes `first`…`last` (siblings, in order). */
|
|
10
|
+
export declare function removeRange(first: Node, last: Node): void;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Moving and removing node ranges (view/03-lists.md "Row boundaries", reconciliation step 4).
|
|
2
|
+
// A row or instance is tracked by its first and last node, with no markers. Moves use
|
|
3
|
+
// `moveBefore()` where the browser has it (it keeps focus, selection, animations, iframe and
|
|
4
|
+
// media state); elsewhere `insertBefore` (ADR 0003 tier 2: an inline fallback).
|
|
5
|
+
/**
|
|
6
|
+
* Whether moves into `parent` can use `moveBefore` (not Baseline yet: detected on the parent,
|
|
7
|
+
* once per reorder): the browser has it and the parent is in a document (state worth keeping
|
|
8
|
+
* only exists there, and both ends share a root).
|
|
9
|
+
*/
|
|
10
|
+
export const canMove = (parent) => 'moveBefore' in parent && parent.isConnected;
|
|
11
|
+
/** Moves the nodes `first`…`last` (siblings, in order) before `ref` in `parent`. */
|
|
12
|
+
export function moveRange(parent, first, last, ref, move) {
|
|
13
|
+
for (let node = first;;) {
|
|
14
|
+
const next = node.nextSibling;
|
|
15
|
+
if (move)
|
|
16
|
+
parent.moveBefore(node, ref);
|
|
17
|
+
else
|
|
18
|
+
parent.insertBefore(node, ref);
|
|
19
|
+
if (node === last || next === null)
|
|
20
|
+
return;
|
|
21
|
+
node = next;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Removes the nodes `first`…`last` (siblings, in order). */
|
|
25
|
+
export function removeRange(first, last) {
|
|
26
|
+
const parent = first.parentNode;
|
|
27
|
+
if (parent === null)
|
|
28
|
+
return;
|
|
29
|
+
for (let node = first;;) {
|
|
30
|
+
const next = node.nextSibling;
|
|
31
|
+
parent.removeChild(node);
|
|
32
|
+
if (node === last || next === null)
|
|
33
|
+
return;
|
|
34
|
+
node = next;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=nodes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodes.js","sourceRoot":"","sources":["../../../src/view/render/nodes.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,sFAAsF;AACtF,6FAA6F;AAC7F,gFAAgF;AAMhF;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAY,EAAW,EAAE,CAAC,YAAY,IAAI,MAAM,IAAI,MAAM,CAAC,WAAW,CAAC;AAE/F,oFAAoF;AACpF,MAAM,UAAU,SAAS,CACvB,MAAY,EACZ,KAAW,EACX,IAAU,EACV,GAAgB,EAChB,IAAa;IAEb,KAAK,IAAI,IAAI,GAAG,KAAK,IAAK,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC;QAC9B,IAAI,IAAI;YAAG,MAAkC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;;YAC/D,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACpC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO;QAC3C,IAAI,GAAG,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,WAAW,CAAC,KAAW,EAAE,IAAU;IACjD,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC;IAChC,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO;IAC5B,KAAK,IAAI,IAAI,GAAG,KAAK,IAAK,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC;QAC9B,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACzB,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO;QAC3C,IAAI,GAAG,IAAI,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["// Moving and removing node ranges (view/03-lists.md \"Row boundaries\", reconciliation step 4).\n// A row or instance is tracked by its first and last node, with no markers. Moves use\n// `moveBefore()` where the browser has it (it keeps focus, selection, animations, iframe and\n// media state); elsewhere `insertBefore` (ADR 0003 tier 2: an inline fallback).\n\ninterface MovingParent {\n moveBefore(node: Node, child: Node | null): void;\n}\n\n/**\n * Whether moves into `parent` can use `moveBefore` (not Baseline yet: detected on the parent,\n * once per reorder): the browser has it and the parent is in a document (state worth keeping\n * only exists there, and both ends share a root).\n */\nexport const canMove = (parent: Node): boolean => 'moveBefore' in parent && parent.isConnected;\n\n/** Moves the nodes `first`…`last` (siblings, in order) before `ref` in `parent`. */\nexport function moveRange(\n parent: Node,\n first: Node,\n last: Node,\n ref: Node | null,\n move: boolean,\n): void {\n for (let node = first; ;) {\n const next = node.nextSibling;\n if (move) (parent as unknown as MovingParent).moveBefore(node, ref);\n else parent.insertBefore(node, ref);\n if (node === last || next === null) return;\n node = next;\n }\n}\n\n/** Removes the nodes `first`…`last` (siblings, in order). */\nexport function removeRange(first: Node, last: Node): void {\n const parent = first.parentNode;\n if (parent === null) return;\n for (let node = first; ;) {\n const next = node.nextSibling;\n parent.removeChild(node);\n if (node === last || next === null) return;\n node = next;\n }\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** A row, as far as placing it goes. */
|
|
2
|
+
export interface Placeable {
|
|
3
|
+
first(): Node | null;
|
|
4
|
+
last(): Node | null;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Marks (1) the positions of one longest strictly increasing subsequence of `src`, ignoring
|
|
8
|
+
* negative entries (new rows). O(n log n).
|
|
9
|
+
*/
|
|
10
|
+
export declare function lis(src: Int32Array): Uint8Array;
|
|
11
|
+
/**
|
|
12
|
+
* Places `rows[from..to]` before `end` in `parent`, back to front. `src[i - from]` is the old
|
|
13
|
+
* position of a reused row, or -1 for a new row (its nodes wait in a fragment). Reused rows
|
|
14
|
+
* marked in `keep` stay (all of them when `keep` is undefined: they are already in order); the
|
|
15
|
+
* others move. Rows that stay cost two array reads; only a row that moves looks up its
|
|
16
|
+
* reference node.
|
|
17
|
+
*/
|
|
18
|
+
export declare function placeRows(parent: Node, rows: readonly Placeable[], from: number, to: number, src: Int32Array, keep: Uint8Array | undefined, end: Node | null): void;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Putting a list's reordered rows in place with the fewest DOM moves (view/03-lists.md
|
|
2
|
+
// "Reconciliation", step 3): the rows whose old positions form a longest increasing
|
|
3
|
+
// subsequence (or that a two-ended scan matched in place) stay; every other reused row moves,
|
|
4
|
+
// and new rows are inserted. The benchmark behind the plan is recorded in the spec.
|
|
5
|
+
import { canMove, moveRange } from './nodes.js';
|
|
6
|
+
/**
|
|
7
|
+
* Marks (1) the positions of one longest strictly increasing subsequence of `src`, ignoring
|
|
8
|
+
* negative entries (new rows). O(n log n).
|
|
9
|
+
*/
|
|
10
|
+
export function lis(src) {
|
|
11
|
+
const n = src.length;
|
|
12
|
+
const tails = new Int32Array(n);
|
|
13
|
+
const prev = new Int32Array(n);
|
|
14
|
+
let len = 0;
|
|
15
|
+
for (let i = 0; i < n; i++) {
|
|
16
|
+
const v = src[i];
|
|
17
|
+
if (v < 0)
|
|
18
|
+
continue;
|
|
19
|
+
let lo = 0;
|
|
20
|
+
let hi = len;
|
|
21
|
+
while (lo < hi) {
|
|
22
|
+
const mid = (lo + hi) >> 1;
|
|
23
|
+
if (src[tails[mid]] < v)
|
|
24
|
+
lo = mid + 1;
|
|
25
|
+
else
|
|
26
|
+
hi = mid;
|
|
27
|
+
}
|
|
28
|
+
prev[i] = lo > 0 ? tails[lo - 1] : -1;
|
|
29
|
+
tails[lo] = i;
|
|
30
|
+
if (lo === len)
|
|
31
|
+
len++;
|
|
32
|
+
}
|
|
33
|
+
const keep = new Uint8Array(n);
|
|
34
|
+
for (let k = len > 0 ? tails[len - 1] : -1; k >= 0; k = prev[k]) {
|
|
35
|
+
keep[k] = 1;
|
|
36
|
+
}
|
|
37
|
+
return keep;
|
|
38
|
+
}
|
|
39
|
+
/** The first node of `rows[from…to]` (already placed), or `end`. */
|
|
40
|
+
function nodeAfter(rows, from, to, end) {
|
|
41
|
+
for (let i = from; i <= to; i++) {
|
|
42
|
+
const node = rows[i].first();
|
|
43
|
+
if (node !== null)
|
|
44
|
+
return node;
|
|
45
|
+
}
|
|
46
|
+
return end;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Places `rows[from..to]` before `end` in `parent`, back to front. `src[i - from]` is the old
|
|
50
|
+
* position of a reused row, or -1 for a new row (its nodes wait in a fragment). Reused rows
|
|
51
|
+
* marked in `keep` stay (all of them when `keep` is undefined: they are already in order); the
|
|
52
|
+
* others move. Rows that stay cost two array reads; only a row that moves looks up its
|
|
53
|
+
* reference node.
|
|
54
|
+
*/
|
|
55
|
+
export function placeRows(parent, rows, from, to, src, keep, end) {
|
|
56
|
+
const move = canMove(parent);
|
|
57
|
+
for (let i = to; i >= from; i--) {
|
|
58
|
+
const fresh = src[i - from] < 0;
|
|
59
|
+
if (!fresh && (keep === undefined || keep[i - from] === 1))
|
|
60
|
+
continue;
|
|
61
|
+
const row = rows[i];
|
|
62
|
+
const first = row.first();
|
|
63
|
+
if (first === null)
|
|
64
|
+
continue;
|
|
65
|
+
const ref = nodeAfter(rows, i + 1, to, end);
|
|
66
|
+
moveRange(parent, first, row.last(), ref, !fresh && move);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=place.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"place.js","sourceRoot":"","sources":["../../../src/view/render/place.ts"],"names":[],"mappings":"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","sourcesContent":["// Putting a list's reordered rows in place with the fewest DOM moves (view/03-lists.md\n// \"Reconciliation\", step 3): the rows whose old positions form a longest increasing\n// subsequence (or that a two-ended scan matched in place) stay; every other reused row moves,\n// and new rows are inserted. The benchmark behind the plan is recorded in the spec.\nimport { canMove, moveRange } from './nodes.js';\n\n/** A row, as far as placing it goes. */\nexport interface Placeable {\n first(): Node | null;\n last(): Node | null;\n}\n\n/**\n * Marks (1) the positions of one longest strictly increasing subsequence of `src`, ignoring\n * negative entries (new rows). O(n log n).\n */\nexport function lis(src: Int32Array): Uint8Array {\n const n = src.length;\n const tails = new Int32Array(n);\n const prev = new Int32Array(n);\n let len = 0;\n for (let i = 0; i < n; i++) {\n const v = src[i] as number;\n if (v < 0) continue;\n let lo = 0;\n let hi = len;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if ((src[tails[mid] as number] as number) < v) lo = mid + 1;\n else hi = mid;\n }\n prev[i] = lo > 0 ? (tails[lo - 1] as number) : -1;\n tails[lo] = i;\n if (lo === len) len++;\n }\n const keep = new Uint8Array(n);\n for (let k = len > 0 ? (tails[len - 1] as number) : -1; k >= 0; k = prev[k] as number) {\n keep[k] = 1;\n }\n return keep;\n}\n\n/** The first node of `rows[from…to]` (already placed), or `end`. */\nfunction nodeAfter(\n rows: readonly Placeable[],\n from: number,\n to: number,\n end: Node | null,\n): Node | null {\n for (let i = from; i <= to; i++) {\n const node = (rows[i] as Placeable).first();\n if (node !== null) return node;\n }\n return end;\n}\n\n/**\n * Places `rows[from..to]` before `end` in `parent`, back to front. `src[i - from]` is the old\n * position of a reused row, or -1 for a new row (its nodes wait in a fragment). Reused rows\n * marked in `keep` stay (all of them when `keep` is undefined: they are already in order); the\n * others move. Rows that stay cost two array reads; only a row that moves looks up its\n * reference node.\n */\nexport function placeRows(\n parent: Node,\n rows: readonly Placeable[],\n from: number,\n to: number,\n src: Int32Array,\n keep: Uint8Array | undefined,\n end: Node | null,\n): void {\n const move = canMove(parent);\n for (let i = to; i >= from; i--) {\n const fresh = (src[i - from] as number) < 0;\n if (!fresh && (keep === undefined || keep[i - from] === 1)) continue;\n const row = rows[i] as Placeable;\n const first = row.first();\n if (first === null) continue;\n const ref = nodeAfter(rows, i + 1, to, end);\n moveRange(parent, first, row.last() as Node, ref, !fresh && move);\n }\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type TemplateObject } from '../normalize/types.js';
|
|
2
|
+
/** Plan kinds of child parts (element parts use their attr-parts.ts kind, ≥ 0). */
|
|
3
|
+
export declare const CHILD = -1;
|
|
4
|
+
export declare const SOLE = -2;
|
|
5
|
+
export declare const ROOT = -3;
|
|
6
|
+
export interface Plan {
|
|
7
|
+
readonly content: DocumentFragment;
|
|
8
|
+
/** One root node and no root-level holes: clone that node instead of the fragment. */
|
|
9
|
+
readonly single: boolean;
|
|
10
|
+
/** Per target node, in document order: keep depth, sibling skip (-1: none), n, n indexes. */
|
|
11
|
+
readonly ops: readonly number[];
|
|
12
|
+
readonly targets: number;
|
|
13
|
+
/** Per part: its element's (or child part's parent's) target, its reference node's target. */
|
|
14
|
+
readonly a: readonly number[];
|
|
15
|
+
readonly b: readonly number[];
|
|
16
|
+
/** Per part: the index of its (first) value, and its kind. */
|
|
17
|
+
readonly at: readonly number[];
|
|
18
|
+
readonly kinds: readonly number[];
|
|
19
|
+
}
|
|
20
|
+
/** Scratch space for walks (never re-entrant: nested instances are created after the walk). */
|
|
21
|
+
export declare const stack: Node[];
|
|
22
|
+
export declare const nodes: Node[];
|
|
23
|
+
/** Fills `nodes` with each target of `plan`, walking from `stack[0]` (or `stack[1]`). */
|
|
24
|
+
export declare function walk(plan: Plan): void;
|
|
25
|
+
/** The plan of `template` (one-entry cache in front of the WeakMap: rows repeat a template). */
|
|
26
|
+
export declare function planOf(template: TemplateObject): Plan;
|