@expressive/mvc 0.0.1 → 0.0.4

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,5 +1,30 @@
1
1
  import React, { useState, useMemo } from 'react';
2
2
 
3
+ /*! *****************************************************************************
4
+ Copyright (c) Microsoft Corporation.
5
+
6
+ Permission to use, copy, modify, and/or distribute this software for any
7
+ purpose with or without fee is hereby granted.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
16
+ ***************************************************************************** */
17
+
18
+ function __awaiter(thisArg, _arguments, P, generator) {
19
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
20
+ return new (P || (P = Promise))(function (resolve, reject) {
21
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
22
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
23
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
24
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
25
+ });
26
+ }
27
+
3
28
  class Issue extends Error {
4
29
  constructor() {
5
30
  super(...arguments);
@@ -18,6 +43,50 @@ function issues(register) {
18
43
  }
19
44
 
20
45
  const Oops$c = issues({
46
+ ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
47
+ });
48
+ function suspend(source, key) {
49
+ const error = Oops$c.ValueNotReady(source.subject, key);
50
+ const promise = new Promise(resolve => {
51
+ const release = source.addListener(forKey => {
52
+ if (forKey == key)
53
+ return () => {
54
+ if (source.state[key] !== undefined) {
55
+ release();
56
+ resolve();
57
+ }
58
+ };
59
+ });
60
+ });
61
+ return Object.assign(promise, {
62
+ toString: () => String(error),
63
+ name: "Suspense",
64
+ message: error.message,
65
+ stack: error.stack
66
+ });
67
+ }
68
+ function mayRetry(fn) {
69
+ const retry = (err) => {
70
+ if (err instanceof Promise)
71
+ return err.then(compute);
72
+ else
73
+ throw err;
74
+ };
75
+ const compute = () => {
76
+ try {
77
+ const output = fn();
78
+ return output instanceof Promise
79
+ ? output.catch(retry)
80
+ : output;
81
+ }
82
+ catch (err) {
83
+ return retry(err);
84
+ }
85
+ };
86
+ return compute();
87
+ }
88
+
89
+ const Oops$b = issues({
21
90
  BadEffectCallback: () => `Callback for effect-callback may only return a function.`
22
91
  });
23
92
  const { assign, create, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
@@ -43,7 +112,7 @@ function createEffect(callback) {
43
112
  if (unSet instanceof Promise)
44
113
  unSet = undefined;
45
114
  if (unSet && typeof unSet !== "function")
46
- throw Oops$c.BadEffectCallback();
115
+ throw Oops$b.BadEffectCallback();
47
116
  };
48
117
  }
49
118
  function createValueEffect(callback) {
@@ -59,28 +128,8 @@ function createValueEffect(callback) {
59
128
  if (typeof out == "function")
60
129
  unSet = out;
61
130
  else
62
- throw Oops$c.BadEffectCallback();
63
- };
64
- }
65
- function suspenseBoundary(fn) {
66
- const retry = (err) => {
67
- if (err instanceof Promise)
68
- return err.then(compute);
69
- else
70
- throw err;
131
+ throw Oops$b.BadEffectCallback();
71
132
  };
72
- const compute = () => {
73
- try {
74
- const output = fn();
75
- return output instanceof Promise
76
- ? output.catch(retry)
77
- : output;
78
- }
79
- catch (err) {
80
- return retry(err);
81
- }
82
- };
83
- return compute();
84
133
  }
85
134
 
86
135
  const UPDATE = new WeakMap();
@@ -142,18 +191,25 @@ class Model {
142
191
  effect(callback, select) {
143
192
  const effect = createEffect(callback);
144
193
  return control(this, control => {
194
+ let busy = false;
195
+ let inject = this.get;
196
+ const invoke = () => {
197
+ if (busy)
198
+ return;
199
+ const output = mayRetry(() => {
200
+ effect.call(inject, inject);
201
+ });
202
+ if (output instanceof Promise) {
203
+ output.finally(() => busy = false);
204
+ busy = true;
205
+ }
206
+ };
145
207
  if (!select) {
146
208
  const sub = new Subscriber(control, () => invoke);
147
- const invoke = () => {
148
- const x = sub.proxy;
149
- effect.call(x, x);
150
- };
209
+ inject = sub.proxy;
151
210
  invoke();
152
211
  return sub.commit();
153
212
  }
154
- const invoke = () => {
155
- effect.call(this.get, this.get);
156
- };
157
213
  invoke();
158
214
  if (!select.length) {
159
215
  control.onDestroy.add(invoke);
@@ -282,30 +338,6 @@ class Subscriber {
282
338
  }
283
339
  }
284
340
 
285
- const Oops$b = issues({
286
- ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
287
- });
288
- function suspend(source, key) {
289
- const error = Oops$b.ValueNotReady(source.subject, key);
290
- const promise = new Promise(resolve => {
291
- const release = source.addListener(forKey => {
292
- if (forKey == key)
293
- return () => {
294
- if (source.state[key] !== undefined) {
295
- release();
296
- resolve();
297
- }
298
- };
299
- });
300
- });
301
- return Object.assign(promise, {
302
- toString: () => String(error),
303
- name: "Suspense",
304
- message: error.message,
305
- stack: error.stack
306
- });
307
- }
308
-
309
341
  const Oops$a = issues({
310
342
  BadComputedSource: (model, property, got) => `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
311
343
  PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
@@ -683,18 +715,19 @@ const Oops$8 = issues({
683
715
  function act(task) {
684
716
  return apply(function act(key) {
685
717
  let pending = false;
686
- const invoke = (...args) => {
718
+ const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
687
719
  if (pending)
688
720
  return Promise.reject(Oops$8.DuplicateAction(key));
689
721
  pending = true;
690
722
  this.update(key);
691
- return new Promise(res => {
692
- res(task.apply(this.subject, args));
693
- }).finally(() => {
723
+ try {
724
+ return yield mayRetry(() => (task.apply(this.subject, args)));
725
+ }
726
+ finally {
694
727
  pending = false;
695
728
  this.update(key);
696
- });
697
- };
729
+ }
730
+ });
698
731
  this.state[key] = undefined;
699
732
  defineProperty(invoke, "active", {
700
733
  get: () => pending
@@ -824,7 +857,7 @@ function pendingFactory(parent, key, fn, required) {
824
857
  let pending;
825
858
  let error;
826
859
  const init = () => {
827
- const output = suspenseBoundary(() => {
860
+ const output = mayRetry(() => {
828
861
  return fn.call(subject, key, subject);
829
862
  });
830
863
  if (output instanceof Promise) {