@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.js CHANGED
@@ -8,6 +8,31 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
8
8
 
9
9
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
10
10
 
11
+ /*! *****************************************************************************
12
+ Copyright (c) Microsoft Corporation.
13
+
14
+ Permission to use, copy, modify, and/or distribute this software for any
15
+ purpose with or without fee is hereby granted.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
18
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
22
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23
+ PERFORMANCE OF THIS SOFTWARE.
24
+ ***************************************************************************** */
25
+
26
+ function __awaiter(thisArg, _arguments, P, generator) {
27
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
28
+ return new (P || (P = Promise))(function (resolve, reject) {
29
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
30
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
31
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
32
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
33
+ });
34
+ }
35
+
11
36
  class Issue extends Error {
12
37
  constructor() {
13
38
  super(...arguments);
@@ -26,6 +51,50 @@ function issues(register) {
26
51
  }
27
52
 
28
53
  const Oops$c = issues({
54
+ ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
55
+ });
56
+ function suspend(source, key) {
57
+ const error = Oops$c.ValueNotReady(source.subject, key);
58
+ const promise = new Promise(resolve => {
59
+ const release = source.addListener(forKey => {
60
+ if (forKey == key)
61
+ return () => {
62
+ if (source.state[key] !== undefined) {
63
+ release();
64
+ resolve();
65
+ }
66
+ };
67
+ });
68
+ });
69
+ return Object.assign(promise, {
70
+ toString: () => String(error),
71
+ name: "Suspense",
72
+ message: error.message,
73
+ stack: error.stack
74
+ });
75
+ }
76
+ function mayRetry(fn) {
77
+ const retry = (err) => {
78
+ if (err instanceof Promise)
79
+ return err.then(compute);
80
+ else
81
+ throw err;
82
+ };
83
+ const compute = () => {
84
+ try {
85
+ const output = fn();
86
+ return output instanceof Promise
87
+ ? output.catch(retry)
88
+ : output;
89
+ }
90
+ catch (err) {
91
+ return retry(err);
92
+ }
93
+ };
94
+ return compute();
95
+ }
96
+
97
+ const Oops$b = issues({
29
98
  BadEffectCallback: () => `Callback for effect-callback may only return a function.`
30
99
  });
31
100
  const { assign, create, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
@@ -51,7 +120,7 @@ function createEffect(callback) {
51
120
  if (unSet instanceof Promise)
52
121
  unSet = undefined;
53
122
  if (unSet && typeof unSet !== "function")
54
- throw Oops$c.BadEffectCallback();
123
+ throw Oops$b.BadEffectCallback();
55
124
  };
56
125
  }
57
126
  function createValueEffect(callback) {
@@ -67,28 +136,8 @@ function createValueEffect(callback) {
67
136
  if (typeof out == "function")
68
137
  unSet = out;
69
138
  else
70
- throw Oops$c.BadEffectCallback();
71
- };
72
- }
73
- function suspenseBoundary(fn) {
74
- const retry = (err) => {
75
- if (err instanceof Promise)
76
- return err.then(compute);
77
- else
78
- throw err;
139
+ throw Oops$b.BadEffectCallback();
79
140
  };
80
- const compute = () => {
81
- try {
82
- const output = fn();
83
- return output instanceof Promise
84
- ? output.catch(retry)
85
- : output;
86
- }
87
- catch (err) {
88
- return retry(err);
89
- }
90
- };
91
- return compute();
92
141
  }
93
142
 
94
143
  const UPDATE = new WeakMap();
@@ -150,18 +199,25 @@ class Model {
150
199
  effect(callback, select) {
151
200
  const effect = createEffect(callback);
152
201
  return control(this, control => {
202
+ let busy = false;
203
+ let inject = this.get;
204
+ const invoke = () => {
205
+ if (busy)
206
+ return;
207
+ const output = mayRetry(() => {
208
+ effect.call(inject, inject);
209
+ });
210
+ if (output instanceof Promise) {
211
+ output.finally(() => busy = false);
212
+ busy = true;
213
+ }
214
+ };
153
215
  if (!select) {
154
216
  const sub = new Subscriber(control, () => invoke);
155
- const invoke = () => {
156
- const x = sub.proxy;
157
- effect.call(x, x);
158
- };
217
+ inject = sub.proxy;
159
218
  invoke();
160
219
  return sub.commit();
161
220
  }
162
- const invoke = () => {
163
- effect.call(this.get, this.get);
164
- };
165
221
  invoke();
166
222
  if (!select.length) {
167
223
  control.onDestroy.add(invoke);
@@ -290,30 +346,6 @@ class Subscriber {
290
346
  }
291
347
  }
292
348
 
293
- const Oops$b = issues({
294
- ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
295
- });
296
- function suspend(source, key) {
297
- const error = Oops$b.ValueNotReady(source.subject, key);
298
- const promise = new Promise(resolve => {
299
- const release = source.addListener(forKey => {
300
- if (forKey == key)
301
- return () => {
302
- if (source.state[key] !== undefined) {
303
- release();
304
- resolve();
305
- }
306
- };
307
- });
308
- });
309
- return Object.assign(promise, {
310
- toString: () => String(error),
311
- name: "Suspense",
312
- message: error.message,
313
- stack: error.stack
314
- });
315
- }
316
-
317
349
  const Oops$a = issues({
318
350
  BadComputedSource: (model, property, got) => `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
319
351
  PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
@@ -691,18 +723,19 @@ const Oops$8 = issues({
691
723
  function act(task) {
692
724
  return apply(function act(key) {
693
725
  let pending = false;
694
- const invoke = (...args) => {
726
+ const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
695
727
  if (pending)
696
728
  return Promise.reject(Oops$8.DuplicateAction(key));
697
729
  pending = true;
698
730
  this.update(key);
699
- return new Promise(res => {
700
- res(task.apply(this.subject, args));
701
- }).finally(() => {
731
+ try {
732
+ return yield mayRetry(() => (task.apply(this.subject, args)));
733
+ }
734
+ finally {
702
735
  pending = false;
703
736
  this.update(key);
704
- });
705
- };
737
+ }
738
+ });
706
739
  this.state[key] = undefined;
707
740
  defineProperty(invoke, "active", {
708
741
  get: () => pending
@@ -832,7 +865,7 @@ function pendingFactory(parent, key, fn, required) {
832
865
  let pending;
833
866
  let error;
834
867
  const init = () => {
835
- const output = suspenseBoundary(() => {
868
+ const output = mayRetry(() => {
836
869
  return fn.call(subject, key, subject);
837
870
  });
838
871
  if (output instanceof Promise) {