@frontiers-labs/argon 0.4.0 → 0.5.1
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/dist/annotations.d.ts +3 -0
- package/dist/annotations.d.ts.map +1 -1
- package/dist/annotations.js +9 -0
- package/dist/annotations.js.map +1 -1
- package/dist/codegen/client.d.ts.map +1 -1
- package/dist/codegen/client.js +291 -32
- package/dist/codegen/client.js.map +1 -1
- package/dist/codegen/dts.d.ts.map +1 -1
- package/dist/codegen/dts.js +9 -0
- package/dist/codegen/dts.js.map +1 -1
- package/dist/codegen/rust.d.ts.map +1 -1
- package/dist/codegen/rust.js +164 -12
- package/dist/codegen/rust.js.map +1 -1
- package/dist/component.d.ts +5 -0
- package/dist/component.d.ts.map +1 -1
- package/dist/component.js.map +1 -1
- package/dist/ir.d.ts +26 -0
- package/dist/ir.d.ts.map +1 -1
- package/dist/ir.js +4 -0
- package/dist/ir.js.map +1 -1
- package/dist/jsx.d.ts.map +1 -1
- package/dist/jsx.js +17 -12
- package/dist/jsx.js.map +1 -1
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +125 -1
- package/dist/lower.js.map +1 -1
- package/dist/template.d.ts.map +1 -1
- package/dist/template.js +10 -4
- package/dist/template.js.map +1 -1
- package/package.json +1 -1
package/dist/annotations.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export type Component = string & {
|
|
|
3
3
|
};
|
|
4
4
|
export declare function css(strings: TemplateStringsArray, ...values: any[]): string;
|
|
5
5
|
export declare function state<T>(initial: T): T;
|
|
6
|
+
export declare function store<T>(initial: T): T;
|
|
7
|
+
export declare function derived<T>(compute: () => T): T;
|
|
6
8
|
export declare function unsafeHtml(html: string): string;
|
|
7
9
|
export interface Ref<T extends Element = Element> {
|
|
8
10
|
readonly current: T | null;
|
|
@@ -10,6 +12,7 @@ export interface Ref<T extends Element = Element> {
|
|
|
10
12
|
export declare function ref<T extends Element = Element>(): Ref<T>;
|
|
11
13
|
export declare function onMount(callback: () => void | (() => void)): void;
|
|
12
14
|
export declare function effect(callback: () => void | (() => void)): void;
|
|
15
|
+
export declare function emit(target: EventTarget, name: string, detail?: unknown): void;
|
|
13
16
|
declare global {
|
|
14
17
|
namespace JSX {
|
|
15
18
|
type Element = string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../src/annotations.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG;IAAE,aAAa,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAE1D,wBAAgB,GAAG,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,CAE3E;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAEtC;AAMD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAKD,MAAM,WAAW,GAAG,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO;IAC9C,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAgB,GAAG,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAEzD;AAED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAEjE;AAED,wBAAgB,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAEhE;AAKD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,GAAG,CAAC;QACZ,KAAK,OAAO,GAAG,MAAM,CAAC;QACtB,UAAU,iBAAiB;YACzB,CAAC,OAAO,EAAE,MAAM,GAAG;gBAAE,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAA;aAAE,CAAC;SACrD;KACF;CACF"}
|
|
1
|
+
{"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../src/annotations.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG;IAAE,aAAa,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAE1D,wBAAgB,GAAG,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,CAE3E;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAEtC;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAEtC;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAE9C;AAMD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAKD,MAAM,WAAW,GAAG,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO;IAC9C,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAgB,GAAG,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAEzD;AAED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAEjE;AAED,wBAAgB,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAEhE;AAED,wBAAgB,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAE9E;AAKD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,GAAG,CAAC;QACZ,KAAK,OAAO,GAAG,MAAM,CAAC;QACtB,UAAU,iBAAiB;YACzB,CAAC,OAAO,EAAE,MAAM,GAAG;gBAAE,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAA;aAAE,CAAC;SACrD;KACF;CACF"}
|
package/dist/annotations.js
CHANGED
|
@@ -4,6 +4,12 @@ export function css(strings, ...values) {
|
|
|
4
4
|
export function state(initial) {
|
|
5
5
|
return initial;
|
|
6
6
|
}
|
|
7
|
+
export function store(initial) {
|
|
8
|
+
return initial;
|
|
9
|
+
}
|
|
10
|
+
export function derived(compute) {
|
|
11
|
+
return compute();
|
|
12
|
+
}
|
|
7
13
|
// Compile-time marker: interpolate the string as raw HTML instead of escaping
|
|
8
14
|
// it. Identity at runtime — the name carries the audit burden (grep for it the
|
|
9
15
|
// way you would `dangerouslySetInnerHTML`). Only feed it markup you trust or
|
|
@@ -20,4 +26,7 @@ export function onMount(callback) {
|
|
|
20
26
|
export function effect(callback) {
|
|
21
27
|
void callback;
|
|
22
28
|
}
|
|
29
|
+
export function emit(target, name, detail) {
|
|
30
|
+
target.dispatchEvent(new CustomEvent(name, { bubbles: true, composed: true, detail }));
|
|
31
|
+
}
|
|
23
32
|
//# sourceMappingURL=annotations.js.map
|
package/dist/annotations.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"annotations.js","sourceRoot":"","sources":["../src/annotations.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,GAAG,CAAC,OAA6B,EAAE,GAAG,MAAa;IACjE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AACxF,CAAC;AAED,MAAM,UAAU,KAAK,CAAI,OAAU;IACjC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,8EAA8E;AAC9E,+EAA+E;AAC/E,6EAA6E;AAC7E,gFAAgF;AAChF,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,IAAI,CAAC;AACd,CAAC;AASD,MAAM,UAAU,GAAG;IACjB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,QAAmC;IACzD,KAAK,QAAQ,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,QAAmC;IACxD,KAAK,QAAQ,CAAC;AAChB,CAAC"}
|
|
1
|
+
{"version":3,"file":"annotations.js","sourceRoot":"","sources":["../src/annotations.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,GAAG,CAAC,OAA6B,EAAE,GAAG,MAAa;IACjE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AACxF,CAAC;AAED,MAAM,UAAU,KAAK,CAAI,OAAU;IACjC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,KAAK,CAAI,OAAU;IACjC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,OAAO,CAAI,OAAgB;IACzC,OAAO,OAAO,EAAE,CAAC;AACnB,CAAC;AAED,8EAA8E;AAC9E,+EAA+E;AAC/E,6EAA6E;AAC7E,gFAAgF;AAChF,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,IAAI,CAAC;AACd,CAAC;AASD,MAAM,UAAU,GAAG;IACjB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,QAAmC;IACzD,KAAK,QAAQ,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,QAAmC;IACxD,KAAK,QAAQ,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,MAAmB,EAAE,IAAY,EAAE,MAAgB;IACtE,MAAM,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AACzF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/codegen/client.ts"],"names":[],"mappings":"AAQA,OAAO,EAWL,KAAK,QAAQ,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/codegen/client.ts"],"names":[],"mappings":"AAQA,OAAO,EAWL,KAAK,QAAQ,EAMd,MAAM,UAAU,CAAC;AAUlB,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,QAAQ,CAAC;IAElB,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAQD,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAE,aAAkB,GAAG,MAAM,CAEhF;AAGD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAE,aAAkB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CA2D5G"}
|
package/dist/codegen/client.js
CHANGED
|
@@ -20,6 +20,9 @@ export function compileClient(module, opts = {}) {
|
|
|
20
20
|
}
|
|
21
21
|
// Full result including the source map (used by the CLI to write .js.map).
|
|
22
22
|
export function compileClientCore(module, opts = {}) {
|
|
23
|
+
if (module.components.length === 0 && module.stores.length > 0) {
|
|
24
|
+
return { code: generateStoreModule(module.stores) };
|
|
25
|
+
}
|
|
23
26
|
if (module.components.length === 0) {
|
|
24
27
|
throw new ArgonCompileError([{
|
|
25
28
|
code: "ARGON001",
|
|
@@ -44,7 +47,7 @@ export function compileClientCore(module, opts = {}) {
|
|
|
44
47
|
}
|
|
45
48
|
}
|
|
46
49
|
for (const component of module.components) {
|
|
47
|
-
edits.push({ start: component.span.start, end: component.span.end, text: generateClass(component, !!opts.compat03) });
|
|
50
|
+
edits.push({ start: component.span.start, end: component.span.end, text: generateClass(component, !!opts.compat03, storeAliases(module)) });
|
|
48
51
|
}
|
|
49
52
|
edits.sort((a, b) => b.start - a.start);
|
|
50
53
|
let out = module.sourceText;
|
|
@@ -61,14 +64,95 @@ export function compileClientCore(module, opts = {}) {
|
|
|
61
64
|
transformers: { before: [stripTags] },
|
|
62
65
|
});
|
|
63
66
|
const composedImports = module.composedImports.map(spec => `import ${JSON.stringify(spec)};\n`).join("");
|
|
67
|
+
const storeImports = [...storeAliases(module)].map(([spec, alias]) => `import { argonSubscribe as ${alias} } from ${JSON.stringify(spec)};\n`).join("");
|
|
64
68
|
// Drop tsc's sourceMappingURL (it derives the wrong extension from the .tsx
|
|
65
69
|
// input); the caller appends the correct `<name>.js.map` reference.
|
|
66
70
|
const body = transpiled.outputText.replace(/\n?\/\/# sourceMappingURL=[^\n]*\n?$/, "");
|
|
67
71
|
const code = "// Generated by Argon compiler — do not edit by hand.\n// CSR output: browser-only hydration and reactive updates. SSR data evaluation stays out of this file.\n\n" +
|
|
68
72
|
composedImports +
|
|
73
|
+
storeImports +
|
|
69
74
|
body.trimStart();
|
|
70
75
|
return { code, map: transpiled.sourceMapText };
|
|
71
76
|
}
|
|
77
|
+
function storeAliases(module) {
|
|
78
|
+
const specs = new Set();
|
|
79
|
+
const note = (expr) => {
|
|
80
|
+
visitExpr(expr, e => {
|
|
81
|
+
if (e.kind === "store")
|
|
82
|
+
specs.add(e.module);
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
for (const component of module.components) {
|
|
86
|
+
for (const stmt of component.setup) {
|
|
87
|
+
if (stmt.kind === "let")
|
|
88
|
+
note(stmt.init);
|
|
89
|
+
}
|
|
90
|
+
for (const expr of component.template.exprs)
|
|
91
|
+
note(expr);
|
|
92
|
+
}
|
|
93
|
+
return new Map([...specs].map((spec, i) => [spec, `__argonStoreSubscribe${i}`]));
|
|
94
|
+
}
|
|
95
|
+
function generateStoreModule(stores) {
|
|
96
|
+
const printInitial = (expr) => printExpr(expr, text => text);
|
|
97
|
+
const lines = [
|
|
98
|
+
"// Generated by Argon compiler — do not edit by hand.",
|
|
99
|
+
"// CSR store output: reactive shared state with no runtime dependency.",
|
|
100
|
+
"",
|
|
101
|
+
"const __argonSubs = new Map();",
|
|
102
|
+
"",
|
|
103
|
+
"function __argonNotify(key) {",
|
|
104
|
+
" for (const fn of __argonSubs.get(key) ?? []) fn();",
|
|
105
|
+
"}",
|
|
106
|
+
"",
|
|
107
|
+
"export function argonSubscribe(key, fn) {",
|
|
108
|
+
" let set = __argonSubs.get(key);",
|
|
109
|
+
" if (!set) __argonSubs.set(key, set = new Set());",
|
|
110
|
+
" set.add(fn);",
|
|
111
|
+
" return () => {",
|
|
112
|
+
" set.delete(fn);",
|
|
113
|
+
" if (set.size === 0) __argonSubs.delete(key);",
|
|
114
|
+
" };",
|
|
115
|
+
"}",
|
|
116
|
+
"",
|
|
117
|
+
];
|
|
118
|
+
for (const store of stores) {
|
|
119
|
+
if (store.derived) {
|
|
120
|
+
const slot = `__argon_${store.name}`;
|
|
121
|
+
const deps = [...referencedNames(store.derived)]
|
|
122
|
+
.filter(name => name.startsWith("store::"))
|
|
123
|
+
.map(name => name.slice("store::".length));
|
|
124
|
+
lines.push(`function __argonCompute_${store.name}() {`, ` return ${printInitial(store.derived)};`, `}`, `let ${slot} = __argonCompute_${store.name}();`, `export const ${store.name} = {`, ` get value() { return ${slot}; },`, `};`, `function __argonUpdate_${store.name}() {`, ` const value = __argonCompute_${store.name}();`, ` if (Object.is(${slot}, value)) return;`, ` ${slot} = value;`, ` __argonNotify(${JSON.stringify(store.name)});`, `}`, ...deps.map(dep => `argonSubscribe(${JSON.stringify(dep)}, __argonUpdate_${store.name});`), "");
|
|
125
|
+
}
|
|
126
|
+
else if (store.fields) {
|
|
127
|
+
lines.push(`export const ${store.name} = {};`);
|
|
128
|
+
for (const field of store.fields) {
|
|
129
|
+
const slot = `__argon_${store.name}_${field.name}`;
|
|
130
|
+
const key = `${store.name}.${field.name}`;
|
|
131
|
+
lines.push(`let ${slot} = ${printInitial(field.initial)};`, `Object.defineProperty(${store.name}, ${JSON.stringify(field.name)}, {`, ` enumerable: true,`, ` get() { return ${slot}; },`, ` set(value) {`, ` if (Object.is(${slot}, value)) return;`, ` ${slot} = value;`, ` __argonNotify(${JSON.stringify(key)});`, ` },`, `});`, "");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else if (store.initial) {
|
|
135
|
+
const slot = `__argon_${store.name}`;
|
|
136
|
+
lines.push(`let ${slot} = ${printInitial(store.initial)};`, `export const ${store.name} = {`, ` get value() { return ${slot}; },`, ` set value(value) {`, ` if (Object.is(${slot}, value)) return;`, ` ${slot} = value;`, ` __argonNotify(${JSON.stringify(store.name)});`, ` },`, `};`, "");
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
lines.push("export function argonSnapshot() {", " return {", stores.map(store => store.fields
|
|
140
|
+
? ` ${store.name}: { ${store.fields.map(f => `${f.name}: ${store.name}.${f.name}`).join(", ")} },`
|
|
141
|
+
: ` ${store.name}: ${store.name}.value,`).join("\n"), " };", "}", "", "export function argonHydrate(snapshot) {", " if (!snapshot) return;");
|
|
142
|
+
for (const store of stores) {
|
|
143
|
+
if (store.fields) {
|
|
144
|
+
lines.push(` if (snapshot.${store.name}) {`);
|
|
145
|
+
for (const field of store.fields)
|
|
146
|
+
lines.push(` if (${JSON.stringify(field.name)} in snapshot.${store.name}) ${store.name}.${field.name} = snapshot.${store.name}.${field.name};`);
|
|
147
|
+
lines.push(" }");
|
|
148
|
+
}
|
|
149
|
+
else if (!store.derived) {
|
|
150
|
+
lines.push(` if (${JSON.stringify(store.name)} in snapshot) ${store.name}.value = snapshot.${store.name};`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
lines.push("}", "", "const __argonPayload = globalThis.document?.querySelector?.('script[type=\"application/json\"][data-argon-stores]');", "if (__argonPayload?.textContent) argonHydrate(JSON.parse(__argonPayload.textContent));", "");
|
|
154
|
+
return lines.join("\n");
|
|
155
|
+
}
|
|
72
156
|
// JSX compiles only in template value positions, where lowering turns it into
|
|
73
157
|
// string templates. Opaque code containing JSX (event handlers, module
|
|
74
158
|
// helpers, untyped consts) would pass through verbatim and break the emitted
|
|
@@ -88,6 +172,12 @@ function collectJsxOpaque(module) {
|
|
|
88
172
|
visitExpr(expr, e => {
|
|
89
173
|
if (e.kind === "opaque" && e.hasJsx)
|
|
90
174
|
flag(e.diagnostic.span);
|
|
175
|
+
if (e.kind === "template") {
|
|
176
|
+
for (const event of e.events ?? []) {
|
|
177
|
+
if (event.handler.kind === "opaque" && event.handler.hasJsx)
|
|
178
|
+
flag(event.handler.diagnostic.span);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
91
181
|
});
|
|
92
182
|
};
|
|
93
183
|
for (const decl of module.decls) {
|
|
@@ -142,11 +232,25 @@ function kebab(name) {
|
|
|
142
232
|
// untouched. `kind` controls printing: statements keep trailing semicolons,
|
|
143
233
|
// expressions must not have one (they land inside `${...}` and call sites).
|
|
144
234
|
function rewriteRefs(text, refs, states, kind) {
|
|
145
|
-
if (refs.size === 0 && states.size === 0)
|
|
146
|
-
return text.trim();
|
|
147
235
|
const sf = ts.createSourceFile("_.ts", text, ts.ScriptTarget.Latest, true);
|
|
148
236
|
const transformer = ctx => {
|
|
149
237
|
const visit = (node) => {
|
|
238
|
+
if (ts.isCallExpression(node) &&
|
|
239
|
+
ts.isIdentifier(node.expression) &&
|
|
240
|
+
node.expression.text === "emit" &&
|
|
241
|
+
node.arguments.length >= 2) {
|
|
242
|
+
const [target, name, detail] = node.arguments;
|
|
243
|
+
return ctx.factory.createCallExpression(ctx.factory.createPropertyAccessExpression(ts.visitNode(target, visit), "dispatchEvent"), undefined, [
|
|
244
|
+
ctx.factory.createNewExpression(ctx.factory.createIdentifier("CustomEvent"), undefined, [
|
|
245
|
+
ts.visitNode(name, visit),
|
|
246
|
+
ctx.factory.createObjectLiteralExpression([
|
|
247
|
+
ctx.factory.createPropertyAssignment("bubbles", ctx.factory.createTrue()),
|
|
248
|
+
ctx.factory.createPropertyAssignment("composed", ctx.factory.createTrue()),
|
|
249
|
+
ctx.factory.createPropertyAssignment("detail", detail ? ts.visitNode(detail, visit) : ctx.factory.createVoidZero()),
|
|
250
|
+
]),
|
|
251
|
+
]),
|
|
252
|
+
]);
|
|
253
|
+
}
|
|
150
254
|
if (ts.isBinaryExpression(node) &&
|
|
151
255
|
ts.isIdentifier(node.left) &&
|
|
152
256
|
states.has(node.left.text)) {
|
|
@@ -203,6 +307,7 @@ function printExpr(e, opaque, attrEnc = "esc") {
|
|
|
203
307
|
case "num": return e.text;
|
|
204
308
|
case "bool": return String(e.value);
|
|
205
309
|
case "ref": return e.space === "prop" || e.space === "state" ? `this.#${e.name}` : e.name;
|
|
310
|
+
case "store": return e.field ? `${e.local}.${e.field}` : `${e.local}.value`;
|
|
206
311
|
case "member": return `${po(e.object)}.${e.name}`;
|
|
207
312
|
case "length": return `${po(e.object)}.length`;
|
|
208
313
|
case "index": return `${po(e.object)}[${p(e.index)}]`;
|
|
@@ -301,7 +406,7 @@ function coerce(type, value) {
|
|
|
301
406
|
}
|
|
302
407
|
}
|
|
303
408
|
// ── Class generation ─────────────────────────────────────────────────────────
|
|
304
|
-
function generateClass(component, compat03 = false) {
|
|
409
|
+
function generateClass(component, compat03 = false, storeAliases = new Map()) {
|
|
305
410
|
const props = new Set(component.props.map(p => p.name));
|
|
306
411
|
const states = new Set(component.states.map(s => s.name));
|
|
307
412
|
const refs = new Set([...props, ...states, ...component.refs]);
|
|
@@ -309,6 +414,40 @@ function generateClass(component, compat03 = false) {
|
|
|
309
414
|
const opaqueExpr = text => rewriteRefs(text, refs, states, "expr");
|
|
310
415
|
const opaqueStmt = text => rewriteRefs(text, refs, states, "stmts");
|
|
311
416
|
const print = (e) => printExpr(e, opaqueExpr);
|
|
417
|
+
const templateEventsIn = (expr) => {
|
|
418
|
+
const events = [];
|
|
419
|
+
visitExpr(expr, e => {
|
|
420
|
+
if (e.kind === "template") {
|
|
421
|
+
for (const event of e.events ?? [])
|
|
422
|
+
events.push(event);
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
return events;
|
|
426
|
+
};
|
|
427
|
+
const nestedEvents = [];
|
|
428
|
+
const noteNestedEvents = (expr) => {
|
|
429
|
+
nestedEvents.push(...templateEventsIn(expr));
|
|
430
|
+
};
|
|
431
|
+
for (const stmt of component.setup)
|
|
432
|
+
if (stmt.kind === "let")
|
|
433
|
+
noteNestedEvents(stmt.init);
|
|
434
|
+
for (const expr of template.exprs)
|
|
435
|
+
noteNestedEvents(expr);
|
|
436
|
+
const storeDeps = new Map();
|
|
437
|
+
const noteStoreDeps = (expr) => {
|
|
438
|
+
visitExpr(expr, e => {
|
|
439
|
+
if (e.kind !== "store")
|
|
440
|
+
return;
|
|
441
|
+
const deps = storeDeps.get(e.module) ?? new Set();
|
|
442
|
+
deps.add(e.key);
|
|
443
|
+
storeDeps.set(e.module, deps);
|
|
444
|
+
});
|
|
445
|
+
};
|
|
446
|
+
for (const stmt of component.setup)
|
|
447
|
+
if (stmt.kind === "let")
|
|
448
|
+
noteStoreDeps(stmt.init);
|
|
449
|
+
for (const expr of template.exprs)
|
|
450
|
+
noteStoreDeps(expr);
|
|
312
451
|
// ── Escape-by-default text rendering (mirrors the Rust backend) ──
|
|
313
452
|
//
|
|
314
453
|
// Setup locals whose value is markup (a JSX string) read raw; every other
|
|
@@ -376,11 +515,30 @@ function generateClass(component, compat03 = false) {
|
|
|
376
515
|
};
|
|
377
516
|
// A map whose items are markup: render each item's result through textExpr so
|
|
378
517
|
// interpolated scalar parts are escaped while the markup passes through.
|
|
379
|
-
const
|
|
518
|
+
const mapEventItem = (html, ctx, events) => {
|
|
519
|
+
if (events.length === 0)
|
|
520
|
+
return html;
|
|
521
|
+
const handlers = `{ ${events.map(event => `${JSON.stringify(event.id)}: ${print(event.handler)}`).join(", ")} }`;
|
|
522
|
+
const ids = `[${[...new Set(events.map(event => event.id))].map(id => JSON.stringify(String(id))).join(", ")}]`;
|
|
523
|
+
return `this.#mapEventItem(${html}, ${ctx}, ${handlers}, ${ids})`;
|
|
524
|
+
};
|
|
525
|
+
const printMapText = (m, result = textExpr, eventContext) => {
|
|
526
|
+
const events = templateEventsIn(m.body.result);
|
|
527
|
+
const needsIndex = events.length > 0 && !eventContext?.key && !m.indexVar;
|
|
380
528
|
const item = typeof m.item === "string" ? m.item : `[${m.item.join(", ")}]`;
|
|
381
|
-
const
|
|
529
|
+
const indexVar = m.indexVar ?? (needsIndex ? "__argonIndex" : undefined);
|
|
530
|
+
const params = indexVar ? `(${item}, ${indexVar})` : `(${item})`;
|
|
382
531
|
const pre = m.body.stmts.map(s => printStmt(s, opaqueExpr, undefined, "esc")).join(" ");
|
|
383
|
-
const
|
|
532
|
+
const rendered = (() => {
|
|
533
|
+
const html = result(m.body.result);
|
|
534
|
+
if (events.length === 0 || !eventContext || eventContext.key)
|
|
535
|
+
return html;
|
|
536
|
+
const ctx = eventContext.key
|
|
537
|
+
? `${JSON.stringify(`${eventContext.bindingId}:`)} + ${print(eventContext.key)}`
|
|
538
|
+
: `${JSON.stringify(`${eventContext.bindingId}:`)} + ${indexVar}`;
|
|
539
|
+
return mapEventItem(html, ctx, events);
|
|
540
|
+
})();
|
|
541
|
+
const body = m.body.stmts.length > 0 ? `{ ${pre} return ${rendered}; }` : rendered;
|
|
384
542
|
return `${po(m.array)}.map(${params} => ${body})`;
|
|
385
543
|
};
|
|
386
544
|
const attrExpr = (e) => {
|
|
@@ -417,7 +575,7 @@ function generateClass(component, compat03 = false) {
|
|
|
417
575
|
.join("\n ");
|
|
418
576
|
// Reactive dependencies per binding, flowing through setup locals. Refs are
|
|
419
577
|
// rewritten like props/states but never change, so they are not tracked.
|
|
420
|
-
const tracked = new Set([...props, ...states]);
|
|
578
|
+
const tracked = new Set([...props, ...states, ...[...storeDeps.entries()].flatMap(([module, keys]) => [...keys].map(key => `store:${module}:${key}`))]);
|
|
421
579
|
const locals = localDependencies(component, tracked);
|
|
422
580
|
const condition = (exprIndices) => {
|
|
423
581
|
const deps = bindingDependencies(component, exprIndices, tracked, locals);
|
|
@@ -537,6 +695,10 @@ function generateClass(component, compat03 = false) {
|
|
|
537
695
|
const info = listInfoOf(b);
|
|
538
696
|
return info !== undefined && info.key === undefined;
|
|
539
697
|
});
|
|
698
|
+
const hasMapEventBindings = template.textBindings.some(b => {
|
|
699
|
+
const info = listInfoOf(b);
|
|
700
|
+
return info !== undefined && templateEventsIn(info.map.body.result).length > 0;
|
|
701
|
+
});
|
|
540
702
|
// `__argonNext` holds the freshly rendered string so unchanged bindings can
|
|
541
703
|
// skip DOM work; the name is reserved and must not collide with user locals.
|
|
542
704
|
const updateStatements = [
|
|
@@ -545,14 +707,19 @@ function generateClass(component, compat03 = false) {
|
|
|
545
707
|
if (info && info.key) {
|
|
546
708
|
// Each item renders to a [key, html] pair; the reconciler matches by
|
|
547
709
|
// key so reordered items move their existing nodes.
|
|
548
|
-
const
|
|
710
|
+
const events = templateEventsIn(info.map.body.result);
|
|
711
|
+
const pair = (r) => {
|
|
712
|
+
const key = print(info.key);
|
|
713
|
+
const html = mapEventItem(textExpr(r), `${JSON.stringify(`${b.id}:`)} + ${key}`, events);
|
|
714
|
+
return `[${key}, ${html}]`;
|
|
715
|
+
};
|
|
549
716
|
return ` if (${condition(b.exprIndices)}) {
|
|
550
|
-
this.#reconcileKeyedList(${b.id}, this.#textStart${b.id}, this.#textEnd${b.id}, ${printMapText(info.map, pair)});
|
|
717
|
+
this.#reconcileKeyedList(${b.id}, this.#textStart${b.id}, this.#textEnd${b.id}, ${printMapText(info.map, pair, { bindingId: b.id, key: info.key })});
|
|
551
718
|
}`;
|
|
552
719
|
}
|
|
553
720
|
if (info) {
|
|
554
721
|
return ` if (${condition(b.exprIndices)}) {
|
|
555
|
-
this.#reconcileList(${b.id}, this.#textStart${b.id}, this.#textEnd${b.id}, ${printMapText(info.map)});
|
|
722
|
+
this.#reconcileList(${b.id}, this.#textStart${b.id}, this.#textEnd${b.id}, ${printMapText(info.map, textExpr, { bindingId: b.id })});
|
|
556
723
|
}`;
|
|
557
724
|
}
|
|
558
725
|
return ` if (${condition(b.exprIndices)}) {
|
|
@@ -633,18 +800,57 @@ ${textCases}
|
|
|
633
800
|
const attrQueries = attrIds
|
|
634
801
|
.map(id => ` this.#attr${id} = root.querySelector('[data-argon-bind="${id}"]');`)
|
|
635
802
|
.join("\n");
|
|
636
|
-
const
|
|
803
|
+
const eventBindings = [
|
|
804
|
+
...template.events.map(b => ({ id: b.id, event: b.event, handler: template.exprs[b.exprIndex] })),
|
|
805
|
+
...nestedEvents,
|
|
806
|
+
];
|
|
807
|
+
const wiring = eventBindings
|
|
637
808
|
.map(b => {
|
|
638
|
-
const handler = print(
|
|
639
|
-
return ` scope
|
|
809
|
+
const handler = print(b.handler);
|
|
810
|
+
return ` this.#eventTargets(scope, '${b.id}').forEach(el => this.#listen(el, '${b.id}', '${b.event}', ${handler}));`;
|
|
640
811
|
})
|
|
641
812
|
.join("\n");
|
|
813
|
+
const mapEventHelpers = hasMapEventBindings ? `
|
|
814
|
+
#mapEventItem(html, ctx, handlers, ids) {
|
|
815
|
+
const key = String(ctx);
|
|
816
|
+
this.#eventContexts[key] = handlers;
|
|
817
|
+
const attr = key.replace(/&/g, '&').replace(/"/g, '"');
|
|
818
|
+
let out = String(html);
|
|
819
|
+
for (const id of ids) out = out.replaceAll(\`data-argon="\${id}"\`, \`data-argon="\${id}" data-argon-c="\${attr}"\`);
|
|
820
|
+
return out;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
#eventHandler(el, id, fallback) {
|
|
824
|
+
const ctx = el.getAttribute('data-argon-c');
|
|
825
|
+
return ctx && this.#eventContexts[ctx]?.[id] ? this.#eventContexts[ctx][id] : fallback;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
` : "";
|
|
829
|
+
const eventHelpers = eventBindings.length === 0 ? "" : `
|
|
830
|
+
#eventTargets(scope, id) {
|
|
831
|
+
const selector = \`[data-argon="\${id}"]\`;
|
|
832
|
+
const targets = [...scope.querySelectorAll(selector)];
|
|
833
|
+
if (scope.nodeType === 1 && scope.matches(selector)) targets.unshift(scope);
|
|
834
|
+
return targets;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
#listen(el, id, event, handler) {
|
|
838
|
+
const key = id + ':' + event;
|
|
839
|
+
if (!el.__argonListeners) Object.defineProperty(el, '__argonListeners', { value: {} });
|
|
840
|
+
const prev = el.__argonListeners[key];
|
|
841
|
+
if (prev) el.removeEventListener(event, prev);
|
|
842
|
+
const next = ${hasMapEventBindings ? "this.#eventHandler(el, id, handler)" : "handler"};
|
|
843
|
+
el.__argonListeners[key] = next;
|
|
844
|
+
el.addEventListener(event, next);
|
|
845
|
+
}
|
|
846
|
+
${mapEventHelpers}`;
|
|
642
847
|
const textFields = template.textBindings.map(b => ` #textStart${b.id};
|
|
643
848
|
#textEnd${b.id};${listBindings.has(b.id) ? "" : `
|
|
644
849
|
#textLast${b.id};`}`).join("\n");
|
|
645
850
|
const attrFields = attrIds.map(id => ` #attr${id};`).join("\n");
|
|
646
851
|
const attrMemoFields = template.attrBindings.map((_b, i) => ` #attrLast${i};`).join("\n");
|
|
647
852
|
const listsField = listBindings.size > 0 ? " #lists = {};" : "";
|
|
853
|
+
const eventContextField = hasMapEventBindings ? " #eventContexts = {};" : "";
|
|
648
854
|
// ── Refs and lifecycle hooks ──
|
|
649
855
|
//
|
|
650
856
|
// A ref resolves lazily against the live shadow DOM, so it stays correct
|
|
@@ -696,6 +902,7 @@ ${textCases}
|
|
|
696
902
|
const mounts = hooksOf("mount");
|
|
697
903
|
const effects = hooksOf("effect");
|
|
698
904
|
const hasHooks = mounts.length > 0 || effects.length > 0;
|
|
905
|
+
const storeField = storeDeps.size > 0 ? " #storeCleanups = [];" : "";
|
|
699
906
|
const hookFields = hasHooks
|
|
700
907
|
? ` #hooksLive = false;${mounts.length > 0 ? "\n #cleanups = [];" : ""}`
|
|
701
908
|
: "";
|
|
@@ -733,13 +940,28 @@ ${[mountRuns, effectRuns].filter(Boolean).join("\n")}`
|
|
|
733
940
|
const effectCleanups = effects
|
|
734
941
|
.map((_e, i) => ` if (this.#effect${i}Cleanup) { this.#effect${i}Cleanup(); this.#effect${i}Cleanup = undefined; }`)
|
|
735
942
|
.join("\n");
|
|
736
|
-
const
|
|
943
|
+
const storeConnect = storeDeps.size === 0 ? "" : `
|
|
944
|
+
#connectStores() {
|
|
945
|
+
if (this.#storeCleanups.length > 0) return;
|
|
946
|
+
${[...storeDeps.entries()].flatMap(([module, keys]) => [...keys].map(key => ` this.#storeCleanups.push(${storeAliases.get(module)}(${JSON.stringify(key)}, () => this.#updateBindings(${JSON.stringify(`store:${module}:${key}`)})));`)).join("\n")}
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
#disconnectStores() {
|
|
950
|
+
for (const cleanup of this.#storeCleanups.splice(0)) cleanup();
|
|
951
|
+
}
|
|
952
|
+
`;
|
|
953
|
+
const disconnectBody = [
|
|
954
|
+
storeDeps.size > 0 ? " this.#disconnectStores();" : "",
|
|
955
|
+
hasHooks ? " this.#hooksLive = false;" : "",
|
|
956
|
+
hasHooks && mounts.length > 0 ? " for (const cleanup of this.#cleanups.splice(0)) cleanup();" : "",
|
|
957
|
+
effectCleanups,
|
|
958
|
+
].filter(Boolean).join("\n");
|
|
959
|
+
const disconnectedCombined = storeDeps.size === 0 && !hasHooks ? "" : `
|
|
737
960
|
|
|
738
961
|
disconnectedCallback() {
|
|
739
|
-
|
|
740
|
-
${[mounts.length > 0 ? " for (const cleanup of this.#cleanups.splice(0)) cleanup();" : "", effectCleanups].filter(Boolean).join("\n")}
|
|
962
|
+
${disconnectBody}
|
|
741
963
|
}`;
|
|
742
|
-
const bindingFields = [textFields, attrFields, attrMemoFields, listsField, refFields, hookFields].filter(Boolean).join("\n");
|
|
964
|
+
const bindingFields = [textFields, attrFields, attrMemoFields, listsField, eventContextField, refFields, storeField, hookFields].filter(Boolean).join("\n");
|
|
743
965
|
// Keyed list patching: items are matched by key, so reordered or spliced
|
|
744
966
|
// items move their existing DOM nodes; only items whose rendered HTML
|
|
745
967
|
// changed (or that are genuinely new) are re-parsed.
|
|
@@ -782,25 +1004,38 @@ ${[mounts.length > 0 ? " for (const cleanup of this.#cleanups.splice(0)) clea
|
|
|
782
1004
|
if (i === p) p++;
|
|
783
1005
|
else anchor.before(...oldNodes[i]);
|
|
784
1006
|
if (oldHtmls[i] !== html) {
|
|
785
|
-
for (let k = 1; k < oldNodes[i].length; k++) oldNodes[i][k].remove();
|
|
786
1007
|
const content = parse(html);
|
|
787
1008
|
const fresh = [oldNodes[i][0], ...content.childNodes];
|
|
788
|
-
oldNodes[i]
|
|
789
|
-
|
|
1009
|
+
if (this.#patchItem(oldNodes[i], fresh)) {
|
|
1010
|
+
nodes.push(oldNodes[i]);
|
|
1011
|
+
} else {
|
|
1012
|
+
for (let k = 1; k < oldNodes[i].length; k++) oldNodes[i][k].remove();
|
|
1013
|
+
oldNodes[i][0].after(content);
|
|
1014
|
+
nodes.push(fresh);
|
|
1015
|
+
}
|
|
790
1016
|
} else {
|
|
791
|
-
|
|
1017
|
+
${hasMapEventBindings ? ` for (let k = 1; k < oldNodes[i].length; k++) this.#wireEvents(oldNodes[i][k]);
|
|
1018
|
+
` : ""} nodes.push(oldNodes[i]);
|
|
792
1019
|
}
|
|
793
1020
|
}
|
|
794
1021
|
keys.push(key);
|
|
795
1022
|
htmls.push(html);
|
|
796
1023
|
}
|
|
797
1024
|
for (let i = 0; i < oldNodes.length; i++) {
|
|
798
|
-
if (!used[i])
|
|
1025
|
+
if (!used[i]) {
|
|
1026
|
+
${hasMapEventBindings ? ` delete this.#eventContexts[id + ':' + oldKeys[i]];
|
|
1027
|
+
` : ""} for (const n of oldNodes[i]) n.remove();
|
|
1028
|
+
}
|
|
799
1029
|
}
|
|
800
1030
|
list.keys = keys;
|
|
801
1031
|
list.htmls = htmls;
|
|
802
1032
|
list.nodes = nodes;
|
|
803
1033
|
}
|
|
1034
|
+
|
|
1035
|
+
#patchItem(current, fresh) {
|
|
1036
|
+
if (current.length !== 2 || fresh.length !== 2) return false;
|
|
1037
|
+
return this.#patchElement(current[1], fresh[1]);
|
|
1038
|
+
}
|
|
804
1039
|
`;
|
|
805
1040
|
// Per-item list patching: each item's rendered HTML is cached, and a
|
|
806
1041
|
// comment marker delimits its DOM nodes. Only items whose HTML changed are
|
|
@@ -816,7 +1051,8 @@ ${[mounts.length > 0 ? " for (const cleanup of this.#cleanups.splice(0)) clea
|
|
|
816
1051
|
}
|
|
817
1052
|
const { htmls, marks } = list;
|
|
818
1053
|
if (items.length < htmls.length) {
|
|
819
|
-
let
|
|
1054
|
+
${hasMapEventBindings ? ` for (let i = items.length; i < htmls.length; i++) delete this.#eventContexts[id + ':' + i];
|
|
1055
|
+
` : ""} let node = marks[items.length];
|
|
820
1056
|
while (node && node !== end) { const next = node.nextSibling; node.remove(); node = next; }
|
|
821
1057
|
htmls.length = items.length;
|
|
822
1058
|
marks.length = items.length;
|
|
@@ -824,8 +1060,12 @@ ${[mounts.length > 0 ? " for (const cleanup of this.#cleanups.splice(0)) clea
|
|
|
824
1060
|
for (let i = 0; i < items.length; i++) {
|
|
825
1061
|
const html = String(items[i]);
|
|
826
1062
|
if (i < htmls.length) {
|
|
827
|
-
if (htmls[i] === html) continue;
|
|
828
1063
|
const stop = i + 1 < marks.length ? marks[i + 1] : end;
|
|
1064
|
+
if (htmls[i] === html) {
|
|
1065
|
+
${hasMapEventBindings ? ` let current = marks[i].nextSibling;
|
|
1066
|
+
while (current && current !== stop) { this.#wireEvents(current); current = current.nextSibling; }
|
|
1067
|
+
` : ""} continue;
|
|
1068
|
+
}
|
|
829
1069
|
let node = marks[i].nextSibling;
|
|
830
1070
|
while (node && node !== stop) { const next = node.nextSibling; node.remove(); node = next; }
|
|
831
1071
|
const template = document.createElement('template');
|
|
@@ -850,12 +1090,13 @@ ${[mounts.length > 0 ? " for (const cleanup of this.#cleanups.splice(0)) clea
|
|
|
850
1090
|
const root = shadow ?? this.attachShadow({ mode: 'open' });
|
|
851
1091
|
if (!shadow) root.innerHTML = this.#render();
|
|
852
1092
|
this.#mount(root);`;
|
|
853
|
-
const
|
|
1093
|
+
const connectStores = storeDeps.size > 0 ? "\n this.#connectStores();" : "";
|
|
1094
|
+
const connected = hasHooks || storeDeps.size > 0
|
|
854
1095
|
? ` connectedCallback() {
|
|
855
1096
|
if (!this.#isCSR && !this.#bindingsMounted) {
|
|
856
1097
|
${hydrate}
|
|
857
|
-
}${hookConnect}
|
|
858
|
-
}${
|
|
1098
|
+
}${connectStores}${hookConnect}
|
|
1099
|
+
}${disconnectedCombined}`
|
|
859
1100
|
: ` connectedCallback() {
|
|
860
1101
|
if (this.#isCSR || this.#bindingsMounted) return;
|
|
861
1102
|
${hydrate}
|
|
@@ -908,21 +1149,39 @@ ${walker}${attrQueries}${attrQueries ? "\n" : ""} this.#bindingsMounted = tru
|
|
|
908
1149
|
const html = String(value);
|
|
909
1150
|
const sole = start.nextSibling;
|
|
910
1151
|
if (sole && sole !== end && sole.nextSibling === end && sole.nodeType === 3 && !/[<&]/.test(html)) {
|
|
911
|
-
sole.data
|
|
1152
|
+
if (html.startsWith(sole.data)) sole.appendData(html.slice(sole.data.length));
|
|
1153
|
+
else sole.data = html;
|
|
912
1154
|
return;
|
|
913
1155
|
}
|
|
1156
|
+
const template = document.createElement('template');
|
|
1157
|
+
template.innerHTML = html;
|
|
1158
|
+
if (sole && sole !== end && sole.nextSibling === end && template.content.childNodes.length === 1 && this.#patchElement(sole, template.content.firstChild)) return;
|
|
914
1159
|
let node = start.nextSibling;
|
|
915
1160
|
while (node && node !== end) {
|
|
916
1161
|
const next = node.nextSibling;
|
|
917
1162
|
node.remove();
|
|
918
1163
|
node = next;
|
|
919
1164
|
}
|
|
920
|
-
const template = document.createElement('template');
|
|
921
|
-
template.innerHTML = html;
|
|
922
1165
|
this.#wireEvents(template.content);
|
|
923
1166
|
end.before(template.content);
|
|
924
1167
|
}
|
|
925
|
-
|
|
1168
|
+
|
|
1169
|
+
#patchElement(oldEl, newEl) {
|
|
1170
|
+
if (!oldEl || !newEl || oldEl.nodeType !== 1 || newEl.nodeType !== 1 || oldEl.localName !== newEl.localName) return false;
|
|
1171
|
+
for (const attr of [...oldEl.attributes]) {
|
|
1172
|
+
if (!newEl.hasAttribute(attr.name)) oldEl.removeAttribute(attr.name);
|
|
1173
|
+
}
|
|
1174
|
+
for (const attr of [...newEl.attributes]) {
|
|
1175
|
+
if (oldEl.getAttribute(attr.name) !== attr.value) oldEl.setAttribute(attr.name, attr.value);
|
|
1176
|
+
}
|
|
1177
|
+
if (oldEl.childNodes.length > 0 || newEl.childNodes.length > 0) {
|
|
1178
|
+
while (oldEl.firstChild) oldEl.firstChild.remove();
|
|
1179
|
+
oldEl.append(...newEl.childNodes);
|
|
1180
|
+
this.#wireEvents(oldEl);
|
|
1181
|
+
}
|
|
1182
|
+
return true;
|
|
1183
|
+
}
|
|
1184
|
+
${reconcileList}${reconcileKeyedList}${attrHelpers}${escHelpers ? escHelpers + "\n\n" : ""}${effectMethods ? effectMethods + "\n\n" : ""}${storeConnect}${eventHelpers}
|
|
926
1185
|
#updateBindings(prop) {
|
|
927
1186
|
if (!this.#bindingsMounted) return;
|
|
928
1187
|
${updatePrelude}
|