@expressive/mvc 0.89.0 → 0.90.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/dist/context.d.ts +4 -17
- package/dist/context.js +36 -62
- package/dist/context.js.map +1 -1
- package/package.json +1 -1
package/dist/context.d.ts
CHANGED
|
@@ -15,8 +15,6 @@ declare class Context {
|
|
|
15
15
|
scope: Set<Context>;
|
|
16
16
|
consume: Map<Model.Extends<Model>, Set<[Expect<Model>, boolean | undefined]> | null>;
|
|
17
17
|
provide: Map<Model.Extends<Model>, Set<[Model, boolean]> | null>;
|
|
18
|
-
protected inputs: Record<string | number, Model | Model.Extends>;
|
|
19
|
-
private cleanup;
|
|
20
18
|
constructor(arg?: Context | Accept);
|
|
21
19
|
private traverse;
|
|
22
20
|
private register;
|
|
@@ -28,25 +26,14 @@ declare class Context {
|
|
|
28
26
|
get<T extends Model>(Type: Model.Extends<T>, callback: Expect<T>, downstream?: boolean): () => void;
|
|
29
27
|
/** Lookup excluding a specific instance (used by Model.prototype.get for upstream-of-self semantics). */
|
|
30
28
|
get<T extends Model>(Type: Model.Extends<T>, arg: boolean | Expect<T> | undefined, downstream: boolean | undefined, skip: Model): T | undefined | (() => void);
|
|
31
|
-
/**
|
|
32
|
-
* Register one or more Models to this context.
|
|
33
|
-
*
|
|
34
|
-
* Context will add or remove Models as needed to keep with provided input.
|
|
35
|
-
*
|
|
36
|
-
* @param inputs Model, Model class, or map of Models / Model classes to register.
|
|
37
|
-
* @param forEach Optional callback to run for each Model registered. Receives
|
|
38
|
-
* whether this context created the Model - and so will destroy it - as
|
|
39
|
-
* opposed to it having been provided already active. May return a callback
|
|
40
|
-
* to run before that entry is dropped.
|
|
41
|
-
*/
|
|
42
|
-
set<T extends Model>(inputs: Accept<T>, forEach?: (state: T, owned: boolean) => (() => void) | void): this;
|
|
43
29
|
add(I: Model, explicit?: boolean): () => void;
|
|
44
30
|
/**
|
|
45
|
-
* Create a child context, optionally registering
|
|
31
|
+
* Create a child context, optionally registering Models to it.
|
|
46
32
|
*
|
|
47
|
-
* @param
|
|
33
|
+
* @param input Model instance to adopt, Model class to create - and destroy when the context pops - or an object of them, all registered before any activates.
|
|
34
|
+
* @param cleanup Called once when the context pops, before its Models are removed.
|
|
48
35
|
*/
|
|
49
|
-
push(
|
|
36
|
+
push(input?: Accept, cleanup?: () => void): Context;
|
|
50
37
|
/**
|
|
51
38
|
* Remove all Models from this context.
|
|
52
39
|
*
|
package/dist/context.js
CHANGED
|
@@ -5,6 +5,7 @@ import { Model, uid } from "./state.js";
|
|
|
5
5
|
const LOOKUP = /* @__PURE__ */ new WeakMap();
|
|
6
6
|
const HELD = /* @__PURE__ */ new WeakMap();
|
|
7
7
|
const HOST = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
const CLEANUP = /* @__PURE__ */ new WeakMap();
|
|
8
9
|
let ROOT;
|
|
9
10
|
var Context = class Context {
|
|
10
11
|
static get root() {
|
|
@@ -19,13 +20,12 @@ var Context = class Context {
|
|
|
19
20
|
scope = /* @__PURE__ */ new Set();
|
|
20
21
|
consume = /* @__PURE__ */ new Map();
|
|
21
22
|
provide = /* @__PURE__ */ new Map();
|
|
22
|
-
inputs = {};
|
|
23
|
-
cleanup = /* @__PURE__ */ new Map();
|
|
24
23
|
constructor(arg) {
|
|
24
|
+
CLEANUP.set(this, /* @__PURE__ */ new Set());
|
|
25
25
|
if (arg instanceof Context) {
|
|
26
26
|
this.parent = arg;
|
|
27
27
|
arg.scope.add(this);
|
|
28
|
-
} else if (arg) this
|
|
28
|
+
} else if (arg) insert(this, arg);
|
|
29
29
|
}
|
|
30
30
|
traverse(accept) {
|
|
31
31
|
const queue = [...this.scope];
|
|
@@ -78,58 +78,8 @@ var Context = class Context {
|
|
|
78
78
|
if (found === null) return null;
|
|
79
79
|
if (arg !== false) throw new Error(`Could not find ${Type} in context.`);
|
|
80
80
|
}
|
|
81
|
-
/**
|
|
82
|
-
* Register one or more Models to this context.
|
|
83
|
-
*
|
|
84
|
-
* Context will add or remove Models as needed to keep with provided input.
|
|
85
|
-
*
|
|
86
|
-
* @param inputs Model, Model class, or map of Models / Model classes to register.
|
|
87
|
-
* @param forEach Optional callback to run for each Model registered. Receives
|
|
88
|
-
* whether this context created the Model - and so will destroy it - as
|
|
89
|
-
* opposed to it having been provided already active. May return a callback
|
|
90
|
-
* to run before that entry is dropped.
|
|
91
|
-
*/
|
|
92
|
-
set(inputs, forEach) {
|
|
93
|
-
const init = /* @__PURE__ */ new Set();
|
|
94
|
-
const { cleanup } = this;
|
|
95
|
-
const single = typeof inputs == "function" || inputs instanceof Model;
|
|
96
|
-
if (typeof inputs == "function" || inputs instanceof Model) inputs = { [0]: inputs };
|
|
97
|
-
for (const K of Object.keys({
|
|
98
|
-
...this.inputs,
|
|
99
|
-
...inputs
|
|
100
|
-
})) {
|
|
101
|
-
const V = inputs[K];
|
|
102
|
-
const E = this.inputs[K];
|
|
103
|
-
if (E === V) continue;
|
|
104
|
-
if (E) {
|
|
105
|
-
cleanup.get(K)?.();
|
|
106
|
-
cleanup.delete(K);
|
|
107
|
-
}
|
|
108
|
-
if (!V) continue;
|
|
109
|
-
const owned = Model.is(V);
|
|
110
|
-
if (!(owned || V instanceof Model)) {
|
|
111
|
-
const as = K == "0" || K == String(V) ? V : `${V} (as '${K}')`;
|
|
112
|
-
throw new Error(`Context can only include an instance or class of Model but got ${as}.`);
|
|
113
|
-
}
|
|
114
|
-
const state = owned ? new V() : V.is;
|
|
115
|
-
const remove = this.add(state, true);
|
|
116
|
-
if (single && this !== ROOT) HOST.set(this, state);
|
|
117
|
-
init.add(() => {
|
|
118
|
-
event(state);
|
|
119
|
-
const dispose = forEach?.(state, owned);
|
|
120
|
-
cleanup.set(K, () => {
|
|
121
|
-
if (typeof dispose == "function") dispose();
|
|
122
|
-
remove();
|
|
123
|
-
if (owned) event(state, null);
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
for (const i of init) i();
|
|
128
|
-
this.inputs = inputs;
|
|
129
|
-
return this;
|
|
130
|
-
}
|
|
131
81
|
add(I, explicit = false) {
|
|
132
|
-
const {
|
|
82
|
+
const { provide } = this;
|
|
133
83
|
const root = this === Context.root;
|
|
134
84
|
const TT = [];
|
|
135
85
|
function conflict(T) {
|
|
@@ -169,6 +119,7 @@ var Context = class Context {
|
|
|
169
119
|
onDone.forEach((r) => r());
|
|
170
120
|
onDone.clear();
|
|
171
121
|
}
|
|
122
|
+
const cleanup = CLEANUP.get(this);
|
|
172
123
|
const held = Array.from(HELD.get(I) || [], ([child, added]) => {
|
|
173
124
|
const done = this.add(child);
|
|
174
125
|
added.add(done);
|
|
@@ -181,17 +132,19 @@ var Context = class Context {
|
|
|
181
132
|
held.forEach((done) => done());
|
|
182
133
|
flush();
|
|
183
134
|
}
|
|
184
|
-
cleanup.
|
|
135
|
+
cleanup.add(remove);
|
|
185
136
|
return remove;
|
|
186
137
|
}
|
|
187
138
|
/**
|
|
188
|
-
* Create a child context, optionally registering
|
|
139
|
+
* Create a child context, optionally registering Models to it.
|
|
189
140
|
*
|
|
190
|
-
* @param
|
|
141
|
+
* @param input Model instance to adopt, Model class to create - and destroy when the context pops - or an object of them, all registered before any activates.
|
|
142
|
+
* @param cleanup Called once when the context pops, before its Models are removed.
|
|
191
143
|
*/
|
|
192
|
-
push(
|
|
144
|
+
push(input, cleanup) {
|
|
193
145
|
const next = new Context(this);
|
|
194
|
-
if (
|
|
146
|
+
if (cleanup) CLEANUP.get(next).add(cleanup);
|
|
147
|
+
if (input) insert(next, input);
|
|
195
148
|
return next;
|
|
196
149
|
}
|
|
197
150
|
/**
|
|
@@ -200,11 +153,11 @@ var Context = class Context {
|
|
|
200
153
|
* Will also run any cleanup callbacks registered when Models were added.
|
|
201
154
|
*/
|
|
202
155
|
pop() {
|
|
203
|
-
this.inputs = {};
|
|
204
156
|
this.scope.forEach((x) => x.pop());
|
|
205
157
|
this.scope.clear();
|
|
206
|
-
|
|
207
|
-
|
|
158
|
+
const cleanup = CLEANUP.get(this);
|
|
159
|
+
cleanup.forEach((cb) => cb());
|
|
160
|
+
cleanup.clear();
|
|
208
161
|
this.consume.clear();
|
|
209
162
|
this.provide.clear();
|
|
210
163
|
if (this.parent) this.parent.scope.delete(this);
|
|
@@ -238,6 +191,27 @@ function host(state) {
|
|
|
238
191
|
if (found && found !== state) return found;
|
|
239
192
|
}
|
|
240
193
|
}
|
|
194
|
+
function insert(into, input) {
|
|
195
|
+
const single = typeof input == "function" || input instanceof Model;
|
|
196
|
+
const entries = Object.entries(single ? { input } : input);
|
|
197
|
+
const init = [];
|
|
198
|
+
const owns = [];
|
|
199
|
+
for (const [K, V] of entries) {
|
|
200
|
+
const owned = Model.is(V);
|
|
201
|
+
if (!(owned || V instanceof Model)) {
|
|
202
|
+
const as = single || K == String(V) ? V : `${V} (as '${K}')`;
|
|
203
|
+
throw new Error(`Context can only include an instance or class of Model but got ${as}.`);
|
|
204
|
+
}
|
|
205
|
+
const state = owned ? new V() : V.is;
|
|
206
|
+
into.add(state, true);
|
|
207
|
+
init.push(state);
|
|
208
|
+
if (single) HOST.set(into, state);
|
|
209
|
+
if (owned) owns.push(state);
|
|
210
|
+
}
|
|
211
|
+
const cleanup = CLEANUP.get(into);
|
|
212
|
+
for (const state of owns) cleanup.add(() => event(state, null));
|
|
213
|
+
for (const state of init) event(state);
|
|
214
|
+
}
|
|
241
215
|
|
|
242
216
|
//#endregion
|
|
243
217
|
export { Context, host, join };
|
package/dist/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","names":[],"sources":["../src/context.ts"],"sourcesContent":["import { listener } from \"./observable\";\nimport { event, Model, uid } from \"./state\";\n\nconst LOOKUP = new WeakMap<Model, Context>();\nconst HELD = new WeakMap<Model, Map<Model, Set<() => void>>>();\nconst HOST = new WeakMap<Context, Model>();\nlet ROOT: Context;\n\ntype Accept<T extends Model = Model> =\n | T\n | Model.Type<T>\n | Record<string | number, T | Model.Type<T>>;\n\ntype Expect<T extends Model = Model> = (\n state: T,\n downstream: boolean,\n) => (() => void) | void;\n\ndeclare namespace Context {\n export { Accept, Expect };\n}\n\nclass Context {\n static get root(): Context {\n return ROOT ??= new Context();\n }\n\n /** Get the context for a Model. Adapters may override to provide framework context. */\n static get(state?: Model): Context {\n return state && LOOKUP.get(state.is) || Context.root;\n }\n\n public id = uid();\n public parent?: Context;\n public scope = new Set<Context>();\n public consume = new Map<\n Model.Extends,\n Set<[Expect, boolean | undefined]> | null\n >();\n public provide = new Map<Model.Extends, Set<[Model, boolean]> | null>();\n\n protected inputs: Record<string | number, Model | Model.Extends> = {};\n\n private cleanup = new Map<string | number | Function, () => void>();\n\n constructor(arg?: Context | Accept) {\n if (arg instanceof Context) {\n this.parent = arg;\n arg.scope.add(this);\n } else if (arg) {\n this.set(arg);\n }\n }\n\n private traverse(accept: (ctx: Context) => boolean | void) {\n const queue = [...this.scope];\n for (const ctx of queue)\n if (accept(ctx) !== false) for (const c of ctx.scope) queue.push(c);\n }\n\n private register<T extends Model>(\n type: Model.Extends<T>,\n value: [Expect<T>, boolean | undefined],\n asConsumer: true,\n ): () => void;\n\n private register<T extends Model>(\n type: Model.Extends<T>,\n value: [T, boolean],\n asConsumer?: false,\n ): () => void;\n\n private register(type: Model.Extends, value: any, asConsumer?: boolean) {\n const mode = asConsumer ? \"consume\" : \"provide\";\n let set = this[mode].get(type) as Set<any>;\n if (!set) this[mode].set(type, (set = new Set()));\n set.add(value);\n\n for (let ctx = this.parent; ctx; ctx = ctx.parent) {\n if (ctx[mode].has(type)) break;\n ctx[mode].set(type, null);\n }\n\n return () => set.delete(value);\n }\n\n /** Find specified type upstream. Throws if not found. */\n public get<T extends Model>(Type: Model.Extends<T>, required?: true): T;\n\n /** Find specified type upstream. Returns undefined if not found. */\n public get<T extends Model>(\n Type: Model.Extends<T>,\n required?: boolean,\n ): T | undefined;\n\n /** Subscribe to a type becoming available in context. */\n public get<T extends Model>(\n Type: Model.Extends<T>,\n callback: Expect<T>,\n downstream?: boolean,\n ): () => void;\n\n /** Lookup excluding a specific instance (used by Model.prototype.get for upstream-of-self semantics). */\n public get<T extends Model>(\n Type: Model.Extends<T>,\n arg: boolean | Expect<T> | undefined,\n downstream: boolean | undefined,\n skip: Model,\n ): T | undefined | (() => void);\n\n public get<T extends Model>(\n Type: Model.Extends<T>,\n arg?: boolean | Expect<T>,\n downstream?: boolean,\n skip?: Model,\n ) {\n let found: T | null | undefined;\n let priority = false;\n\n for (let ctx: Context | undefined = this; ctx; ctx = ctx.parent) {\n const entries = ctx.provide.get(Type);\n if (!entries) continue;\n\n for (const [state, explicit] of entries) {\n if (state === skip || found === state) continue;\n if (!found || (explicit && !priority)) {\n found = state as T;\n priority = explicit;\n continue;\n }\n if (!priority) {\n found = null;\n break;\n }\n if (explicit)\n throw new Error(\n `Did find ${Type} in context, but multiple were defined.`,\n );\n }\n if (found !== undefined) break;\n }\n\n if (typeof arg === \"function\") {\n if (found && !downstream) arg(found, false);\n\n if (downstream !== false) {\n this.traverse((ctx) => {\n const has = ctx.provide.get(Type);\n if (has) for (const x of has) if (x[0] !== skip) arg(x[0] as T, true);\n return has !== undefined;\n });\n }\n\n return this.register(Type, [arg as Expect, downstream], true);\n }\n\n if (found) return found;\n if (found === null) return null;\n if (arg !== false) throw new Error(`Could not find ${Type} in context.`);\n }\n\n /**\n * Register one or more Models to this context.\n *\n * Context will add or remove Models as needed to keep with provided input.\n *\n * @param inputs Model, Model class, or map of Models / Model classes to register.\n * @param forEach Optional callback to run for each Model registered. Receives\n * whether this context created the Model - and so will destroy it - as\n * opposed to it having been provided already active. May return a callback\n * to run before that entry is dropped.\n */\n public set<T extends Model>(\n inputs: Accept<T>,\n forEach?: (state: T, owned: boolean) => (() => void) | void,\n ) {\n const init = new Set<() => void>();\n const { cleanup } = this;\n\n const single = typeof inputs == \"function\" || inputs instanceof Model;\n\n if (typeof inputs == \"function\" || inputs instanceof Model)\n inputs = { [0]: inputs };\n\n for (const K of Object.keys({ ...this.inputs, ...inputs })) {\n const V = inputs[K];\n const E = this.inputs[K];\n\n if (E === V) continue;\n\n if (E) {\n cleanup.get(K)?.();\n cleanup.delete(K);\n }\n\n if (!V) continue;\n\n // a class is constructed here - and so destroyed here; an instance is\n // adopted as-is and outlives this context\n const owned = Model.is(V);\n\n if (!(owned || V instanceof Model)) {\n const as = K == \"0\" || K == String(V) ? V : `${V} (as '${K}')`;\n throw new Error(\n `Context can only include an instance or class of Model but got ${as}.`,\n );\n }\n\n const state = owned ? new (V as Model.Type)() : V.is;\n const remove = this.add(state, true);\n\n if (single && this !== ROOT) HOST.set(this, state);\n\n init.add(() => {\n event(state);\n const dispose = forEach?.(state as T, owned);\n cleanup.set(K, () => {\n if (typeof dispose == \"function\") dispose();\n remove();\n if (owned) event(state, null);\n });\n });\n }\n\n for (const i of init) i();\n\n this.inputs = inputs;\n\n return this;\n }\n\n add(I: Model, explicit = false) {\n const { cleanup, provide } = this;\n const root = this === Context.root;\n const TT: Model.Extends[] = [];\n\n function conflict(T: Model.Extends) {\n const entries = provide.get(T);\n if (entries)\n for (const entry of entries)\n if (!entry[1] && entry[0] !== I) return entries.delete(entry);\n }\n\n for (\n let T = I.constructor as Model.Extends;\n T !== Model;\n T = Object.getPrototypeOf(T)\n )\n if (explicit || !root || !conflict(T)) TT.push(T);\n\n const expects = new Map<Expect, () => void>();\n const onDone = new Set<() => void>();\n\n for (const T of TT) onDone.add(this.register(T, [I, explicit]));\n\n function queue(ctx: Context, downstream: boolean, same?: boolean) {\n let found = false;\n for (const T of TT) {\n const list = ctx.consume.get(T);\n if (list !== undefined) found = true;\n if (list)\n for (const [cb, filter] of list)\n if (same || filter == null || filter === downstream)\n expects.set(cb, () => {\n const r = cb(I, filter ?? downstream);\n if (r) onDone.add(r);\n });\n }\n return found;\n }\n\n queue(this, true, true);\n for (let ctx = this.parent; ctx; ctx = ctx.parent) queue(ctx, true);\n this.traverse((ctx) => queue(ctx, false));\n\n if (!LOOKUP.has(I)) LOOKUP.set(I, this);\n\n listener(I, () => {\n expects.forEach((f) => f());\n expects.clear();\n return null;\n });\n\n function flush() {\n onDone.forEach((r) => r());\n onDone.clear();\n }\n\n const held = Array.from(HELD.get(I) || [], ([child, added]) => {\n const done = this.add(child);\n added.add(done);\n return () => {\n if (added.delete(done)) done();\n };\n });\n\n function remove() {\n cleanup.delete(remove);\n held.forEach((done) => done());\n flush();\n }\n\n cleanup.set(remove, remove);\n\n return remove;\n }\n\n /**\n * Create a child context, optionally registering one or more Models to it.\n *\n * @param inputs Model, Model class, or map of Models / Model classes to register.\n */\n public push(inputs?: Accept) {\n const next = new Context(this);\n if (inputs) next.set(inputs);\n return next;\n }\n\n /**\n * Remove all Models from this context.\n *\n * Will also run any cleanup callbacks registered when Models were added.\n */\n public pop() {\n this.inputs = {};\n this.scope.forEach((x) => x.pop());\n this.scope.clear();\n this.cleanup.forEach((cb) => cb());\n this.cleanup.clear();\n this.consume.clear();\n this.provide.clear();\n if (this.parent) {\n this.parent.scope.delete(this);\n }\n }\n}\n\nObject.defineProperty(Context.prototype, \"toString\", {\n value() {\n return `Context-${this.id}`;\n },\n});\n\n/**\n * Add `value` to the context `state` was added to. A context-less `state` holds\n * it instead - every context adding `state` later adds its held children too.\n */\nfunction join(state: Model, value: Model): () => void {\n const ctx = LOOKUP.get(state.is);\n\n if (ctx) return ctx.add(value);\n\n const held = HELD.get(state) || new Map();\n const added = new Set<() => void>();\n\n HELD.set(state, held.set(value, added));\n\n return () => {\n held.delete(value);\n added.forEach((done) => {\n added.delete(done);\n done();\n });\n };\n}\n\n/** The Model a host mounted `state` under - the one its nearest enclosing context was set up for. */\nfunction host(state: Model) {\n for (let ctx = LOOKUP.get(state); ctx; ctx = ctx.parent) {\n const found = HOST.get(ctx);\n if (found && found !== state) return found;\n }\n}\n\nexport { Context, host, join };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"context.js","names":[],"sources":["../src/context.ts"],"sourcesContent":["import { listener } from \"./observable\";\nimport { event, Model, uid } from \"./state\";\n\nconst LOOKUP = new WeakMap<Model, Context>();\nconst HELD = new WeakMap<Model, Map<Model, Set<() => void>>>();\nconst HOST = new WeakMap<Context, Model>();\nconst CLEANUP = new WeakMap<Context, Set<() => void>>();\nlet ROOT: Context;\n\ntype Accept<T extends Model = Model> =\n | T\n | Model.Type<T>\n | Record<string | number, T | Model.Type<T>>;\n\ntype Expect<T extends Model = Model> = (\n state: T,\n downstream: boolean,\n) => (() => void) | void;\n\ndeclare namespace Context {\n export { Accept, Expect };\n}\n\nclass Context {\n static get root(): Context {\n return ROOT ??= new Context();\n }\n\n /** Get the context for a Model. Adapters may override to provide framework context. */\n static get(state?: Model): Context {\n return state && LOOKUP.get(state.is) || Context.root;\n }\n\n public id = uid();\n public parent?: Context;\n public scope = new Set<Context>();\n public consume = new Map<\n Model.Extends,\n Set<[Expect, boolean | undefined]> | null\n >();\n public provide = new Map<Model.Extends, Set<[Model, boolean]> | null>();\n\n constructor(arg?: Context | Accept) {\n CLEANUP.set(this, new Set());\n\n if (arg instanceof Context) {\n this.parent = arg;\n arg.scope.add(this);\n } else if (arg) {\n insert(this, arg);\n }\n }\n\n private traverse(accept: (ctx: Context) => boolean | void) {\n const queue = [...this.scope];\n for (const ctx of queue)\n if (accept(ctx) !== false) for (const c of ctx.scope) queue.push(c);\n }\n\n private register<T extends Model>(\n type: Model.Extends<T>,\n value: [Expect<T>, boolean | undefined],\n asConsumer: true,\n ): () => void;\n\n private register<T extends Model>(\n type: Model.Extends<T>,\n value: [T, boolean],\n asConsumer?: false,\n ): () => void;\n\n private register(type: Model.Extends, value: any, asConsumer?: boolean) {\n const mode = asConsumer ? \"consume\" : \"provide\";\n let set = this[mode].get(type) as Set<any>;\n if (!set) this[mode].set(type, (set = new Set()));\n set.add(value);\n\n for (let ctx = this.parent; ctx; ctx = ctx.parent) {\n if (ctx[mode].has(type)) break;\n ctx[mode].set(type, null);\n }\n\n return () => set.delete(value);\n }\n\n /** Find specified type upstream. Throws if not found. */\n public get<T extends Model>(Type: Model.Extends<T>, required?: true): T;\n\n /** Find specified type upstream. Returns undefined if not found. */\n public get<T extends Model>(\n Type: Model.Extends<T>,\n required?: boolean,\n ): T | undefined;\n\n /** Subscribe to a type becoming available in context. */\n public get<T extends Model>(\n Type: Model.Extends<T>,\n callback: Expect<T>,\n downstream?: boolean,\n ): () => void;\n\n /** Lookup excluding a specific instance (used by Model.prototype.get for upstream-of-self semantics). */\n public get<T extends Model>(\n Type: Model.Extends<T>,\n arg: boolean | Expect<T> | undefined,\n downstream: boolean | undefined,\n skip: Model,\n ): T | undefined | (() => void);\n\n public get<T extends Model>(\n Type: Model.Extends<T>,\n arg?: boolean | Expect<T>,\n downstream?: boolean,\n skip?: Model,\n ) {\n let found: T | null | undefined;\n let priority = false;\n\n for (let ctx: Context | undefined = this; ctx; ctx = ctx.parent) {\n const entries = ctx.provide.get(Type);\n if (!entries) continue;\n\n for (const [state, explicit] of entries) {\n if (state === skip || found === state) continue;\n if (!found || (explicit && !priority)) {\n found = state as T;\n priority = explicit;\n continue;\n }\n if (!priority) {\n found = null;\n break;\n }\n if (explicit)\n throw new Error(\n `Did find ${Type} in context, but multiple were defined.`,\n );\n }\n if (found !== undefined) break;\n }\n\n if (typeof arg === \"function\") {\n if (found && !downstream) arg(found, false);\n\n if (downstream !== false) {\n this.traverse((ctx) => {\n const has = ctx.provide.get(Type);\n if (has) for (const x of has) if (x[0] !== skip) arg(x[0] as T, true);\n return has !== undefined;\n });\n }\n\n return this.register(Type, [arg as Expect, downstream], true);\n }\n\n if (found) return found;\n if (found === null) return null;\n if (arg !== false) throw new Error(`Could not find ${Type} in context.`);\n }\n\n add(I: Model, explicit = false) {\n const { provide } = this;\n const root = this === Context.root;\n const TT: Model.Extends[] = [];\n\n function conflict(T: Model.Extends) {\n const entries = provide.get(T);\n if (entries)\n for (const entry of entries)\n if (!entry[1] && entry[0] !== I) return entries.delete(entry);\n }\n\n for (\n let T = I.constructor as Model.Extends;\n T !== Model;\n T = Object.getPrototypeOf(T)\n )\n if (explicit || !root || !conflict(T)) TT.push(T);\n\n const expects = new Map<Expect, () => void>();\n const onDone = new Set<() => void>();\n\n for (const T of TT) onDone.add(this.register(T, [I, explicit]));\n\n function queue(ctx: Context, downstream: boolean, same?: boolean) {\n let found = false;\n for (const T of TT) {\n const list = ctx.consume.get(T);\n if (list !== undefined) found = true;\n if (list)\n for (const [cb, filter] of list)\n if (same || filter == null || filter === downstream)\n expects.set(cb, () => {\n const r = cb(I, filter ?? downstream);\n if (r) onDone.add(r);\n });\n }\n return found;\n }\n\n queue(this, true, true);\n for (let ctx = this.parent; ctx; ctx = ctx.parent) queue(ctx, true);\n this.traverse((ctx) => queue(ctx, false));\n\n if (!LOOKUP.has(I)) LOOKUP.set(I, this);\n\n listener(I, () => {\n expects.forEach((f) => f());\n expects.clear();\n return null;\n });\n\n function flush() {\n onDone.forEach((r) => r());\n onDone.clear();\n }\n\n const cleanup = CLEANUP.get(this)!;\n const held = Array.from(HELD.get(I) || [], ([child, added]) => {\n const done = this.add(child);\n added.add(done);\n return () => {\n if (added.delete(done)) done();\n };\n });\n\n function remove() {\n cleanup.delete(remove);\n held.forEach((done) => done());\n flush();\n }\n\n cleanup.add(remove);\n\n return remove;\n }\n\n /**\n * Create a child context, optionally registering Models to it.\n *\n * @param input Model instance to adopt, Model class to create - and destroy when the context pops - or an object of them, all registered before any activates.\n * @param cleanup Called once when the context pops, before its Models are removed.\n */\n public push(input?: Accept, cleanup?: () => void) {\n const next = new Context(this);\n\n if (cleanup) CLEANUP.get(next)!.add(cleanup);\n if (input) insert(next, input);\n\n return next;\n }\n\n /**\n * Remove all Models from this context.\n *\n * Will also run any cleanup callbacks registered when Models were added.\n */\n public pop() {\n this.scope.forEach((x) => x.pop());\n this.scope.clear();\n const cleanup = CLEANUP.get(this)!;\n cleanup.forEach((cb) => cb());\n cleanup.clear();\n this.consume.clear();\n this.provide.clear();\n if (this.parent) {\n this.parent.scope.delete(this);\n }\n }\n}\n\nObject.defineProperty(Context.prototype, \"toString\", {\n value() {\n return `Context-${this.id}`;\n },\n});\n\n/**\n * Add `value` to the context `state` was added to. A context-less `state` holds\n * it instead - every context adding `state` later adds its held children too.\n */\nfunction join(state: Model, value: Model): () => void {\n const ctx = LOOKUP.get(state.is);\n\n if (ctx) return ctx.add(value);\n\n const held = HELD.get(state) || new Map();\n const added = new Set<() => void>();\n\n HELD.set(state, held.set(value, added));\n\n return () => {\n held.delete(value);\n added.forEach((done) => {\n added.delete(done);\n done();\n });\n };\n}\n\n/** The Model a host mounted `state` under - the one its nearest enclosing context was set up for. */\nfunction host(state: Model) {\n for (let ctx = LOOKUP.get(state); ctx; ctx = ctx.parent) {\n const found = HOST.get(ctx);\n if (found && found !== state) return found;\n }\n}\n\nfunction insert(into: Context, input: Accept) {\n const single = typeof input == \"function\" || input instanceof Model;\n const entries = Object.entries(single ? { input } : input);\n const init: Model[] = [];\n const owns: Model[] = [];\n\n for (const [K, V] of entries) {\n const owned = Model.is(V);\n\n if (!(owned || V instanceof Model)) {\n const as = single || K == String(V) ? V : `${V} (as '${K}')`;\n throw new Error(\n `Context can only include an instance or class of Model but got ${as}.`,\n );\n }\n\n const state = owned ? new V() : V.is;\n\n into.add(state, true);\n init.push(state);\n\n if (single) HOST.set(into, state);\n if (owned) owns.push(state);\n }\n\n const cleanup = CLEANUP.get(into)!;\n\n for (const state of owns) cleanup.add(() => event(state, null));\n for (const state of init) event(state);\n}\n\nexport { Context, host, join };\n"],"mappings":"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"}
|