@expressive/mvc 0.52.1 → 0.53.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/index.d.ts +69 -55
- package/dist/index.js +301 -282
- package/dist/index.mjs +298 -281
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,71 +1,106 @@
|
|
|
1
1
|
// src/control.ts
|
|
2
|
+
var onReady = () => null;
|
|
3
|
+
var LISTENERS = /* @__PURE__ */ new WeakMap();
|
|
4
|
+
var PENDING = /* @__PURE__ */ new WeakMap();
|
|
5
|
+
var PENDING_KEYS = /* @__PURE__ */ new WeakMap();
|
|
2
6
|
var DISPATCH = /* @__PURE__ */ new Set();
|
|
3
7
|
var OBSERVER = /* @__PURE__ */ new WeakMap();
|
|
4
|
-
var LISTENER = /* @__PURE__ */ new WeakMap();
|
|
5
|
-
var onReady = () => null;
|
|
6
8
|
function addListener(subject, callback, select) {
|
|
7
|
-
let
|
|
8
|
-
if (!
|
|
9
|
-
|
|
10
|
-
const filter = select
|
|
11
|
-
if (!
|
|
12
|
-
callback(true, subject);
|
|
13
|
-
|
|
14
|
-
return () =>
|
|
15
|
-
}
|
|
16
|
-
function watch(from, key2, value) {
|
|
17
|
-
const access = OBSERVER.get(from);
|
|
18
|
-
return access ? access(from, key2, value) : value;
|
|
9
|
+
let listeners = LISTENERS.get(subject);
|
|
10
|
+
if (!listeners)
|
|
11
|
+
LISTENERS.set(subject, listeners = /* @__PURE__ */ new Map([[onReady, void 0]]));
|
|
12
|
+
const filter = select === void 0 ? void 0 : /* @__PURE__ */ new Set([select]);
|
|
13
|
+
if (!listeners.has(onReady) && !filter)
|
|
14
|
+
callback.call(subject, true, subject);
|
|
15
|
+
listeners.set(callback, filter);
|
|
16
|
+
return () => listeners.delete(callback);
|
|
19
17
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
if (key2 === true && ready)
|
|
18
|
+
function emit(model, key2) {
|
|
19
|
+
const listeners = LISTENERS.get(model);
|
|
20
|
+
const notReady = listeners.has(onReady);
|
|
21
|
+
if (key2 === true && !notReady)
|
|
25
22
|
return;
|
|
26
|
-
let
|
|
27
|
-
if (
|
|
28
|
-
|
|
23
|
+
let pending2 = PENDING.get(model);
|
|
24
|
+
if (pending2) {
|
|
25
|
+
pending2.add(key2);
|
|
29
26
|
return;
|
|
30
27
|
}
|
|
31
|
-
PENDING.set(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
queue(after);
|
|
28
|
+
PENDING.set(model, pending2 = new Set(notReady ? [true, key2] : [key2]));
|
|
29
|
+
for (const key3 of pending2)
|
|
30
|
+
for (const [callback, filter] of listeners)
|
|
31
|
+
if (!filter || filter.has(key3)) {
|
|
32
|
+
const after = callback.call(model, key3, model);
|
|
33
|
+
if (after)
|
|
34
|
+
enqueue(after);
|
|
35
|
+
else if (after === null)
|
|
36
|
+
listeners.delete(callback);
|
|
41
37
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
38
|
+
if (key2 === null)
|
|
39
|
+
listeners.clear();
|
|
40
|
+
PENDING.delete(model);
|
|
41
|
+
}
|
|
42
|
+
function event(subject, key2, silent) {
|
|
43
|
+
if (key2 === null)
|
|
44
|
+
return emit(subject, key2);
|
|
45
|
+
if (!key2)
|
|
46
|
+
return emit(subject, true);
|
|
47
|
+
let pending2 = PENDING_KEYS.get(subject);
|
|
48
|
+
if (!pending2) {
|
|
49
|
+
PENDING_KEYS.set(subject, pending2 = /* @__PURE__ */ new Set());
|
|
50
|
+
if (!silent)
|
|
51
|
+
enqueue(() => {
|
|
52
|
+
emit(subject, false);
|
|
53
|
+
PENDING_KEYS.delete(subject);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
pending2.add(key2);
|
|
57
|
+
if (!silent)
|
|
58
|
+
emit(subject, key2);
|
|
47
59
|
}
|
|
48
|
-
function
|
|
60
|
+
function pending(subject) {
|
|
61
|
+
if (PENDING_KEYS.has(subject))
|
|
62
|
+
return {
|
|
63
|
+
then: (res) => new Promise((res2) => {
|
|
64
|
+
const remove = addListener(subject, (key2) => {
|
|
65
|
+
if (key2 !== true) {
|
|
66
|
+
remove();
|
|
67
|
+
return res2.bind(null, Array.from(PENDING_KEYS.get(subject)));
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}).then(res)
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function enqueue(eventHandler) {
|
|
49
74
|
if (!DISPATCH.size)
|
|
50
75
|
setTimeout(() => {
|
|
51
|
-
DISPATCH.forEach((
|
|
76
|
+
DISPATCH.forEach((event2) => {
|
|
52
77
|
try {
|
|
53
|
-
|
|
78
|
+
event2();
|
|
54
79
|
} catch (err) {
|
|
55
80
|
console.error(err);
|
|
56
81
|
}
|
|
57
82
|
});
|
|
58
83
|
DISPATCH.clear();
|
|
59
84
|
}, 0);
|
|
60
|
-
DISPATCH.add(
|
|
85
|
+
DISPATCH.add(eventHandler);
|
|
86
|
+
}
|
|
87
|
+
function createProxy(from, observer) {
|
|
88
|
+
const proxy = Object.create(from);
|
|
89
|
+
OBSERVER.set(proxy, observer);
|
|
90
|
+
return proxy;
|
|
91
|
+
}
|
|
92
|
+
function watch(from, key2, value) {
|
|
93
|
+
const access = OBSERVER.get(from);
|
|
94
|
+
return access ? access(from, key2, value) : value;
|
|
61
95
|
}
|
|
62
|
-
function
|
|
63
|
-
const listeners =
|
|
96
|
+
function createEffect(target, callback, requireValues) {
|
|
97
|
+
const listeners = LISTENERS.get(target);
|
|
64
98
|
let unset;
|
|
65
99
|
let reset;
|
|
66
100
|
function invoke() {
|
|
67
101
|
let stale;
|
|
68
|
-
const subscriber =
|
|
102
|
+
const subscriber = createProxy(target, access);
|
|
103
|
+
LISTENERS.set(subscriber, listeners);
|
|
69
104
|
function onUpdate() {
|
|
70
105
|
if (stale)
|
|
71
106
|
return null;
|
|
@@ -79,20 +114,19 @@ function effect(target, callback, requireValues) {
|
|
|
79
114
|
function access(from, key2, value) {
|
|
80
115
|
if (value === void 0 && requireValues)
|
|
81
116
|
throw new Error(`${from}.${key2} is required in this context.`);
|
|
82
|
-
const listeners2 =
|
|
117
|
+
const listeners2 = LISTENERS.get(from);
|
|
83
118
|
let listener = listeners2.get(onUpdate);
|
|
84
119
|
if (!listener)
|
|
85
120
|
listeners2.set(onUpdate, listener = /* @__PURE__ */ new Set());
|
|
86
121
|
listener.add(key2);
|
|
87
|
-
const nested =
|
|
88
|
-
if (nested)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
122
|
+
const nested = LISTENERS.get(value);
|
|
123
|
+
if (nested)
|
|
124
|
+
LISTENERS.set(
|
|
125
|
+
value = createProxy(value, access),
|
|
126
|
+
nested
|
|
127
|
+
);
|
|
92
128
|
return value;
|
|
93
129
|
}
|
|
94
|
-
LISTENER.set(subscriber, listeners);
|
|
95
|
-
OBSERVER.set(subscriber, access);
|
|
96
130
|
try {
|
|
97
131
|
const out = callback.call(subscriber, subscriber);
|
|
98
132
|
unset = typeof out == "function" ? out : void 0;
|
|
@@ -125,80 +159,55 @@ var define = Object.defineProperty;
|
|
|
125
159
|
var ID = /* @__PURE__ */ new WeakMap();
|
|
126
160
|
var STATE = /* @__PURE__ */ new WeakMap();
|
|
127
161
|
var NOTIFY = /* @__PURE__ */ new WeakMap();
|
|
128
|
-
var PENDING2 = /* @__PURE__ */ new WeakMap();
|
|
129
162
|
var PARENT = /* @__PURE__ */ new WeakMap();
|
|
130
163
|
var METHODS = /* @__PURE__ */ new WeakMap();
|
|
131
164
|
var METHOD = /* @__PURE__ */ new WeakMap();
|
|
132
|
-
var
|
|
133
|
-
var Model = class _Model {
|
|
165
|
+
var Model = class {
|
|
134
166
|
constructor(...args) {
|
|
135
|
-
define(this, "is", { value: this });
|
|
136
|
-
ID.set(this, `${this.constructor}-${uid()}`);
|
|
137
|
-
STATE.set(this, {});
|
|
138
167
|
prepare(this);
|
|
168
|
+
define(this, "is", { value: this });
|
|
139
169
|
init(this, args);
|
|
140
170
|
}
|
|
141
171
|
get(arg1, arg2) {
|
|
142
172
|
const self = this.is;
|
|
143
|
-
if (arg1 === void 0)
|
|
144
|
-
return values(self);
|
|
145
173
|
if (typeof arg1 == "function") {
|
|
146
|
-
let
|
|
147
|
-
return
|
|
148
|
-
const cb = arg1.call(
|
|
174
|
+
let pending2 = /* @__PURE__ */ new Set();
|
|
175
|
+
return createEffect(self, (proxy) => {
|
|
176
|
+
const cb = arg1.call(proxy, proxy, pending2);
|
|
149
177
|
return cb === null ? cb : (update2) => {
|
|
150
|
-
|
|
178
|
+
pending2 = PENDING_KEYS.get(self);
|
|
151
179
|
if (typeof cb == "function")
|
|
152
|
-
|
|
180
|
+
cb(update2);
|
|
153
181
|
};
|
|
154
182
|
});
|
|
155
183
|
}
|
|
156
|
-
if (
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (arg1 in state)
|
|
161
|
-
arg2.call(this, state[arg1], arg1, this);
|
|
162
|
-
return addListener(self, () => {
|
|
163
|
-
arg2.call(this, arg1 in state ? state[arg1] : arg1, arg1, this);
|
|
164
|
-
}, arg1);
|
|
165
|
-
}
|
|
184
|
+
if (arg1 === void 0)
|
|
185
|
+
return snapshot(self);
|
|
186
|
+
if (typeof arg2 == "function")
|
|
187
|
+
return addListener(self, arg2, arg1);
|
|
166
188
|
return arg1 === null ? Object.isFrozen(STATE.get(self)) : fetch(self, arg1, arg2);
|
|
167
189
|
}
|
|
168
|
-
set(arg1, arg2
|
|
190
|
+
set(arg1, arg2) {
|
|
169
191
|
const self = this.is;
|
|
170
192
|
if (typeof arg1 == "function")
|
|
171
193
|
return addListener(self, (key2) => {
|
|
172
194
|
if (typeof key2 == "string")
|
|
173
195
|
return arg1.call(self, key2, self);
|
|
174
196
|
});
|
|
175
|
-
if (arg1
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
else if (1 in arguments)
|
|
184
|
-
update(self, arg1, arg2, arg3);
|
|
185
|
-
else
|
|
197
|
+
if (arg1 && typeof arg1 == "object") {
|
|
198
|
+
const methods = METHODS.get(self.constructor);
|
|
199
|
+
for (const key2 in arg1)
|
|
200
|
+
if (methods.has(key2))
|
|
201
|
+
self[key2] = arg1[key2];
|
|
202
|
+
else if (key2 in self)
|
|
203
|
+
update(self, key2, arg1[key2], arg2 === true);
|
|
204
|
+
} else
|
|
186
205
|
event(self, arg1);
|
|
187
|
-
|
|
188
|
-
return {
|
|
189
|
-
then: (res) => new Promise((res2) => {
|
|
190
|
-
const remove = addListener(self, (key2) => {
|
|
191
|
-
if (key2 !== true) {
|
|
192
|
-
remove();
|
|
193
|
-
return res2.bind(null, Array.from(PENDING2.get(self)));
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
}).then(res)
|
|
197
|
-
};
|
|
206
|
+
return pending(self);
|
|
198
207
|
}
|
|
199
208
|
/**
|
|
200
209
|
* Iterate over managed properties in this instance of Model.
|
|
201
|
-
* Yeilds the key and
|
|
210
|
+
* Yeilds the key and current value for each property.
|
|
202
211
|
*/
|
|
203
212
|
[Symbol.iterator]() {
|
|
204
213
|
return Object.entries(STATE.get(this.is))[Symbol.iterator]();
|
|
@@ -211,9 +220,8 @@ var Model = class _Model {
|
|
|
211
220
|
* @param args - arguments sent to constructor
|
|
212
221
|
*/
|
|
213
222
|
static new(...args) {
|
|
214
|
-
_Model.is(this);
|
|
215
223
|
const instance = new this(...args);
|
|
216
|
-
|
|
224
|
+
event(instance);
|
|
217
225
|
return instance;
|
|
218
226
|
}
|
|
219
227
|
/**
|
|
@@ -223,9 +231,7 @@ var Model = class _Model {
|
|
|
223
231
|
* methods and properties of this class.
|
|
224
232
|
*/
|
|
225
233
|
static is(maybe) {
|
|
226
|
-
|
|
227
|
-
throw new Error("Model is abstract and not a valid type.");
|
|
228
|
-
return typeof maybe == "function" && maybe.prototype instanceof this;
|
|
234
|
+
return maybe === this || typeof maybe == "function" && maybe.prototype instanceof this;
|
|
229
235
|
}
|
|
230
236
|
/**
|
|
231
237
|
* Register a callback to run when any instance of this Model is updated.
|
|
@@ -249,48 +255,48 @@ define(Model, "toString", {
|
|
|
249
255
|
}
|
|
250
256
|
});
|
|
251
257
|
function prepare(model) {
|
|
258
|
+
let T = model.constructor;
|
|
259
|
+
if (T === Model)
|
|
260
|
+
throw new Error("Cannot create base Model.");
|
|
252
261
|
const chain = [];
|
|
253
|
-
let type = model.constructor;
|
|
254
262
|
let keys2 = /* @__PURE__ */ new Set();
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
259
|
-
for (const type2 of chain) {
|
|
260
|
-
for (const cb of NOTIFY.get(type2) || [])
|
|
263
|
+
ID.set(model, `${T}-${uid()}`);
|
|
264
|
+
while (T.name) {
|
|
265
|
+
for (const cb of NOTIFY.get(T) || [])
|
|
261
266
|
addListener(model, cb);
|
|
262
|
-
if (
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
267
|
+
if (T === Model)
|
|
268
|
+
break;
|
|
269
|
+
else
|
|
270
|
+
chain.unshift(T);
|
|
271
|
+
T = Object.getPrototypeOf(T);
|
|
272
|
+
}
|
|
273
|
+
for (const type of chain) {
|
|
274
|
+
if (METHODS.has(type)) {
|
|
275
|
+
keys2 = METHODS.get(type);
|
|
266
276
|
continue;
|
|
267
277
|
}
|
|
268
|
-
METHODS.set(
|
|
278
|
+
METHODS.set(type, keys2 = new Set(keys2));
|
|
269
279
|
for (const [key2, { value }] of Object.entries(
|
|
270
|
-
Object.getOwnPropertyDescriptors(
|
|
280
|
+
Object.getOwnPropertyDescriptors(type.prototype)
|
|
271
281
|
)) {
|
|
272
|
-
let
|
|
273
|
-
const value2 = method.bind(
|
|
282
|
+
let bind2 = function(method = value) {
|
|
283
|
+
const value2 = method.bind(model);
|
|
274
284
|
METHOD.set(value2, method);
|
|
275
|
-
define(
|
|
285
|
+
define(model, key2, { value: value2, writable: true });
|
|
276
286
|
return value2;
|
|
277
287
|
};
|
|
278
|
-
var
|
|
288
|
+
var bind = bind2;
|
|
279
289
|
if (!value || key2 == "constructor")
|
|
280
290
|
continue;
|
|
281
291
|
keys2.add(key2);
|
|
282
|
-
|
|
283
|
-
set: set3,
|
|
284
|
-
get() {
|
|
285
|
-
return this.hasOwnProperty(key2) ? value : set3.call(this, value);
|
|
286
|
-
}
|
|
287
|
-
});
|
|
292
|
+
define(type.prototype, key2, { get: bind2, set: bind2 });
|
|
288
293
|
}
|
|
289
294
|
}
|
|
290
295
|
}
|
|
291
296
|
function init(model, args) {
|
|
292
|
-
const
|
|
293
|
-
const state =
|
|
297
|
+
const methods = METHODS.get(model.constructor);
|
|
298
|
+
const state = {};
|
|
299
|
+
STATE.set(model, state);
|
|
294
300
|
args = args.flat().filter((arg) => {
|
|
295
301
|
if (typeof arg != "string")
|
|
296
302
|
return true;
|
|
@@ -307,9 +313,12 @@ function init(model, args) {
|
|
|
307
313
|
console.error(err);
|
|
308
314
|
});
|
|
309
315
|
else if (typeof use2 == "function")
|
|
310
|
-
|
|
311
|
-
else if (typeof use2 == "object")
|
|
312
|
-
|
|
316
|
+
addListener(model, use2, null);
|
|
317
|
+
else if (typeof use2 == "object") {
|
|
318
|
+
for (const key2 in use2)
|
|
319
|
+
if (key2 in model || methods.has(key2))
|
|
320
|
+
model[key2] = use2[key2];
|
|
321
|
+
}
|
|
313
322
|
});
|
|
314
323
|
for (const key2 in model) {
|
|
315
324
|
const desc = Object.getOwnPropertyDescriptor(model, key2);
|
|
@@ -317,22 +326,30 @@ function init(model, args) {
|
|
|
317
326
|
update(model, key2, desc.value, true);
|
|
318
327
|
define(model, key2, {
|
|
319
328
|
configurable: false,
|
|
320
|
-
set: (x) => update(model, key2, x),
|
|
321
329
|
get() {
|
|
322
330
|
return watch(this, key2, state[key2]);
|
|
331
|
+
},
|
|
332
|
+
set(value) {
|
|
333
|
+
update(model, key2, value);
|
|
334
|
+
mayAdopt(model, value);
|
|
323
335
|
}
|
|
324
336
|
});
|
|
325
337
|
}
|
|
326
338
|
}
|
|
339
|
+
addListener(model, () => {
|
|
340
|
+
for (const [_, value] of model)
|
|
341
|
+
if (value instanceof Model && PARENT.get(value) === model)
|
|
342
|
+
value.set(null);
|
|
343
|
+
Object.freeze(state);
|
|
344
|
+
}, null);
|
|
327
345
|
return null;
|
|
328
346
|
});
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
}, null);
|
|
347
|
+
}
|
|
348
|
+
function mayAdopt(parent, child) {
|
|
349
|
+
if (child instanceof Model && !PARENT.has(child)) {
|
|
350
|
+
PARENT.set(child, parent);
|
|
351
|
+
event(child);
|
|
352
|
+
}
|
|
336
353
|
}
|
|
337
354
|
function fetch(subject, property, required) {
|
|
338
355
|
const state = STATE.get(subject);
|
|
@@ -359,19 +376,24 @@ function fetch(subject, property, required) {
|
|
|
359
376
|
stack: error.stack
|
|
360
377
|
});
|
|
361
378
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
const
|
|
379
|
+
var EXPORT;
|
|
380
|
+
function snapshot(model) {
|
|
381
|
+
const values = {};
|
|
382
|
+
let isNotRecursive;
|
|
383
|
+
if (!EXPORT) {
|
|
384
|
+
isNotRecursive = true;
|
|
385
|
+
EXPORT = /* @__PURE__ */ new Map([[model, values]]);
|
|
386
|
+
}
|
|
365
387
|
for (let [key2, value] of model) {
|
|
366
388
|
if (EXPORT.has(value))
|
|
367
389
|
value = EXPORT.get(value);
|
|
368
|
-
else if (value && typeof value.get === "function")
|
|
390
|
+
else if (value && typeof value == "object" && "get" in value && typeof value.get === "function")
|
|
369
391
|
EXPORT.set(value, value = value.get());
|
|
370
|
-
|
|
392
|
+
values[key2] = value;
|
|
371
393
|
}
|
|
372
|
-
if (
|
|
394
|
+
if (isNotRecursive)
|
|
373
395
|
EXPORT = void 0;
|
|
374
|
-
return Object.freeze(
|
|
396
|
+
return Object.freeze(values);
|
|
375
397
|
}
|
|
376
398
|
function update(subject, key2, value, arg) {
|
|
377
399
|
const state = STATE.get(subject);
|
|
@@ -386,46 +408,23 @@ function update(subject, key2, value, arg) {
|
|
|
386
408
|
value = out();
|
|
387
409
|
}
|
|
388
410
|
if (value === previous)
|
|
389
|
-
return
|
|
390
|
-
if (value instanceof Model && !PARENT.has(value)) {
|
|
391
|
-
PARENT.set(value, subject);
|
|
392
|
-
emit(value, true);
|
|
393
|
-
}
|
|
411
|
+
return;
|
|
394
412
|
state[key2] = value;
|
|
395
413
|
if (arg !== true)
|
|
396
414
|
event(subject, key2);
|
|
397
|
-
|
|
398
|
-
function event(subject, key2, silent) {
|
|
399
|
-
let pending = PENDING2.get(subject);
|
|
400
|
-
if (!pending) {
|
|
401
|
-
PENDING2.set(subject, pending = /* @__PURE__ */ new Set());
|
|
402
|
-
if (!silent)
|
|
403
|
-
queue(() => {
|
|
404
|
-
emit(subject, false);
|
|
405
|
-
PENDING2.delete(subject);
|
|
406
|
-
});
|
|
407
|
-
}
|
|
408
|
-
pending.add(key2);
|
|
409
|
-
if (!silent)
|
|
410
|
-
emit(subject, key2);
|
|
411
|
-
}
|
|
412
|
-
function assign(to, values2) {
|
|
413
|
-
const methods = METHODS.get(to.constructor);
|
|
414
|
-
for (const key2 in values2)
|
|
415
|
-
if (key2 in to || methods.has(key2))
|
|
416
|
-
to[key2] = values2[key2];
|
|
415
|
+
return true;
|
|
417
416
|
}
|
|
418
417
|
function uid() {
|
|
419
|
-
return (Math.random() * 0.722
|
|
418
|
+
return (0.278 + Math.random() * 0.722).toString(36).substring(2, 8).toUpperCase();
|
|
420
419
|
}
|
|
421
420
|
|
|
422
421
|
// src/context.ts
|
|
423
|
-
var
|
|
424
|
-
var
|
|
422
|
+
var LOOKUP = /* @__PURE__ */ new WeakMap();
|
|
423
|
+
var KEYS = /* @__PURE__ */ new Map();
|
|
425
424
|
function key(T, upstream) {
|
|
426
|
-
let K =
|
|
425
|
+
let K = KEYS.get(T);
|
|
427
426
|
if (!K)
|
|
428
|
-
|
|
427
|
+
KEYS.set(T, K = Symbol(
|
|
429
428
|
typeof T == "symbol" ? "get " + T.description : String(T)
|
|
430
429
|
));
|
|
431
430
|
return upstream ? key(K) : K;
|
|
@@ -445,7 +444,7 @@ var Context = class _Context {
|
|
|
445
444
|
this.include(inputs);
|
|
446
445
|
}
|
|
447
446
|
static get(from, callback) {
|
|
448
|
-
const waiting =
|
|
447
|
+
const waiting = LOOKUP.get(from);
|
|
449
448
|
if (waiting instanceof _Context) {
|
|
450
449
|
if (callback)
|
|
451
450
|
callback(waiting);
|
|
@@ -455,11 +454,14 @@ var Context = class _Context {
|
|
|
455
454
|
if (waiting)
|
|
456
455
|
waiting.push(callback);
|
|
457
456
|
else
|
|
458
|
-
|
|
457
|
+
LOOKUP.set(from, [callback]);
|
|
459
458
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
459
|
+
/** Run callback when a specified type is registered to a **child** context. */
|
|
460
|
+
has(Type, callback) {
|
|
461
|
+
define(this, key(Type, true), { value: callback });
|
|
462
|
+
}
|
|
463
|
+
/** Find specified type registered to a parent context. Returns undefined if none are found. */
|
|
464
|
+
get(Type) {
|
|
463
465
|
const result = this[key(Type)];
|
|
464
466
|
if (result === null)
|
|
465
467
|
throw new Error(`Did find ${Type} in context, but multiple were defined.`);
|
|
@@ -481,9 +483,16 @@ var Context = class _Context {
|
|
|
481
483
|
}
|
|
482
484
|
include(inputs, forEach) {
|
|
483
485
|
const init2 = /* @__PURE__ */ new Map();
|
|
486
|
+
if (typeof inputs == "function" || inputs instanceof Model)
|
|
487
|
+
inputs = { 0: inputs };
|
|
484
488
|
Object.entries(inputs).forEach(([K, V]) => {
|
|
485
|
-
if (
|
|
486
|
-
|
|
489
|
+
if (Model.is(V) || V instanceof Model)
|
|
490
|
+
return;
|
|
491
|
+
if (K && K != V)
|
|
492
|
+
V = `${V} (as '${K}')`;
|
|
493
|
+
throw new Error(
|
|
494
|
+
`Context may only include instance or class \`extends Model\` but got ${V}.`
|
|
495
|
+
);
|
|
487
496
|
});
|
|
488
497
|
for (const key2 in inputs) {
|
|
489
498
|
const input = inputs[key2];
|
|
@@ -500,8 +509,10 @@ var Context = class _Context {
|
|
|
500
509
|
}
|
|
501
510
|
for (const [model, explicit] of init2) {
|
|
502
511
|
model.set();
|
|
503
|
-
if (forEach)
|
|
512
|
+
if (typeof forEach == "function")
|
|
504
513
|
forEach(model, explicit);
|
|
514
|
+
else if (forEach && explicit)
|
|
515
|
+
model.set(forEach);
|
|
505
516
|
for (const [_key, value] of model)
|
|
506
517
|
if (PARENT.get(value) === model) {
|
|
507
518
|
this.add(value, true);
|
|
@@ -518,8 +529,8 @@ var Context = class _Context {
|
|
|
518
529
|
I = new input();
|
|
519
530
|
this.cleanup.add(() => I.set(null));
|
|
520
531
|
} else {
|
|
532
|
+
T = input.constructor;
|
|
521
533
|
I = input;
|
|
522
|
-
T = I.constructor;
|
|
523
534
|
}
|
|
524
535
|
keys(T, true).forEach((K) => {
|
|
525
536
|
const result = this[K];
|
|
@@ -532,15 +543,15 @@ var Context = class _Context {
|
|
|
532
543
|
keys(T).forEach((K) => {
|
|
533
544
|
const value = this.hasOwnProperty(K) ? null : I;
|
|
534
545
|
if (value || this[K] !== I && !implicit)
|
|
535
|
-
|
|
546
|
+
define(this, K, {
|
|
536
547
|
configurable: true,
|
|
537
548
|
value
|
|
538
549
|
});
|
|
539
550
|
});
|
|
540
|
-
const waiting =
|
|
551
|
+
const waiting = LOOKUP.get(I);
|
|
541
552
|
if (waiting instanceof Array)
|
|
542
553
|
waiting.forEach((cb) => cb(this));
|
|
543
|
-
|
|
554
|
+
LOOKUP.set(I, this);
|
|
544
555
|
return I;
|
|
545
556
|
}
|
|
546
557
|
};
|
|
@@ -576,8 +587,7 @@ Model.on((_, model) => {
|
|
|
576
587
|
const { value } = Object.getOwnPropertyDescriptor(model, key2);
|
|
577
588
|
const instruction = INSTRUCT.get(value);
|
|
578
589
|
if (!instruction) {
|
|
579
|
-
|
|
580
|
-
update(model, key2, value);
|
|
590
|
+
mayAdopt(model, value);
|
|
581
591
|
continue;
|
|
582
592
|
}
|
|
583
593
|
INSTRUCT.delete(value);
|
|
@@ -588,7 +598,7 @@ Model.on((_, model) => {
|
|
|
588
598
|
const desc = typeof output == "object" ? output : { get: output };
|
|
589
599
|
if ("value" in desc)
|
|
590
600
|
state[key2] = desc.value;
|
|
591
|
-
|
|
601
|
+
define(model, key2, {
|
|
592
602
|
enumerable: desc.enumerable !== false,
|
|
593
603
|
get() {
|
|
594
604
|
return watch(
|
|
@@ -611,81 +621,84 @@ Model.on((_, model) => {
|
|
|
611
621
|
var STALE = /* @__PURE__ */ new WeakSet();
|
|
612
622
|
function get(arg0, arg1) {
|
|
613
623
|
return use((key2, subject, state) => {
|
|
614
|
-
let from = subject;
|
|
615
624
|
if (typeof arg0 == "symbol")
|
|
616
|
-
throw new Error(`Attempted to use an instruction result (probably use or get) as computed source for ${
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
625
|
+
throw new Error(`Attempted to use an instruction result (probably use or get) as computed source for ${subject}.${key2}. This is not allowed.`);
|
|
626
|
+
if (Model.is(arg0)) {
|
|
627
|
+
let assign2 = function(value) {
|
|
628
|
+
if (typeof arg1 == "function")
|
|
629
|
+
value.get((x) => arg1(x, key2));
|
|
630
|
+
update(subject, key2, value);
|
|
631
|
+
};
|
|
632
|
+
var assign = assign2;
|
|
633
|
+
const hasParent = PARENT.get(subject);
|
|
622
634
|
if (!hasParent) {
|
|
623
635
|
if (arg1 === true)
|
|
624
|
-
throw new Error(`${
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
});
|
|
633
|
-
};
|
|
636
|
+
throw new Error(`${subject} may only exist as a child of type ${arg0}.`);
|
|
637
|
+
Context.get(subject, (context) => {
|
|
638
|
+
const model = context.get(arg0);
|
|
639
|
+
if (model)
|
|
640
|
+
assign2(model);
|
|
641
|
+
else if (arg1 !== false)
|
|
642
|
+
throw new Error(`Required ${arg0} not found in context for ${subject}.`);
|
|
643
|
+
});
|
|
634
644
|
} else if (!arg0 || hasParent instanceof arg0)
|
|
635
|
-
|
|
645
|
+
assign2(hasParent);
|
|
636
646
|
else
|
|
637
|
-
throw new Error(`New ${
|
|
647
|
+
throw new Error(`New ${subject} created as child of ${hasParent}, but must be instanceof ${arg0}.`);
|
|
648
|
+
return {
|
|
649
|
+
get: arg1 !== false
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
let from = subject;
|
|
653
|
+
if (arg0 instanceof Model) {
|
|
654
|
+
from = arg0;
|
|
638
655
|
} else {
|
|
639
656
|
const fn = METHOD.get(arg0) || arg0;
|
|
640
657
|
arg1 = (p, k) => fn.call(p, k, p);
|
|
641
658
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
} else
|
|
682
|
-
source((got) => subject.set(key2, got));
|
|
683
|
-
return { get: arg1 };
|
|
659
|
+
const source = (resolve) => resolve(from);
|
|
660
|
+
const getter = arg1;
|
|
661
|
+
let reset;
|
|
662
|
+
let isAsync;
|
|
663
|
+
let proxy;
|
|
664
|
+
function connect(model) {
|
|
665
|
+
reset = createEffect(model, (current) => {
|
|
666
|
+
proxy = current;
|
|
667
|
+
if (!(key2 in state) || STALE.delete(compute))
|
|
668
|
+
compute(!reset);
|
|
669
|
+
return (didUpdate) => {
|
|
670
|
+
if (didUpdate) {
|
|
671
|
+
STALE.add(compute);
|
|
672
|
+
event(subject, key2, true);
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
function compute(initial) {
|
|
678
|
+
let next;
|
|
679
|
+
try {
|
|
680
|
+
next = getter.call(proxy, proxy, key2);
|
|
681
|
+
} catch (err) {
|
|
682
|
+
console.warn(`An exception was thrown while ${initial ? "initializing" : "refreshing"} ${subject}.${key2}.`);
|
|
683
|
+
if (initial)
|
|
684
|
+
throw err;
|
|
685
|
+
console.error(err);
|
|
686
|
+
}
|
|
687
|
+
update(subject, key2, next, !isAsync);
|
|
688
|
+
}
|
|
689
|
+
return () => {
|
|
690
|
+
if (!proxy) {
|
|
691
|
+
source(connect);
|
|
692
|
+
isAsync = true;
|
|
693
|
+
}
|
|
694
|
+
if (STALE.delete(compute))
|
|
695
|
+
compute();
|
|
696
|
+
return fetch(subject, key2, !proxy);
|
|
697
|
+
};
|
|
684
698
|
});
|
|
685
699
|
}
|
|
686
700
|
|
|
687
701
|
// src/instruction/ref.ts
|
|
688
|
-
var define2 = Object.defineProperty;
|
|
689
702
|
function ref(arg, arg2) {
|
|
690
703
|
return use((key2, subject, state) => {
|
|
691
704
|
let value = {};
|
|
@@ -693,20 +706,22 @@ function ref(arg, arg2) {
|
|
|
693
706
|
subject.get(() => {
|
|
694
707
|
for (const key3 in state)
|
|
695
708
|
if (typeof arg2 == "function")
|
|
696
|
-
|
|
709
|
+
define(value, key3, {
|
|
697
710
|
configurable: true,
|
|
698
711
|
get() {
|
|
699
712
|
const out = arg2(key3);
|
|
700
|
-
|
|
713
|
+
define(value, key3, { value: out });
|
|
701
714
|
return out;
|
|
702
715
|
}
|
|
703
716
|
});
|
|
704
717
|
else {
|
|
705
718
|
const get2 = () => state[key3];
|
|
706
|
-
const set2 = (value2) =>
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
719
|
+
const set2 = (value2) => {
|
|
720
|
+
update(subject, key3, value2);
|
|
721
|
+
};
|
|
722
|
+
define(set2, "current", { get: get2, set: set2 });
|
|
723
|
+
define(set2, "get", { value: get2 });
|
|
724
|
+
define(value, key3, { value: set2 });
|
|
710
725
|
}
|
|
711
726
|
});
|
|
712
727
|
else if (typeof arg == "object")
|
|
@@ -715,7 +730,7 @@ function ref(arg, arg2) {
|
|
|
715
730
|
let unSet;
|
|
716
731
|
const get2 = () => state[key2];
|
|
717
732
|
const set2 = (value2) => {
|
|
718
|
-
if (!subject
|
|
733
|
+
if (!update(subject, key2, value2) || !arg)
|
|
719
734
|
return;
|
|
720
735
|
if (unSet)
|
|
721
736
|
unSet = void unSet(value2);
|
|
@@ -731,7 +746,7 @@ function ref(arg, arg2) {
|
|
|
731
746
|
get: { value: get2 }
|
|
732
747
|
});
|
|
733
748
|
}
|
|
734
|
-
|
|
749
|
+
define(subject, key2, { value });
|
|
735
750
|
});
|
|
736
751
|
}
|
|
737
752
|
|
|
@@ -751,16 +766,16 @@ function set(value, argument) {
|
|
|
751
766
|
output.get = argument === true;
|
|
752
767
|
if (value instanceof Promise) {
|
|
753
768
|
value.then((value2) => {
|
|
754
|
-
subject
|
|
769
|
+
update(subject, key2, value2);
|
|
755
770
|
return value2;
|
|
756
771
|
}).catch((err) => {
|
|
757
|
-
subject
|
|
772
|
+
event(subject, key2);
|
|
758
773
|
output.get = () => {
|
|
759
774
|
throw err;
|
|
760
775
|
};
|
|
761
776
|
});
|
|
762
777
|
} else
|
|
763
|
-
subject
|
|
778
|
+
update(subject, key2, value);
|
|
764
779
|
if (0 in arguments)
|
|
765
780
|
return subject[key2];
|
|
766
781
|
};
|
|
@@ -785,7 +800,7 @@ function set(value, argument) {
|
|
|
785
800
|
} else
|
|
786
801
|
output.set = (value2) => {
|
|
787
802
|
output.get = void 0;
|
|
788
|
-
subject
|
|
803
|
+
update(subject, key2, value2);
|
|
789
804
|
};
|
|
790
805
|
return output;
|
|
791
806
|
});
|
|
@@ -813,17 +828,17 @@ var APPLY = /* @__PURE__ */ new WeakMap();
|
|
|
813
828
|
function has(arg1, arg2) {
|
|
814
829
|
return use((key2, subject) => {
|
|
815
830
|
const applied = /* @__PURE__ */ new Set();
|
|
816
|
-
const
|
|
817
|
-
subject
|
|
831
|
+
const apply = () => {
|
|
832
|
+
update(subject, key2, Object.freeze(Array.from(applied)));
|
|
818
833
|
};
|
|
819
834
|
if (Model.is(arg1))
|
|
820
835
|
Context.get(subject, (context) => {
|
|
821
|
-
context.
|
|
836
|
+
context.has(arg1, (model) => {
|
|
822
837
|
let remove;
|
|
823
838
|
let disconnect;
|
|
824
|
-
if (applied.has(
|
|
839
|
+
if (applied.has(model))
|
|
825
840
|
return;
|
|
826
|
-
const callback = APPLY.get(
|
|
841
|
+
const callback = APPLY.get(model);
|
|
827
842
|
if (callback) {
|
|
828
843
|
const after = callback(subject);
|
|
829
844
|
if (after === false)
|
|
@@ -832,7 +847,7 @@ function has(arg1, arg2) {
|
|
|
832
847
|
disconnect = after;
|
|
833
848
|
}
|
|
834
849
|
if (typeof arg2 == "function") {
|
|
835
|
-
const done2 = arg2(
|
|
850
|
+
const done2 = arg2(model, subject);
|
|
836
851
|
if (done2 === false)
|
|
837
852
|
return false;
|
|
838
853
|
remove = () => {
|
|
@@ -840,18 +855,18 @@ function has(arg1, arg2) {
|
|
|
840
855
|
done2();
|
|
841
856
|
};
|
|
842
857
|
}
|
|
843
|
-
applied.add(
|
|
844
|
-
|
|
858
|
+
applied.add(model);
|
|
859
|
+
apply();
|
|
845
860
|
const done = () => {
|
|
846
|
-
|
|
847
|
-
applied.delete(
|
|
848
|
-
|
|
861
|
+
ignore();
|
|
862
|
+
applied.delete(model);
|
|
863
|
+
apply();
|
|
849
864
|
if (disconnect)
|
|
850
865
|
disconnect();
|
|
851
866
|
if (typeof remove == "function")
|
|
852
867
|
remove();
|
|
853
868
|
};
|
|
854
|
-
const
|
|
869
|
+
const ignore = model.get(null, done);
|
|
855
870
|
return done;
|
|
856
871
|
});
|
|
857
872
|
});
|
|
@@ -866,10 +881,10 @@ function has(arg1, arg2) {
|
|
|
866
881
|
return false;
|
|
867
882
|
}
|
|
868
883
|
applied.add(recipient);
|
|
869
|
-
|
|
884
|
+
apply();
|
|
870
885
|
return () => {
|
|
871
886
|
applied.delete(recipient);
|
|
872
|
-
|
|
887
|
+
apply();
|
|
873
888
|
if (typeof remove == "function")
|
|
874
889
|
remove();
|
|
875
890
|
};
|
|
@@ -881,8 +896,10 @@ function has(arg1, arg2) {
|
|
|
881
896
|
export {
|
|
882
897
|
Context,
|
|
883
898
|
Model,
|
|
899
|
+
addListener,
|
|
900
|
+
createEffect,
|
|
901
|
+
createProxy,
|
|
884
902
|
Model as default,
|
|
885
|
-
effect,
|
|
886
903
|
get,
|
|
887
904
|
has,
|
|
888
905
|
ref,
|