@expressive/mvc 0.4.6 → 0.6.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/lib/index.d.ts +83 -94
- package/lib/index.esm.js +636 -654
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +636 -657
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/index.esm.js
CHANGED
|
@@ -1,30 +1,5 @@
|
|
|
1
1
|
import React, { useLayoutEffect, useState, useMemo } from 'react';
|
|
2
2
|
|
|
3
|
-
/*! *****************************************************************************
|
|
4
|
-
Copyright (c) Microsoft Corporation.
|
|
5
|
-
|
|
6
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
7
|
-
purpose with or without fee is hereby granted.
|
|
8
|
-
|
|
9
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
16
|
-
***************************************************************************** */
|
|
17
|
-
|
|
18
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
19
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
20
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
21
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
22
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
23
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
24
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
3
|
class Issue extends Error {
|
|
29
4
|
constructor() {
|
|
30
5
|
super(...arguments);
|
|
@@ -42,11 +17,11 @@ function issues(register) {
|
|
|
42
17
|
return Library;
|
|
43
18
|
}
|
|
44
19
|
|
|
45
|
-
const Oops$
|
|
20
|
+
const Oops$b = issues({
|
|
46
21
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
|
|
47
22
|
});
|
|
48
23
|
function suspend(source, key) {
|
|
49
|
-
const error = Oops$
|
|
24
|
+
const error = Oops$b.NotReady(source.subject, key);
|
|
50
25
|
const promise = new Promise(resolve => {
|
|
51
26
|
const release = source.addListener(forKey => {
|
|
52
27
|
if (forKey == key)
|
|
@@ -86,174 +61,170 @@ function mayRetry(fn) {
|
|
|
86
61
|
return compute();
|
|
87
62
|
}
|
|
88
63
|
|
|
89
|
-
const Oops$b = issues({
|
|
90
|
-
BadCallback: () => `Callback for effect-callback may only return a function.`
|
|
91
|
-
});
|
|
92
|
-
const { assign, create, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
93
|
-
function define(target, key, value) {
|
|
94
|
-
defineProperty(target, key, { value });
|
|
95
|
-
}
|
|
96
|
-
function defineLazy(object, property, init) {
|
|
97
|
-
defineProperty(object, property, {
|
|
98
|
-
configurable: true,
|
|
99
|
-
get() {
|
|
100
|
-
const value = init.call(this);
|
|
101
|
-
defineProperty(this, property, { value });
|
|
102
|
-
return value;
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
function createEffect(callback) {
|
|
107
|
-
let unSet;
|
|
108
|
-
return function (value) {
|
|
109
|
-
if (typeof unSet == "function")
|
|
110
|
-
unSet();
|
|
111
|
-
unSet = callback.call(this, value);
|
|
112
|
-
if (unSet instanceof Promise)
|
|
113
|
-
unSet = undefined;
|
|
114
|
-
if (unSet && typeof unSet !== "function")
|
|
115
|
-
throw Oops$b.BadCallback();
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
function createValueEffect(callback) {
|
|
119
|
-
let unSet;
|
|
120
|
-
return function (value) {
|
|
121
|
-
if (typeof unSet == "function")
|
|
122
|
-
unSet(value);
|
|
123
|
-
const out = callback.call(this, value, this);
|
|
124
|
-
if (typeof out == "boolean")
|
|
125
|
-
return out;
|
|
126
|
-
if (!out || out instanceof Promise)
|
|
127
|
-
return;
|
|
128
|
-
if (typeof out == "function")
|
|
129
|
-
unSet = out;
|
|
130
|
-
else
|
|
131
|
-
throw Oops$b.BadCallback();
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function ensure(subject, cb) {
|
|
136
|
-
let control = subject[CONTROL];
|
|
137
|
-
if (!control) {
|
|
138
|
-
control = new Controller(subject);
|
|
139
|
-
define(subject, CONTROL, control);
|
|
140
|
-
}
|
|
141
|
-
if (!control.state) {
|
|
142
|
-
const { waiting } = control;
|
|
143
|
-
if (cb) {
|
|
144
|
-
let done;
|
|
145
|
-
waiting.add(() => {
|
|
146
|
-
done = cb(control);
|
|
147
|
-
});
|
|
148
|
-
return () => done && done();
|
|
149
|
-
}
|
|
150
|
-
control.state = new Map();
|
|
151
|
-
for (const key in subject)
|
|
152
|
-
control.add(key);
|
|
153
|
-
const callback = Array.from(waiting);
|
|
154
|
-
waiting.clear();
|
|
155
|
-
for (const cb of callback)
|
|
156
|
-
cb();
|
|
157
|
-
}
|
|
158
|
-
return cb ? cb(control) : control;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
64
|
const Oops$a = issues({
|
|
162
65
|
BadSource: (model, property, got) => `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
|
|
163
66
|
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
|
|
164
|
-
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}]
|
|
67
|
+
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`,
|
|
68
|
+
FactoryFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
|
|
69
|
+
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
|
|
70
|
+
ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`
|
|
165
71
|
});
|
|
166
72
|
const INFO = new WeakMap();
|
|
167
73
|
const KEYS = new WeakMap();
|
|
168
74
|
const ORDER = new WeakMap();
|
|
169
|
-
function get(
|
|
170
|
-
return apply(function
|
|
171
|
-
const { subject
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
arg1 = undefined;
|
|
75
|
+
function get(arg0, arg1, arg2) {
|
|
76
|
+
return apply(function get(key) {
|
|
77
|
+
const { subject } = this;
|
|
78
|
+
const computeRequired = arg1 === true || arg2 === true;
|
|
79
|
+
const factoryRequired = arg1 !== false && arg2 !== false;
|
|
80
|
+
let getter;
|
|
176
81
|
// Easy mistake, using a peer, will always be unresolved.
|
|
177
|
-
if (typeof
|
|
82
|
+
if (typeof arg0 == "symbol")
|
|
178
83
|
throw Oops$a.PeerNotAllowed(subject, key);
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
let sub;
|
|
193
|
-
let order = ORDER.get(this);
|
|
194
|
-
if (!order)
|
|
195
|
-
ORDER.set(this, order = []);
|
|
196
|
-
state.set(key, undefined);
|
|
197
|
-
const compute = (initial) => {
|
|
198
|
-
try {
|
|
199
|
-
return setter.call(sub.proxy, sub.proxy);
|
|
200
|
-
}
|
|
201
|
-
catch (err) {
|
|
202
|
-
Oops$a.Failed(subject, key, initial).warn();
|
|
203
|
-
throw err;
|
|
204
|
-
}
|
|
205
|
-
};
|
|
206
|
-
const refreshValue = () => {
|
|
207
|
-
let value;
|
|
208
|
-
try {
|
|
209
|
-
value = compute(false);
|
|
210
|
-
}
|
|
211
|
-
catch (e) {
|
|
212
|
-
console.error(e);
|
|
213
|
-
}
|
|
214
|
-
finally {
|
|
215
|
-
if (state.get(key) !== value) {
|
|
216
|
-
state.set(key, value);
|
|
217
|
-
this.update(key);
|
|
218
|
-
return value;
|
|
84
|
+
if (typeof arg0 == "function" && /^[A-Z]/.test(arg0.name))
|
|
85
|
+
throw Oops$a.BadSource(subject, key, arg0);
|
|
86
|
+
this.state.set(key, undefined);
|
|
87
|
+
const init = () => {
|
|
88
|
+
let source = this;
|
|
89
|
+
let setter;
|
|
90
|
+
if (typeof arg0 == "function") {
|
|
91
|
+
const result = mayRetry(() => arg0.call(subject, key, subject));
|
|
92
|
+
if (typeof result == "function")
|
|
93
|
+
setter = result;
|
|
94
|
+
else {
|
|
95
|
+
getter = factoryMode(this, result, key, factoryRequired);
|
|
96
|
+
return;
|
|
219
97
|
}
|
|
220
98
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
if (source !== this) {
|
|
224
|
-
refreshValue();
|
|
99
|
+
else if (arg0 instanceof Promise) {
|
|
100
|
+
getter = factoryMode(this, arg0, key, factoryRequired);
|
|
225
101
|
return;
|
|
226
102
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
103
|
+
else if (typeof arg1 == "function") {
|
|
104
|
+
// replace source controller in-case it is different
|
|
105
|
+
source = ensure(arg0);
|
|
106
|
+
setter = arg1;
|
|
107
|
+
}
|
|
108
|
+
else
|
|
109
|
+
throw new Error(`Factory argument cannot be ${arg1}`);
|
|
110
|
+
getter = computeMode(this, source, setter, key, computeRequired);
|
|
231
111
|
};
|
|
232
|
-
|
|
233
|
-
const control = getSource();
|
|
234
|
-
sub = control.subscribe(dependancyDidUpdate);
|
|
112
|
+
if (typeof arg0 == "function" && factoryRequired)
|
|
235
113
|
try {
|
|
236
|
-
|
|
237
|
-
state.set(key, value);
|
|
238
|
-
return value;
|
|
239
|
-
}
|
|
240
|
-
catch (e) {
|
|
241
|
-
throw e;
|
|
114
|
+
init();
|
|
242
115
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
116
|
+
catch (err) {
|
|
117
|
+
Oops$a.ComputeFailed(subject, key).warn();
|
|
118
|
+
throw err;
|
|
246
119
|
}
|
|
247
|
-
};
|
|
248
|
-
INFO.set(refreshValue, info);
|
|
249
120
|
return () => {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
return value;
|
|
121
|
+
if (!getter)
|
|
122
|
+
init();
|
|
123
|
+
return getter();
|
|
254
124
|
};
|
|
255
125
|
});
|
|
256
126
|
}
|
|
127
|
+
function factoryMode(self, output, key, required) {
|
|
128
|
+
const { subject, state } = self;
|
|
129
|
+
let pending;
|
|
130
|
+
let error;
|
|
131
|
+
if (output instanceof Promise) {
|
|
132
|
+
state.set(key, undefined);
|
|
133
|
+
pending = output
|
|
134
|
+
.catch(err => error = err)
|
|
135
|
+
.then(val => {
|
|
136
|
+
state.set(key, val);
|
|
137
|
+
return val;
|
|
138
|
+
})
|
|
139
|
+
.finally(() => {
|
|
140
|
+
pending = undefined;
|
|
141
|
+
self.update(key);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
state.set(key, output);
|
|
145
|
+
const suspend = () => {
|
|
146
|
+
if (required === false)
|
|
147
|
+
return undefined;
|
|
148
|
+
const issue = Oops$a.NotReady(subject, key);
|
|
149
|
+
Object.assign(pending, {
|
|
150
|
+
message: issue.message,
|
|
151
|
+
stack: issue.stack
|
|
152
|
+
});
|
|
153
|
+
throw pending;
|
|
154
|
+
};
|
|
155
|
+
return () => {
|
|
156
|
+
if (error)
|
|
157
|
+
throw error;
|
|
158
|
+
if (pending)
|
|
159
|
+
return suspend();
|
|
160
|
+
if (state.has(key))
|
|
161
|
+
return state.get(key);
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function computeMode(self, source, setter, key, required) {
|
|
165
|
+
const { subject, state } = self;
|
|
166
|
+
let sub;
|
|
167
|
+
let order = ORDER.get(self);
|
|
168
|
+
if (!order)
|
|
169
|
+
ORDER.set(self, order = []);
|
|
170
|
+
const compute = (initial) => {
|
|
171
|
+
try {
|
|
172
|
+
return setter.call(sub.proxy, sub.proxy);
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
Oops$a.Failed(subject, key, initial).warn();
|
|
176
|
+
throw err;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
const refresh = () => {
|
|
180
|
+
let value;
|
|
181
|
+
try {
|
|
182
|
+
value = compute(false);
|
|
183
|
+
}
|
|
184
|
+
catch (e) {
|
|
185
|
+
console.error(e);
|
|
186
|
+
}
|
|
187
|
+
finally {
|
|
188
|
+
if (state.get(key) !== value) {
|
|
189
|
+
state.set(key, value);
|
|
190
|
+
self.update(key);
|
|
191
|
+
return value;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
const update = (_key, source) => {
|
|
196
|
+
if (source !== self) {
|
|
197
|
+
refresh();
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
let pending = KEYS.get(self);
|
|
201
|
+
if (!pending)
|
|
202
|
+
KEYS.set(self, pending = []);
|
|
203
|
+
pending.push(refresh);
|
|
204
|
+
};
|
|
205
|
+
const create = () => {
|
|
206
|
+
sub = source.subscribe(update);
|
|
207
|
+
try {
|
|
208
|
+
const value = compute(true);
|
|
209
|
+
state.set(key, value);
|
|
210
|
+
return value;
|
|
211
|
+
}
|
|
212
|
+
catch (e) {
|
|
213
|
+
throw e;
|
|
214
|
+
}
|
|
215
|
+
finally {
|
|
216
|
+
sub.commit();
|
|
217
|
+
order.push(refresh);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
INFO.set(refresh, key);
|
|
221
|
+
return () => {
|
|
222
|
+
const value = sub ? state.get(key) : create();
|
|
223
|
+
if (value === undefined && required)
|
|
224
|
+
throw suspend(self, key);
|
|
225
|
+
return value;
|
|
226
|
+
};
|
|
227
|
+
}
|
|
257
228
|
function flush(control) {
|
|
258
229
|
const pending = KEYS.get(control);
|
|
259
230
|
if (!pending)
|
|
@@ -263,186 +234,77 @@ function flush(control) {
|
|
|
263
234
|
const compute = pending
|
|
264
235
|
.sort((a, b) => list.indexOf(b) - list.indexOf(a))
|
|
265
236
|
.pop();
|
|
266
|
-
const
|
|
237
|
+
const key = INFO.get(compute);
|
|
267
238
|
if (!control.frame.has(key))
|
|
268
239
|
compute();
|
|
269
240
|
}
|
|
270
241
|
KEYS.delete(control);
|
|
271
242
|
}
|
|
272
243
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
});
|
|
289
|
-
const release = parent.addListener(key => {
|
|
290
|
-
if (!this.active)
|
|
291
|
-
return;
|
|
292
|
-
const handler = using.get(key);
|
|
293
|
-
let notify;
|
|
294
|
-
if (typeof handler == "function") {
|
|
295
|
-
const callback = handler();
|
|
296
|
-
if (callback === true)
|
|
297
|
-
notify = this.onUpdate(key, parent);
|
|
298
|
-
}
|
|
299
|
-
else if (handler === true)
|
|
300
|
-
notify = this.onUpdate(key, parent);
|
|
301
|
-
const getWhy = () => {
|
|
302
|
-
const update = getUpdate(parent.subject);
|
|
303
|
-
const applicable = update.filter(k => using.has(k));
|
|
304
|
-
UPDATE.set(proxy, applicable);
|
|
305
|
-
};
|
|
306
|
-
if (notify) {
|
|
307
|
-
parent.waiting.add(getWhy);
|
|
308
|
-
parent.waiting.add(notify);
|
|
309
|
-
}
|
|
310
|
-
});
|
|
311
|
-
this.commit = () => {
|
|
312
|
-
this.active = true;
|
|
313
|
-
this.dependant.forEach(x => x.commit());
|
|
314
|
-
return this.release;
|
|
315
|
-
};
|
|
316
|
-
this.release = () => {
|
|
317
|
-
this.dependant.forEach(x => x.release());
|
|
318
|
-
release();
|
|
319
|
-
};
|
|
320
|
-
this.add = (key, value) => {
|
|
321
|
-
if (value !== undefined)
|
|
322
|
-
using.set(key, value);
|
|
323
|
-
else if (!using.has(key))
|
|
324
|
-
using.set(key, true);
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
const UPDATE = new WeakMap();
|
|
330
|
-
function getUpdate(subject) {
|
|
331
|
-
return UPDATE.get(subject);
|
|
244
|
+
const Oops$9 = issues({
|
|
245
|
+
BadCallback: () => `Callback for effect-callback may only return a function.`
|
|
246
|
+
});
|
|
247
|
+
const { assign, create, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
248
|
+
function createEffect(callback) {
|
|
249
|
+
let unSet;
|
|
250
|
+
return function (value) {
|
|
251
|
+
if (typeof unSet == "function")
|
|
252
|
+
unSet();
|
|
253
|
+
unSet = callback.call(this, value);
|
|
254
|
+
if (unSet instanceof Promise)
|
|
255
|
+
unSet = undefined;
|
|
256
|
+
if (unSet && typeof unSet !== "function")
|
|
257
|
+
throw Oops$9.BadCallback();
|
|
258
|
+
};
|
|
332
259
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
}
|
|
343
|
-
add(key) {
|
|
344
|
-
const { subject, state } = this;
|
|
345
|
-
const { value } = getOwnPropertyDescriptor(subject, key);
|
|
346
|
-
if (typeof value == "function")
|
|
347
|
-
return;
|
|
348
|
-
if (typeof value == "symbol") {
|
|
349
|
-
const instruction = PENDING.get(value);
|
|
350
|
-
if (instruction)
|
|
351
|
-
instruction.call(this, key, this);
|
|
352
|
-
return;
|
|
353
|
-
}
|
|
354
|
-
state.set(key, value);
|
|
355
|
-
defineProperty(subject, key, {
|
|
356
|
-
enumerable: false,
|
|
357
|
-
set: this.ref(key),
|
|
358
|
-
get() {
|
|
359
|
-
const local = this[LOCAL];
|
|
360
|
-
if (local)
|
|
361
|
-
local.add(key);
|
|
362
|
-
return state.get(key);
|
|
363
|
-
}
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
addListener(listener) {
|
|
367
|
-
this.followers.add(listener);
|
|
368
|
-
return () => {
|
|
369
|
-
this.followers.delete(listener);
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
ref(key, handler) {
|
|
373
|
-
const { subject, state } = this;
|
|
374
|
-
return (value) => {
|
|
375
|
-
if (state.get(key) == value)
|
|
376
|
-
return;
|
|
377
|
-
if (handler)
|
|
378
|
-
switch (handler.call(subject, value)) {
|
|
379
|
-
case true:
|
|
380
|
-
this.update(key);
|
|
381
|
-
case false:
|
|
382
|
-
return;
|
|
383
|
-
}
|
|
384
|
-
state.set(key, value);
|
|
385
|
-
this.update(key);
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
update(key) {
|
|
389
|
-
const { followers, frame, subject, waiting } = this;
|
|
390
|
-
if (frame.has(key))
|
|
260
|
+
function createValueEffect(callback) {
|
|
261
|
+
let unSet;
|
|
262
|
+
return function (value) {
|
|
263
|
+
if (typeof unSet == "function")
|
|
264
|
+
unSet(value);
|
|
265
|
+
const out = callback.call(this, value, this);
|
|
266
|
+
if (typeof out == "boolean")
|
|
267
|
+
return out;
|
|
268
|
+
if (!out || out instanceof Promise)
|
|
391
269
|
return;
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
UPDATE.delete(subject);
|
|
398
|
-
}, 0);
|
|
399
|
-
frame.clear();
|
|
400
|
-
for (const notify of waiting)
|
|
401
|
-
try {
|
|
402
|
-
waiting.delete(notify);
|
|
403
|
-
notify();
|
|
404
|
-
}
|
|
405
|
-
catch (err) {
|
|
406
|
-
console.error(err);
|
|
407
|
-
}
|
|
408
|
-
}, 0);
|
|
409
|
-
frame.add(key);
|
|
410
|
-
for (const callback of followers) {
|
|
411
|
-
const event = callback(key, this);
|
|
412
|
-
if (typeof event == "function")
|
|
413
|
-
waiting.add(event);
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
clear() {
|
|
417
|
-
const listeners = [...this.followers];
|
|
418
|
-
this.followers.clear();
|
|
419
|
-
listeners.forEach(x => x(null, this));
|
|
420
|
-
}
|
|
270
|
+
if (typeof out == "function")
|
|
271
|
+
unSet = out;
|
|
272
|
+
else
|
|
273
|
+
throw Oops$9.BadCallback();
|
|
274
|
+
};
|
|
421
275
|
}
|
|
422
276
|
|
|
423
|
-
const Oops$
|
|
277
|
+
const Oops$8 = issues({
|
|
424
278
|
Timeout: (keys, timeout) => `No update for [${keys}] within ${timeout}.`,
|
|
425
279
|
StrictUpdate: () => `Strict update() did not find pending updates.`,
|
|
426
280
|
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
|
|
427
281
|
});
|
|
428
|
-
const CONTROL = Symbol("CONTROL");
|
|
429
282
|
const WHY = Symbol("UPDATE");
|
|
430
283
|
const LOCAL = Symbol("LOCAL");
|
|
431
284
|
const STATE = Symbol("STATE");
|
|
432
285
|
class Model {
|
|
433
286
|
constructor() {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
287
|
+
defineProperty(this, CONTROL, {
|
|
288
|
+
value: new Controller(this)
|
|
289
|
+
});
|
|
290
|
+
defineProperty(this, "is", {
|
|
291
|
+
value: this
|
|
292
|
+
});
|
|
293
|
+
defineProperty(this, "set", {
|
|
294
|
+
configurable: true,
|
|
295
|
+
get: () => {
|
|
296
|
+
const controller = ensure(this);
|
|
297
|
+
const value = (key, value) => {
|
|
298
|
+
controller.state.set(key, value);
|
|
299
|
+
controller.update(key);
|
|
300
|
+
};
|
|
301
|
+
for (const key of controller.state.keys())
|
|
302
|
+
defineProperty(value, key, {
|
|
303
|
+
value: controller.ref(key)
|
|
304
|
+
});
|
|
305
|
+
defineProperty(this, "set", { value });
|
|
306
|
+
return value;
|
|
307
|
+
}
|
|
446
308
|
});
|
|
447
309
|
}
|
|
448
310
|
get [STATE]() {
|
|
@@ -495,7 +357,7 @@ class Model {
|
|
|
495
357
|
const invoke = (key) => {
|
|
496
358
|
if (!key) {
|
|
497
359
|
clear();
|
|
498
|
-
reject(Oops$
|
|
360
|
+
reject(Oops$8.Timeout(select, typeof argument == "number"
|
|
499
361
|
? `${argument}ms`
|
|
500
362
|
: `lifetime of ${this}`));
|
|
501
363
|
}
|
|
@@ -582,11 +444,11 @@ class Model {
|
|
|
582
444
|
arg = undefined;
|
|
583
445
|
}
|
|
584
446
|
if (!frame.size && arg === true)
|
|
585
|
-
return Promise.reject(Oops$
|
|
447
|
+
return Promise.reject(Oops$8.StrictUpdate());
|
|
586
448
|
return {
|
|
587
449
|
then: (callback) => {
|
|
588
450
|
if (!callback)
|
|
589
|
-
throw Oops$
|
|
451
|
+
throw Oops$8.NoChaining();
|
|
590
452
|
if (frame.size || arg !== false)
|
|
591
453
|
waiting.add(() => {
|
|
592
454
|
callback(getUpdate(this));
|
|
@@ -605,27 +467,204 @@ class Model {
|
|
|
605
467
|
toString() {
|
|
606
468
|
return this.constructor.name;
|
|
607
469
|
}
|
|
608
|
-
/**
|
|
609
|
-
* Creates a new instance of this controller.
|
|
610
|
-
*
|
|
611
|
-
* Beyond `new this(...)`, method will activate managed-state.
|
|
612
|
-
*
|
|
613
|
-
* @param args - arguments sent to constructor
|
|
614
|
-
*/
|
|
615
|
-
static create(...args) {
|
|
616
|
-
const instance = new this(...args);
|
|
617
|
-
ensure(instance);
|
|
618
|
-
return instance;
|
|
470
|
+
/**
|
|
471
|
+
* Creates a new instance of this controller.
|
|
472
|
+
*
|
|
473
|
+
* Beyond `new this(...)`, method will activate managed-state.
|
|
474
|
+
*
|
|
475
|
+
* @param args - arguments sent to constructor
|
|
476
|
+
*/
|
|
477
|
+
static create(...args) {
|
|
478
|
+
const instance = new this(...args);
|
|
479
|
+
ensure(instance);
|
|
480
|
+
return instance;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Static equivalent of `x instanceof this`.
|
|
484
|
+
*
|
|
485
|
+
* Will determine if provided class is a subtype of this one.
|
|
486
|
+
*/
|
|
487
|
+
static isTypeof(maybe) {
|
|
488
|
+
return (typeof maybe == "function" &&
|
|
489
|
+
maybe.prototype instanceof this);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
class Subscriber {
|
|
494
|
+
constructor(parent, onUpdate) {
|
|
495
|
+
this.onUpdate = onUpdate;
|
|
496
|
+
this.active = false;
|
|
497
|
+
this.dependant = new Set();
|
|
498
|
+
const proxy = create(parent.subject);
|
|
499
|
+
const using = new Map();
|
|
500
|
+
const listen = this.add = (key, value) => {
|
|
501
|
+
if (value !== undefined)
|
|
502
|
+
using.set(key, value);
|
|
503
|
+
else if (!using.has(key))
|
|
504
|
+
using.set(key, true);
|
|
505
|
+
};
|
|
506
|
+
LISTEN.set(proxy, listen);
|
|
507
|
+
defineProperty(proxy, LOCAL, { value: this });
|
|
508
|
+
defineProperty(this, "proxy", {
|
|
509
|
+
configurable: true,
|
|
510
|
+
get() {
|
|
511
|
+
if (UPDATE.has(proxy))
|
|
512
|
+
setTimeout(() => UPDATE.delete(proxy), 0);
|
|
513
|
+
return proxy;
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
const release = parent.addListener(key => {
|
|
517
|
+
if (!this.active)
|
|
518
|
+
return;
|
|
519
|
+
const handler = using.get(key);
|
|
520
|
+
let notify;
|
|
521
|
+
if (typeof handler == "function") {
|
|
522
|
+
const callback = handler();
|
|
523
|
+
if (callback === true)
|
|
524
|
+
notify = this.onUpdate(key, parent);
|
|
525
|
+
}
|
|
526
|
+
else if (handler === true)
|
|
527
|
+
notify = this.onUpdate(key, parent);
|
|
528
|
+
if (!notify)
|
|
529
|
+
return;
|
|
530
|
+
const notate = () => {
|
|
531
|
+
UPDATE.set(proxy, getUpdate(parent.subject).filter(k => using.has(k)));
|
|
532
|
+
};
|
|
533
|
+
parent.waiting.add(notate);
|
|
534
|
+
parent.waiting.add(notify);
|
|
535
|
+
});
|
|
536
|
+
this.commit = () => {
|
|
537
|
+
this.active = true;
|
|
538
|
+
this.dependant.forEach(x => x.commit());
|
|
539
|
+
return this.release;
|
|
540
|
+
};
|
|
541
|
+
this.release = () => {
|
|
542
|
+
this.dependant.forEach(x => x.release());
|
|
543
|
+
release();
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const UPDATE = new WeakMap();
|
|
549
|
+
const LISTEN = new WeakMap();
|
|
550
|
+
const CONTROL = Symbol("CONTROL");
|
|
551
|
+
function getUpdate(subject) {
|
|
552
|
+
return UPDATE.get(subject);
|
|
553
|
+
}
|
|
554
|
+
class Controller {
|
|
555
|
+
constructor(subject) {
|
|
556
|
+
this.subject = subject;
|
|
557
|
+
this.frame = new Set();
|
|
558
|
+
this.waiting = new Set();
|
|
559
|
+
this.followers = new Set();
|
|
560
|
+
}
|
|
561
|
+
subscribe(callback) {
|
|
562
|
+
return new Subscriber(this, callback);
|
|
563
|
+
}
|
|
564
|
+
add(key) {
|
|
565
|
+
const { subject, state } = this;
|
|
566
|
+
const { value } = getOwnPropertyDescriptor(subject, key);
|
|
567
|
+
if (typeof value == "function")
|
|
568
|
+
return;
|
|
569
|
+
if (typeof value == "symbol") {
|
|
570
|
+
const instruction = PENDING.get(value);
|
|
571
|
+
if (instruction)
|
|
572
|
+
instruction.call(this, key, this);
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
state.set(key, value);
|
|
576
|
+
defineProperty(subject, key, {
|
|
577
|
+
enumerable: false,
|
|
578
|
+
set: this.ref(key),
|
|
579
|
+
get() {
|
|
580
|
+
const listen = LISTEN.get(this);
|
|
581
|
+
if (listen)
|
|
582
|
+
listen(key);
|
|
583
|
+
return state.get(key);
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
addListener(listener) {
|
|
588
|
+
this.followers.add(listener);
|
|
589
|
+
return () => {
|
|
590
|
+
this.followers.delete(listener);
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
ref(key, handler) {
|
|
594
|
+
const { subject, state } = this;
|
|
595
|
+
return (value) => {
|
|
596
|
+
if (state.get(key) == value)
|
|
597
|
+
return;
|
|
598
|
+
if (handler)
|
|
599
|
+
switch (handler.call(subject, value)) {
|
|
600
|
+
case true:
|
|
601
|
+
this.update(key);
|
|
602
|
+
case false:
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
state.set(key, value);
|
|
606
|
+
this.update(key);
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
update(key) {
|
|
610
|
+
const { followers, frame, subject, waiting } = this;
|
|
611
|
+
if (frame.has(key))
|
|
612
|
+
return;
|
|
613
|
+
else if (!frame.size)
|
|
614
|
+
setTimeout(() => {
|
|
615
|
+
flush(this);
|
|
616
|
+
UPDATE.set(subject, Array.from(frame));
|
|
617
|
+
setTimeout(() => {
|
|
618
|
+
UPDATE.delete(subject);
|
|
619
|
+
}, 0);
|
|
620
|
+
frame.clear();
|
|
621
|
+
for (const notify of waiting)
|
|
622
|
+
try {
|
|
623
|
+
waiting.delete(notify);
|
|
624
|
+
notify();
|
|
625
|
+
}
|
|
626
|
+
catch (err) {
|
|
627
|
+
console.error(err);
|
|
628
|
+
}
|
|
629
|
+
}, 0);
|
|
630
|
+
frame.add(key);
|
|
631
|
+
for (const callback of followers) {
|
|
632
|
+
const event = callback(key, this);
|
|
633
|
+
if (typeof event == "function")
|
|
634
|
+
waiting.add(event);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
clear() {
|
|
638
|
+
const listeners = [...this.followers];
|
|
639
|
+
this.followers.clear();
|
|
640
|
+
listeners.forEach(x => x(null, this));
|
|
619
641
|
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
642
|
+
}
|
|
643
|
+
function ensure(subject, cb) {
|
|
644
|
+
let control = subject[CONTROL];
|
|
645
|
+
if (!control)
|
|
646
|
+
defineProperty(subject, CONTROL, {
|
|
647
|
+
value: control =
|
|
648
|
+
new Controller(subject)
|
|
649
|
+
});
|
|
650
|
+
if (!control.state) {
|
|
651
|
+
const { waiting } = control;
|
|
652
|
+
if (cb) {
|
|
653
|
+
let done;
|
|
654
|
+
waiting.add(() => {
|
|
655
|
+
done = cb(control);
|
|
656
|
+
});
|
|
657
|
+
return () => done && done();
|
|
658
|
+
}
|
|
659
|
+
control.state = new Map();
|
|
660
|
+
for (const key in subject)
|
|
661
|
+
control.add(key);
|
|
662
|
+
const callback = Array.from(waiting);
|
|
663
|
+
waiting.clear();
|
|
664
|
+
for (const cb of callback)
|
|
665
|
+
cb();
|
|
628
666
|
}
|
|
667
|
+
return cb ? cb(control) : control;
|
|
629
668
|
}
|
|
630
669
|
|
|
631
670
|
const PENDING = new Map();
|
|
@@ -646,11 +685,11 @@ function apply(fn, label) {
|
|
|
646
685
|
defineProperty(subject, key, output);
|
|
647
686
|
return false;
|
|
648
687
|
}
|
|
688
|
+
let { get: onGet, set: onSet, suspense } = output;
|
|
689
|
+
if ("value" in output)
|
|
690
|
+
state.set(key, output.value);
|
|
649
691
|
if ("recursive" in output && output.recursive)
|
|
650
|
-
|
|
651
|
-
const desc = output;
|
|
652
|
-
if ("value" in desc)
|
|
653
|
-
state.set(key, desc.value);
|
|
692
|
+
onGet = getRecursive(key, this);
|
|
654
693
|
if ("destroy" in output) {
|
|
655
694
|
const { destroy } = output;
|
|
656
695
|
if (destroy)
|
|
@@ -659,58 +698,86 @@ function apply(fn, label) {
|
|
|
659
698
|
destroy();
|
|
660
699
|
});
|
|
661
700
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
local
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
701
|
+
defineProperty(subject, key, {
|
|
702
|
+
enumerable: output.enumerable,
|
|
703
|
+
set: onSet !== false
|
|
704
|
+
? this.ref(key, onSet)
|
|
705
|
+
: undefined,
|
|
706
|
+
get() {
|
|
707
|
+
if (!state.has(key) && suspense)
|
|
708
|
+
throw suspend(control, key);
|
|
709
|
+
const listen = LISTEN.get(this);
|
|
710
|
+
const local = this[LOCAL];
|
|
711
|
+
if (listen)
|
|
712
|
+
listen(key);
|
|
713
|
+
return onGet
|
|
714
|
+
? onGet(local)
|
|
715
|
+
: state.get(key);
|
|
716
|
+
}
|
|
717
|
+
});
|
|
677
718
|
}
|
|
678
719
|
PENDING.set(placeholder, setup);
|
|
679
720
|
return placeholder;
|
|
680
721
|
}
|
|
681
722
|
function getRecursive(key, from) {
|
|
682
723
|
const context = new WeakMap();
|
|
683
|
-
const { state } = from;
|
|
684
724
|
return (local) => {
|
|
685
725
|
if (!local)
|
|
686
|
-
return state.get(key);
|
|
726
|
+
return from.state.get(key);
|
|
687
727
|
if (!context.has(local)) {
|
|
688
|
-
let
|
|
728
|
+
let reset;
|
|
689
729
|
const init = () => {
|
|
690
|
-
if (
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
context.set(local, undefined);
|
|
694
|
-
child = undefined;
|
|
695
|
-
}
|
|
696
|
-
const value = state.get(key);
|
|
730
|
+
if (reset)
|
|
731
|
+
reset();
|
|
732
|
+
const value = from.state.get(key);
|
|
697
733
|
if (value && CONTROL in value) {
|
|
698
|
-
child = ensure(value).subscribe(local.onUpdate);
|
|
734
|
+
const child = ensure(value).subscribe(local.onUpdate);
|
|
699
735
|
if (local.active)
|
|
700
736
|
child.commit();
|
|
701
737
|
local.dependant.add(child);
|
|
702
738
|
context.set(local, child.proxy);
|
|
739
|
+
reset = () => {
|
|
740
|
+
child.release();
|
|
741
|
+
local.dependant.delete(child);
|
|
742
|
+
context.set(local, undefined);
|
|
743
|
+
reset = undefined;
|
|
744
|
+
};
|
|
703
745
|
}
|
|
704
746
|
return true;
|
|
705
747
|
};
|
|
706
|
-
init();
|
|
707
748
|
local.add(key, init);
|
|
749
|
+
init();
|
|
708
750
|
}
|
|
709
751
|
return context.get(local);
|
|
710
752
|
};
|
|
711
753
|
}
|
|
712
754
|
|
|
713
|
-
|
|
755
|
+
/*! *****************************************************************************
|
|
756
|
+
Copyright (c) Microsoft Corporation.
|
|
757
|
+
|
|
758
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
759
|
+
purpose with or without fee is hereby granted.
|
|
760
|
+
|
|
761
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
762
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
763
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
764
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
765
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
766
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
767
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
768
|
+
***************************************************************************** */
|
|
769
|
+
|
|
770
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
771
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
772
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
773
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
774
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
775
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
776
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
const Oops$7 = issues({
|
|
714
781
|
DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
|
|
715
782
|
});
|
|
716
783
|
function act(task) {
|
|
@@ -718,7 +785,7 @@ function act(task) {
|
|
|
718
785
|
let pending = false;
|
|
719
786
|
const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
720
787
|
if (pending)
|
|
721
|
-
return Promise.reject(Oops$
|
|
788
|
+
return Promise.reject(Oops$7.DuplicatePending(key));
|
|
722
789
|
pending = true;
|
|
723
790
|
this.update(key);
|
|
724
791
|
try {
|
|
@@ -740,74 +807,6 @@ function act(task) {
|
|
|
740
807
|
});
|
|
741
808
|
}
|
|
742
809
|
|
|
743
|
-
class Managed extends Array {
|
|
744
|
-
constructor(onUpdate) {
|
|
745
|
-
super();
|
|
746
|
-
this.lastUpdate = [0, 0];
|
|
747
|
-
this.update = (from, to) => {
|
|
748
|
-
this.lastUpdate = [from, to];
|
|
749
|
-
onUpdate();
|
|
750
|
-
};
|
|
751
|
-
}
|
|
752
|
-
push(...items) {
|
|
753
|
-
const { length } = this;
|
|
754
|
-
const end = super.push(...items);
|
|
755
|
-
this.update(length, end);
|
|
756
|
-
return end;
|
|
757
|
-
}
|
|
758
|
-
unshift(...items) {
|
|
759
|
-
const end = super.push(...items);
|
|
760
|
-
this.update(0, end);
|
|
761
|
-
return end;
|
|
762
|
-
}
|
|
763
|
-
splice(start, deleteCount, ...rest) {
|
|
764
|
-
const end = deleteCount !== rest.length ? Infinity : deleteCount;
|
|
765
|
-
this.update(start, end);
|
|
766
|
-
return super.splice(start, deleteCount, ...rest);
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
function array() {
|
|
770
|
-
return apply(function array(key) {
|
|
771
|
-
const context = new WeakMap();
|
|
772
|
-
const array = new Managed(() => this.update(key));
|
|
773
|
-
const getLocal = (context) => {
|
|
774
|
-
const proxy = Object.create(array);
|
|
775
|
-
let rangeA = 0;
|
|
776
|
-
let rangeB = 0;
|
|
777
|
-
const onUpdate = () => {
|
|
778
|
-
const [lastA, lastB] = array.lastUpdate;
|
|
779
|
-
if (rangeA <= lastB && rangeB >= lastA)
|
|
780
|
-
return true;
|
|
781
|
-
};
|
|
782
|
-
const listen = (eventA, eventB) => {
|
|
783
|
-
if (context.active)
|
|
784
|
-
return;
|
|
785
|
-
context.add(key, onUpdate);
|
|
786
|
-
rangeA = Math.min(rangeA, eventA);
|
|
787
|
-
rangeB = Math.max(rangeB, eventB);
|
|
788
|
-
};
|
|
789
|
-
proxy[Symbol.iterator] = () => {
|
|
790
|
-
listen(0, Infinity);
|
|
791
|
-
return array[Symbol.iterator]();
|
|
792
|
-
};
|
|
793
|
-
return proxy;
|
|
794
|
-
};
|
|
795
|
-
return {
|
|
796
|
-
value: array,
|
|
797
|
-
set: false,
|
|
798
|
-
get: (local) => {
|
|
799
|
-
if (!local)
|
|
800
|
-
return this.state.get(key);
|
|
801
|
-
if (context.has(local))
|
|
802
|
-
return context.get(local);
|
|
803
|
-
const output = getLocal(local);
|
|
804
|
-
context.set(local, output);
|
|
805
|
-
return output;
|
|
806
|
-
}
|
|
807
|
-
};
|
|
808
|
-
});
|
|
809
|
-
}
|
|
810
|
-
|
|
811
810
|
function ref(callback) {
|
|
812
811
|
return apply(function ref(key) {
|
|
813
812
|
const value = this.ref(key, callback && createValueEffect(callback));
|
|
@@ -822,83 +821,6 @@ function ref(callback) {
|
|
|
822
821
|
});
|
|
823
822
|
}
|
|
824
823
|
|
|
825
|
-
const Oops$7 = issues({
|
|
826
|
-
NonOptional: (Parent, key) => `Property ${Parent}.${key} is marked as required.`,
|
|
827
|
-
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
|
|
828
|
-
Failed: (model, key) => `Generating initial value for ${model}.${key} failed.`
|
|
829
|
-
});
|
|
830
|
-
function put(factory, argument) {
|
|
831
|
-
return apply(function set(key) {
|
|
832
|
-
const { subject, state } = this;
|
|
833
|
-
const required = argument === true || argument === undefined;
|
|
834
|
-
let set;
|
|
835
|
-
let get;
|
|
836
|
-
let pending;
|
|
837
|
-
let error;
|
|
838
|
-
const init = () => {
|
|
839
|
-
const output = typeof factory == "function" ?
|
|
840
|
-
mayRetry(() => factory.call(subject, key, subject)) :
|
|
841
|
-
factory;
|
|
842
|
-
if (output instanceof Promise) {
|
|
843
|
-
pending = output
|
|
844
|
-
.catch(err => error = err)
|
|
845
|
-
.then(val => {
|
|
846
|
-
state.set(key, val);
|
|
847
|
-
return val;
|
|
848
|
-
})
|
|
849
|
-
.finally(() => {
|
|
850
|
-
pending = undefined;
|
|
851
|
-
this.update(key);
|
|
852
|
-
});
|
|
853
|
-
return;
|
|
854
|
-
}
|
|
855
|
-
state.set(key, output);
|
|
856
|
-
return output;
|
|
857
|
-
};
|
|
858
|
-
const suspend = () => {
|
|
859
|
-
if (required === false)
|
|
860
|
-
return undefined;
|
|
861
|
-
const issue = Oops$7.NotReady(subject, key);
|
|
862
|
-
Object.assign(pending, {
|
|
863
|
-
message: issue.message,
|
|
864
|
-
stack: issue.stack
|
|
865
|
-
});
|
|
866
|
-
throw pending;
|
|
867
|
-
};
|
|
868
|
-
if (required)
|
|
869
|
-
try {
|
|
870
|
-
init();
|
|
871
|
-
}
|
|
872
|
-
catch (err) {
|
|
873
|
-
Oops$7.Failed(subject, key).warn();
|
|
874
|
-
throw err;
|
|
875
|
-
}
|
|
876
|
-
get = () => {
|
|
877
|
-
if (pending)
|
|
878
|
-
return suspend();
|
|
879
|
-
if (error)
|
|
880
|
-
throw error;
|
|
881
|
-
if (state.has(key))
|
|
882
|
-
return state.get(key);
|
|
883
|
-
let output = init();
|
|
884
|
-
return pending
|
|
885
|
-
? suspend()
|
|
886
|
-
: output;
|
|
887
|
-
};
|
|
888
|
-
if (typeof argument == "function")
|
|
889
|
-
set = createValueEffect(argument);
|
|
890
|
-
else
|
|
891
|
-
set = (value) => {
|
|
892
|
-
if (value === undefined && required)
|
|
893
|
-
throw Oops$7.NonOptional(subject, key);
|
|
894
|
-
};
|
|
895
|
-
return {
|
|
896
|
-
set,
|
|
897
|
-
get
|
|
898
|
-
};
|
|
899
|
-
});
|
|
900
|
-
}
|
|
901
|
-
|
|
902
824
|
function set(value, argument) {
|
|
903
825
|
if (!(1 in arguments)) {
|
|
904
826
|
argument = value;
|
|
@@ -916,186 +838,246 @@ function set(value, argument) {
|
|
|
916
838
|
});
|
|
917
839
|
}
|
|
918
840
|
|
|
919
|
-
const Parent = new WeakMap();
|
|
920
|
-
const Oops$6 = issues({
|
|
921
|
-
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
922
|
-
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
923
|
-
});
|
|
924
|
-
function parent(Expects, required) {
|
|
925
|
-
return apply(function parent() {
|
|
926
|
-
const child = this.subject;
|
|
927
|
-
const value = Parent.get(child);
|
|
928
|
-
const expected = Expects.name;
|
|
929
|
-
if (!value) {
|
|
930
|
-
if (required !== false)
|
|
931
|
-
throw Oops$6.Required(expected, child);
|
|
932
|
-
}
|
|
933
|
-
else if (!(value instanceof Expects))
|
|
934
|
-
throw Oops$6.Unexpected(expected, child, value);
|
|
935
|
-
return { value };
|
|
936
|
-
});
|
|
937
|
-
}
|
|
938
|
-
|
|
939
841
|
const ANY = Symbol("any");
|
|
940
842
|
function keyed(control, property, initial) {
|
|
941
|
-
const
|
|
942
|
-
const context = new WeakMap();
|
|
943
|
-
const observers = new Set();
|
|
843
|
+
const init = createProxy(emit, watch);
|
|
944
844
|
const frozen = new Set();
|
|
945
|
-
|
|
946
|
-
|
|
845
|
+
const context = new Map();
|
|
846
|
+
const users = new Map();
|
|
847
|
+
const watched = new WeakMap();
|
|
848
|
+
const update = new Set();
|
|
849
|
+
let managed = init(initial);
|
|
850
|
+
function watch(on, key) {
|
|
851
|
+
const include = watched.get(on);
|
|
852
|
+
if (include)
|
|
853
|
+
include.add(key);
|
|
947
854
|
}
|
|
948
855
|
function emit(key) {
|
|
949
|
-
control.waiting.add(reset);
|
|
950
856
|
control.update(property);
|
|
951
|
-
|
|
857
|
+
control.waiting.add(() => frozen.clear());
|
|
858
|
+
update.forEach(notify => notify(key));
|
|
952
859
|
}
|
|
953
|
-
function
|
|
860
|
+
function subscribe(local) {
|
|
954
861
|
const proxy = create(managed);
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
refresh();
|
|
862
|
+
let watch = users.get(local);
|
|
863
|
+
if (!watch) {
|
|
864
|
+
const using = watch = new Set();
|
|
865
|
+
users.set(local, using);
|
|
866
|
+
function onEvent(key) {
|
|
867
|
+
if (frozen.has(local))
|
|
868
|
+
return;
|
|
869
|
+
if (key === ANY || using.has(key) || using.has(ANY)) {
|
|
870
|
+
const refresh = local.onUpdate(property, control);
|
|
871
|
+
if (refresh) {
|
|
872
|
+
frozen.add(local);
|
|
873
|
+
refresh();
|
|
874
|
+
}
|
|
964
875
|
}
|
|
965
876
|
}
|
|
877
|
+
local.add(property, false);
|
|
878
|
+
local.dependant.add({
|
|
879
|
+
commit() {
|
|
880
|
+
if (using.size === 0)
|
|
881
|
+
using.add(ANY);
|
|
882
|
+
update.add(onEvent);
|
|
883
|
+
},
|
|
884
|
+
release() {
|
|
885
|
+
update.delete(onEvent);
|
|
886
|
+
}
|
|
887
|
+
});
|
|
966
888
|
}
|
|
889
|
+
watched.set(proxy, watch);
|
|
967
890
|
context.set(local, proxy);
|
|
968
|
-
proxy.watch = (key) => {
|
|
969
|
-
if (!local.active)
|
|
970
|
-
using.add(key);
|
|
971
|
-
};
|
|
972
|
-
local.add(property, false);
|
|
973
|
-
local.dependant.add({
|
|
974
|
-
commit() {
|
|
975
|
-
if (using.size === 0)
|
|
976
|
-
using.add(ANY);
|
|
977
|
-
observers.add(onEvent);
|
|
978
|
-
},
|
|
979
|
-
release() {
|
|
980
|
-
observers.delete(onEvent);
|
|
981
|
-
}
|
|
982
|
-
});
|
|
983
891
|
return proxy;
|
|
984
892
|
}
|
|
985
893
|
return {
|
|
986
894
|
value: initial,
|
|
987
895
|
get(local) {
|
|
988
896
|
return local ?
|
|
989
|
-
context.get(local) ||
|
|
897
|
+
context.get(local) || subscribe(local) :
|
|
990
898
|
managed;
|
|
991
899
|
},
|
|
992
900
|
set(next) {
|
|
993
|
-
managed.source = next;
|
|
994
901
|
control.state.set(property, next);
|
|
902
|
+
managed = init(next);
|
|
903
|
+
context.clear();
|
|
995
904
|
emit(ANY);
|
|
996
905
|
},
|
|
997
906
|
destroy() {
|
|
998
|
-
|
|
907
|
+
update.clear();
|
|
908
|
+
context.clear();
|
|
999
909
|
}
|
|
1000
910
|
};
|
|
1001
911
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
912
|
+
function createProxy(emit, watch) {
|
|
913
|
+
return (from) => {
|
|
914
|
+
const proxy = create(from);
|
|
915
|
+
assign(proxy, {
|
|
916
|
+
from,
|
|
917
|
+
delete(key) {
|
|
918
|
+
emit(key);
|
|
919
|
+
return from.delete(key);
|
|
920
|
+
},
|
|
921
|
+
clear() {
|
|
922
|
+
emit(ANY);
|
|
923
|
+
from.clear();
|
|
924
|
+
},
|
|
925
|
+
has(key) {
|
|
926
|
+
watch(this, key);
|
|
927
|
+
return from.has(key);
|
|
928
|
+
},
|
|
929
|
+
keys() {
|
|
930
|
+
watch(this, ANY);
|
|
931
|
+
return from.keys();
|
|
932
|
+
},
|
|
933
|
+
values() {
|
|
934
|
+
watch(this, ANY);
|
|
935
|
+
return from.values();
|
|
936
|
+
},
|
|
937
|
+
entries() {
|
|
938
|
+
watch(this, ANY);
|
|
939
|
+
return from.entries();
|
|
940
|
+
},
|
|
941
|
+
forEach(callbackfn, thisArg) {
|
|
942
|
+
const acc = [];
|
|
943
|
+
from.forEach((a, b, c) => {
|
|
944
|
+
const result = callbackfn.call(thisArg, a, b, c);
|
|
945
|
+
if (result !== undefined)
|
|
946
|
+
acc.push(result);
|
|
947
|
+
});
|
|
948
|
+
watch(this, ANY);
|
|
949
|
+
return acc;
|
|
950
|
+
},
|
|
951
|
+
[Symbol.iterator]() {
|
|
952
|
+
watch(this, ANY);
|
|
953
|
+
return from[Symbol.iterator]();
|
|
954
|
+
},
|
|
955
|
+
}, from instanceof Set
|
|
956
|
+
? {
|
|
1008
957
|
add(key) {
|
|
1009
|
-
|
|
958
|
+
from.add(key);
|
|
1010
959
|
emit(key);
|
|
1011
960
|
return this;
|
|
1012
961
|
}
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
assign(this, {
|
|
962
|
+
}
|
|
963
|
+
: {
|
|
1016
964
|
get(key) {
|
|
1017
|
-
|
|
1018
|
-
return
|
|
965
|
+
watch(this, ANY);
|
|
966
|
+
return from.get(key);
|
|
1019
967
|
},
|
|
1020
968
|
set(key, value) {
|
|
1021
|
-
|
|
969
|
+
from.set(key, value);
|
|
1022
970
|
emit(key);
|
|
1023
971
|
return this;
|
|
1024
972
|
}
|
|
1025
973
|
});
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
this.emit(key);
|
|
1035
|
-
return this.source.delete(key);
|
|
1036
|
-
}
|
|
1037
|
-
;
|
|
1038
|
-
clear() {
|
|
1039
|
-
this.emit(ANY);
|
|
1040
|
-
this.source.clear();
|
|
1041
|
-
}
|
|
1042
|
-
keys() {
|
|
1043
|
-
this.watch(ANY);
|
|
1044
|
-
return this.source.keys();
|
|
1045
|
-
}
|
|
1046
|
-
values() {
|
|
1047
|
-
this.watch(ANY);
|
|
1048
|
-
return this.source.values();
|
|
1049
|
-
}
|
|
1050
|
-
entries() {
|
|
1051
|
-
this.watch(ANY);
|
|
1052
|
-
return this.source.entries();
|
|
1053
|
-
}
|
|
1054
|
-
;
|
|
1055
|
-
get size() {
|
|
1056
|
-
this.watch(ANY);
|
|
1057
|
-
return this.source.size;
|
|
1058
|
-
}
|
|
1059
|
-
[Symbol.iterator]() {
|
|
1060
|
-
this.watch(ANY);
|
|
1061
|
-
return this.source[Symbol.iterator]();
|
|
1062
|
-
}
|
|
1063
|
-
;
|
|
974
|
+
defineProperty(proxy, "size", {
|
|
975
|
+
get() {
|
|
976
|
+
watch(this, ANY);
|
|
977
|
+
return from.size;
|
|
978
|
+
}
|
|
979
|
+
});
|
|
980
|
+
return proxy;
|
|
981
|
+
};
|
|
1064
982
|
}
|
|
1065
983
|
|
|
1066
|
-
const
|
|
984
|
+
const Parent = new WeakMap();
|
|
985
|
+
const Oops$6 = issues({
|
|
1067
986
|
BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
|
|
987
|
+
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
1068
988
|
});
|
|
1069
989
|
function use$1(input, argument) {
|
|
1070
990
|
return apply(function use(key) {
|
|
1071
991
|
const { state, subject } = this;
|
|
992
|
+
const required = argument !== false;
|
|
993
|
+
let pending;
|
|
994
|
+
let error;
|
|
995
|
+
let get = (_local) => state.get(key);
|
|
1072
996
|
if (typeof input === "function")
|
|
1073
|
-
input =
|
|
1074
|
-
? new input()
|
|
1075
|
-
: input();
|
|
997
|
+
input = /^[A-Z]/.test(input.name)
|
|
998
|
+
? new input() : input;
|
|
1076
999
|
else if (input && typeof input !== "object")
|
|
1077
|
-
throw Oops$
|
|
1000
|
+
throw Oops$6.BadArgument(typeof input);
|
|
1078
1001
|
if (input instanceof Map || input instanceof Set)
|
|
1079
1002
|
return keyed(this, key, input);
|
|
1080
|
-
|
|
1003
|
+
const onUpdate = (next) => {
|
|
1081
1004
|
state.set(key, next);
|
|
1082
1005
|
if (next) {
|
|
1006
|
+
get = getRecursive(key, this);
|
|
1083
1007
|
Parent.set(next, subject);
|
|
1084
1008
|
ensure(next);
|
|
1085
1009
|
}
|
|
1086
1010
|
if (typeof argument == "function")
|
|
1087
1011
|
argument(next);
|
|
1088
1012
|
return true;
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1013
|
+
};
|
|
1014
|
+
const suspend = () => {
|
|
1015
|
+
if (required === false)
|
|
1016
|
+
return;
|
|
1017
|
+
const issue = Oops$6.NotReady(subject, key);
|
|
1018
|
+
Object.assign(pending, {
|
|
1019
|
+
message: issue.message,
|
|
1020
|
+
stack: issue.stack
|
|
1021
|
+
});
|
|
1022
|
+
throw pending;
|
|
1023
|
+
};
|
|
1024
|
+
const initialize = () => {
|
|
1025
|
+
const output = typeof input == "function" ?
|
|
1026
|
+
mayRetry(() => input.call(subject, subject)) :
|
|
1027
|
+
input;
|
|
1028
|
+
if (output instanceof Promise) {
|
|
1029
|
+
pending = output
|
|
1030
|
+
.catch(err => error = err)
|
|
1031
|
+
.then(val => {
|
|
1032
|
+
onUpdate(val);
|
|
1033
|
+
return val;
|
|
1034
|
+
})
|
|
1035
|
+
.finally(() => {
|
|
1036
|
+
pending = undefined;
|
|
1037
|
+
this.update(key);
|
|
1038
|
+
});
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
onUpdate(output);
|
|
1042
|
+
};
|
|
1043
|
+
if (input !== undefined && required)
|
|
1044
|
+
initialize();
|
|
1092
1045
|
return {
|
|
1093
1046
|
set: onUpdate,
|
|
1094
|
-
|
|
1047
|
+
get(local) {
|
|
1048
|
+
if (pending)
|
|
1049
|
+
return suspend();
|
|
1050
|
+
if (error)
|
|
1051
|
+
throw error;
|
|
1052
|
+
if (!state.has(key))
|
|
1053
|
+
initialize();
|
|
1054
|
+
if (pending)
|
|
1055
|
+
return suspend();
|
|
1056
|
+
return get(local);
|
|
1057
|
+
}
|
|
1095
1058
|
};
|
|
1096
1059
|
});
|
|
1097
1060
|
}
|
|
1098
1061
|
|
|
1062
|
+
const Oops$5 = issues({
|
|
1063
|
+
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
1064
|
+
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
1065
|
+
});
|
|
1066
|
+
function has(Expects, required) {
|
|
1067
|
+
return apply(function parent() {
|
|
1068
|
+
const child = this.subject;
|
|
1069
|
+
const value = Parent.get(child);
|
|
1070
|
+
const expected = Expects.name;
|
|
1071
|
+
if (!value) {
|
|
1072
|
+
if (required !== false)
|
|
1073
|
+
throw Oops$5.Required(expected, child);
|
|
1074
|
+
}
|
|
1075
|
+
else if (!(value instanceof Expects))
|
|
1076
|
+
throw Oops$5.Unexpected(expected, child, value);
|
|
1077
|
+
return { value };
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1099
1081
|
class Lookup {
|
|
1100
1082
|
constructor() {
|
|
1101
1083
|
this.table = new Map();
|
|
@@ -1380,12 +1362,12 @@ class MVC extends Model {
|
|
|
1380
1362
|
});
|
|
1381
1363
|
return instance;
|
|
1382
1364
|
}, []);
|
|
1383
|
-
usePeerContext(instance.
|
|
1365
|
+
usePeerContext(instance.is);
|
|
1384
1366
|
return instance;
|
|
1385
1367
|
}
|
|
1386
1368
|
static use(a, b) {
|
|
1387
1369
|
const instance = useModel(this, a, b);
|
|
1388
|
-
usePeerContext(instance.
|
|
1370
|
+
usePeerContext(instance.is);
|
|
1389
1371
|
return instance;
|
|
1390
1372
|
}
|
|
1391
1373
|
/**
|
|
@@ -1519,5 +1501,5 @@ class Global extends MVC {
|
|
|
1519
1501
|
}
|
|
1520
1502
|
}
|
|
1521
1503
|
|
|
1522
|
-
export { CONTROL, Consumer, Global, LOCAL, MVC as Model, Provider, STATE, WHY, act, apply,
|
|
1504
|
+
export { CONTROL, Consumer, Global, LOCAL, MVC as Model, Provider, STATE, WHY, act, apply, MVC as default, get, has, ref, set, tap, use$1 as use, useFrom, useLocal, useModel, useTap };
|
|
1523
1505
|
//# sourceMappingURL=index.esm.js.map
|