@expressive/mvc 0.87.0 → 0.88.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/README.md +2 -2
- package/dist/component.d.ts +31 -11
- package/dist/component.js +76 -49
- package/dist/component.js.map +1 -1
- package/dist/context.d.ts +3 -1
- package/dist/context.js +30 -12
- package/dist/context.js.map +1 -1
- package/dist/dispatch.d.ts +6 -1
- package/dist/dispatch.js +14 -6
- package/dist/dispatch.js.map +1 -1
- package/dist/field/def.js +3 -3
- package/dist/field/def.js.map +1 -1
- package/dist/field/get.js +21 -5
- package/dist/field/get.js.map +1 -1
- package/dist/field/has.js +1 -1
- package/dist/field/map.js +1 -1
- package/dist/field/ref.js +1 -1
- package/dist/field/set.js +1 -1
- package/dist/hot.d.ts +1 -4
- package/dist/hot.js +122 -10
- package/dist/hot.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/jsx-dev-runtime.d.ts +1 -2
- package/dist/jsx-dev-runtime.js +1 -1
- package/dist/jsx-runtime.d.ts +78 -5
- package/dist/jsx-runtime.js +69 -2
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/state.d.ts +66 -38
- package/dist/state.js +73 -164
- package/dist/state.js.map +1 -1
- package/package.json +7 -5
- package/dist/_virtual/_rolldown/runtime.js +0 -18
- package/dist/caught.d.ts +0 -5237
- package/dist/caught.js +0 -64
- package/dist/caught.js.map +0 -1
- package/dist/runtime.d.ts +0 -72
- package/dist/runtime.js +0 -70
- package/dist/runtime.js.map +0 -1
package/dist/field/def.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"def.js","names":[],"sources":["../../src/field/def.ts"],"sourcesContent":["import { listener } from '../observable';\nimport { PENDING, State, STORE, uid, apply } from '../state';\n\ndeclare namespace def {\n /**\n * Property initializer, will run upon instance creation.\n * Optional returned callback will run when once upon first access.\n */\n type Factory<T = any, M extends State = any> = (\n this: M,\n key: Extract<State.Field<M>, string>,\n thisArg: M,\n state: State.Values<M>\n ) => def.Config<T> | (() => void) | void;\n\n interface Config<T = any> extends State.Apply<T> {\n destroy?: () => void;\n }\n}\n\nconst APPLY = new Map<symbol, [def.Factory, State[]] | null>();\nconst RESET = () => APPLY.clear();\n\nfunction def<T>(arg1: def.Factory<T>) {\n if (!PENDING.size || (PENDING.size == 1 && PENDING.has(RESET)))\n throw new Error(\n 'Instruction created with no State under construction.'\n );\n\n PENDING.add(RESET);\n\n const token = Symbol('field-' + uid());\n\n APPLY.set(token, [arg1, [...PENDING].filter((x) => x instanceof State) as State[]]);\n\n return token as T extends void ? unknown : T;\n}\n\nState.on((self)
|
|
1
|
+
{"version":3,"file":"def.js","names":[],"sources":["../../src/field/def.ts"],"sourcesContent":["import { listener } from '../observable';\nimport { PENDING, State, STORE, uid, apply } from '../state';\n\ndeclare namespace def {\n /**\n * Property initializer, will run upon instance creation.\n * Optional returned callback will run when once upon first access.\n */\n type Factory<T = any, M extends State = any> = (\n this: M,\n key: Extract<State.Field<M>, string>,\n thisArg: M,\n state: State.Values<M>\n ) => def.Config<T> | (() => void) | void;\n\n interface Config<T = any> extends State.Apply<T> {\n destroy?: () => void;\n }\n}\n\nconst APPLY = new Map<symbol, [def.Factory, State[]] | null>();\nconst RESET = () => APPLY.clear();\n\nfunction def<T>(arg1: def.Factory<T>) {\n if (!PENDING.size || (PENDING.size == 1 && PENDING.has(RESET)))\n throw new Error(\n 'Instruction created with no State under construction.'\n );\n\n PENDING.add(RESET);\n\n const token = Symbol('field-' + uid());\n\n APPLY.set(token, [arg1, [...PENDING].filter((x) => x instanceof State) as State[]]);\n\n return token as T extends void ? unknown : T;\n}\n\nState.on({\n setup(self) {\n const store = STORE.get(self)!;\n\n for (const key in self) {\n const property: PropertyDescriptor = Object.getOwnPropertyDescriptor(self, key) || {};\n const entry = APPLY.get(property.value);\n\n if (entry === null)\n throw new Error(\n `${self}.${key} has an instruction applied to another State.`\n );\n\n if (!entry) continue;\n\n if (key[0] == '_')\n throw new Error(`${self}.${key} is unmanaged - instructions cannot apply to _ keys.`);\n\n const [instruction, pending] = entry;\n\n APPLY.set(property.value, null);\n discard(self, pending);\n delete (self as any)[key];\n\n const output = instruction.call(self, key, self, store);\n\n if (!output) continue;\n\n const desc = typeof output == 'function' ? { destroy: output } : output;\n\n if (desc.destroy) listener(self, desc.destroy, null);\n\n apply(self, key, desc, true);\n }\n }\n});\n\n/**\n * Drop pending States constructed after `self` and before the instruction -\n * products of its own initializers, discarded when this token replaced them.\n */\nfunction discard(self: State, pending: State[]) {\n let seen = false;\n\n for (const item of pending)\n if (!seen) seen = item === self;\n else PENDING.delete(item);\n}\n\nexport { def };\n"],"mappings":";;;;AAoBA,MAAM,wBAAQ,IAAI,KAA4C;AAC9D,MAAM,cAAc,MAAM,OAAO;AAEjC,SAAS,IAAO,MAAsB;AACpC,KAAI,CAAC,QAAQ,QAAS,QAAQ,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAC3D,OAAM,IAAI,MACR,wDACD;AAEH,SAAQ,IAAI,MAAM;CAElB,MAAM,QAAQ,OAAO,WAAW,KAAK,CAAC;AAEtC,OAAM,IAAI,OAAO,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,QAAQ,MAAM,aAAa,MAAM,CAAY,CAAC;AAEnF,QAAO;;AAGT,MAAM,GAAG,EACP,MAAM,MAAM;CACV,MAAM,QAAQ,MAAM,IAAI,KAAK;AAE7B,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,WAA+B,OAAO,yBAAyB,MAAM,IAAI,IAAI,EAAE;EACrF,MAAM,QAAQ,MAAM,IAAI,SAAS,MAAM;AAEvC,MAAI,UAAU,KACZ,OAAM,IAAI,MACR,GAAG,KAAK,GAAG,IAAI,+CAChB;AAEH,MAAI,CAAC,MAAO;AAEZ,MAAI,IAAI,MAAM,IACZ,OAAM,IAAI,MAAM,GAAG,KAAK,GAAG,IAAI,sDAAsD;EAEvF,MAAM,CAAC,aAAa,WAAW;AAE/B,QAAM,IAAI,SAAS,OAAO,KAAK;AAC/B,UAAQ,MAAM,QAAQ;AACtB,SAAQ,KAAa;EAErB,MAAM,SAAS,YAAY,KAAK,MAAM,KAAK,MAAM,MAAM;AAEvD,MAAI,CAAC,OAAQ;EAEb,MAAM,OAAO,OAAO,UAAU,aAAa,EAAE,SAAS,QAAQ,GAAG;AAEjE,MAAI,KAAK,QAAS,UAAS,MAAM,KAAK,SAAS,KAAK;AAEpD,QAAM,MAAM,KAAK,MAAM,KAAK;;GAGjC,CAAC;;;;;AAMF,SAAS,QAAQ,MAAa,SAAkB;CAC9C,IAAI,OAAO;AAEX,MAAK,MAAM,QAAQ,QACjB,KAAI,CAAC,KAAM,QAAO,SAAS;KACtB,SAAQ,OAAO,KAAK"}
|
package/dist/field/get.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { STORE, children, parent, update } from "../state.js";
|
|
2
1
|
import { capture, listener, observer } from "../observable.js";
|
|
2
|
+
import { STORE, State, children, owned, parent, update } from "../state.js";
|
|
3
3
|
import { Context } from "../context.js";
|
|
4
4
|
import { def } from "./def.js";
|
|
5
5
|
|
|
@@ -23,11 +23,26 @@ function above(Type, argument) {
|
|
|
23
23
|
assign(hasParent);
|
|
24
24
|
return {};
|
|
25
25
|
}
|
|
26
|
+
if (Type === State) {
|
|
27
|
+
if (argument === false) return {
|
|
28
|
+
get: false,
|
|
29
|
+
enumerable: false
|
|
30
|
+
};
|
|
31
|
+
throw new Error(`${subject} has no owner.`);
|
|
32
|
+
}
|
|
26
33
|
let found = false;
|
|
27
34
|
let depth = Infinity;
|
|
28
35
|
let level = 0;
|
|
29
36
|
for (let p = hasParent; p; p = parent(p), level++) {
|
|
30
37
|
const at = level;
|
|
38
|
+
if (p instanceof Type) {
|
|
39
|
+
if (!found) {
|
|
40
|
+
found = true;
|
|
41
|
+
depth = at;
|
|
42
|
+
assign(p);
|
|
43
|
+
}
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
31
46
|
const remove = children(p, (child) => {
|
|
32
47
|
if (child !== subject && child instanceof Type && at <= depth) {
|
|
33
48
|
found = true;
|
|
@@ -68,13 +83,14 @@ function above(Type, argument) {
|
|
|
68
83
|
function below(Type, arg) {
|
|
69
84
|
return def((key, subject) => {
|
|
70
85
|
const context = Context.get(subject);
|
|
86
|
+
const watch = (callback) => Type === State ? owned(subject, callback) : context.get(Type, callback, true);
|
|
71
87
|
if (typeof arg == "boolean") {
|
|
72
|
-
|
|
88
|
+
watch((state) => {
|
|
73
89
|
update(subject, key, state);
|
|
74
90
|
return state.set(null, () => {
|
|
75
91
|
update(subject, key, void 0);
|
|
76
92
|
});
|
|
77
|
-
}
|
|
93
|
+
});
|
|
78
94
|
return {
|
|
79
95
|
get: arg,
|
|
80
96
|
value: void 0,
|
|
@@ -82,7 +98,7 @@ function below(Type, arg) {
|
|
|
82
98
|
};
|
|
83
99
|
}
|
|
84
100
|
const applied = /* @__PURE__ */ new Set();
|
|
85
|
-
|
|
101
|
+
watch((state) => {
|
|
86
102
|
let remove;
|
|
87
103
|
let release;
|
|
88
104
|
if (applied.has(state)) return;
|
|
@@ -107,7 +123,7 @@ function below(Type, arg) {
|
|
|
107
123
|
}
|
|
108
124
|
const ignore = state.set(null, done);
|
|
109
125
|
return done;
|
|
110
|
-
}
|
|
126
|
+
});
|
|
111
127
|
return {
|
|
112
128
|
value: [],
|
|
113
129
|
enumerable: false
|
package/dist/field/get.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get.js","names":[],"sources":["../../src/field/get.ts"],"sourcesContent":["import { capture, listener, observer } from '../observable';\nimport { Context } from '../context';\nimport { State, children, parent, STORE, update } from '../state';\nimport { def } from './def';\n\ndeclare namespace get {\n type Callback<T = any> = (\n state: T,\n subject: State\n ) => void | boolean | (() => void);\n}\n\n/**\n * Fetches upstream State from context with optional lifecycle callback.\n * Callback runs on mount and can return cleanup function for unmount.\n *\n * @param Type - Type of State to fetch.\n * @param callback - Optional lifecycle callback, receives (state, subject). Can return cleanup function.\n */\nfunction get<T extends State>(\n Type: State.Extends<T>,\n callback?: get.Callback<T>\n): T;\n\n/**\n * Fetches and assigns the controller which spawned this host.\n * When parent assigns an instance via `use()` directive, it\n * will be made available to child upon this request.\n *\n * @param Type - Type of controller compatible with this class.\n * @param required - If false, property may be undefined. Otherwise will throw.\n */\nfunction get<T extends State>(\n Type: State.Extends<T>,\n required: false\n): T | undefined;\n\n/**\n * Collects downstream States, accumulating all instances of specified type\n * for which this is an ancestor. Returns an array that updates as States\n * are added or removed. Callback runs on each registration and can return\n * cleanup or false to prevent registration.\n *\n * @param Type - Type of State to collect.\n * @param downstream - Must be true to enable downstream mode.\n * @param callback - Optional lifecycle callback, receives (state, subject). May return false to prevent registration.\n */\nfunction get<T extends State>(\n Type: State.Extends<T>,\n downstream: true,\n callback?: get.Callback<T>\n): T[];\n\n/**\n * Fetches a single downstream State of specified type.\n * Updates when a matching child appears or is removed.\n * Throws if not found.\n *\n * @param Type - Type of State to fetch.\n * @param downstream - Must be true to enable downstream mode.\n * @param required - Throw if no match found.\n */\nfunction get<T extends State>(\n Type: State.Extends<T>,\n downstream: true,\n single: true\n): T;\n\n/**\n * Fetches a single downstream State of specified type.\n * Updates when a matching child appears or is removed.\n * Returns undefined if not found.\n *\n * @param Type - Type of State to fetch.\n * @param downstream - Must be true to enable downstream mode.\n * @param required - If false, returns undefined if no match found.\n */\nfunction get<T extends State>(\n Type: State.Extends<T>,\n downstream: true,\n required: false\n): T | undefined;\n\nfunction get<T extends State>(\n Type: State.Extends<T>,\n arg1?: get.Callback<T> | boolean,\n arg2?: get.Callback<T> | boolean\n) {\n return arg1 === true ? below(Type, arg2) : above(Type, arg1);\n}\n\nfunction above<T extends State>(\n Type: State.Extends<T>,\n argument: get.Callback<T> | boolean | undefined\n) {\n return def<T>((key, subject) => {\n const hasParent = parent(subject);\n const callback =\n typeof argument === 'function'\n ? (argument as get.Callback<T>)\n : undefined;\n\n function assign(value: T) {\n if (STORE.get(subject)![key] === value) return;\n\n if (callback) {\n const result = callback(value, subject);\n if (typeof result === 'function') subject.set(null, result);\n }\n update(subject, key, value);\n }\n\n if (hasParent && hasParent instanceof Type) {\n assign(hasParent as T);\n return {};\n }\n\n let found = false;\n let depth = Infinity;\n let level = 0;\n\n for (let p: State | null | undefined = hasParent; p; p = parent(p), level++) {\n const at = level;\n\n const remove = children(p, (child) => {\n if (child !== subject && child instanceof Type && at <= depth) {\n found = true;\n depth = at;\n assign(child as T);\n }\n });\n\n subject.set(null, () => { remove(); });\n }\n\n if (!found) {\n const remove = Context.get(subject).get(Type, (state) => {\n if (depth !== Infinity) return;\n found = true;\n assign(state);\n }, false, subject) as () => void;\n\n subject.set(null, () => { remove(); });\n }\n\n if (!found && argument !== false) {\n const missing = () =>\n new Error(`Required ${Type} not found in context for ${subject}.`);\n\n let activating: State | undefined;\n\n for (\n let p: State | null | undefined = hasParent;\n p && !observer(p)!.ready;\n p = parent(p)\n )\n activating = p;\n\n if (!activating) throw missing();\n\n listener(activating, () => {\n if (!found) throw missing();\n return null;\n }, true);\n }\n\n return {\n get: argument !== false,\n enumerable: false\n };\n });\n}\n\nfunction below<T extends State>(\n Type: State.Extends<T>,\n arg: get.Callback<T> | boolean | undefined\n) {\n return def<T[]>((key, subject) => {\n const context = Context.get(subject);\n\n if (typeof arg == 'boolean') {\n
|
|
1
|
+
{"version":3,"file":"get.js","names":[],"sources":["../../src/field/get.ts"],"sourcesContent":["import { capture, listener, observer } from '../observable';\nimport { Context } from '../context';\nimport { State, children, owned, parent, STORE, update } from '../state';\nimport { def } from './def';\n\ndeclare namespace get {\n type Callback<T = any> = (\n state: T,\n subject: State\n ) => void | boolean | (() => void);\n}\n\n/**\n * Fetches upstream State from context with optional lifecycle callback.\n * Callback runs on mount and can return cleanup function for unmount.\n *\n * @param Type - Type of State to fetch.\n * @param callback - Optional lifecycle callback, receives (state, subject). Can return cleanup function.\n */\nfunction get<T extends State>(\n Type: State.Extends<T>,\n callback?: get.Callback<T>\n): T;\n\n/**\n * Fetches and assigns the controller which spawned this host.\n * When parent assigns an instance via `use()` directive, it\n * will be made available to child upon this request.\n *\n * @param Type - Type of controller compatible with this class.\n * @param required - If false, property may be undefined. Otherwise will throw.\n */\nfunction get<T extends State>(\n Type: State.Extends<T>,\n required: false\n): T | undefined;\n\n/**\n * Collects downstream States, accumulating all instances of specified type\n * for which this is an ancestor. Returns an array that updates as States\n * are added or removed. Callback runs on each registration and can return\n * cleanup or false to prevent registration.\n *\n * @param Type - Type of State to collect.\n * @param downstream - Must be true to enable downstream mode.\n * @param callback - Optional lifecycle callback, receives (state, subject). May return false to prevent registration.\n */\nfunction get<T extends State>(\n Type: State.Extends<T>,\n downstream: true,\n callback?: get.Callback<T>\n): T[];\n\n/**\n * Fetches a single downstream State of specified type.\n * Updates when a matching child appears or is removed.\n * Throws if not found.\n *\n * @param Type - Type of State to fetch.\n * @param downstream - Must be true to enable downstream mode.\n * @param required - Throw if no match found.\n */\nfunction get<T extends State>(\n Type: State.Extends<T>,\n downstream: true,\n single: true\n): T;\n\n/**\n * Fetches a single downstream State of specified type.\n * Updates when a matching child appears or is removed.\n * Returns undefined if not found.\n *\n * @param Type - Type of State to fetch.\n * @param downstream - Must be true to enable downstream mode.\n * @param required - If false, returns undefined if no match found.\n */\nfunction get<T extends State>(\n Type: State.Extends<T>,\n downstream: true,\n required: false\n): T | undefined;\n\nfunction get<T extends State>(\n Type: State.Extends<T>,\n arg1?: get.Callback<T> | boolean,\n arg2?: get.Callback<T> | boolean\n) {\n return arg1 === true ? below(Type, arg2) : above(Type, arg1);\n}\n\nfunction above<T extends State>(\n Type: State.Extends<T>,\n argument: get.Callback<T> | boolean | undefined\n) {\n return def<T>((key, subject) => {\n const hasParent = parent(subject);\n const callback =\n typeof argument === 'function'\n ? (argument as get.Callback<T>)\n : undefined;\n\n function assign(value: T) {\n if (STORE.get(subject)![key] === value) return;\n\n if (callback) {\n const result = callback(value, subject);\n if (typeof result === 'function') subject.set(null, result);\n }\n update(subject, key, value);\n }\n\n if (hasParent && hasParent instanceof Type) {\n assign(hasParent as T);\n return {};\n }\n\n if (Type === State) {\n if (argument === false) return { get: false, enumerable: false };\n throw new Error(`${subject} has no owner.`);\n }\n\n let found = false;\n let depth = Infinity;\n let level = 0;\n\n for (let p: State | null | undefined = hasParent; p; p = parent(p), level++) {\n const at = level;\n\n if (p instanceof Type) {\n if (!found) {\n found = true;\n depth = at;\n assign(p as T);\n }\n break;\n }\n\n const remove = children(p, (child) => {\n if (child !== subject && child instanceof Type && at <= depth) {\n found = true;\n depth = at;\n assign(child as T);\n }\n });\n\n subject.set(null, () => { remove(); });\n }\n\n if (!found) {\n const remove = Context.get(subject).get(Type, (state) => {\n if (depth !== Infinity) return;\n found = true;\n assign(state);\n }, false, subject) as () => void;\n\n subject.set(null, () => { remove(); });\n }\n\n if (!found && argument !== false) {\n const missing = () =>\n new Error(`Required ${Type} not found in context for ${subject}.`);\n\n let activating: State | undefined;\n\n for (\n let p: State | null | undefined = hasParent;\n p && !observer(p)!.ready;\n p = parent(p)\n )\n activating = p;\n\n if (!activating) throw missing();\n\n listener(activating, () => {\n if (!found) throw missing();\n return null;\n }, true);\n }\n\n return {\n get: argument !== false,\n enumerable: false\n };\n });\n}\n\nfunction below<T extends State>(\n Type: State.Extends<T>,\n arg: get.Callback<T> | boolean | undefined\n) {\n return def<T[]>((key, subject) => {\n const context = Context.get(subject);\n const watch = (callback: (state: T) => (() => void) | void) =>\n Type === State\n ? owned(subject, callback as (state: State) => (() => void) | void)\n : context.get(Type, callback, true);\n\n if (typeof arg == 'boolean') {\n watch(\n (state) => {\n update(subject, key, state);\n return state.set(null, () => {\n update(subject, key, undefined);\n });\n }\n );\n\n return {\n get: arg,\n value: undefined,\n enumerable: false\n };\n }\n\n const applied = new Set<State>();\n\n watch(\n (state) => {\n let remove: (() => void) | undefined;\n let release: (() => void) | undefined;\n\n if (applied.has(state)) return;\n\n if (arg) {\n let rejected = false;\n\n capture((fn) => {\n const done = arg(state, subject);\n\n if (done === false) rejected = true;\n else if (typeof done == 'function') remove = done;\n\n release = fn;\n });\n\n if (rejected) return;\n }\n\n applied.add(state);\n update(subject, key, [...applied]);\n\n function done() {\n if (release) release();\n ignore();\n\n applied.delete(state);\n update(subject, key, [...applied]);\n\n if (typeof remove == 'function') remove();\n }\n\n const ignore = state.set(null, done);\n\n return done;\n }\n );\n\n return {\n value: [],\n enumerable: false\n };\n });\n}\n\nexport { get };\n"],"mappings":"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"}
|
package/dist/field/has.js
CHANGED
package/dist/field/map.js
CHANGED
package/dist/field/ref.js
CHANGED
package/dist/field/set.js
CHANGED
package/dist/hot.d.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { State } from "./state.js";
|
|
2
2
|
|
|
3
3
|
//#region src/hot.d.ts
|
|
4
|
-
declare namespace hot_d_exports {
|
|
5
|
-
export { Replaced, accept, replaced };
|
|
6
|
-
}
|
|
7
4
|
interface Replaced {
|
|
8
5
|
/** Module id the class was accepted under. */
|
|
9
6
|
id: string;
|
|
@@ -28,5 +25,5 @@ declare function accept<T extends Record<string, unknown>>(id: string, classes:
|
|
|
28
25
|
*/
|
|
29
26
|
declare function replaced(listener: (event: Replaced) => void): () => void;
|
|
30
27
|
//#endregion
|
|
31
|
-
export { type Replaced, accept,
|
|
28
|
+
export { type Replaced, accept, replaced };
|
|
32
29
|
//# sourceMappingURL=hot.d.ts.map
|
package/dist/hot.js
CHANGED
|
@@ -1,17 +1,128 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { State,
|
|
3
|
-
import { event, observer } from "./observable.js";
|
|
1
|
+
import { event } from "./observable.js";
|
|
2
|
+
import { GETTERS, LATEST, METHODS, SETUP, State, UNBIND, classify, compute } from "./state.js";
|
|
4
3
|
import { rechain } from "./component.js";
|
|
5
4
|
|
|
6
5
|
//#region src/hot.ts
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
const define = Object.defineProperty;
|
|
7
|
+
/** Method implementations replaced by a hot patch. */
|
|
8
|
+
const PAST = /* @__PURE__ */ new WeakSet();
|
|
9
|
+
/** Live instances, tracked once hot patching is enabled. */
|
|
10
|
+
let LIVE;
|
|
11
|
+
/** Bootstrapped subclasses of each class, tracked once hot patching is enabled. */
|
|
12
|
+
const SUBCLASSES = /* @__PURE__ */ new WeakMap();
|
|
11
13
|
const MODULES = /* @__PURE__ */ new Map();
|
|
12
14
|
const LISTENERS = /* @__PURE__ */ new Set();
|
|
13
15
|
const REFRESH = Symbol.for("@expressive/mvc.refresh");
|
|
14
16
|
const PRIVATE = /(?:^|[\s;{}*])#[\w$]+(?=[\s=;(}])/;
|
|
17
|
+
/** Begin tracking live instances, so a hot patch can reach them. */
|
|
18
|
+
function track() {
|
|
19
|
+
if (LIVE) return;
|
|
20
|
+
LIVE = /* @__PURE__ */ new Set();
|
|
21
|
+
State.on({
|
|
22
|
+
type(type) {
|
|
23
|
+
const parent = Object.getPrototypeOf(type);
|
|
24
|
+
let children = SUBCLASSES.get(parent);
|
|
25
|
+
if (!children) SUBCLASSES.set(parent, children = /* @__PURE__ */ new Set());
|
|
26
|
+
children.add(type);
|
|
27
|
+
},
|
|
28
|
+
setup(state) {
|
|
29
|
+
const ref = new WeakRef(state);
|
|
30
|
+
LIVE.add(ref);
|
|
31
|
+
return () => LIVE.delete(ref);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Move the members of `next` onto `prev`, which keeps its identity. Returns the
|
|
37
|
+
* live instances of `prev`, each needing a refresh.
|
|
38
|
+
*/
|
|
39
|
+
function patch(prev, next, own) {
|
|
40
|
+
const proto = prev.prototype;
|
|
41
|
+
const incoming = Object.getOwnPropertyDescriptors(next.prototype);
|
|
42
|
+
const keys = METHODS.get(prev);
|
|
43
|
+
const getters = GETTERS.get(prev);
|
|
44
|
+
const methods = /* @__PURE__ */ new Map();
|
|
45
|
+
const knownKeys = new Set(keys?.keys());
|
|
46
|
+
const knownGetters = new Set(getters?.keys());
|
|
47
|
+
let setup = SETUP.get(prev);
|
|
48
|
+
for (const handler of own) setup.delete(handler);
|
|
49
|
+
for (const handler of handlers(next)) {
|
|
50
|
+
if (!setup) SETUP.set(prev, setup = /* @__PURE__ */ new Set());
|
|
51
|
+
setup.add(handler);
|
|
52
|
+
}
|
|
53
|
+
for (const key of Reflect.ownKeys(next)) {
|
|
54
|
+
if (key == "prototype" || key == "length" || key == "name") continue;
|
|
55
|
+
if (Object.getOwnPropertyDescriptor(prev, key)?.configurable !== false) define(prev, key, Object.getOwnPropertyDescriptor(next, key));
|
|
56
|
+
}
|
|
57
|
+
const removed = /* @__PURE__ */ new Set();
|
|
58
|
+
for (const key of Object.getOwnPropertyNames(proto)) if (key != "constructor" && !(key in incoming)) {
|
|
59
|
+
const bind = keys?.get(key);
|
|
60
|
+
if (bind && Object.getOwnPropertyDescriptor(proto, key).get === bind) {
|
|
61
|
+
PAST.add(UNBIND.get(bind));
|
|
62
|
+
keys.delete(key);
|
|
63
|
+
}
|
|
64
|
+
removed.add(key);
|
|
65
|
+
Reflect.deleteProperty(proto, key);
|
|
66
|
+
getters?.delete(key);
|
|
67
|
+
}
|
|
68
|
+
for (const [key, desc] of Object.entries(incoming)) {
|
|
69
|
+
if (key == "constructor") continue;
|
|
70
|
+
const current = Object.getOwnPropertyDescriptor(proto, key);
|
|
71
|
+
if (typeof desc.value == "function") methods.set(key, desc.value);
|
|
72
|
+
if (current?.configurable === false) {
|
|
73
|
+
if (current.writable) proto[key] = desc.value;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (current?.get && keys?.get(key) === current.get) PAST.add(UNBIND.get(current.get));
|
|
77
|
+
const getter = getters?.get(key);
|
|
78
|
+
if (getter) LATEST.set(getter, desc.get);
|
|
79
|
+
define(proto, key, {
|
|
80
|
+
...desc,
|
|
81
|
+
configurable: true
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
if (keys) {
|
|
85
|
+
for (let T = prev;; T = Object.getPrototypeOf(T)) {
|
|
86
|
+
for (const handler of SETUP.get(T) || []) if (handler.type) handler.type(prev);
|
|
87
|
+
if (T === State) break;
|
|
88
|
+
}
|
|
89
|
+
classify(prev, keys, getters);
|
|
90
|
+
}
|
|
91
|
+
const live = [];
|
|
92
|
+
for (const ref of LIVE) {
|
|
93
|
+
const state = ref.deref();
|
|
94
|
+
if (!state) LIVE.delete(ref);
|
|
95
|
+
else if (state instanceof prev) live.push(state);
|
|
96
|
+
}
|
|
97
|
+
const descendants = new Set([prev, ...live.map((state) => state.constructor)]);
|
|
98
|
+
for (const type of descendants) for (const child of SUBCLASSES.get(type) || []) descendants.add(child);
|
|
99
|
+
descendants.delete(prev);
|
|
100
|
+
for (const type of descendants) {
|
|
101
|
+
const inherit = METHODS.get(type);
|
|
102
|
+
const computed = GETTERS.get(type);
|
|
103
|
+
for (const [key, bind] of keys) if (!knownKeys.has(key) && !inherit.has(key)) inherit.set(key, bind);
|
|
104
|
+
for (const [key, get] of getters) if (!knownGetters.has(key) && !computed.has(key)) computed.set(key, get);
|
|
105
|
+
for (const key of removed) if (!(key in type.prototype)) {
|
|
106
|
+
inherit.delete(key);
|
|
107
|
+
computed.delete(key);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
for (const state of live) {
|
|
111
|
+
for (const [key, value] of methods) {
|
|
112
|
+
const desc = Object.getOwnPropertyDescriptor(state, key);
|
|
113
|
+
if (!desc) continue;
|
|
114
|
+
if (desc.set) desc.set.call(state, value);
|
|
115
|
+
else if (PAST.has(UNBIND.get(desc.value))) delete state[key];
|
|
116
|
+
}
|
|
117
|
+
for (const key of removed) if (PAST.has(UNBIND.get(Object.getOwnPropertyDescriptor(state, key)?.value))) delete state[key];
|
|
118
|
+
for (const [key, get] of GETTERS.get(state.constructor)) if (!knownGetters.has(key) && get === getters.get(key)) compute.call(state, get, key);
|
|
119
|
+
}
|
|
120
|
+
return live;
|
|
121
|
+
}
|
|
122
|
+
/** Lifecycle handlers registered on a class itself. */
|
|
123
|
+
function handlers(type) {
|
|
124
|
+
return [...SETUP.get(type) || []];
|
|
125
|
+
}
|
|
15
126
|
function isState(value) {
|
|
16
127
|
return typeof value == "function" && value.prototype instanceof State;
|
|
17
128
|
}
|
|
@@ -28,9 +139,10 @@ function describe(type) {
|
|
|
28
139
|
shape = shape.replace(text.call(fn), "");
|
|
29
140
|
if (target !== type) kinds[key] = desc.set ? "accessor" : desc.get ? "get" : "fn";
|
|
30
141
|
}
|
|
142
|
+
shape = shape.replace(/\s+/g, " ").replace(/__vite_ssr_import_\d+__/g, "__vite_ssr_import__");
|
|
31
143
|
return {
|
|
32
144
|
type,
|
|
33
|
-
shape
|
|
145
|
+
shape,
|
|
34
146
|
kinds,
|
|
35
147
|
own: handlers(type)
|
|
36
148
|
};
|
|
@@ -90,7 +202,7 @@ function accept(id, classes) {
|
|
|
90
202
|
}
|
|
91
203
|
}
|
|
92
204
|
if (patched) rechain();
|
|
93
|
-
for (const state of refresh)
|
|
205
|
+
for (const state of refresh) event(state, REFRESH);
|
|
94
206
|
for (const event of replace) for (const listener of LISTENERS) try {
|
|
95
207
|
listener(event);
|
|
96
208
|
} catch (error) {
|
|
@@ -109,5 +221,5 @@ function replaced(listener) {
|
|
|
109
221
|
}
|
|
110
222
|
|
|
111
223
|
//#endregion
|
|
112
|
-
export { accept,
|
|
224
|
+
export { accept, replaced };
|
|
113
225
|
//# sourceMappingURL=hot.js.map
|
package/dist/hot.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hot.js","names":[],"sources":["../src/hot.ts"],"sourcesContent":["import { rechain } from './component';\nimport { event, observer } from './observable';\nimport { State, handlers, patch, track } from './state';\n\ninterface Entry {\n type: Function;\n shape: string;\n kinds: Record<string, 'get' | 'accessor' | 'fn'>;\n own: ReturnType<typeof handlers>;\n}\n\ninterface Replaced {\n /** Module id the class was accepted under. */\n id: string;\n /** Local declaration name of the class. */\n name: string;\n /** Class live instances belong to. */\n prev: State.Extends;\n /** Class that took its place. */\n next: State.Extends;\n}\n\nconst MODULES = new Map<string, Record<string, Entry>>();\nconst LISTENERS = new Set<(event: Replaced) => void>();\nconst REFRESH = Symbol.for('@expressive/mvc.refresh');\nconst PRIVATE = /(?:^|[\\s;{}*])#[\\w$]+(?=[\\s=;(}])/;\n\nfunction isState(value: unknown): value is State.Extends {\n return typeof value == 'function' && value.prototype instanceof State;\n}\n\n/** What a patch cannot carry: class source less its members, and member kinds. */\nfunction describe(type: Function): Entry {\n const text = Function.prototype.toString;\n const kinds: Entry['kinds'] = {};\n let shape = text.call(type);\n\n for (const target of [type.prototype, type])\n for (const [key, desc] of Object.entries(Object.getOwnPropertyDescriptors(target)))\n for (const fn of [desc.value, desc.get, desc.set])\n if (typeof fn == 'function' && fn !== type) {\n shape = shape.replace(text.call(fn), '');\n if (target !== type) kinds[key] = desc.set ? 'accessor' : desc.get ? 'get' : 'fn';\n }\n\n return { type, shape: shape.replace(/\\s+/g, ' '), kinds, own: handlers(type as State.Extends) };\n}\n\nfunction compatible(prev: Entry, next: Entry) {\n if (prev.shape !== next.shape || PRIVATE.test(next.shape)) return false;\n if (Object.getPrototypeOf(prev.type) !== Object.getPrototypeOf(next.type)) return false;\n\n for (const key in next.kinds)\n if (key in prev.kinds && prev.kinds[key] !== next.kinds[key]) return false;\n\n return true;\n}\n\n/**\n * Keep a module's State classes stable across runs. A class seen before is\n * patched with its replacement and returned in its place, refreshing live\n * instances; one whose shape or parent changed is returned as-is, and\n * reported to `replaced` listeners before `accept` returns.\n */\nfunction accept<T extends Record<string, unknown>>(id: string, classes: T): T {\n let known = MODULES.get(id);\n\n if (!known) MODULES.set(id, (known = {}));\n\n const output: Record<string, unknown> = { ...classes };\n const refresh = new Set<State>();\n const replace: Replaced[] = [];\n let patched = false;\n\n track();\n\n for (const [name, type] of Object.entries(classes)) {\n if (!isState(type)) continue;\n\n const prev = known[name];\n\n if (prev?.type === type) continue;\n\n const next = describe(type);\n\n if (!prev || !compatible(prev, next)) {\n if (prev) replace.push({ id, name, prev: prev.type as State.Extends, next: type });\n known[name] = next;\n continue;\n }\n\n try {\n for (const state of patch(prev.type as State.Extends, type, prev.own)) refresh.add(state);\n patched = true;\n known[name] = { ...next, type: prev.type };\n output[name] = prev.type;\n } catch (error) {\n console.error(error);\n replace.push({ id, name, prev: prev.type as State.Extends, next: type });\n known[name] = next;\n }\n }\n\n if (patched) rechain();\n\n for (const state of refresh) if (observer(state)?.ready) event(state, REFRESH);\n\n for (const event of replace)\n for (const listener of LISTENERS)\n try {\n listener(event);\n } catch (error) {\n console.error(error);\n }\n\n return output as T;\n}\n\n/**\n * Observe classes `accept` replaced instead of patching. Fires synchronously\n * inside `accept`, while the module re-runs, so a host can retire instances of\n * `prev` before anything resolves the module again.\n */\nfunction replaced(listener: (event: Replaced) => void): () => void {\n LISTENERS.add(listener);\n return () => void LISTENERS.delete(listener);\n}\n\nexport { accept, replaced };\nexport type { Replaced };\n"],"mappings":";;;;;;;;;;AAsBA,MAAM,0BAAU,IAAI,KAAoC;AACxD,MAAM,4BAAY,IAAI,KAAgC;AACtD,MAAM,UAAU,OAAO,IAAI,0BAA0B;AACrD,MAAM,UAAU;AAEhB,SAAS,QAAQ,OAAwC;AACvD,QAAO,OAAO,SAAS,cAAc,MAAM,qBAAqB;;;AAIlE,SAAS,SAAS,MAAuB;CACvC,MAAM,OAAO,SAAS,UAAU;CAChC,MAAM,QAAwB,EAAE;CAChC,IAAI,QAAQ,KAAK,KAAK,KAAK;AAE3B,MAAK,MAAM,UAAU,CAAC,KAAK,WAAW,KAAK,CACzC,MAAK,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,OAAO,0BAA0B,OAAO,CAAC,CAChF,MAAK,MAAM,MAAM;EAAC,KAAK;EAAO,KAAK;EAAK,KAAK;EAAI,CAC/C,KAAI,OAAO,MAAM,cAAc,OAAO,MAAM;AAC1C,UAAQ,MAAM,QAAQ,KAAK,KAAK,GAAG,EAAE,GAAG;AACxC,MAAI,WAAW,KAAM,OAAM,OAAO,KAAK,MAAM,aAAa,KAAK,MAAM,QAAQ;;AAGrF,QAAO;EAAE;EAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI;EAAE;EAAO,KAAK,SAAS,KAAsB;EAAE;;AAGjG,SAAS,WAAW,MAAa,MAAa;AAC5C,KAAI,KAAK,UAAU,KAAK,SAAS,QAAQ,KAAK,KAAK,MAAM,CAAE,QAAO;AAClE,KAAI,OAAO,eAAe,KAAK,KAAK,KAAK,OAAO,eAAe,KAAK,KAAK,CAAE,QAAO;AAElF,MAAK,MAAM,OAAO,KAAK,MACrB,KAAI,OAAO,KAAK,SAAS,KAAK,MAAM,SAAS,KAAK,MAAM,KAAM,QAAO;AAEvE,QAAO;;;;;;;;AAST,SAAS,OAA0C,IAAY,SAAe;CAC5E,IAAI,QAAQ,QAAQ,IAAI,GAAG;AAE3B,KAAI,CAAC,MAAO,SAAQ,IAAI,IAAK,QAAQ,EAAE,CAAE;CAEzC,MAAM,SAAkC,EAAE,GAAG,SAAS;CACtD,MAAM,0BAAU,IAAI,KAAY;CAChC,MAAM,UAAsB,EAAE;CAC9B,IAAI,UAAU;AAEd,QAAO;AAEP,MAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,QAAQ,EAAE;AAClD,MAAI,CAAC,QAAQ,KAAK,CAAE;EAEpB,MAAM,OAAO,MAAM;AAEnB,MAAI,MAAM,SAAS,KAAM;EAEzB,MAAM,OAAO,SAAS,KAAK;AAE3B,MAAI,CAAC,QAAQ,CAAC,WAAW,MAAM,KAAK,EAAE;AACpC,OAAI,KAAM,SAAQ,KAAK;IAAE;IAAI;IAAM,MAAM,KAAK;IAAuB,MAAM;IAAM,CAAC;AAClF,SAAM,QAAQ;AACd;;AAGF,MAAI;AACF,QAAK,MAAM,SAAS,MAAM,KAAK,MAAuB,MAAM,KAAK,IAAI,CAAE,SAAQ,IAAI,MAAM;AACzF,aAAU;AACV,SAAM,QAAQ;IAAE,GAAG;IAAM,MAAM,KAAK;IAAM;AAC1C,UAAO,QAAQ,KAAK;WACb,OAAO;AACd,WAAQ,MAAM,MAAM;AACpB,WAAQ,KAAK;IAAE;IAAI;IAAM,MAAM,KAAK;IAAuB,MAAM;IAAM,CAAC;AACxE,SAAM,QAAQ;;;AAIlB,KAAI,QAAS,UAAS;AAEtB,MAAK,MAAM,SAAS,QAAS,KAAI,SAAS,MAAM,EAAE,MAAO,OAAM,OAAO,QAAQ;AAE9E,MAAK,MAAM,SAAS,QAClB,MAAK,MAAM,YAAY,UACrB,KAAI;AACF,WAAS,MAAM;UACR,OAAO;AACd,UAAQ,MAAM,MAAM;;AAG1B,QAAO;;;;;;;AAQT,SAAS,SAAS,UAAiD;AACjE,WAAU,IAAI,SAAS;AACvB,cAAa,KAAK,UAAU,OAAO,SAAS"}
|
|
1
|
+
{"version":3,"file":"hot.js","names":[],"sources":["../src/hot.ts"],"sourcesContent":["import { rechain } from './component';\nimport { event } from './observable';\nimport {\n State,\n GETTERS,\n LATEST,\n METHODS,\n SETUP,\n UNBIND,\n classify,\n compute,\n type Handler\n} from './state';\n\ninterface Entry {\n type: Function;\n shape: string;\n kinds: Record<string, 'get' | 'accessor' | 'fn'>;\n own: Handler[];\n}\n\ninterface Replaced {\n /** Module id the class was accepted under. */\n id: string;\n /** Local declaration name of the class. */\n name: string;\n /** Class live instances belong to. */\n prev: State.Extends;\n /** Class that took its place. */\n next: State.Extends;\n}\n\nconst define = Object.defineProperty;\n\n/** Method implementations replaced by a hot patch. */\nconst PAST = new WeakSet<Function>();\n\n/** Live instances, tracked once hot patching is enabled. */\nlet LIVE: Set<WeakRef<State>> | undefined;\n\n/** Bootstrapped subclasses of each class, tracked once hot patching is enabled. */\nconst SUBCLASSES = new WeakMap<Function, Set<State.Extends>>();\n\nconst MODULES = new Map<string, Record<string, Entry>>();\nconst LISTENERS = new Set<(event: Replaced) => void>();\nconst REFRESH = Symbol.for('@expressive/mvc.refresh');\nconst PRIVATE = /(?:^|[\\s;{}*])#[\\w$]+(?=[\\s=;(}])/;\n\n/** Begin tracking live instances, so a hot patch can reach them. */\nfunction track() {\n if (LIVE) return;\n\n LIVE = new Set();\n\n State.on({\n type(type) {\n const parent = Object.getPrototypeOf(type);\n let children = SUBCLASSES.get(parent);\n if (!children) SUBCLASSES.set(parent, (children = new Set()));\n children.add(type);\n },\n setup(state) {\n const ref = new WeakRef(state);\n LIVE!.add(ref);\n return () => LIVE!.delete(ref);\n }\n });\n}\n\n/**\n * Move the members of `next` onto `prev`, which keeps its identity. Returns the\n * live instances of `prev`, each needing a refresh.\n */\nfunction patch(prev: State.Extends, next: State.Extends, own: Handler[]): State[] {\n const proto = prev.prototype;\n const incoming = Object.getOwnPropertyDescriptors(next.prototype);\n const keys = METHODS.get(prev);\n const getters = GETTERS.get(prev);\n const methods = new Map<string, Function>();\n const knownKeys = new Set(keys?.keys());\n const knownGetters = new Set(getters?.keys());\n\n let setup = SETUP.get(prev);\n\n for (const handler of own) setup!.delete(handler);\n for (const handler of handlers(next)) {\n if (!setup) SETUP.set(prev, (setup = new Set()));\n setup.add(handler);\n }\n\n for (const key of Reflect.ownKeys(next)) {\n if (key == 'prototype' || key == 'length' || key == 'name') continue;\n if (Object.getOwnPropertyDescriptor(prev, key)?.configurable !== false)\n define(prev, key, Object.getOwnPropertyDescriptor(next, key)!);\n }\n\n const removed = new Set<string>();\n\n for (const key of Object.getOwnPropertyNames(proto))\n if (key != 'constructor' && !(key in incoming)) {\n const bind = keys?.get(key);\n\n if (bind && Object.getOwnPropertyDescriptor(proto, key)!.get === bind) {\n PAST.add(UNBIND.get(bind));\n keys!.delete(key);\n }\n\n removed.add(key);\n Reflect.deleteProperty(proto, key);\n getters?.delete(key);\n }\n\n for (const [key, desc] of Object.entries(incoming)) {\n if (key == 'constructor') continue;\n\n const current = Object.getOwnPropertyDescriptor(proto, key);\n\n if (typeof desc.value == 'function') methods.set(key, desc.value);\n if (current?.configurable === false) {\n if (current.writable) (proto as any)[key] = desc.value;\n continue;\n }\n\n if (current?.get && keys?.get(key) === current.get)\n PAST.add(UNBIND.get(current.get));\n\n const getter = getters?.get(key);\n\n if (getter) LATEST.set(getter, desc.get!);\n\n define(proto, key, { ...desc, configurable: true });\n }\n\n if (keys) {\n for (let T: State.Extends = prev; ; T = Object.getPrototypeOf(T)) {\n for (const handler of SETUP.get(T) || [])\n if (handler.type) handler.type(prev);\n\n if (T === State) break;\n }\n\n classify(prev, keys, getters!);\n }\n\n const live: State[] = [];\n\n for (const ref of LIVE!) {\n const state = ref.deref();\n\n if (!state) LIVE!.delete(ref);\n else if (state instanceof prev) live.push(state);\n }\n\n const descendants = new Set([prev, ...live.map((state) => state.constructor as State.Extends)]);\n\n for (const type of descendants) for (const child of SUBCLASSES.get(type) || []) descendants.add(child);\n\n descendants.delete(prev);\n\n for (const type of descendants) {\n const inherit = METHODS.get(type)!;\n const computed = GETTERS.get(type)!;\n\n for (const [key, bind] of keys!) if (!knownKeys.has(key) && !inherit.has(key)) inherit.set(key, bind);\n for (const [key, get] of getters!) if (!knownGetters.has(key) && !computed.has(key)) computed.set(key, get);\n for (const key of removed)\n if (!(key in type.prototype)) {\n inherit.delete(key);\n computed.delete(key);\n }\n }\n\n for (const state of live) {\n for (const [key, value] of methods) {\n const desc = Object.getOwnPropertyDescriptor(state, key);\n\n if (!desc) continue;\n if (desc.set) desc.set.call(state, value);\n else if (PAST.has(UNBIND.get(desc.value))) delete (state as any)[key];\n }\n\n for (const key of removed)\n if (PAST.has(UNBIND.get(Object.getOwnPropertyDescriptor(state, key)?.value))) delete (state as any)[key];\n\n for (const [key, get] of GETTERS.get(state.constructor)!)\n if (!knownGetters.has(key) && get === getters!.get(key)) compute.call(state, get, key);\n }\n\n return live;\n}\n\n/** Lifecycle handlers registered on a class itself. */\nfunction handlers(type: State.Extends): Handler[] {\n return [...(SETUP.get(type) || [])];\n}\n\nfunction isState(value: unknown): value is State.Extends {\n return typeof value == 'function' && value.prototype instanceof State;\n}\n\n/** What a patch cannot carry: class source less its members, and member kinds. */\nfunction describe(type: Function): Entry {\n const text = Function.prototype.toString;\n const kinds: Entry['kinds'] = {};\n let shape = text.call(type);\n\n for (const target of [type.prototype, type])\n for (const [key, desc] of Object.entries(Object.getOwnPropertyDescriptors(target)))\n for (const fn of [desc.value, desc.get, desc.set])\n if (typeof fn == 'function' && fn !== type) {\n shape = shape.replace(text.call(fn), '');\n if (target !== type) kinds[key] = desc.set ? 'accessor' : desc.get ? 'get' : 'fn';\n }\n\n shape = shape.replace(/\\s+/g, ' ').replace(/__vite_ssr_import_\\d+__/g, '__vite_ssr_import__');\n\n return { type, shape, kinds, own: handlers(type as State.Extends) };\n}\n\nfunction compatible(prev: Entry, next: Entry) {\n if (prev.shape !== next.shape || PRIVATE.test(next.shape)) return false;\n if (Object.getPrototypeOf(prev.type) !== Object.getPrototypeOf(next.type)) return false;\n\n for (const key in next.kinds)\n if (key in prev.kinds && prev.kinds[key] !== next.kinds[key]) return false;\n\n return true;\n}\n\n/**\n * Keep a module's State classes stable across runs. A class seen before is\n * patched with its replacement and returned in its place, refreshing live\n * instances; one whose shape or parent changed is returned as-is, and\n * reported to `replaced` listeners before `accept` returns.\n */\nfunction accept<T extends Record<string, unknown>>(id: string, classes: T): T {\n let known = MODULES.get(id);\n\n if (!known) MODULES.set(id, (known = {}));\n\n const output: Record<string, unknown> = { ...classes };\n const refresh = new Set<State>();\n const replace: Replaced[] = [];\n let patched = false;\n\n track();\n\n for (const [name, type] of Object.entries(classes)) {\n if (!isState(type)) continue;\n\n const prev = known[name];\n\n if (prev?.type === type) continue;\n\n const next = describe(type);\n\n if (!prev || !compatible(prev, next)) {\n if (prev) replace.push({ id, name, prev: prev.type as State.Extends, next: type });\n known[name] = next;\n continue;\n }\n\n try {\n for (const state of patch(prev.type as State.Extends, type, prev.own)) refresh.add(state);\n patched = true;\n known[name] = { ...next, type: prev.type };\n output[name] = prev.type;\n } catch (error) {\n console.error(error);\n replace.push({ id, name, prev: prev.type as State.Extends, next: type });\n known[name] = next;\n }\n }\n\n if (patched) rechain();\n\n for (const state of refresh) event(state, REFRESH);\n\n for (const event of replace)\n for (const listener of LISTENERS)\n try {\n listener(event);\n } catch (error) {\n console.error(error);\n }\n\n return output as T;\n}\n\n/**\n * Observe classes `accept` replaced instead of patching. Fires synchronously\n * inside `accept`, while the module re-runs, so a host can retire instances of\n * `prev` before anything resolves the module again.\n */\nfunction replaced(listener: (event: Replaced) => void): () => void {\n LISTENERS.add(listener);\n return () => void LISTENERS.delete(listener);\n}\n\nexport { accept, replaced };\nexport type { Replaced };\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Context } from "./context.js";
|
|
2
2
|
import { State, unbind } from "./state.js";
|
|
3
|
-
import { Caught } from "./caught.js";
|
|
4
3
|
import { Component } from "./component.js";
|
|
5
4
|
import { pending } from "./dispatch.js";
|
|
6
5
|
import { def } from "./field/def.js";
|
|
@@ -9,4 +8,4 @@ import { has } from "./field/has.js";
|
|
|
9
8
|
import { map } from "./field/map.js";
|
|
10
9
|
import { ref } from "./field/ref.js";
|
|
11
10
|
import { set } from "./field/set.js";
|
|
12
|
-
export {
|
|
11
|
+
export { Component, Context, State, def, State as default, get, has, map, pending, ref, set, unbind };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Caught } from "./caught.js";
|
|
2
|
-
import { State, unbind } from "./state.js";
|
|
3
1
|
import { pending } from "./dispatch.js";
|
|
2
|
+
import { State, unbind } from "./state.js";
|
|
4
3
|
import { Context } from "./context.js";
|
|
5
4
|
import { def } from "./field/def.js";
|
|
6
5
|
import { set } from "./field/set.js";
|
|
@@ -15,5 +14,5 @@ import { ref } from "./field/ref.js";
|
|
|
15
14
|
var src_default = State;
|
|
16
15
|
|
|
17
16
|
//#endregion
|
|
18
|
-
export {
|
|
17
|
+
export { Component, Context, State, def, src_default as default, get, has, map, pending, ref, set, unbind };
|
|
19
18
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["export { def } from './field/def';\nexport { get } from './field/get';\nexport { has } from './field/has';\nexport { map } from './field/map';\nexport { set } from './field/set';\nexport { ref } from './field/ref';\n\nimport { State } from './state';\n\nexport { State, unbind } from './state';\n\n/** @deprecated Import `{ State }` as a named export. Adapter-augmented `State.*` types are not visible through the default alias. */\nexport default State;\nexport { Context } from './context';\nexport { Component } from './component';\nexport { pending } from './dispatch';\
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["export { def } from './field/def';\nexport { get } from './field/get';\nexport { has } from './field/has';\nexport { map } from './field/map';\nexport { set } from './field/set';\nexport { ref } from './field/ref';\n\nimport { State } from './state';\n\nexport { State, unbind } from './state';\n\n/** @deprecated Import `{ State }` as a named export. Adapter-augmented `State.*` types are not visible through the default alias. */\nexport default State;\nexport { Context } from './context';\nexport { Component } from './component';\nexport { pending } from './dispatch';\n"],"mappings":";;;;;;;;;;;;;AAYA,kBAAe"}
|
package/dist/jsx-dev-runtime.js
CHANGED
package/dist/jsx-runtime.d.ts
CHANGED
|
@@ -1,12 +1,85 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Component } from "./component.js";
|
|
1
|
+
import { Component, compose } from "./component.js";
|
|
3
2
|
|
|
4
3
|
//#region src/jsx-runtime.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Per-adapter interpretation manifest. Each adapter augments this interface to
|
|
6
|
+
* declare how it renders; the first member is `node` - the element type produced
|
|
7
|
+
* by `Component.render` (surfaced as `Component.Node`) - alongside `intrinsics`,
|
|
8
|
+
* the host's tag map (surfaced as `JSX.IntrinsicElements`), `elementClass`,
|
|
9
|
+
* the instance a class must construct to render as an element, and optionally
|
|
10
|
+
* `element`, further element types the host renders (joined into
|
|
11
|
+
* `JSX.ElementType`).
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* declare module '@expressive/mvc/jsx-runtime' {
|
|
15
|
+
* interface Host {
|
|
16
|
+
* node: React.ReactNode;
|
|
17
|
+
* intrinsics: React.JSX.IntrinsicElements;
|
|
18
|
+
* elementClass: React.Component<any, any>;
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* Only one adapter is expected per compilation; two augmenting the same member
|
|
24
|
+
* with different types in the same build would conflict - by design.
|
|
25
|
+
*/
|
|
26
|
+
interface Host {}
|
|
27
|
+
/**
|
|
28
|
+
* Host runtime, registered by an adapter (e.g. `@expressive/react`) as an
|
|
29
|
+
* import side effect. One host per build - a second registration with a
|
|
30
|
+
* different runtime throws.
|
|
31
|
+
*
|
|
32
|
+
* Members are ambient host capabilities: plain functions the host uniquely
|
|
33
|
+
* owns, callable outside render - element mechanics always, plus optional
|
|
34
|
+
* extras that fall back sanely when absent. Hook-shaped (render-resident)
|
|
35
|
+
* capabilities do not belong here; those live with the adapter.
|
|
36
|
+
*/
|
|
37
|
+
interface HostRuntime {
|
|
38
|
+
childrenOf(children: unknown): Component.Node[];
|
|
39
|
+
isElement(node: unknown): boolean;
|
|
40
|
+
jsx(type: unknown, props: object, key?: unknown): Component.Node;
|
|
41
|
+
jsxDEV?(type: unknown, props: object, key?: unknown, isStatic?: boolean, source?: object, self?: unknown): Component.Node;
|
|
42
|
+
jsxs(type: unknown, props: object, key?: unknown): Component.Node;
|
|
43
|
+
propsOf(node: unknown): Record<string, unknown>;
|
|
44
|
+
typeOf(node: unknown): unknown;
|
|
45
|
+
Fragment: unknown;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Agnostic Fragment sentinel. The runtime entries translate it to the host's
|
|
49
|
+
* Fragment on element creation; `typeOf` translates back, so identity checks
|
|
50
|
+
* against this value hold for fragments from either pragma.
|
|
51
|
+
*/
|
|
52
|
+
declare const Fragment: unique symbol;
|
|
53
|
+
/**
|
|
54
|
+
* Register the host runtime. Idempotent for the same runtime - re-registering
|
|
55
|
+
* picks up members added since (e.g. an optional dev seam). Element mechanics
|
|
56
|
+
* the host leaves unset keep defaults that throw a setup-pointing error;
|
|
57
|
+
* `jsxDEV` is routed around at the call site instead.
|
|
58
|
+
*/
|
|
59
|
+
declare function host(runtime: HostRuntime): void;
|
|
60
|
+
declare function jsx(type: unknown, props: object, key?: unknown): Component.Node;
|
|
61
|
+
declare function jsxs(type: unknown, props: object, key?: unknown): Component.Node;
|
|
62
|
+
/** Dev-transpiled element creation. Hosts without a `jsxDEV` of their own fall
|
|
63
|
+
* back to the production entries (prod-only host under a dev build). */
|
|
64
|
+
declare function jsxDEV(type: unknown, props: object, key?: unknown, isStatic?: boolean, source?: object, self?: unknown): Component.Node;
|
|
65
|
+
/** Flatten `children` to an array of nodes, per the host's semantics. */
|
|
66
|
+
declare function childrenOf(children: unknown): Component.Node[];
|
|
67
|
+
/** Is `node` a host element? */
|
|
68
|
+
declare function isElement(node: unknown): boolean;
|
|
69
|
+
/** Element type of `node`; host Fragments surface as the agnostic `Fragment`. */
|
|
70
|
+
declare function typeOf(node: unknown): unknown;
|
|
71
|
+
/** Props carried by element `node`. */
|
|
72
|
+
declare function propsOf(node: unknown): Record<string, unknown>;
|
|
5
73
|
declare namespace JSX {
|
|
6
74
|
type Element = Component.Node;
|
|
7
|
-
type ElementType = keyof IntrinsicElements | ((props: any) => Component.Node) | (
|
|
75
|
+
type ElementType = keyof IntrinsicElements | ((props: any) => Component.Node) | (new (...args: any[]) => Host extends {
|
|
76
|
+
elementClass: infer I;
|
|
77
|
+
} ? I : ElementClass) | (Host extends {
|
|
78
|
+
element: infer T;
|
|
79
|
+
} ? T : never);
|
|
8
80
|
/**
|
|
9
|
-
*
|
|
81
|
+
* Class instance contract when no host declares `elementClass`. Gates on the
|
|
82
|
+
* `render` contract alone - requiring full
|
|
10
83
|
* `Component` assignability trips contravariance on `props` members (e.g.
|
|
11
84
|
* the `is` callback narrows per subclass), rejecting every subclass.
|
|
12
85
|
*/
|
|
@@ -32,5 +105,5 @@ declare namespace JSX {
|
|
|
32
105
|
} ? T : {};
|
|
33
106
|
}
|
|
34
107
|
//#endregion
|
|
35
|
-
export { Fragment, JSX, jsx, jsxs };
|
|
108
|
+
export { Fragment, Host, HostRuntime, JSX, childrenOf, compose, host, isElement, jsx, jsxDEV, jsxs, propsOf, typeOf };
|
|
36
109
|
//# sourceMappingURL=jsx-runtime.d.ts.map
|
package/dist/jsx-runtime.js
CHANGED
|
@@ -1,3 +1,70 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { compose } from "./component.js";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
//#region src/jsx-runtime.ts
|
|
4
|
+
/**
|
|
5
|
+
* Agnostic Fragment sentinel. The runtime entries translate it to the host's
|
|
6
|
+
* Fragment on element creation; `typeOf` translates back, so identity checks
|
|
7
|
+
* against this value hold for fragments from either pragma.
|
|
8
|
+
*/
|
|
9
|
+
const Fragment = Symbol.for("@expressive/mvc.Fragment");
|
|
10
|
+
/** Default for seams only a registered host can provide. */
|
|
11
|
+
function absent() {
|
|
12
|
+
throw new Error("No JSX host is registered for @expressive/mvc. Import a host adapter (e.g. '@expressive/react') before anything renders - typically as the first import of your application entry module.");
|
|
13
|
+
}
|
|
14
|
+
const HOST = {
|
|
15
|
+
childrenOf: absent,
|
|
16
|
+
isElement: absent,
|
|
17
|
+
jsx: absent,
|
|
18
|
+
jsxs: absent,
|
|
19
|
+
propsOf: absent,
|
|
20
|
+
typeOf: absent,
|
|
21
|
+
Fragment
|
|
22
|
+
};
|
|
23
|
+
let registered;
|
|
24
|
+
/**
|
|
25
|
+
* Register the host runtime. Idempotent for the same runtime - re-registering
|
|
26
|
+
* picks up members added since (e.g. an optional dev seam). Element mechanics
|
|
27
|
+
* the host leaves unset keep defaults that throw a setup-pointing error;
|
|
28
|
+
* `jsxDEV` is routed around at the call site instead.
|
|
29
|
+
*/
|
|
30
|
+
function host(runtime) {
|
|
31
|
+
if (registered && registered !== runtime) throw new Error("A different JSX host is already registered for @expressive/mvc. Only one host adapter may be active per build.");
|
|
32
|
+
registered = runtime;
|
|
33
|
+
Object.assign(HOST, runtime);
|
|
34
|
+
}
|
|
35
|
+
/** Translate the agnostic Fragment sentinel to the host's Fragment. */
|
|
36
|
+
function hostType(type) {
|
|
37
|
+
return type === Fragment ? HOST.Fragment : type;
|
|
38
|
+
}
|
|
39
|
+
function jsx(type, props, key) {
|
|
40
|
+
return HOST.jsx(hostType(type), props, key);
|
|
41
|
+
}
|
|
42
|
+
function jsxs(type, props, key) {
|
|
43
|
+
return HOST.jsxs(hostType(type), props, key);
|
|
44
|
+
}
|
|
45
|
+
/** Dev-transpiled element creation. Hosts without a `jsxDEV` of their own fall
|
|
46
|
+
* back to the production entries (prod-only host under a dev build). */
|
|
47
|
+
function jsxDEV(type, props, key, isStatic, source, self) {
|
|
48
|
+
return HOST.jsxDEV ? HOST.jsxDEV(hostType(type), props, key, isStatic, source, self) : isStatic ? jsxs(type, props, key) : jsx(type, props, key);
|
|
49
|
+
}
|
|
50
|
+
/** Flatten `children` to an array of nodes, per the host's semantics. */
|
|
51
|
+
function childrenOf(children) {
|
|
52
|
+
return HOST.childrenOf(children);
|
|
53
|
+
}
|
|
54
|
+
/** Is `node` a host element? */
|
|
55
|
+
function isElement(node) {
|
|
56
|
+
return HOST.isElement(node);
|
|
57
|
+
}
|
|
58
|
+
/** Element type of `node`; host Fragments surface as the agnostic `Fragment`. */
|
|
59
|
+
function typeOf(node) {
|
|
60
|
+
const type = HOST.typeOf(node);
|
|
61
|
+
return type === HOST.Fragment ? Fragment : type;
|
|
62
|
+
}
|
|
63
|
+
/** Props carried by element `node`. */
|
|
64
|
+
function propsOf(node) {
|
|
65
|
+
return HOST.propsOf(node);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
export { Fragment, childrenOf, compose, host, isElement, jsx, jsxDEV, jsxs, propsOf, typeOf };
|
|
70
|
+
//# sourceMappingURL=jsx-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsx-runtime.js","names":[],"sources":["../src/jsx-runtime.ts"],"sourcesContent":["import type { Component } from './component';\n\nexport { compose } from './component';\n\n/**\n * Per-adapter interpretation manifest. Each adapter augments this interface to\n * declare how it renders; the first member is `node` - the element type produced\n * by `Component.render` (surfaced as `Component.Node`) - alongside `intrinsics`,\n * the host's tag map (surfaced as `JSX.IntrinsicElements`), `elementClass`,\n * the instance a class must construct to render as an element, and optionally\n * `element`, further element types the host renders (joined into\n * `JSX.ElementType`).\n *\n * ```ts\n * declare module '@expressive/mvc/jsx-runtime' {\n * interface Host {\n * node: React.ReactNode;\n * intrinsics: React.JSX.IntrinsicElements;\n * elementClass: React.Component<any, any>;\n * }\n * }\n * ```\n *\n * Only one adapter is expected per compilation; two augmenting the same member\n * with different types in the same build would conflict - by design.\n */\nexport interface Host { }\n\n/**\n * Host runtime, registered by an adapter (e.g. `@expressive/react`) as an\n * import side effect. One host per build - a second registration with a\n * different runtime throws.\n *\n * Members are ambient host capabilities: plain functions the host uniquely\n * owns, callable outside render - element mechanics always, plus optional\n * extras that fall back sanely when absent. Hook-shaped (render-resident)\n * capabilities do not belong here; those live with the adapter.\n */\nexport interface HostRuntime {\n childrenOf(children: unknown): Component.Node[];\n isElement(node: unknown): boolean;\n jsx(type: unknown, props: object, key?: unknown): Component.Node;\n jsxDEV?(type: unknown, props: object, key?: unknown, isStatic?: boolean, source?: object, self?: unknown): Component.Node;\n jsxs(type: unknown, props: object, key?: unknown): Component.Node;\n propsOf(node: unknown): Record<string, unknown>;\n typeOf(node: unknown): unknown;\n Fragment: unknown;\n}\n\n/**\n * Agnostic Fragment sentinel. The runtime entries translate it to the host's\n * Fragment on element creation; `typeOf` translates back, so identity checks\n * against this value hold for fragments from either pragma.\n */\nexport const Fragment = Symbol.for('@expressive/mvc.Fragment');\n\n/** Default for seams only a registered host can provide. */\nfunction absent(): never {\n throw new Error(\n 'No JSX host is registered for @expressive/mvc. ' +\n \"Import a host adapter (e.g. '@expressive/react') before anything renders - \" +\n 'typically as the first import of your application entry module.'\n );\n}\n\nconst HOST: HostRuntime = {\n childrenOf: absent,\n isElement: absent,\n jsx: absent,\n jsxs: absent,\n propsOf: absent,\n typeOf: absent,\n Fragment\n};\n\nlet registered: HostRuntime | undefined;\n\n/**\n * Register the host runtime. Idempotent for the same runtime - re-registering\n * picks up members added since (e.g. an optional dev seam). Element mechanics\n * the host leaves unset keep defaults that throw a setup-pointing error;\n * `jsxDEV` is routed around at the call site instead.\n */\nexport function host(runtime: HostRuntime) {\n if (registered && registered !== runtime)\n throw new Error(\n 'A different JSX host is already registered for @expressive/mvc. ' +\n 'Only one host adapter may be active per build.'\n );\n\n registered = runtime;\n Object.assign(HOST, runtime);\n}\n\n/** Translate the agnostic Fragment sentinel to the host's Fragment. */\nfunction hostType(type: unknown): unknown {\n return type === Fragment ? HOST.Fragment : type;\n}\n\nexport function jsx(type: unknown, props: object, key?: unknown): Component.Node {\n return HOST.jsx(hostType(type), props, key);\n}\n\nexport function jsxs(type: unknown, props: object, key?: unknown): Component.Node {\n return HOST.jsxs(hostType(type), props, key);\n}\n\n/** Dev-transpiled element creation. Hosts without a `jsxDEV` of their own fall\n * back to the production entries (prod-only host under a dev build). */\nexport function jsxDEV(\n type: unknown,\n props: object,\n key?: unknown,\n isStatic?: boolean,\n source?: object,\n self?: unknown\n): Component.Node {\n return HOST.jsxDEV\n ? HOST.jsxDEV(hostType(type), props, key, isStatic, source, self)\n : isStatic\n ? jsxs(type, props, key)\n : jsx(type, props, key);\n}\n\n/** Flatten `children` to an array of nodes, per the host's semantics. */\nexport function childrenOf(children: unknown): Component.Node[] {\n return HOST.childrenOf(children);\n}\n\n/** Is `node` a host element? */\nexport function isElement(node: unknown): boolean {\n return HOST.isElement(node);\n}\n\n/** Element type of `node`; host Fragments surface as the agnostic `Fragment`. */\nexport function typeOf(node: unknown): unknown {\n const type = HOST.typeOf(node);\n return type === HOST.Fragment ? Fragment : type;\n}\n\n/** Props carried by element `node`. */\nexport function propsOf(node: unknown): Record<string, unknown> {\n return HOST.propsOf(node);\n}\n\n\nexport declare namespace JSX {\n type Element = Component.Node;\n type ElementType =\n | keyof IntrinsicElements\n | ((props: any) => Component.Node)\n | (new (...args: any[]) => Host extends { elementClass: infer I } ? I : ElementClass)\n | (Host extends { element: infer T } ? T : never);\n /**\n * Class instance contract when no host declares `elementClass`. Gates on the\n * `render` contract alone - requiring full\n * `Component` assignability trips contravariance on `props` members (e.g.\n * the `is` callback narrows per subclass), rejecting every subclass.\n */\n interface ElementClass { render(props?: any): Component.Node }\n interface ElementAttributesProperty { props: {} }\n interface ElementChildrenAttribute { children: {} }\n interface IntrinsicAttributes { key?: string | number | null }\n /**\n * Host tag manifest, via the {@link Host} seam. Resolves to `{}` until an\n * adapter augments `Host` with `intrinsics` - agnostic code is\n * components-only by design, since it cannot know what tags a host renders.\n */\n type IntrinsicElements =\n Host extends { intrinsics: infer T extends object } ? T : {};\n}\n"],"mappings":";;;;;;;;AAsDA,MAAa,WAAW,OAAO,IAAI,2BAA2B;;AAG9D,SAAS,SAAgB;AACvB,OAAM,IAAI,MACR,4LAGD;;AAGH,MAAM,OAAoB;CACxB,YAAY;CACZ,WAAW;CACX,KAAK;CACL,MAAM;CACN,SAAS;CACT,QAAQ;CACR;CACD;AAED,IAAI;;;;;;;AAQJ,SAAgB,KAAK,SAAsB;AACzC,KAAI,cAAc,eAAe,QAC/B,OAAM,IAAI,MACR,iHAED;AAEH,cAAa;AACb,QAAO,OAAO,MAAM,QAAQ;;;AAI9B,SAAS,SAAS,MAAwB;AACxC,QAAO,SAAS,WAAW,KAAK,WAAW;;AAG7C,SAAgB,IAAI,MAAe,OAAe,KAA+B;AAC/E,QAAO,KAAK,IAAI,SAAS,KAAK,EAAE,OAAO,IAAI;;AAG7C,SAAgB,KAAK,MAAe,OAAe,KAA+B;AAChF,QAAO,KAAK,KAAK,SAAS,KAAK,EAAE,OAAO,IAAI;;;;AAK9C,SAAgB,OACd,MACA,OACA,KACA,UACA,QACA,MACgB;AAChB,QAAO,KAAK,SACR,KAAK,OAAO,SAAS,KAAK,EAAE,OAAO,KAAK,UAAU,QAAQ,KAAK,GAC/D,WACE,KAAK,MAAM,OAAO,IAAI,GACtB,IAAI,MAAM,OAAO,IAAI;;;AAI7B,SAAgB,WAAW,UAAqC;AAC9D,QAAO,KAAK,WAAW,SAAS;;;AAIlC,SAAgB,UAAU,MAAwB;AAChD,QAAO,KAAK,UAAU,KAAK;;;AAI7B,SAAgB,OAAO,MAAwB;CAC7C,MAAM,OAAO,KAAK,OAAO,KAAK;AAC9B,QAAO,SAAS,KAAK,WAAW,WAAW;;;AAI7C,SAAgB,QAAQ,MAAwC;AAC9D,QAAO,KAAK,QAAQ,KAAK"}
|