@expressive/mvc 0.72.0 → 0.73.1
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/esm/context.d.ts +62 -0
- package/dist/esm/context.js +151 -163
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.js +9 -23
- package/dist/esm/instruction/get.d.ts +36 -0
- package/dist/esm/instruction/get.js +75 -79
- package/dist/esm/instruction/ref.d.ts +71 -0
- package/dist/esm/instruction/ref.js +65 -66
- package/dist/esm/instruction/set.d.ts +69 -0
- package/dist/esm/instruction/set.js +113 -131
- package/dist/esm/instruction/use.d.ts +23 -0
- package/dist/esm/instruction/use.js +48 -55
- package/dist/esm/observable.d.ts +42 -0
- package/dist/esm/observable.js +121 -0
- package/dist/esm/state.d.ts +234 -0
- package/dist/esm/state.js +267 -298
- package/dist/index.d.ts +322 -332
- package/dist/index.js +820 -931
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
- package/dist/esm/control.js +0 -136
package/dist/index.js
CHANGED
|
@@ -1,983 +1,872 @@
|
|
|
1
|
-
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key2 of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key2) && key2 !== except)
|
|
14
|
-
__defProp(to, key2, { get: () => from[key2], enumerable: !(desc = __getOwnPropDesc(from, key2)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/index.ts
|
|
21
|
-
var index_exports = {};
|
|
22
|
-
__export(index_exports, {
|
|
23
|
-
Context: () => Context,
|
|
24
|
-
METHOD: () => METHOD,
|
|
25
|
-
Observable: () => Observable,
|
|
26
|
-
State: () => State,
|
|
27
|
-
addListener: () => addListener,
|
|
28
|
-
default: () => State,
|
|
29
|
-
event: () => event,
|
|
30
|
-
get: () => get,
|
|
31
|
-
ref: () => ref,
|
|
32
|
-
set: () => set,
|
|
33
|
-
use: () => use,
|
|
34
|
-
watch: () => watch
|
|
35
|
-
});
|
|
36
|
-
module.exports = __toCommonJS(index_exports);
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
37
2
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
3
|
+
//#region src/observable.ts
|
|
4
|
+
const Observable = Symbol("observe");
|
|
5
|
+
/** Placeholder event determines if state is initialized or not. */
|
|
6
|
+
const onReady = () => null;
|
|
7
|
+
const LISTENERS = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
/** Events pending for a given object. */
|
|
9
|
+
const PENDING = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
/** Update register. */
|
|
11
|
+
const PENDING_KEYS = /* @__PURE__ */ new WeakMap();
|
|
12
|
+
/** Central event dispatch. Bunches all updates to occur at same time. */
|
|
13
|
+
const DISPATCH = /* @__PURE__ */ new Set();
|
|
45
14
|
function addListener(subject, callback, select) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
callback.call(subject, true, subject);
|
|
53
|
-
}
|
|
54
|
-
listeners.set(callback, select);
|
|
55
|
-
return () => listeners.delete(callback);
|
|
15
|
+
let listeners = LISTENERS.get(subject);
|
|
16
|
+
if (!listeners) LISTENERS.set(subject, listeners = new Map([[onReady, void 0]]));
|
|
17
|
+
if (select !== void 0 && !(select instanceof Set)) select = new Set([select]);
|
|
18
|
+
if (!listeners.has(onReady) && !select) callback.call(subject, true, subject);
|
|
19
|
+
listeners.set(callback, select);
|
|
20
|
+
return () => listeners.delete(callback);
|
|
56
21
|
}
|
|
57
|
-
function emit(state,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
listeners.delete(callback);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if (key2 === null) listeners.clear();
|
|
78
|
-
PENDING.delete(state);
|
|
22
|
+
function emit(state, key) {
|
|
23
|
+
const listeners = LISTENERS.get(state);
|
|
24
|
+
const notReady = listeners.has(onReady);
|
|
25
|
+
if (key === true && !notReady) return;
|
|
26
|
+
let pending = PENDING.get(state);
|
|
27
|
+
if (pending) {
|
|
28
|
+
pending.add(key);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
PENDING.set(state, pending = new Set(notReady ? [true, key] : [key]));
|
|
32
|
+
for (const key of pending) for (const [callback, filter] of listeners) if (!filter || filter.has(key)) {
|
|
33
|
+
const after = callback.call(state, key, state);
|
|
34
|
+
if (after) enqueue(after);
|
|
35
|
+
else if (after === null) listeners.delete(callback);
|
|
36
|
+
}
|
|
37
|
+
if (key === null) listeners.clear();
|
|
38
|
+
PENDING.delete(state);
|
|
79
39
|
}
|
|
80
|
-
function event(subject,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (!silent) emit(subject, key2);
|
|
40
|
+
function event(subject, key, silent) {
|
|
41
|
+
if (key === null) return emit(subject, key);
|
|
42
|
+
if (!key) return emit(subject, true);
|
|
43
|
+
let pending = PENDING_KEYS.get(subject);
|
|
44
|
+
if (!pending) {
|
|
45
|
+
PENDING_KEYS.set(subject, pending = /* @__PURE__ */ new Set());
|
|
46
|
+
if (!silent) enqueue(() => {
|
|
47
|
+
emit(subject, false);
|
|
48
|
+
PENDING_KEYS.delete(subject);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
pending.add(key);
|
|
52
|
+
if (!silent) emit(subject, key);
|
|
94
53
|
}
|
|
95
54
|
function enqueue(eventHandler) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
DISPATCH.add(eventHandler);
|
|
55
|
+
if (!DISPATCH.size) setTimeout(() => {
|
|
56
|
+
DISPATCH.forEach((event) => {
|
|
57
|
+
try {
|
|
58
|
+
event();
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error(err);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
DISPATCH.clear();
|
|
64
|
+
}, 0);
|
|
65
|
+
DISPATCH.add(eventHandler);
|
|
108
66
|
}
|
|
109
67
|
function watch(target, callback, argument) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
});
|
|
153
|
-
return cleanup;
|
|
68
|
+
let unset;
|
|
69
|
+
let reset;
|
|
70
|
+
function invoke() {
|
|
71
|
+
let ignore = true;
|
|
72
|
+
function onUpdate() {
|
|
73
|
+
if (ignore || reset === null) return;
|
|
74
|
+
ignore = true;
|
|
75
|
+
if (reset && unset) {
|
|
76
|
+
unset(true);
|
|
77
|
+
unset = void 0;
|
|
78
|
+
}
|
|
79
|
+
enqueue(invoke);
|
|
80
|
+
return { then: enqueue };
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const exit = argument === false ? void 0 : scope();
|
|
84
|
+
const output = callback(target[Observable](onUpdate, argument === true));
|
|
85
|
+
const flush = exit ? exit() : () => {};
|
|
86
|
+
ignore = false;
|
|
87
|
+
reset = output === null ? null : invoke;
|
|
88
|
+
unset = (key) => {
|
|
89
|
+
if (typeof output == "function") output(key);
|
|
90
|
+
flush();
|
|
91
|
+
};
|
|
92
|
+
} catch (err) {
|
|
93
|
+
if (err instanceof Promise) {
|
|
94
|
+
reset = void 0;
|
|
95
|
+
err.then(invoke);
|
|
96
|
+
} else throw err;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function cleanup() {
|
|
100
|
+
if (unset) unset(false);
|
|
101
|
+
reset = null;
|
|
102
|
+
}
|
|
103
|
+
if (EffectContext && argument !== false) EffectContext.add(cleanup);
|
|
104
|
+
addListener(target, (key) => {
|
|
105
|
+
if (key === true) invoke();
|
|
106
|
+
else if (!reset) return reset;
|
|
107
|
+
if (key === null && unset) unset(null);
|
|
108
|
+
});
|
|
109
|
+
return cleanup;
|
|
154
110
|
}
|
|
155
|
-
|
|
156
|
-
function
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
return () => context.forEach((fn) => fn());
|
|
164
|
-
};
|
|
111
|
+
let EffectContext;
|
|
112
|
+
function scope() {
|
|
113
|
+
const last = EffectContext;
|
|
114
|
+
const context = EffectContext = /* @__PURE__ */ new Set();
|
|
115
|
+
return () => {
|
|
116
|
+
EffectContext = last;
|
|
117
|
+
return () => context.forEach((fn) => fn());
|
|
118
|
+
};
|
|
165
119
|
}
|
|
166
120
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/state.ts
|
|
123
|
+
const define = Object.defineProperty;
|
|
124
|
+
/** Register for all active states via string identifiers (usually unique). */
|
|
125
|
+
const ID = /* @__PURE__ */ new WeakMap();
|
|
126
|
+
/** Internal state assigned to states. */
|
|
127
|
+
const STATE = /* @__PURE__ */ new WeakMap();
|
|
128
|
+
/** External listeners for any given State. */
|
|
129
|
+
const NOTIFY = /* @__PURE__ */ new WeakMap();
|
|
130
|
+
/** Parent-child relationships. */
|
|
131
|
+
const PARENT = /* @__PURE__ */ new WeakMap();
|
|
132
|
+
/** List of methods defined by a given type. */
|
|
133
|
+
const METHODS = /* @__PURE__ */ new WeakMap();
|
|
134
|
+
/** Reference bound instance methods to real ones. */
|
|
135
|
+
const METHOD = /* @__PURE__ */ new WeakMap();
|
|
136
|
+
/** Currently accumulating export. Stores real values of placeholder properties such as ref() or child states. */
|
|
137
|
+
let EXPORT;
|
|
176
138
|
var State = class {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
* If so, language server will make available all static
|
|
261
|
-
* methods and properties of this class.
|
|
262
|
-
*/
|
|
263
|
-
static is(maybe) {
|
|
264
|
-
return maybe === this || typeof maybe == "function" && maybe.prototype instanceof this;
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* Register a callback to run when any instance of this State is updated.
|
|
268
|
-
*/
|
|
269
|
-
static on(listener) {
|
|
270
|
-
let notify = NOTIFY.get(this);
|
|
271
|
-
if (!notify) NOTIFY.set(this, notify = /* @__PURE__ */ new Set());
|
|
272
|
-
notify.add(listener);
|
|
273
|
-
return () => notify.delete(listener);
|
|
274
|
-
}
|
|
139
|
+
constructor(...args) {
|
|
140
|
+
prepare(this);
|
|
141
|
+
define(this, "is", { value: this });
|
|
142
|
+
init$1(this, ...args, (x) => x.new && x.new());
|
|
143
|
+
}
|
|
144
|
+
[Observable](callback, required) {
|
|
145
|
+
const watch = /* @__PURE__ */ new Set();
|
|
146
|
+
const proxy = Object.create(this);
|
|
147
|
+
addListener(this, (key) => {
|
|
148
|
+
if (watch.has(key)) callback();
|
|
149
|
+
});
|
|
150
|
+
OBSERVER.set(proxy, (key, value) => {
|
|
151
|
+
if (value === void 0 && required) throw new Error(`${this}.${key} is required in this context.`);
|
|
152
|
+
watch.add(key);
|
|
153
|
+
if (value instanceof Object && Observable in value) return value[Observable](callback, required) || value;
|
|
154
|
+
return value;
|
|
155
|
+
});
|
|
156
|
+
return proxy;
|
|
157
|
+
}
|
|
158
|
+
get(arg1, arg2) {
|
|
159
|
+
const self = this.is;
|
|
160
|
+
if (arg1 === void 0) return values(self);
|
|
161
|
+
if (typeof arg1 == "function") return effect(self, arg1);
|
|
162
|
+
if (typeof arg2 == "function") return addListener(self, arg2, arg1);
|
|
163
|
+
if (arg1 === null) return Object.isFrozen(STATE.get(self));
|
|
164
|
+
return access(self, arg1, arg2);
|
|
165
|
+
}
|
|
166
|
+
set(arg1, arg2, arg3) {
|
|
167
|
+
const self = this.is;
|
|
168
|
+
if (typeof arg1 == "function") return addListener(self, (key) => {
|
|
169
|
+
if (arg2 === key || arg2 === void 0 && typeof key == "string") return arg1.call(self, key, self);
|
|
170
|
+
});
|
|
171
|
+
if (arg1 && typeof arg1 == "object") assign(self, arg1, arg2 === true);
|
|
172
|
+
else if (!arg2) event(self, arg1);
|
|
173
|
+
else if (arg3) manage(self, arg1, arg2);
|
|
174
|
+
else update(self, arg1, arg2);
|
|
175
|
+
const pending = PENDING_KEYS.get(this);
|
|
176
|
+
if (pending) return { then: (resolve) => new Promise((res) => {
|
|
177
|
+
const remove = addListener(this, (key) => {
|
|
178
|
+
if (key !== true) {
|
|
179
|
+
remove();
|
|
180
|
+
return () => res(Array.from(pending));
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}).then(resolve) };
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Iterate over managed properties in this instance of State.
|
|
187
|
+
* Yeilds the key and current value for each property.
|
|
188
|
+
*/
|
|
189
|
+
[Symbol.iterator]() {
|
|
190
|
+
return Object.entries(STATE.get(this.is))[Symbol.iterator]();
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Create and activate a new instance of this state.
|
|
194
|
+
*
|
|
195
|
+
* **Important** - Unlike `new this(...)` - this method also activates state.
|
|
196
|
+
*
|
|
197
|
+
* @param args - arguments sent to constructor
|
|
198
|
+
*/
|
|
199
|
+
static new(...args) {
|
|
200
|
+
const instance = new this(...args);
|
|
201
|
+
event(instance);
|
|
202
|
+
return instance;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Static equivalent of `x instanceof this`.
|
|
206
|
+
* Determines if provided class is a subtype of this one.
|
|
207
|
+
* If so, language server will make available all static
|
|
208
|
+
* methods and properties of this class.
|
|
209
|
+
*/
|
|
210
|
+
static is(maybe) {
|
|
211
|
+
return maybe === this || typeof maybe == "function" && maybe.prototype instanceof this;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Register a callback to run when any instance of this State is updated.
|
|
215
|
+
*/
|
|
216
|
+
static on(listener) {
|
|
217
|
+
let notify = NOTIFY.get(this);
|
|
218
|
+
if (!notify) NOTIFY.set(this, notify = /* @__PURE__ */ new Set());
|
|
219
|
+
notify.add(listener);
|
|
220
|
+
return () => notify.delete(listener);
|
|
221
|
+
}
|
|
275
222
|
};
|
|
276
|
-
define(State.prototype, "toString", {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
value() {
|
|
283
|
-
return this.name;
|
|
284
|
-
}
|
|
285
|
-
});
|
|
223
|
+
define(State.prototype, "toString", { value() {
|
|
224
|
+
return ID.get(this.is);
|
|
225
|
+
} });
|
|
226
|
+
define(State, "toString", { value() {
|
|
227
|
+
return this.name;
|
|
228
|
+
} });
|
|
286
229
|
function assign(subject, data, silent) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
230
|
+
const methods = METHODS.get(subject.constructor);
|
|
231
|
+
for (const key in data) {
|
|
232
|
+
const bind = methods.get(key);
|
|
233
|
+
if (bind) bind.call(subject, data[key]);
|
|
234
|
+
else if (key in subject && key !== "is") {
|
|
235
|
+
const desc = Object.getOwnPropertyDescriptor(subject, key);
|
|
236
|
+
const set = desc && desc.set;
|
|
237
|
+
if (set) set.call(subject, data[key], silent);
|
|
238
|
+
else subject[key] = data[key];
|
|
239
|
+
}
|
|
240
|
+
}
|
|
301
241
|
}
|
|
242
|
+
/** Apply instructions and inherited event listeners. Ensure class metadata is ready. */
|
|
302
243
|
function prepare(state) {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
244
|
+
let T = state.constructor;
|
|
245
|
+
if (T === State) throw new Error("Cannot create base State.");
|
|
246
|
+
const chain = [];
|
|
247
|
+
let keys = /* @__PURE__ */ new Map();
|
|
248
|
+
ID.set(state, `${T}-${uid()}`);
|
|
249
|
+
while (T.name) {
|
|
250
|
+
for (const cb of NOTIFY.get(T) || []) addListener(state, cb);
|
|
251
|
+
if (T === State) break;
|
|
252
|
+
else chain.unshift(T);
|
|
253
|
+
T = Object.getPrototypeOf(T);
|
|
254
|
+
}
|
|
255
|
+
for (const type of chain) {
|
|
256
|
+
if (METHODS.has(type)) {
|
|
257
|
+
keys = METHODS.get(type);
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
METHODS.set(type, keys = new Map(keys));
|
|
261
|
+
for (const [key, { value }] of Object.entries(Object.getOwnPropertyDescriptors(type.prototype))) {
|
|
262
|
+
if (!value || key == "constructor") continue;
|
|
263
|
+
function bind(original) {
|
|
264
|
+
const { is } = this;
|
|
265
|
+
if (is.hasOwnProperty(key) && !original) return value;
|
|
266
|
+
const fn = original || value;
|
|
267
|
+
const bound = fn.bind(is);
|
|
268
|
+
METHOD.set(bound, fn);
|
|
269
|
+
define(is, key, {
|
|
270
|
+
value: bound,
|
|
271
|
+
writable: true
|
|
272
|
+
});
|
|
273
|
+
return bound;
|
|
274
|
+
}
|
|
275
|
+
keys.set(key, bind);
|
|
276
|
+
define(type.prototype, key, {
|
|
277
|
+
get: bind,
|
|
278
|
+
set: bind
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
340
282
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
283
|
+
/**
|
|
284
|
+
* Apply state arguemnts, run callbacks and observe properties.
|
|
285
|
+
* Accumulate and handle cleanup events.
|
|
286
|
+
**/
|
|
287
|
+
function init$1(self, ...args) {
|
|
288
|
+
const state = {};
|
|
289
|
+
STATE.set(self, state);
|
|
290
|
+
args = args.flat().filter((arg) => {
|
|
291
|
+
if (typeof arg == "string") ID.set(self, arg);
|
|
292
|
+
else return true;
|
|
293
|
+
});
|
|
294
|
+
addListener(self, () => {
|
|
295
|
+
if (!PARENT.has(self)) PARENT.set(self, null);
|
|
296
|
+
for (const key in self) {
|
|
297
|
+
const desc = Object.getOwnPropertyDescriptor(self, key);
|
|
298
|
+
if ("value" in desc) manage(self, key, desc.value, true);
|
|
299
|
+
}
|
|
300
|
+
for (const arg of args) {
|
|
301
|
+
const use = typeof arg == "function" ? arg.call(self, self) : arg;
|
|
302
|
+
if (use instanceof Promise) use.catch((err) => {
|
|
303
|
+
console.error(`Async error in constructor for ${self}:`);
|
|
304
|
+
console.error(err);
|
|
305
|
+
});
|
|
306
|
+
else if (Array.isArray(use)) args.push(...use);
|
|
307
|
+
else if (typeof use == "function") addListener(self, use, null);
|
|
308
|
+
else if (typeof use == "object") assign(self, use, true);
|
|
309
|
+
}
|
|
310
|
+
addListener(self, () => {
|
|
311
|
+
for (const [_, value] of self) if (value instanceof State && PARENT.get(value) === self) value.set(null);
|
|
312
|
+
Object.freeze(state);
|
|
313
|
+
}, null);
|
|
314
|
+
return null;
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
function manage(target, key, value, silent) {
|
|
318
|
+
const state = STATE.get(target);
|
|
319
|
+
function get() {
|
|
320
|
+
return follow(this, key, state[key]);
|
|
321
|
+
}
|
|
322
|
+
function set(value, silent) {
|
|
323
|
+
update(target, key, value, silent);
|
|
324
|
+
if (value instanceof State && !PARENT.has(value)) {
|
|
325
|
+
PARENT.set(value, target);
|
|
326
|
+
event(value);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
define(target, key, {
|
|
330
|
+
set,
|
|
331
|
+
get
|
|
332
|
+
});
|
|
333
|
+
set(value, silent);
|
|
377
334
|
}
|
|
378
335
|
function effect(target, fn) {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
336
|
+
const effect = METHOD.get(fn) || fn;
|
|
337
|
+
let pending = /* @__PURE__ */ new Set();
|
|
338
|
+
return watch(target, (proxy) => {
|
|
339
|
+
const cb = effect.call(proxy, proxy, pending);
|
|
340
|
+
if (cb === null) return cb;
|
|
341
|
+
return (update) => {
|
|
342
|
+
pending = PENDING_KEYS.get(target);
|
|
343
|
+
if (typeof cb == "function") cb(update);
|
|
344
|
+
};
|
|
345
|
+
});
|
|
389
346
|
}
|
|
390
347
|
function values(target) {
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
return Object.freeze(values2);
|
|
405
|
-
}
|
|
406
|
-
function manage(target, key2, value, silent) {
|
|
407
|
-
const state = STATE.get(target);
|
|
408
|
-
function get2() {
|
|
409
|
-
return follow(this, key2, state[key2]);
|
|
410
|
-
}
|
|
411
|
-
function set2(value2, silent2) {
|
|
412
|
-
update(target, key2, value2, silent2);
|
|
413
|
-
if (value2 instanceof State && !PARENT.has(value2)) {
|
|
414
|
-
PARENT.set(value2, target);
|
|
415
|
-
event(value2);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
define(target, key2, { set: set2, get: get2 });
|
|
419
|
-
set2(value, silent);
|
|
348
|
+
const values = {};
|
|
349
|
+
let isNotRecursive;
|
|
350
|
+
if (!EXPORT) {
|
|
351
|
+
isNotRecursive = true;
|
|
352
|
+
EXPORT = new Map([[target, values]]);
|
|
353
|
+
}
|
|
354
|
+
for (let [key, value] of target) {
|
|
355
|
+
if (EXPORT.has(value)) value = EXPORT.get(value);
|
|
356
|
+
else if (value && typeof value == "object" && "get" in value && typeof value.get === "function") EXPORT.set(value, value = value.get());
|
|
357
|
+
values[key] = value;
|
|
358
|
+
}
|
|
359
|
+
if (isNotRecursive) EXPORT = void 0;
|
|
360
|
+
return Object.freeze(values);
|
|
420
361
|
}
|
|
421
|
-
|
|
422
|
-
function follow(from,
|
|
423
|
-
|
|
424
|
-
|
|
362
|
+
const OBSERVER = /* @__PURE__ */ new WeakMap();
|
|
363
|
+
function follow(from, key, value) {
|
|
364
|
+
const observe = OBSERVER.get(from);
|
|
365
|
+
return observe ? observe(key, value) : value;
|
|
425
366
|
}
|
|
426
367
|
function access(subject, property, required) {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
message: error.message,
|
|
450
|
-
stack: error.stack
|
|
451
|
-
});
|
|
368
|
+
const state = STATE.get(subject);
|
|
369
|
+
if (property in state || required === false) {
|
|
370
|
+
const value = state[property];
|
|
371
|
+
if (value !== void 0 || !required) return value;
|
|
372
|
+
}
|
|
373
|
+
if (METHODS.get(subject.constructor).has(property)) return METHOD.get(subject[property]);
|
|
374
|
+
const error = /* @__PURE__ */ new Error(`${subject}.${property} is not yet available.`);
|
|
375
|
+
const promise = new Promise((resolve, reject) => {
|
|
376
|
+
addListener(subject, (key) => {
|
|
377
|
+
if (key === property) {
|
|
378
|
+
resolve(state[key]);
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
if (key === null) reject(/* @__PURE__ */ new Error(`${subject} is destroyed.`));
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
throw Object.assign(promise, {
|
|
385
|
+
toString: () => String(error),
|
|
386
|
+
name: "Suspense",
|
|
387
|
+
message: error.message,
|
|
388
|
+
stack: error.stack
|
|
389
|
+
});
|
|
452
390
|
}
|
|
453
|
-
function update(subject,
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
state[key2] = value;
|
|
467
|
-
if (arg !== true) event(subject, key2);
|
|
468
|
-
return true;
|
|
391
|
+
function update(subject, key, value, arg) {
|
|
392
|
+
const state = STATE.get(subject);
|
|
393
|
+
if (Object.isFrozen(state)) throw new Error(`Tried to update ${subject}.${String(key)} but state is destroyed.`);
|
|
394
|
+
const previous = state[key];
|
|
395
|
+
if (typeof arg == "function") {
|
|
396
|
+
const out = arg.call(subject, value, previous);
|
|
397
|
+
if (out === false) return false;
|
|
398
|
+
if (typeof out == "function") value = out();
|
|
399
|
+
}
|
|
400
|
+
if (value === previous && key in state) return;
|
|
401
|
+
state[key] = value;
|
|
402
|
+
if (arg !== true) event(subject, key);
|
|
403
|
+
return true;
|
|
469
404
|
}
|
|
405
|
+
/** Random alphanumberic of length 6; always starts with a letter. */
|
|
470
406
|
function uid() {
|
|
471
|
-
|
|
407
|
+
return (.278 + Math.random() * .722).toString(36).substring(2, 8).toUpperCase();
|
|
472
408
|
}
|
|
473
409
|
|
|
474
|
-
|
|
475
|
-
|
|
410
|
+
//#endregion
|
|
411
|
+
//#region src/instruction/use.ts
|
|
412
|
+
const INSTRUCTION = /* @__PURE__ */ new Map();
|
|
476
413
|
function use(arg1, arg2) {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
414
|
+
if (State.is(arg1)) arg1 = childInstruction(arg1, arg2);
|
|
415
|
+
const token = Symbol("instruction-" + uid());
|
|
416
|
+
INSTRUCTION.set(token, arg1);
|
|
417
|
+
return token;
|
|
481
418
|
}
|
|
482
419
|
function childInstruction(type, arg2) {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
value.set();
|
|
497
|
-
return { set: set2 };
|
|
498
|
-
};
|
|
420
|
+
return (key, subject) => {
|
|
421
|
+
function set(next) {
|
|
422
|
+
if (next ? !(next instanceof type) : arg2 !== false) throw new Error(`${subject}.${key} expected State of type ${type} but got ${next && next.constructor}.`);
|
|
423
|
+
update(subject, key, next);
|
|
424
|
+
if (next && typeof arg2 == "function") arg2(next);
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
const value = new type();
|
|
428
|
+
set(value);
|
|
429
|
+
PARENT.set(value, subject);
|
|
430
|
+
value.set();
|
|
431
|
+
return { set };
|
|
432
|
+
};
|
|
499
433
|
}
|
|
500
|
-
function
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
}
|
|
526
|
-
update(self, key2, next, desc.set);
|
|
527
|
-
}
|
|
528
|
-
});
|
|
529
|
-
}
|
|
530
|
-
return null;
|
|
434
|
+
function init() {
|
|
435
|
+
const state = STATE.get(this);
|
|
436
|
+
for (const key in this) {
|
|
437
|
+
const { value } = Object.getOwnPropertyDescriptor(this, key);
|
|
438
|
+
const instruction = INSTRUCTION.get(value);
|
|
439
|
+
if (!instruction) continue;
|
|
440
|
+
INSTRUCTION.delete(value);
|
|
441
|
+
delete this[key];
|
|
442
|
+
const output = instruction.call(this, key, this, state);
|
|
443
|
+
if (!output) continue;
|
|
444
|
+
const desc = typeof output == "object" ? output : { get: output };
|
|
445
|
+
if ("value" in desc) state[key] = desc.value;
|
|
446
|
+
const self = this;
|
|
447
|
+
Object.defineProperty(self, key, {
|
|
448
|
+
enumerable: desc.enumerable !== false,
|
|
449
|
+
get() {
|
|
450
|
+
return follow(this, key, typeof desc.get == "function" ? desc.get(this) : access(self, key, desc.get));
|
|
451
|
+
},
|
|
452
|
+
set(next) {
|
|
453
|
+
if (desc.set === false) throw new Error(`${self}.${key} is read-only.`);
|
|
454
|
+
update(self, key, next, desc.set);
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
return null;
|
|
531
459
|
}
|
|
532
|
-
State.on(
|
|
460
|
+
State.on(init);
|
|
533
461
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
462
|
+
//#endregion
|
|
463
|
+
//#region src/context.ts
|
|
464
|
+
const LOOKUP = /* @__PURE__ */ new WeakMap();
|
|
465
|
+
const KEYS = /* @__PURE__ */ new Map();
|
|
537
466
|
function key(T, upstream) {
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
467
|
+
let K = KEYS.get(T);
|
|
468
|
+
if (!K) {
|
|
469
|
+
K = Symbol(typeof T == "symbol" ? "get " + T.description : String(T));
|
|
470
|
+
KEYS.set(T, K);
|
|
471
|
+
}
|
|
472
|
+
return upstream ? key(K) : K;
|
|
544
473
|
}
|
|
545
474
|
function keys(from, upstream) {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
475
|
+
const keys = /* @__PURE__ */ new Set();
|
|
476
|
+
do {
|
|
477
|
+
keys.add(key(from, upstream));
|
|
478
|
+
from = Object.getPrototypeOf(from);
|
|
479
|
+
} while (from !== State);
|
|
480
|
+
return keys;
|
|
552
481
|
}
|
|
553
|
-
var Context = class
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
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
|
-
}
|
|
682
|
-
/**
|
|
683
|
-
* Remove all States from this context.
|
|
684
|
-
*
|
|
685
|
-
* Will also run any cleanup callbacks registered when States were added.
|
|
686
|
-
*/
|
|
687
|
-
pop() {
|
|
688
|
-
for (const key2 of Object.getOwnPropertySymbols(this)) delete this[key2];
|
|
689
|
-
this.cleanup.forEach((cb) => cb());
|
|
690
|
-
this.cleanup.clear();
|
|
691
|
-
this.inputs = {};
|
|
692
|
-
}
|
|
482
|
+
var Context = class Context {
|
|
483
|
+
static get({ is }, callback) {
|
|
484
|
+
const context = LOOKUP.get(is);
|
|
485
|
+
if (context instanceof Context) {
|
|
486
|
+
if (callback) callback(context);
|
|
487
|
+
return context;
|
|
488
|
+
}
|
|
489
|
+
if (callback) if (context) context.push(callback);
|
|
490
|
+
else LOOKUP.set(is, [callback]);
|
|
491
|
+
}
|
|
492
|
+
constructor(inputs) {
|
|
493
|
+
this.id = uid();
|
|
494
|
+
this.inputs = {};
|
|
495
|
+
this.cleanup = /* @__PURE__ */ new Set();
|
|
496
|
+
if (inputs) this.use(inputs);
|
|
497
|
+
}
|
|
498
|
+
get(Type, arg2) {
|
|
499
|
+
if (typeof arg2 == "function") {
|
|
500
|
+
const k = key(Type, true);
|
|
501
|
+
Object.defineProperty(this, k, {
|
|
502
|
+
value: arg2,
|
|
503
|
+
configurable: true
|
|
504
|
+
});
|
|
505
|
+
return () => {
|
|
506
|
+
delete this[k];
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
const result = this[key(Type)];
|
|
510
|
+
if (result === null) throw new Error(`Did find ${Type} in context, but multiple were defined.`);
|
|
511
|
+
if (result) return result;
|
|
512
|
+
if (arg2) throw new Error(`Could not find ${Type} in context.`);
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Adds a State to this context.
|
|
516
|
+
*/
|
|
517
|
+
add(input, implicit) {
|
|
518
|
+
const cleanup = /* @__PURE__ */ new Set();
|
|
519
|
+
let T;
|
|
520
|
+
let I;
|
|
521
|
+
if (typeof input == "function") {
|
|
522
|
+
T = input;
|
|
523
|
+
I = new input();
|
|
524
|
+
} else {
|
|
525
|
+
T = input.constructor;
|
|
526
|
+
I = input;
|
|
527
|
+
}
|
|
528
|
+
keys(T, true).forEach((K) => {
|
|
529
|
+
const expects = this[K];
|
|
530
|
+
if (expects) addListener(I, (event) => {
|
|
531
|
+
if (event === true) {
|
|
532
|
+
const cb = expects(I);
|
|
533
|
+
if (cb) cleanup.add(cb);
|
|
534
|
+
}
|
|
535
|
+
return null;
|
|
536
|
+
});
|
|
537
|
+
});
|
|
538
|
+
keys(T).forEach((K) => {
|
|
539
|
+
const value = this.hasOwnProperty(K) ? null : I;
|
|
540
|
+
if (value || this[K] !== I && !implicit) Object.defineProperty(this, K, {
|
|
541
|
+
configurable: true,
|
|
542
|
+
value
|
|
543
|
+
});
|
|
544
|
+
});
|
|
545
|
+
this.cleanup.add(() => {
|
|
546
|
+
cleanup.forEach((cb) => cb());
|
|
547
|
+
if (I !== input) event(I, null);
|
|
548
|
+
});
|
|
549
|
+
const waiting = LOOKUP.get(I);
|
|
550
|
+
if (waiting instanceof Array) waiting.forEach((cb) => cb(this));
|
|
551
|
+
LOOKUP.set(I, this);
|
|
552
|
+
return I;
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Register one or more States to this context.
|
|
556
|
+
*
|
|
557
|
+
* Context will add or remove States as needed to keep with provided input.
|
|
558
|
+
*
|
|
559
|
+
* @param inputs State, State class, or map of States / State classes to register.
|
|
560
|
+
* @param forEach Optional callback to run for each State registered.
|
|
561
|
+
*/
|
|
562
|
+
use(inputs, forEach) {
|
|
563
|
+
const init = /* @__PURE__ */ new Map();
|
|
564
|
+
if (typeof inputs == "function" || inputs instanceof State) inputs = { [0]: inputs };
|
|
565
|
+
for (const [K, V] of Object.entries(inputs)) {
|
|
566
|
+
if (!(State.is(V) || V instanceof State)) throw new Error(`Context may only include instance or class \`extends State\` but got ${K == "0" || K == String(V) ? V : `${V} (as '${K}')`}.`);
|
|
567
|
+
const exists = this.inputs[K];
|
|
568
|
+
if (!exists) init.set(this.add(V), true);
|
|
569
|
+
else if (exists !== V) {
|
|
570
|
+
this.pop();
|
|
571
|
+
this.use(inputs);
|
|
572
|
+
this.id = uid();
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
for (const [state, explicit] of init) {
|
|
577
|
+
state.set();
|
|
578
|
+
if (explicit && forEach) forEach(state);
|
|
579
|
+
for (const [_key, value] of state) if (PARENT.get(value) === state) {
|
|
580
|
+
this.add(value, true);
|
|
581
|
+
init.set(value, false);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
this.inputs = inputs;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Create a child context, optionally registering one or more States to it.
|
|
588
|
+
*
|
|
589
|
+
* @param inputs State, State class, or map of States / State classes to register.
|
|
590
|
+
*/
|
|
591
|
+
push(inputs) {
|
|
592
|
+
const next = Object.create(this);
|
|
593
|
+
this.cleanup = new Set([() => next.pop(), ...this.cleanup]);
|
|
594
|
+
next.inputs = {};
|
|
595
|
+
next.cleanup = /* @__PURE__ */ new Set();
|
|
596
|
+
if (inputs) next.use(inputs);
|
|
597
|
+
return next;
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Remove all States from this context.
|
|
601
|
+
*
|
|
602
|
+
* Will also run any cleanup callbacks registered when States were added.
|
|
603
|
+
*/
|
|
604
|
+
pop() {
|
|
605
|
+
for (const key of Object.getOwnPropertySymbols(this)) delete this[key];
|
|
606
|
+
this.cleanup.forEach((cb) => cb());
|
|
607
|
+
this.cleanup.clear();
|
|
608
|
+
this.inputs = {};
|
|
609
|
+
}
|
|
693
610
|
};
|
|
694
|
-
Object.defineProperty(Context.prototype, "toString", {
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
}
|
|
698
|
-
});
|
|
611
|
+
Object.defineProperty(Context.prototype, "toString", { value() {
|
|
612
|
+
return `Context-${this.id}`;
|
|
613
|
+
} });
|
|
699
614
|
|
|
700
|
-
|
|
615
|
+
//#endregion
|
|
616
|
+
//#region src/instruction/get.ts
|
|
701
617
|
function get(Type, arg1, arg2) {
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
});
|
|
768
|
-
return {
|
|
769
|
-
get: !isOptional,
|
|
770
|
-
enumerable: false
|
|
771
|
-
};
|
|
772
|
-
});
|
|
618
|
+
const isDownstream = arg1 === true;
|
|
619
|
+
const isOptional = arg1 === false;
|
|
620
|
+
return use((key, subject) => {
|
|
621
|
+
if (isDownstream) {
|
|
622
|
+
const callback = typeof arg2 === "function" ? arg2 : void 0;
|
|
623
|
+
const applied = /* @__PURE__ */ new Set();
|
|
624
|
+
const reset = () => {
|
|
625
|
+
update(subject, key, Object.freeze(Array.from(applied)));
|
|
626
|
+
};
|
|
627
|
+
Context.get(subject, (context) => {
|
|
628
|
+
context.get(Type, (state) => {
|
|
629
|
+
let remove;
|
|
630
|
+
let flush;
|
|
631
|
+
if (applied.has(state)) return;
|
|
632
|
+
if (callback) {
|
|
633
|
+
const exit = scope();
|
|
634
|
+
try {
|
|
635
|
+
const done = callback(state, subject);
|
|
636
|
+
if (done === false) return false;
|
|
637
|
+
if (typeof done == "function") remove = done;
|
|
638
|
+
} finally {
|
|
639
|
+
flush = exit();
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
applied.add(state);
|
|
643
|
+
reset();
|
|
644
|
+
const done = () => {
|
|
645
|
+
if (flush) flush();
|
|
646
|
+
ignore();
|
|
647
|
+
applied.delete(state);
|
|
648
|
+
reset();
|
|
649
|
+
if (typeof remove == "function") remove();
|
|
650
|
+
remove = void 0;
|
|
651
|
+
};
|
|
652
|
+
const ignore = state.set(done, null);
|
|
653
|
+
return done;
|
|
654
|
+
});
|
|
655
|
+
});
|
|
656
|
+
return {
|
|
657
|
+
value: [],
|
|
658
|
+
enumerable: false
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
const hasParent = PARENT.get(subject);
|
|
662
|
+
function assign(value) {
|
|
663
|
+
if (typeof arg1 === "function") {
|
|
664
|
+
const result = arg1(value, subject);
|
|
665
|
+
if (typeof result === "function") subject.set(result, null);
|
|
666
|
+
}
|
|
667
|
+
update(subject, key, value);
|
|
668
|
+
}
|
|
669
|
+
if (hasParent && hasParent instanceof Type) {
|
|
670
|
+
assign(hasParent);
|
|
671
|
+
return {};
|
|
672
|
+
}
|
|
673
|
+
Context.get(subject, (context) => {
|
|
674
|
+
const self = context.get(Type);
|
|
675
|
+
if (self && self !== subject) assign(self);
|
|
676
|
+
else if (!isOptional) throw new Error(`Required ${Type} not found in context for ${subject}.`);
|
|
677
|
+
});
|
|
678
|
+
return {
|
|
679
|
+
get: !isOptional,
|
|
680
|
+
enumerable: false
|
|
681
|
+
};
|
|
682
|
+
});
|
|
773
683
|
}
|
|
774
684
|
|
|
775
|
-
|
|
776
|
-
|
|
685
|
+
//#endregion
|
|
686
|
+
//#region src/instruction/set.ts
|
|
687
|
+
const STALE = /* @__PURE__ */ new WeakSet();
|
|
777
688
|
function set(value, argument) {
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
if (typeof argument == "function") {
|
|
870
|
-
let unset;
|
|
871
|
-
property.set = function(value2, previous) {
|
|
872
|
-
const exit = enter();
|
|
873
|
-
const returns = argument.call(this, value2, previous);
|
|
874
|
-
const flush = exit();
|
|
875
|
-
if (returns === false) return false;
|
|
876
|
-
if (typeof unset == "function") unset(value2);
|
|
877
|
-
unset = (next) => {
|
|
878
|
-
if (typeof returns == "function") returns(next);
|
|
879
|
-
flush();
|
|
880
|
-
};
|
|
881
|
-
};
|
|
882
|
-
} else
|
|
883
|
-
property.set = (value2) => {
|
|
884
|
-
property.get = void 0;
|
|
885
|
-
update(subject, key2, value2);
|
|
886
|
-
};
|
|
887
|
-
return property;
|
|
888
|
-
});
|
|
689
|
+
return use((key, subject, state) => {
|
|
690
|
+
if (typeof value == "symbol") throw new Error(`Attempted to use an instruction result (probably use or get) as computed source for ${subject}.${key}. This is not allowed.`);
|
|
691
|
+
const property = {};
|
|
692
|
+
if (value instanceof State || value === true) {
|
|
693
|
+
let from = subject;
|
|
694
|
+
let getter;
|
|
695
|
+
if (value instanceof State) {
|
|
696
|
+
from = value;
|
|
697
|
+
getter = argument;
|
|
698
|
+
} else {
|
|
699
|
+
const fn = METHOD.get(argument) || argument;
|
|
700
|
+
getter = ((p, k) => fn.call(p, k, p));
|
|
701
|
+
}
|
|
702
|
+
const source = (resolve) => resolve(from);
|
|
703
|
+
let reset;
|
|
704
|
+
let isAsync;
|
|
705
|
+
let proxy;
|
|
706
|
+
function connect(self) {
|
|
707
|
+
reset = watch(self, (current) => {
|
|
708
|
+
proxy = current;
|
|
709
|
+
if (!(key in state) || STALE.delete(compute)) compute(!reset);
|
|
710
|
+
return (didUpdate) => {
|
|
711
|
+
if (didUpdate) {
|
|
712
|
+
STALE.add(compute);
|
|
713
|
+
event(subject, key, true);
|
|
714
|
+
}
|
|
715
|
+
};
|
|
716
|
+
}, false);
|
|
717
|
+
}
|
|
718
|
+
function compute(initial) {
|
|
719
|
+
let next;
|
|
720
|
+
try {
|
|
721
|
+
next = getter.call(proxy, proxy, key);
|
|
722
|
+
} catch (err) {
|
|
723
|
+
console.warn(`An exception was thrown while ${initial ? "initializing" : "refreshing"} ${subject}.${key}.`);
|
|
724
|
+
if (initial) throw err;
|
|
725
|
+
console.error(err);
|
|
726
|
+
}
|
|
727
|
+
update(subject, key, next, !isAsync);
|
|
728
|
+
}
|
|
729
|
+
return () => {
|
|
730
|
+
if (!proxy) {
|
|
731
|
+
source(connect);
|
|
732
|
+
isAsync = true;
|
|
733
|
+
}
|
|
734
|
+
if (STALE.delete(compute)) compute();
|
|
735
|
+
return access(subject, key, !proxy);
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
if (typeof value == "function" || value instanceof Promise) {
|
|
739
|
+
function init() {
|
|
740
|
+
if (typeof value == "function") try {
|
|
741
|
+
value = attempt(value.bind(subject, key));
|
|
742
|
+
} catch (err) {
|
|
743
|
+
console.warn(`Generating initial value for ${subject}.${key} failed.`);
|
|
744
|
+
throw err;
|
|
745
|
+
}
|
|
746
|
+
property.get = argument !== false;
|
|
747
|
+
const set = (value) => subject[key] = value;
|
|
748
|
+
if (value instanceof Promise) value.then(set, (error) => {
|
|
749
|
+
event(subject, key);
|
|
750
|
+
property.get = () => {
|
|
751
|
+
throw error;
|
|
752
|
+
};
|
|
753
|
+
});
|
|
754
|
+
else set(value);
|
|
755
|
+
if (argument) return null;
|
|
756
|
+
return subject[key];
|
|
757
|
+
}
|
|
758
|
+
if (argument) addListener(subject, init, true);
|
|
759
|
+
else property.get = init;
|
|
760
|
+
} else if (value !== void 0) property.value = value;
|
|
761
|
+
if (typeof argument == "function") {
|
|
762
|
+
let unset;
|
|
763
|
+
property.set = function(value, previous) {
|
|
764
|
+
const exit = scope();
|
|
765
|
+
const returns = argument.call(this, value, previous);
|
|
766
|
+
const flush = exit();
|
|
767
|
+
if (returns === false) return false;
|
|
768
|
+
if (typeof unset == "function") unset(value);
|
|
769
|
+
unset = (next) => {
|
|
770
|
+
if (typeof returns == "function") returns(next);
|
|
771
|
+
flush();
|
|
772
|
+
};
|
|
773
|
+
};
|
|
774
|
+
} else property.set = (value) => {
|
|
775
|
+
property.get = void 0;
|
|
776
|
+
update(subject, key, value);
|
|
777
|
+
};
|
|
778
|
+
return property;
|
|
779
|
+
});
|
|
889
780
|
}
|
|
890
781
|
function attempt(fn) {
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
782
|
+
function retry(err) {
|
|
783
|
+
if (err instanceof Promise) return err.then(compute);
|
|
784
|
+
else throw err;
|
|
785
|
+
}
|
|
786
|
+
function compute() {
|
|
787
|
+
try {
|
|
788
|
+
const output = fn();
|
|
789
|
+
return output instanceof Promise ? output.catch(retry) : output;
|
|
790
|
+
} catch (err) {
|
|
791
|
+
return retry(err);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
return compute();
|
|
904
795
|
}
|
|
905
796
|
|
|
906
|
-
|
|
907
|
-
|
|
797
|
+
//#endregion
|
|
798
|
+
//#region src/instruction/ref.ts
|
|
799
|
+
const { defineProperty, defineProperties } = Object;
|
|
908
800
|
function ref(arg, arg2) {
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
}
|
|
966
|
-
defineProperty(subject, key2, { value });
|
|
967
|
-
});
|
|
801
|
+
return use((key, subject, state) => {
|
|
802
|
+
let value = {};
|
|
803
|
+
const method = (key, from) => (callback) => callback ? addListener(subject, () => callback(from[key]), key) : from[key];
|
|
804
|
+
if (arg === subject) addListener(subject, () => {
|
|
805
|
+
for (const key in subject) if (typeof arg2 == "function") defineProperty(value, key, {
|
|
806
|
+
configurable: true,
|
|
807
|
+
get() {
|
|
808
|
+
const out = arg2(key);
|
|
809
|
+
defineProperty(value, key, { value: out });
|
|
810
|
+
return out;
|
|
811
|
+
}
|
|
812
|
+
});
|
|
813
|
+
else {
|
|
814
|
+
const get = method(key, subject);
|
|
815
|
+
const set = (x) => subject[key] = x;
|
|
816
|
+
defineProperties(set, {
|
|
817
|
+
current: {
|
|
818
|
+
get,
|
|
819
|
+
set
|
|
820
|
+
},
|
|
821
|
+
get: { value: get },
|
|
822
|
+
is: { value: subject },
|
|
823
|
+
key: { value: key }
|
|
824
|
+
});
|
|
825
|
+
defineProperty(value, key, { value: set });
|
|
826
|
+
}
|
|
827
|
+
return null;
|
|
828
|
+
}, true);
|
|
829
|
+
else if (typeof arg == "object") throw new Error("ref instruction does not support object which is not 'this'");
|
|
830
|
+
else {
|
|
831
|
+
let unset;
|
|
832
|
+
const get = method(key, state);
|
|
833
|
+
const set = (value) => {
|
|
834
|
+
if (!update(subject, key, value) || !arg) return;
|
|
835
|
+
if (unset) unset = void unset(value);
|
|
836
|
+
if (value === null && arg2 !== false) return;
|
|
837
|
+
const exit = scope();
|
|
838
|
+
const out = arg.call(subject, value);
|
|
839
|
+
const flush = exit();
|
|
840
|
+
unset = (key) => {
|
|
841
|
+
if (typeof out == "function") out(key);
|
|
842
|
+
flush();
|
|
843
|
+
};
|
|
844
|
+
};
|
|
845
|
+
state[key] = null;
|
|
846
|
+
value = defineProperty({
|
|
847
|
+
get,
|
|
848
|
+
key,
|
|
849
|
+
is: subject
|
|
850
|
+
}, "current", {
|
|
851
|
+
get,
|
|
852
|
+
set
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
defineProperty(subject, key, { value });
|
|
856
|
+
});
|
|
968
857
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
858
|
+
|
|
859
|
+
//#endregion
|
|
860
|
+
exports.Context = Context;
|
|
861
|
+
exports.METHOD = METHOD;
|
|
862
|
+
exports.Observable = Observable;
|
|
863
|
+
exports.State = State;
|
|
864
|
+
exports.addListener = addListener;
|
|
865
|
+
exports.default = State;
|
|
866
|
+
exports.event = event;
|
|
867
|
+
exports.get = get;
|
|
868
|
+
exports.ref = ref;
|
|
869
|
+
exports.set = set;
|
|
870
|
+
exports.use = use;
|
|
871
|
+
exports.watch = watch;
|
|
983
872
|
//# sourceMappingURL=index.js.map
|