@expressive/mvc 0.24.2 → 0.25.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 CHANGED
@@ -57,16 +57,17 @@ declare namespace Control {
57
57
  type Getter<T> = (source: Model) => T;
58
58
  type Setter<T> = (value: T) => boolean | void;
59
59
  type PropertyDescriptor<T = any> = {
60
- enumerable?: boolean;
61
- value?: T;
62
60
  get?: Getter<T>;
63
61
  set?: Setter<T> | false;
62
+ enumerable?: boolean;
63
+ value?: T;
64
64
  };
65
+ type Callback = (control: Control) => void;
65
66
  /**
66
67
  * Callback for Controller.for() static method.
67
68
  * Returned callback is forwarded.
68
69
  */
69
- type OnReady<T extends {}> = (control: Control<T>) => Callback | void;
70
+ type OnReady<T extends {}> = (control: Control<T>) => (() => void) | void;
70
71
  type RequestRefresh = (update: (tick: number) => number) => void;
71
72
  type GetContext = (target: Model) => (callback: (got: Context) => void) => void;
72
73
  type GetAdapter<T> = (refresh: RequestRefresh, context: Context) => {
@@ -75,15 +76,14 @@ declare namespace Control {
75
76
  } | void;
76
77
  type GetHook = <T>(adapter: GetAdapter<T>) => T | null;
77
78
  type UseAdapter<T extends Model, R> = (refresh: RequestRefresh) => {
78
- local: T;
79
+ instance: T;
79
80
  mount: () => (() => void) | void;
80
81
  render: R;
81
82
  };
82
83
  type UseHook = <T extends Model, R>(adapter: UseAdapter<T, R>) => R;
83
84
  }
84
85
  declare class Control<T extends {} = any> {
85
- subject: T;
86
- id: string | number;
86
+ static ready: Set<Control.Callback>;
87
87
  static after: Set<Callback>;
88
88
  static before: Set<Callback>;
89
89
  static pending: Set<Callback>;
@@ -93,6 +93,8 @@ declare class Control<T extends {} = any> {
93
93
  static for: typeof control;
94
94
  static apply: typeof apply;
95
95
  static watch: typeof watch;
96
+ id: string | number;
97
+ subject: T;
96
98
  state: {
97
99
  [key: string]: any;
98
100
  };
@@ -154,19 +156,12 @@ type Debug<T extends Model = Model> = T & {
154
156
 
155
157
  /** Type may not be undefined - instead will be null. */
156
158
  type NoVoid<T> = T extends undefined | void ? null : T;
157
- declare function get$1<T extends Model>(this: Model.Type<T>): T;
158
- /** Fetch instance of this class in passive mode. Will not subscribe to events. */
159
+ /** Fetch instance of this class from context. */
159
160
  declare function get$1<T extends Model>(this: Model.Type<T>, ignoreUpdates?: true): T;
160
161
  /** Fetch instance of this class optionally. May be undefined, but will never subscribe. */
161
162
  declare function get$1<T extends Model>(this: Model.Type<T>, required: boolean): T | undefined;
162
- declare function get$1<T extends Model, R extends []>(this: Model.Type<T>, factory: Model.GetCallback<T, R | (() => R)>, expect?: boolean): R;
163
- declare function get$1<T extends Model, R extends []>(this: Model.Type<T>, factory: Model.GetCallback<T, Promise<R> | (() => R) | null>, expect?: boolean): R | null;
164
- declare function get$1<T extends Model, R extends []>(this: Model.Type<T>, factory: Model.GetCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
165
- declare function get$1<T extends Model, R>(this: Model.Type<T>, init: Model.GetCallback<T, () => R>): NoVoid<R>;
166
- declare function get$1<T extends Model, R>(this: Model.Type<T>, init: Model.GetCallback<T, (() => R) | null>): NoVoid<R> | null;
167
- declare function get$1<T extends Model, R>(this: Model.Type<T>, compute: Model.GetCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
168
- declare function get$1<T extends Model, R>(this: Model.Type<T>, compute: Model.GetCallback<T, Promise<R>>, expect?: boolean): NoVoid<R> | null;
169
- declare function get$1<T extends Model, R>(this: Model.Type<T>, compute: Model.GetCallback<T, R>, expect?: boolean): NoVoid<R>;
163
+ declare function get$1<T extends Model, R>(this: Model.Type<T>, factory: Model.GetCallback<T, (() => R) | R | Promise<R>>): NoVoid<R>;
164
+ declare function get$1<T extends Model, R>(this: Model.Type<T>, factory: Model.GetCallback<T, (() => R) | null>): NoVoid<R> | null;
170
165
 
171
166
  declare function use$1<T extends Model>(this: Model.New<T>, callback?: (instance: T) => void, repeat?: boolean): T;
172
167
  declare function use$1<T extends Model>(this: Model.New<T>, apply?: Model.Compat<T>, repeat?: boolean): T;
@@ -251,7 +246,7 @@ declare class Model {
251
246
  get<P extends Model.Key<this>>(select: Iterable<P>): Model.Get<this, P>;
252
247
  get<P extends Model.Key<this>>(select: P, listener: (this: this, value: this[P]) => void): Callback;
253
248
  get<P extends Model.Key<this>>(select: Iterable<P>, listener: (this: this, value: Model.Get<this, P>) => void): Callback;
254
- set<T extends Model.Compat<this>>(source: T, select?: (keyof T)[]): Promise<Model.Key<T>[]>;
249
+ set<T extends Model.Compat<this>>(source: T, only?: (keyof T)[]): Promise<Model.Key<T>[]>;
255
250
  set<K extends Model.Event<this>>(key: K, value?: Model.ValueOf<this, K>): Promise<Model.Event<this>[] | false>;
256
251
  /** Mark this instance for garbage collection. */
257
252
  null(): void;
package/lib/index.esm.js CHANGED
@@ -197,18 +197,18 @@ function awaitUpdate(source, select, timeout) {
197
197
  const Oops$6 = issues({
198
198
  NotFound: (name) => `Could not find ${name} in context.`
199
199
  });
200
- function get$1(arg1, arg2) {
200
+ function get$1(argument) {
201
201
  return Control.get((dispatch, context) => {
202
202
  const refresh = () => dispatch(x => x + 1);
203
203
  let onUpdate;
204
204
  let value;
205
- if (typeof arg1 !== "function") {
205
+ if (typeof argument !== "function") {
206
206
  const got = context.get(this);
207
207
  if (got)
208
- value = arg1 === undefined
208
+ value = argument === undefined
209
209
  ? Control.watch(got, k => k ? onUpdate : undefined)
210
210
  : got;
211
- else if (arg1 !== false)
211
+ else if (argument !== false)
212
212
  throw Oops$6.NotFound(this);
213
213
  return {
214
214
  mount() {
@@ -218,7 +218,7 @@ function get$1(arg1, arg2) {
218
218
  render: () => value
219
219
  };
220
220
  }
221
- let compute = arg1;
221
+ let compute = argument;
222
222
  let suspense;
223
223
  let getValue;
224
224
  let factory;
@@ -268,7 +268,7 @@ function get$1(arg1, arg2) {
268
268
  else
269
269
  onUpdate = () => {
270
270
  const next = getValue();
271
- if (notEqual(value, next))
271
+ if (value !== next)
272
272
  didUpdate(next);
273
273
  };
274
274
  return {
@@ -278,30 +278,25 @@ function get$1(arg1, arg2) {
278
278
  render: () => {
279
279
  if (value !== undefined)
280
280
  return value;
281
- if (arg2)
282
- throw new Promise(res => {
283
- suspense = res;
284
- });
285
- return null;
281
+ if (onUpdate)
282
+ return null;
283
+ throw new Promise(res => {
284
+ suspense = res;
285
+ });
286
286
  }
287
287
  };
288
288
  });
289
- }
290
- /** Values are not equal for purposes of a refresh. */
291
- const notEqual = (a, b) => (b !== a && (!Array.isArray(a) ||
292
- !Array.isArray(b) ||
293
- a.length !== b.length ||
294
- a.some((x, i) => x !== b[i])));
289
+ }
295
290
 
296
- function use$1(arg1, arg2) {
291
+ function use$1(apply, repeat) {
297
292
  const render = Control.use(dispatch => {
298
293
  const instance = this.new();
299
294
  const local = Control.watch(instance, () => onUpdate);
300
295
  const refresh = () => dispatch(x => x + 1);
301
296
  let onUpdate;
302
- let apply = !!arg1;
297
+ let shouldApply = !!apply;
303
298
  return {
304
- local,
299
+ instance,
305
300
  mount() {
306
301
  onUpdate = refresh;
307
302
  return () => {
@@ -310,7 +305,7 @@ function use$1(arg1, arg2) {
310
305
  };
311
306
  },
312
307
  render(props) {
313
- if (apply) {
308
+ if (shouldApply) {
314
309
  onUpdate = undefined;
315
310
  if (typeof props == "function")
316
311
  props(instance);
@@ -318,15 +313,15 @@ function use$1(arg1, arg2) {
318
313
  for (const key in instance)
319
314
  if (props.hasOwnProperty(key))
320
315
  instance[key] = props[key];
321
- if (!arg2)
322
- apply = false;
316
+ if (!repeat)
317
+ shouldApply = false;
323
318
  instance.on(0).then(() => onUpdate = refresh);
324
319
  }
325
320
  return local;
326
321
  }
327
322
  };
328
323
  });
329
- return render(arg1);
324
+ return render(apply);
330
325
  }
331
326
 
332
327
  class Model {
@@ -427,17 +422,20 @@ const Oops$5 = issues({
427
422
  BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
428
423
  });
429
424
  const INSTRUCTION = new Map();
425
+ const PENDING$1 = new WeakMap();
430
426
  const REGISTER = new WeakMap();
431
427
  const OBSERVER = new WeakMap();
432
428
  const PARENTS = new WeakMap();
433
429
  class Control {
434
- constructor(subject, id = uid()) {
435
- this.subject = subject;
436
- this.id = id;
430
+ constructor(subject, id) {
431
+ this.state = {};
437
432
  this.frame = new Set();
438
433
  this.followers = new Set();
439
434
  this.observers = new Map([["", this.followers]]);
435
+ this.id = typeof id == "undefined" ? uid() : id;
436
+ this.subject = subject;
440
437
  REGISTER.set(subject, this);
438
+ PENDING$1.set(this, new Set(Control.ready));
441
439
  }
442
440
  add(key) {
443
441
  const { value } = getOwnPropertyDescriptor(this.subject, key);
@@ -529,31 +527,30 @@ class Control {
529
527
  this.observers.clear();
530
528
  }
531
529
  }
530
+ Control.ready = new Set();
532
531
  Control.after = new Set();
533
532
  Control.before = new Set();
534
533
  Control.pending = new Set();
535
534
  Control.for = control;
536
535
  Control.apply = apply;
537
536
  Control.watch = watch;
538
- const PENDING_INIT = new WeakMap();
539
537
  function control(subject, ready) {
540
538
  const control = REGISTER.get(subject.is);
541
- const onReady = typeof ready == "function" && ready;
542
- if (!control.state && ready) {
543
- let waiting = PENDING_INIT.get(control);
544
- if (!waiting)
545
- PENDING_INIT.set(control, waiting = new Set());
546
- if (onReady) {
547
- let callback;
548
- waiting.add(() => callback = onReady(control));
549
- return () => callback && callback();
550
- }
551
- control.state = {};
539
+ const pending = PENDING$1.get(control);
540
+ if (typeof ready == "function") {
541
+ if (!pending)
542
+ return ready(control);
543
+ let done;
544
+ pending.add(() => done = ready(control));
545
+ return () => done && done();
546
+ }
547
+ if (pending && ready) {
548
+ PENDING$1.delete(control);
552
549
  for (const key in control.subject)
553
550
  control.add(key);
554
- waiting.forEach(cb => cb());
551
+ pending.forEach(cb => cb(control));
555
552
  }
556
- return onReady ? onReady(control) : control;
553
+ return control;
557
554
  }
558
555
  function requestUpdateFrame(event) {
559
556
  const { after, before, pending } = Control;
@@ -586,10 +583,10 @@ function setRecursive(on, key, value) {
586
583
  on.watch(key, { set });
587
584
  set(value);
588
585
  }
589
- function parent(child, register) {
590
- if (!register)
586
+ function parent(child, assign) {
587
+ if (!assign)
591
588
  return PARENTS.get(child);
592
- PARENTS.set(child, register);
589
+ PARENTS.set(child, assign);
593
590
  }
594
591
  function watch(on, cb) {
595
592
  if (!on.hasOwnProperty("is"))
package/lib/index.js CHANGED
@@ -201,18 +201,18 @@ function awaitUpdate(source, select, timeout) {
201
201
  const Oops$6 = issues({
202
202
  NotFound: (name) => `Could not find ${name} in context.`
203
203
  });
204
- function get$1(arg1, arg2) {
204
+ function get$1(argument) {
205
205
  return Control.get((dispatch, context) => {
206
206
  const refresh = () => dispatch(x => x + 1);
207
207
  let onUpdate;
208
208
  let value;
209
- if (typeof arg1 !== "function") {
209
+ if (typeof argument !== "function") {
210
210
  const got = context.get(this);
211
211
  if (got)
212
- value = arg1 === undefined
212
+ value = argument === undefined
213
213
  ? Control.watch(got, k => k ? onUpdate : undefined)
214
214
  : got;
215
- else if (arg1 !== false)
215
+ else if (argument !== false)
216
216
  throw Oops$6.NotFound(this);
217
217
  return {
218
218
  mount() {
@@ -222,7 +222,7 @@ function get$1(arg1, arg2) {
222
222
  render: () => value
223
223
  };
224
224
  }
225
- let compute = arg1;
225
+ let compute = argument;
226
226
  let suspense;
227
227
  let getValue;
228
228
  let factory;
@@ -272,7 +272,7 @@ function get$1(arg1, arg2) {
272
272
  else
273
273
  onUpdate = () => {
274
274
  const next = getValue();
275
- if (notEqual(value, next))
275
+ if (value !== next)
276
276
  didUpdate(next);
277
277
  };
278
278
  return {
@@ -282,30 +282,25 @@ function get$1(arg1, arg2) {
282
282
  render: () => {
283
283
  if (value !== undefined)
284
284
  return value;
285
- if (arg2)
286
- throw new Promise(res => {
287
- suspense = res;
288
- });
289
- return null;
285
+ if (onUpdate)
286
+ return null;
287
+ throw new Promise(res => {
288
+ suspense = res;
289
+ });
290
290
  }
291
291
  };
292
292
  });
293
- }
294
- /** Values are not equal for purposes of a refresh. */
295
- const notEqual = (a, b) => (b !== a && (!Array.isArray(a) ||
296
- !Array.isArray(b) ||
297
- a.length !== b.length ||
298
- a.some((x, i) => x !== b[i])));
293
+ }
299
294
 
300
- function use$1(arg1, arg2) {
295
+ function use$1(apply, repeat) {
301
296
  const render = Control.use(dispatch => {
302
297
  const instance = this.new();
303
298
  const local = Control.watch(instance, () => onUpdate);
304
299
  const refresh = () => dispatch(x => x + 1);
305
300
  let onUpdate;
306
- let apply = !!arg1;
301
+ let shouldApply = !!apply;
307
302
  return {
308
- local,
303
+ instance,
309
304
  mount() {
310
305
  onUpdate = refresh;
311
306
  return () => {
@@ -314,7 +309,7 @@ function use$1(arg1, arg2) {
314
309
  };
315
310
  },
316
311
  render(props) {
317
- if (apply) {
312
+ if (shouldApply) {
318
313
  onUpdate = undefined;
319
314
  if (typeof props == "function")
320
315
  props(instance);
@@ -322,15 +317,15 @@ function use$1(arg1, arg2) {
322
317
  for (const key in instance)
323
318
  if (props.hasOwnProperty(key))
324
319
  instance[key] = props[key];
325
- if (!arg2)
326
- apply = false;
320
+ if (!repeat)
321
+ shouldApply = false;
327
322
  instance.on(0).then(() => onUpdate = refresh);
328
323
  }
329
324
  return local;
330
325
  }
331
326
  };
332
327
  });
333
- return render(arg1);
328
+ return render(apply);
334
329
  }
335
330
 
336
331
  class Model {
@@ -431,17 +426,20 @@ const Oops$5 = issues({
431
426
  BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
432
427
  });
433
428
  const INSTRUCTION = new Map();
429
+ const PENDING$1 = new WeakMap();
434
430
  const REGISTER = new WeakMap();
435
431
  const OBSERVER = new WeakMap();
436
432
  const PARENTS = new WeakMap();
437
433
  class Control {
438
- constructor(subject, id = uid()) {
439
- this.subject = subject;
440
- this.id = id;
434
+ constructor(subject, id) {
435
+ this.state = {};
441
436
  this.frame = new Set();
442
437
  this.followers = new Set();
443
438
  this.observers = new Map([["", this.followers]]);
439
+ this.id = typeof id == "undefined" ? uid() : id;
440
+ this.subject = subject;
444
441
  REGISTER.set(subject, this);
442
+ PENDING$1.set(this, new Set(Control.ready));
445
443
  }
446
444
  add(key) {
447
445
  const { value } = getOwnPropertyDescriptor(this.subject, key);
@@ -533,31 +531,30 @@ class Control {
533
531
  this.observers.clear();
534
532
  }
535
533
  }
534
+ Control.ready = new Set();
536
535
  Control.after = new Set();
537
536
  Control.before = new Set();
538
537
  Control.pending = new Set();
539
538
  Control.for = control;
540
539
  Control.apply = apply;
541
540
  Control.watch = watch;
542
- const PENDING_INIT = new WeakMap();
543
541
  function control(subject, ready) {
544
542
  const control = REGISTER.get(subject.is);
545
- const onReady = typeof ready == "function" && ready;
546
- if (!control.state && ready) {
547
- let waiting = PENDING_INIT.get(control);
548
- if (!waiting)
549
- PENDING_INIT.set(control, waiting = new Set());
550
- if (onReady) {
551
- let callback;
552
- waiting.add(() => callback = onReady(control));
553
- return () => callback && callback();
554
- }
555
- control.state = {};
543
+ const pending = PENDING$1.get(control);
544
+ if (typeof ready == "function") {
545
+ if (!pending)
546
+ return ready(control);
547
+ let done;
548
+ pending.add(() => done = ready(control));
549
+ return () => done && done();
550
+ }
551
+ if (pending && ready) {
552
+ PENDING$1.delete(control);
556
553
  for (const key in control.subject)
557
554
  control.add(key);
558
- waiting.forEach(cb => cb());
555
+ pending.forEach(cb => cb(control));
559
556
  }
560
- return onReady ? onReady(control) : control;
557
+ return control;
561
558
  }
562
559
  function requestUpdateFrame(event) {
563
560
  const { after, before, pending } = Control;
@@ -590,10 +587,10 @@ function setRecursive(on, key, value) {
590
587
  on.watch(key, { set });
591
588
  set(value);
592
589
  }
593
- function parent(child, register) {
594
- if (!register)
590
+ function parent(child, assign) {
591
+ if (!assign)
595
592
  return PARENTS.get(child);
596
- PARENTS.set(child, register);
593
+ PARENTS.set(child, assign);
597
594
  }
598
595
  function watch(on, cb) {
599
596
  if (!on.hasOwnProperty("is"))
package/package.json CHANGED
@@ -26,6 +26,6 @@
26
26
  "prebuild": "rm -rf lib/",
27
27
  "preversion": "npm run test && npm run build"
28
28
  },
29
- "version": "0.24.2",
30
- "gitHead": "97e6daffcf793d8aa1152d553b4c427546e90dbc"
29
+ "version": "0.25.0",
30
+ "gitHead": "a7c707bf59325bd4bf1388e061f7991acb726a13"
31
31
  }