@expressive/mvc 0.11.1 → 0.13.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.esm.js CHANGED
@@ -1,8 +1,17 @@
1
- import React, { useState, useMemo } from 'react';
1
+ import React, { useState, Suspense } from 'react';
2
2
 
3
3
  const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
4
- function unique(array) {
5
- return Array.from(new Set(array));
4
+ const UID_CACHE = new WeakMap();
5
+ function assignWeak(into, from) {
6
+ for (const K in from)
7
+ if (K in into)
8
+ into[K] = from[K];
9
+ }
10
+ function uid(object) {
11
+ let uid = UID_CACHE.get(object);
12
+ if (!uid)
13
+ UID_CACHE.set(object, uid = Math.random());
14
+ return uid;
6
15
  }
7
16
 
8
17
  class Issue extends Error {
@@ -161,7 +170,7 @@ const Oops$d = issues({
161
170
  BadCallback: () => `Callback for effect-callback may only return a function.`
162
171
  });
163
172
  function createEffect(model, callback, keys) {
164
- return Control.for(model, control => {
173
+ return control(model, controller => {
165
174
  let unSet;
166
175
  let busy = false;
167
176
  function effect(value) {
@@ -186,7 +195,7 @@ function createEffect(model, callback, keys) {
186
195
  }
187
196
  if (Array.isArray(keys)) {
188
197
  invoke();
189
- return control.addListener(key => {
198
+ return controller.addListener(key => {
190
199
  if (key === null) {
191
200
  if (!keys.length)
192
201
  invoke();
@@ -195,7 +204,7 @@ function createEffect(model, callback, keys) {
195
204
  return invoke;
196
205
  });
197
206
  }
198
- const sub = control.subscribe(() => invoke);
207
+ const sub = controller.subscribe(() => invoke);
199
208
  model = sub.proxy;
200
209
  invoke();
201
210
  return sub.commit();
@@ -227,13 +236,13 @@ const Oops$c = issues({
227
236
  function addEventListener(source, arg1, arg2, arg3) {
228
237
  if (typeof arg1 == "string")
229
238
  arg1 = [arg1];
230
- return Control.for(source, control => {
239
+ return control(source, controller => {
231
240
  for (const key of arg1)
232
241
  try {
233
242
  void source[key];
234
243
  }
235
244
  catch (e) { }
236
- const removeListener = control.addListener(key => {
245
+ const removeListener = controller.addListener(key => {
237
246
  if (!key && !arg1.length)
238
247
  arg2.call(source, []);
239
248
  if (arg1.includes(key)) {
@@ -256,8 +265,8 @@ function awaitUpdate(source, arg1, arg2) {
256
265
  removeListener();
257
266
  reject(Oops$c.Timeout(k, message));
258
267
  };
259
- const removeListener = Control.for(source, control => {
260
- const pending = control.frame;
268
+ const removeListener = control(source, controller => {
269
+ const pending = controller.frame;
261
270
  if (keys === null) {
262
271
  if (pending.size)
263
272
  reject(Oops$c.StrictNoUpdate());
@@ -284,8 +293,8 @@ function awaitUpdate(source, arg1, arg2) {
284
293
  return;
285
294
  }
286
295
  else
287
- control.waiting.add(resolve);
288
- return control.addListener(key => {
296
+ controller.waiting.add(resolve);
297
+ return controller.addListener(key => {
289
298
  if (!key) {
290
299
  if (keys && !keys.length)
291
300
  resolve([]);
@@ -294,7 +303,7 @@ function awaitUpdate(source, arg1, arg2) {
294
303
  }
295
304
  else if (!keys || keys.includes(key)) {
296
305
  removeListener();
297
- return keys => resolve(single ? control.state.get(key) : keys);
306
+ return keys => resolve(single ? controller.state.get(key) : keys);
298
307
  }
299
308
  });
300
309
  });
@@ -311,35 +320,6 @@ class Subscriber {
311
320
  this.active = false;
312
321
  this.dependant = new Set();
313
322
  this.watch = new Map();
314
- this.commit = () => {
315
- const release = this.parent.addListener(this.event);
316
- this.active = true;
317
- this.dependant.forEach(x => x.commit());
318
- return this.release = () => {
319
- this.dependant.forEach(x => x.release());
320
- release();
321
- };
322
- };
323
- this.event = (key) => {
324
- if (!this.active)
325
- return;
326
- const { parent, watch } = this;
327
- const handler = watch.get(key);
328
- let notify;
329
- if (typeof handler == "function") {
330
- const callback = handler();
331
- if (callback === true)
332
- notify = this.onUpdate(key, parent);
333
- }
334
- else if (handler === true)
335
- notify = this.onUpdate(key, parent);
336
- if (!notify)
337
- return;
338
- parent.waiting.add(update => {
339
- this.latest = update.filter(k => watch.has(k));
340
- });
341
- parent.waiting.add(notify);
342
- };
343
323
  const proxy = create(parent.subject);
344
324
  const reset = () => this.latest = undefined;
345
325
  REGISTER$1.set(proxy, this);
@@ -351,28 +331,45 @@ class Subscriber {
351
331
  }
352
332
  });
353
333
  }
354
- static get(from) {
355
- return REGISTER$1.get(from);
356
- }
357
334
  get using() {
358
335
  return Array.from(this.watch.keys());
359
336
  }
360
- assign(apply, keys) {
361
- const { waiting, subject } = this.parent;
362
- this.active = false;
363
- if (typeof keys !== "object")
364
- keys = getOwnPropertyNames(subject);
365
- for (const key of keys)
366
- if (key in apply)
367
- subject[key] = apply[key];
368
- waiting.add(() => this.active = true);
369
- }
370
337
  add(key, value) {
371
338
  if (value !== undefined)
372
339
  this.watch.set(key, value);
373
340
  else if (!this.watch.has(key))
374
341
  this.watch.set(key, true);
375
342
  }
343
+ commit() {
344
+ const release = this.parent.addListener(key => {
345
+ if (this.active)
346
+ this.onEvent(key);
347
+ });
348
+ this.active = true;
349
+ this.dependant.forEach(x => x.commit());
350
+ return this.release = () => {
351
+ this.dependant.forEach(x => x.release());
352
+ release();
353
+ };
354
+ }
355
+ onEvent(key) {
356
+ const { parent, watch } = this;
357
+ let handler = watch.get(key);
358
+ if (typeof handler == "function")
359
+ handler = handler();
360
+ if (handler) {
361
+ const notify = this.onUpdate(key, parent);
362
+ if (notify) {
363
+ parent.waiting.add(update => {
364
+ this.latest = update.filter(k => watch.has(k));
365
+ });
366
+ parent.waiting.add(notify);
367
+ }
368
+ }
369
+ }
370
+ }
371
+ function subscriber(from) {
372
+ return REGISTER$1.get(from);
376
373
  }
377
374
 
378
375
  const Oops$b = issues({
@@ -392,7 +389,7 @@ class Model {
392
389
  return addEventListener(this.is, arg1, arg2, arg3);
393
390
  }
394
391
  get(arg1, arg2) {
395
- const { state } = Control.for(this);
392
+ const { state } = control(this);
396
393
  const extract = typeof arg1 == "string"
397
394
  ? () => state.get(arg1)
398
395
  : () => {
@@ -409,19 +406,20 @@ class Model {
409
406
  return this.on(arg1, timeout).then(extract);
410
407
  }
411
408
  set(arg1, arg2) {
412
- const control = Control.for(this);
409
+ const controller = control(this);
410
+ const { state } = controller;
413
411
  if (typeof arg1 == "object")
414
412
  for (const key in arg1) {
415
- if (arg2 === true || (arg2 ? arg2.includes(key) : control.state.has(key))) {
416
- control.state.set(key, arg1[key]);
417
- control.update(key);
413
+ if (arg2 === true || (arg2 ? arg2.includes(key) : state.has(key))) {
414
+ state.set(key, arg1[key]);
415
+ controller.update(key);
418
416
  }
419
417
  }
420
418
  else if (typeof arg1 == "string") {
421
- control.update(arg1);
419
+ controller.update(arg1);
422
420
  if (1 in arguments) {
423
- if (control.state.has(arg1))
424
- control.state.set(arg1, arg2);
421
+ if (state.has(arg1))
422
+ state.set(arg1, arg2);
425
423
  else if (arg1 in this) {
426
424
  const method = this[arg1];
427
425
  if (typeof method == "function")
@@ -433,7 +431,7 @@ class Model {
433
431
  then: (callback) => {
434
432
  if (!callback)
435
433
  throw Oops$b.NoChaining();
436
- control.waiting.add(callback);
434
+ controller.waiting.add(callback);
437
435
  }
438
436
  };
439
437
  }
@@ -441,7 +439,7 @@ class Model {
441
439
  * Clean up side effects and mark this instance for garbage-collection.
442
440
  */
443
441
  end() {
444
- Control.for(this).clear();
442
+ control(this).clear();
445
443
  }
446
444
  /**
447
445
  * Creates a new instance of this controller.
@@ -452,7 +450,7 @@ class Model {
452
450
  */
453
451
  static new(...args) {
454
452
  const instance = new this(...args);
455
- Control.for(instance);
453
+ control(instance);
456
454
  return instance;
457
455
  }
458
456
  /**
@@ -507,7 +505,7 @@ class Control {
507
505
  enumerable: false,
508
506
  set: this.ref(key),
509
507
  get() {
510
- const sub = Subscriber.get(this);
508
+ const sub = subscriber(this);
511
509
  if (sub)
512
510
  sub.add(key);
513
511
  return state.get(key);
@@ -567,34 +565,34 @@ class Control {
567
565
  this.followers.clear();
568
566
  listeners.forEach(x => x(null, this));
569
567
  }
570
- static get(from) {
571
- if (from && "is" in from)
572
- from = from.is;
573
- return REGISTER.get(from);
574
- }
575
- static for(subject, cb) {
576
- const control = this.get(subject) || new this(subject);
577
- if (!control.state) {
578
- const { waiting } = control;
579
- if (cb) {
580
- let callback;
581
- waiting.add(() => {
582
- callback = cb(control);
583
- });
584
- return () => {
585
- if (callback)
586
- callback();
587
- };
588
- }
589
- control.state = new Map();
590
- for (const key in subject)
591
- control.watch(key);
592
- control.waiting = new Set();
593
- for (const cb of waiting)
594
- cb([]);
568
+ }
569
+ function controller(from) {
570
+ if ("is" in from)
571
+ from = from.is;
572
+ return REGISTER.get(from);
573
+ }
574
+ function control(subject, cb) {
575
+ const control = controller(subject) || new Control(subject);
576
+ if (!control.state) {
577
+ const { waiting } = control;
578
+ if (cb) {
579
+ let callback;
580
+ waiting.add(() => {
581
+ callback = cb(control);
582
+ });
583
+ return () => {
584
+ if (callback)
585
+ callback();
586
+ };
595
587
  }
596
- return cb ? cb(control) : control;
588
+ control.state = new Map();
589
+ for (const key in subject)
590
+ control.watch(key);
591
+ control.waiting = new Set();
592
+ for (const cb of waiting)
593
+ cb([]);
597
594
  }
595
+ return cb ? cb(control) : control;
598
596
  }
599
597
 
600
598
  const Parent = new WeakMap();
@@ -613,8 +611,8 @@ function getRecursive(key, from) {
613
611
  if (reset)
614
612
  reset();
615
613
  const value = state.get(key);
616
- if (Control.get(value)) {
617
- const child = Control.for(value).subscribe(local.onUpdate);
614
+ if (value && controller(value)) {
615
+ const child = control(value).subscribe(local.onUpdate);
618
616
  if (local.active)
619
617
  child.commit();
620
618
  local.dependant.add(child);
@@ -634,24 +632,24 @@ function getRecursive(key, from) {
634
632
  return context.get(local);
635
633
  };
636
634
  }
637
- function setRecursive(control, key, initial) {
638
- const { state, subject } = control;
635
+ function setRecursive(controller, key, initial) {
636
+ const { state, subject } = controller;
639
637
  const Type = initial.constructor;
640
638
  let get;
641
639
  const onUpdate = (next) => {
642
640
  state.set(key, next);
643
641
  if (!(next instanceof Type))
644
642
  throw Oops$a.BadAssignment(`${subject}.${key}`, Type.name, String(next));
645
- get = getRecursive(key, control);
643
+ get = getRecursive(key, controller);
646
644
  Parent.set(next, subject);
647
- Control.for(next);
645
+ control(next);
648
646
  return true;
649
647
  };
650
648
  onUpdate(initial);
651
649
  defineProperty(subject, key, {
652
- set: control.ref(key, onUpdate),
650
+ set: controller.ref(key, onUpdate),
653
651
  get() {
654
- const local = Subscriber.get(this);
652
+ const local = subscriber(this);
655
653
  if (local)
656
654
  local.add(key);
657
655
  return get(local);
@@ -699,7 +697,7 @@ function add(instruction, label) {
699
697
  get() {
700
698
  if (!state.has(key) && shouldSuspend)
701
699
  throw suspend(control, key);
702
- const local = Subscriber.get(this);
700
+ const local = subscriber(this);
703
701
  if (local)
704
702
  local.add(key);
705
703
  return onGet
@@ -770,13 +768,13 @@ function run(task) {
770
768
  const Oops$8 = issues({
771
769
  NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
772
770
  });
773
- function factoryMode(self, output, key, required) {
771
+ function factoryMode(self, value, key, required) {
774
772
  const { subject, state } = self;
775
773
  let pending;
776
774
  let error;
777
- if (output instanceof Promise) {
775
+ if (value instanceof Promise) {
778
776
  state.set(key, undefined);
779
- pending = output
777
+ pending = value
780
778
  .catch(err => error = err)
781
779
  .then(val => {
782
780
  state.set(key, val);
@@ -787,7 +785,8 @@ function factoryMode(self, output, key, required) {
787
785
  self.update(key);
788
786
  });
789
787
  }
790
- state.set(key, output);
788
+ else
789
+ state.set(key, value);
791
790
  const suspend = () => {
792
791
  if (required === false)
793
792
  return undefined;
@@ -829,7 +828,7 @@ function get(arg0, arg1, arg2) {
829
828
  let source = this;
830
829
  let setter;
831
830
  if (typeof arg0 == "function") {
832
- const result = mayRetry(() => arg0.call(subject, key, subject));
831
+ let result = mayRetry(arg0.bind(subject, key, subject));
833
832
  if (typeof result == "function")
834
833
  setter = result;
835
834
  else {
@@ -843,7 +842,7 @@ function get(arg0, arg1, arg2) {
843
842
  }
844
843
  else if (typeof arg1 == "function") {
845
844
  // replace source controller in-case it is different
846
- source = Control.for(arg0);
845
+ source = control(arg0);
847
846
  setter = arg1;
848
847
  }
849
848
  else
@@ -873,7 +872,7 @@ function ref(arg, mapper) {
873
872
  if (typeof arg != "object")
874
873
  value = createRef(this, key, arg);
875
874
  else
876
- Control.for(arg).state.forEach((_val, key) => {
875
+ control(arg).state.forEach((_val, key) => {
877
876
  defineProperty(value, key, mapper ? {
878
877
  configurable: true,
879
878
  get() {
@@ -1084,7 +1083,7 @@ function use$1(input, argument) {
1084
1083
  if (next) {
1085
1084
  get = getRecursive(key, this);
1086
1085
  Parent.set(next, subject);
1087
- Control.for(next);
1086
+ control(next);
1088
1087
  }
1089
1088
  if (typeof argument == "function")
1090
1089
  argument(next);
@@ -1164,9 +1163,6 @@ class Lookup {
1164
1163
  constructor() {
1165
1164
  this.table = new Map();
1166
1165
  }
1167
- get local() {
1168
- return unique(getOwnPropertySymbols(this).map(symbol => this[symbol]));
1169
- }
1170
1166
  key(T) {
1171
1167
  let key = this.table.get(T);
1172
1168
  if (!key) {
@@ -1175,8 +1171,21 @@ class Lookup {
1175
1171
  }
1176
1172
  return key;
1177
1173
  }
1178
- get(T) {
1179
- return this[this.key(T)];
1174
+ get(Type) {
1175
+ return this[this.key(Type)];
1176
+ }
1177
+ has(key, input, callback) {
1178
+ if (MVC.isTypeof(input) && input.global)
1179
+ return input.new();
1180
+ if (this.register.get(key) === input)
1181
+ return typeof input == "object"
1182
+ ? input
1183
+ : this.get(input);
1184
+ const instance = this.add(input);
1185
+ this.register.set(key, input);
1186
+ if (callback)
1187
+ callback(instance);
1188
+ return instance;
1180
1189
  }
1181
1190
  add(input) {
1182
1191
  let writable = true;
@@ -1184,7 +1193,7 @@ class Lookup {
1184
1193
  let I;
1185
1194
  if (typeof input == "function") {
1186
1195
  T = input;
1187
- I = input.new();
1196
+ I = new input();
1188
1197
  }
1189
1198
  else {
1190
1199
  I = input;
@@ -1193,21 +1202,19 @@ class Lookup {
1193
1202
  }
1194
1203
  do {
1195
1204
  const key = this.key(T);
1196
- const conflict = this.hasOwnProperty(key);
1197
1205
  defineProperty(this, key, {
1198
- value: conflict ? null : I,
1199
1206
  configurable: true,
1207
+ value: this.hasOwnProperty(key) ? null : I,
1200
1208
  writable
1201
1209
  });
1202
1210
  T = getPrototypeOf(T);
1203
1211
  } while (T !== Model);
1204
- Control.for(I).state.forEach(value => {
1205
- if (Parent.get(value) === I)
1206
- this.add(value);
1207
- });
1212
+ return I;
1208
1213
  }
1209
1214
  push() {
1210
- return create(this);
1215
+ const next = create(this);
1216
+ this.register = new Map();
1217
+ return next;
1211
1218
  }
1212
1219
  pop() {
1213
1220
  const items = new Set();
@@ -1237,7 +1244,7 @@ const Pending = new WeakMap();
1237
1244
  const Applied = new WeakMap();
1238
1245
  function tap(type, argument) {
1239
1246
  return add(function tap(key) {
1240
- if (type.global)
1247
+ if (MVC.isTypeof(type) && type.global)
1241
1248
  return {
1242
1249
  recursive: true,
1243
1250
  value: type.get()
@@ -1284,20 +1291,13 @@ function getPending(subject) {
1284
1291
  return pending;
1285
1292
  }
1286
1293
 
1287
- function use(init) {
1288
- const [state, update] = React.useState(() => [
1289
- init(() => update(state.concat()))
1290
- ]);
1291
- return state[0];
1292
- }
1293
-
1294
1294
  function useNew(source, arg1, arg2) {
1295
1295
  const instance = React.useMemo(() => {
1296
1296
  const callback = arg2 || arg1;
1297
1297
  const instance = Model.isTypeof(source)
1298
1298
  ? new source()
1299
1299
  : source();
1300
- Control.for(instance);
1300
+ control(instance);
1301
1301
  if (typeof callback == "function")
1302
1302
  callback(instance);
1303
1303
  return instance;
@@ -1315,9 +1315,22 @@ function useNew(source, arg1, arg2) {
1315
1315
  }, []);
1316
1316
  return instance;
1317
1317
  }
1318
- const local = use(refresh => (Control.for(instance).subscribe(() => refresh)));
1319
- if (typeof arg1 == "object")
1320
- local.assign(arg1, arg2);
1318
+ const state = React.useState(0);
1319
+ const local = React.useMemo(() => {
1320
+ const refresh = state[1].bind(null, x => x + 1);
1321
+ return control(instance).subscribe(() => refresh);
1322
+ }, []);
1323
+ if (typeof arg1 == "object") {
1324
+ const { waiting, subject } = local.parent;
1325
+ let keys = arg2;
1326
+ local.active = false;
1327
+ if (!keys)
1328
+ keys = getOwnPropertyNames(subject);
1329
+ for (const key of keys)
1330
+ if (key in arg1)
1331
+ subject[key] = arg1[key];
1332
+ waiting.add(() => local.active = true);
1333
+ }
1321
1334
  React.useLayoutEffect(() => {
1322
1335
  local.commit();
1323
1336
  return () => {
@@ -1329,9 +1342,17 @@ function useNew(source, arg1, arg2) {
1329
1342
  return local.proxy;
1330
1343
  }
1331
1344
 
1332
- function useValue(source, compute, suspend) {
1345
+ function use(init, deps) {
1346
+ const state = React.useState(0);
1347
+ return React.useMemo(() => {
1348
+ return init(state[1].bind(null, x => x + 1));
1349
+ }, deps);
1350
+ }
1351
+
1352
+ function useCompute(source, compute, suspend) {
1353
+ const deps = [uid(source)];
1333
1354
  const local = use(refresh => {
1334
- const sub = Control.for(source).subscribe(() => update);
1355
+ const sub = control(source).subscribe(() => update);
1335
1356
  const spy = sub.proxy;
1336
1357
  let value = compute.call(spy, spy);
1337
1358
  let update;
@@ -1380,30 +1401,30 @@ function useValue(source, compute, suspend) {
1380
1401
  }
1381
1402
  });
1382
1403
  return sub;
1383
- });
1384
- React.useLayoutEffect(() => local.release, []);
1404
+ }, deps);
1405
+ React.useLayoutEffect(() => local.release, deps);
1385
1406
  return local.proxy;
1386
1407
  }
1387
1408
 
1388
1409
  function useTap(source, arg1, arg2) {
1389
- const instance = useMemo(() => {
1390
- if (typeof source == "object")
1391
- return () => source;
1392
- if (Model.isTypeof(source))
1393
- return "get" in source
1394
- ? () => source.get()
1395
- : () => useContext(source);
1396
- return source;
1397
- }, [])();
1398
- if (typeof arg1 == "function")
1399
- return useValue(instance, arg1, arg2);
1400
- const local = use(refresh => (Control.for(instance).subscribe(() => refresh)));
1401
- React.useLayoutEffect(local.commit, []);
1402
- if (arg1 === undefined)
1410
+ const instance = typeof source == "object"
1411
+ ? source
1412
+ : "get" in source
1413
+ ? source.get()
1414
+ : useContext(source);
1415
+ return typeof arg1 == "function"
1416
+ ? useCompute(instance, arg1, arg2)
1417
+ : useSubscribe(instance, arg1, arg2);
1418
+ }
1419
+ function useSubscribe(source, path, expect) {
1420
+ const deps = [uid(source)];
1421
+ const local = use(refresh => (control(source).subscribe(() => refresh)), deps);
1422
+ React.useLayoutEffect(() => local.commit(), deps);
1423
+ if (path === undefined)
1403
1424
  return local.proxy;
1404
- const value = local.proxy[arg1];
1405
- if (value === undefined && arg2)
1406
- throw suspend(local.parent, arg1);
1425
+ const value = local.proxy[path];
1426
+ if (value === undefined && expect)
1427
+ throw suspend(local.parent, path);
1407
1428
  return value;
1408
1429
  }
1409
1430
 
@@ -1461,14 +1482,19 @@ class MVC extends Model {
1461
1482
  callback(arg2);
1462
1483
  return instance;
1463
1484
  }
1464
- static tap(key, expect) {
1465
- return useTap(this, key, expect);
1485
+ static tap(arg1, arg2) {
1486
+ const instance = this.get();
1487
+ return typeof arg1 == "function"
1488
+ ? useCompute(instance, arg1, arg2)
1489
+ : useSubscribe(instance, arg1, arg2);
1466
1490
  }
1467
1491
  static use(a, b) {
1468
1492
  return useNew(this, a, b);
1469
1493
  }
1470
- static meta(path, expect) {
1471
- return useTap(() => this, path, expect);
1494
+ static meta(arg1, arg2) {
1495
+ return typeof arg1 == "function"
1496
+ ? useCompute(this, arg1, arg2)
1497
+ : useSubscribe(this, arg1, arg2);
1472
1498
  }
1473
1499
  }
1474
1500
 
@@ -1492,52 +1518,39 @@ const Oops = issues({
1492
1518
  });
1493
1519
  function Provider(props) {
1494
1520
  const context = useNewContext(props.for, props.and);
1495
- const render = props.children;
1496
- React.useLayoutEffect(() => () => context.pop(), []);
1497
- return React.createElement(LookupContext.Provider, { value: context }, typeof render == "function"
1498
- ? React.createElement(RenderFunction, { context, render })
1499
- : render);
1521
+ return (React.createElement(LookupContext.Provider, { value: context }, props.fallback === false
1522
+ ? props.children
1523
+ : (React.createElement(Suspense, { fallback: props.fallback || null }, props.children))));
1500
1524
  }
1501
1525
  function useNewContext(include, assign) {
1526
+ const init = new Set();
1502
1527
  const ambient = useLookup();
1503
1528
  const context = React.useMemo(() => {
1504
1529
  if (!include)
1505
1530
  throw Oops.NoType();
1506
- const next = ambient.push();
1507
- if (include instanceof Model || typeof include == "function")
1508
- next.add(include);
1509
- else
1510
- values(include).forEach(x => next.add(x));
1511
- for (const instance of next.local)
1512
- if (instance) {
1513
- if (assign)
1514
- assignWeak(instance, assign);
1515
- for (const apply of getPending(instance))
1516
- apply(next);
1517
- }
1518
- return next;
1531
+ return ambient.push();
1519
1532
  }, []);
1520
- if (assign)
1521
- for (const into of context.local)
1522
- if (into)
1523
- assignWeak(into, assign);
1533
+ function register(key, T) {
1534
+ const instance = context.has(key, T, i => init.add(i));
1535
+ if (assign)
1536
+ assignWeak(instance, assign);
1537
+ }
1538
+ if (typeof include == "function" || include instanceof Model)
1539
+ register(0, include);
1540
+ else
1541
+ entries(include).forEach(e => register(...e));
1542
+ for (const instance of init) {
1543
+ control(instance).state.forEach(value => {
1544
+ if (Parent.get(value) === instance) {
1545
+ context.add(value);
1546
+ init.add(value);
1547
+ }
1548
+ });
1549
+ for (const apply of getPending(instance))
1550
+ apply(context);
1551
+ }
1552
+ React.useLayoutEffect(() => () => context.pop(), []);
1524
1553
  return context;
1525
- }
1526
- function RenderFunction(props) {
1527
- const hook = use(refresh => {
1528
- const targets = props.context.local;
1529
- if (targets.length == 1)
1530
- return Control.for(targets[0]).subscribe(() => refresh);
1531
- return {};
1532
- });
1533
- if (hook.commit)
1534
- React.useLayoutEffect(hook.commit, []);
1535
- return props.render(hook.proxy);
1536
- }
1537
- function assignWeak(into, from) {
1538
- for (const K in from)
1539
- if (K in into)
1540
- into[K] = from[K];
1541
1554
  }
1542
1555
 
1543
1556
  class Global extends MVC {
@@ -1552,17 +1565,17 @@ const CONTROL = "$debug controller";
1552
1565
  defineProperties(Model.prototype, {
1553
1566
  [CONTROL]: {
1554
1567
  get() {
1555
- return Control.get(this);
1568
+ return controller(this);
1556
1569
  }
1557
1570
  },
1558
1571
  [LOCAL]: {
1559
1572
  get() {
1560
- return Subscriber.get(this);
1573
+ return subscriber(this);
1561
1574
  }
1562
1575
  },
1563
1576
  [STATE]: {
1564
1577
  get() {
1565
- const { state } = Control.get(this);
1578
+ const { state } = controller(this);
1566
1579
  const output = {};
1567
1580
  state.forEach((value, key) => output[key] = value);
1568
1581
  return output;
@@ -1570,8 +1583,7 @@ defineProperties(Model.prototype, {
1570
1583
  },
1571
1584
  [UPDATE]: {
1572
1585
  get() {
1573
- const source = Subscriber.get(this) || Control.get(this);
1574
- return source && source.latest;
1586
+ return (subscriber(this) || controller(this)).latest;
1575
1587
  }
1576
1588
  }
1577
1589
  });