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