@legendapp/state 1.0.0-rc.31 → 1.0.0-rc.32
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/index.d.ts +1 -1
- package/index.js +235 -216
- package/index.js.map +1 -1
- package/index.mjs +235 -217
- package/index.mjs.map +1 -1
- package/package.json +1 -1
- package/persist.js +8 -6
- package/persist.js.map +1 -1
- package/persist.mjs +9 -7
- package/persist.mjs.map +1 -1
- package/react.js +38 -28
- package/react.js.map +1 -1
- package/react.mjs +39 -29
- package/react.mjs.map +1 -1
- package/src/batching.d.ts +8 -10
- package/src/observableInterfaces.d.ts +2 -1
- package/src/observe.d.ts +1 -2
- package/src/react/For.d.ts +1 -0
- package/src/react/Switch.d.ts +5 -10
- package/src/react/useObserve.d.ts +4 -4
- package/src/react/useObserveEffect.d.ts +4 -4
- package/src/when.d.ts +1 -0
- package/src/notify.d.ts +0 -3
package/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { batch, beginBatch, endBatch, afterBatch } from './src/batching';
|
|
|
4
4
|
export { computed } from './src/computed';
|
|
5
5
|
export { event } from './src/event';
|
|
6
6
|
export { observe } from './src/observe';
|
|
7
|
-
export { when } from './src/when';
|
|
7
|
+
export { when, whenReady } from './src/when';
|
|
8
8
|
export * from './src/observableInterfaces';
|
|
9
9
|
export { isEmpty, isArray, isBoolean, isFunction, isObject, isPrimitive, isPromise, isString, isSymbol, } from './src/is';
|
|
10
10
|
import { setAtPath, getNode } from './src/helpers';
|
package/index.js
CHANGED
|
@@ -51,155 +51,6 @@ function isChildNodeValue(node) {
|
|
|
51
51
|
return !!node.parent;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
let timeout;
|
|
55
|
-
let numInBatch = 0;
|
|
56
|
-
let isRunningBatch = false;
|
|
57
|
-
let didDelayEndBatch = false;
|
|
58
|
-
let _batch = [];
|
|
59
|
-
let _afterBatch = [];
|
|
60
|
-
// Use a Map of callbacks for fast lookups to update the BatchItem
|
|
61
|
-
let _batchMap = new Map();
|
|
62
|
-
function onActionTimeout() {
|
|
63
|
-
if (_batch.length > 0) {
|
|
64
|
-
if (process.env.NODE_ENV === 'development') {
|
|
65
|
-
console.error('Forcibly completing observableBatcher because end() was never called. This may be due to an uncaught error between begin() and end().');
|
|
66
|
-
}
|
|
67
|
-
endBatch(/*force*/ true);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
function createPreviousHandler(value, changes) {
|
|
71
|
-
// Create a function that clones the current state and injects the previous data at the changed path
|
|
72
|
-
return function () {
|
|
73
|
-
let clone = value ? JSON.parse(JSON.stringify(value)) : {};
|
|
74
|
-
for (let i = 0; i < changes.length; i++) {
|
|
75
|
-
const { path, prevAtPath } = changes[i];
|
|
76
|
-
let o = clone;
|
|
77
|
-
if (path.length > 0) {
|
|
78
|
-
let i;
|
|
79
|
-
for (i = 0; i < path.length - 1; i++) {
|
|
80
|
-
o = o[path[i]];
|
|
81
|
-
}
|
|
82
|
-
o[path[i]] = prevAtPath;
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
clone = prevAtPath;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return clone;
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
function batchNotify(b, immediate) {
|
|
92
|
-
const isFunc = isFunction(b);
|
|
93
|
-
const cb = isFunc ? b : b.cb;
|
|
94
|
-
if (!immediate && numInBatch > 0) {
|
|
95
|
-
// Set a timeout to call end() in case end() is never called or there's an uncaught error
|
|
96
|
-
if (!timeout) {
|
|
97
|
-
timeout = setTimeout(onActionTimeout, 0);
|
|
98
|
-
}
|
|
99
|
-
const existing = _batchMap.get(cb);
|
|
100
|
-
// If this callback already exists, make sure it has the latest value but do not add it
|
|
101
|
-
if (existing) {
|
|
102
|
-
if (!isFunc) {
|
|
103
|
-
const params = existing.params;
|
|
104
|
-
params.value = b.params.value;
|
|
105
|
-
params.changes.push(...b.params.changes);
|
|
106
|
-
params.getPrevious = createPreviousHandler(params.value, params.changes);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
if (!isFunc) {
|
|
111
|
-
b.params.getPrevious = createPreviousHandler(b.params.value, b.params.changes);
|
|
112
|
-
}
|
|
113
|
-
_batch.push(b);
|
|
114
|
-
_batchMap.set(cb, isFunc ? true : b);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
// If not batched callback immediately
|
|
119
|
-
if (isFunc) {
|
|
120
|
-
b();
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
b.params.getPrevious = createPreviousHandler(b.params.value, b.params.changes);
|
|
124
|
-
b.cb(b.params);
|
|
125
|
-
}
|
|
126
|
-
if (numInBatch === 0) {
|
|
127
|
-
// Run afterBatch callbacks if this is not batched
|
|
128
|
-
const after = _afterBatch;
|
|
129
|
-
_afterBatch = [];
|
|
130
|
-
for (let i = 0; i < after.length; i++) {
|
|
131
|
-
after[i]();
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
function batch(fn, onComplete) {
|
|
137
|
-
if (onComplete) {
|
|
138
|
-
_afterBatch.push(onComplete);
|
|
139
|
-
}
|
|
140
|
-
beginBatch();
|
|
141
|
-
try {
|
|
142
|
-
fn();
|
|
143
|
-
}
|
|
144
|
-
finally {
|
|
145
|
-
endBatch();
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
function beginBatch() {
|
|
149
|
-
numInBatch++;
|
|
150
|
-
}
|
|
151
|
-
function endBatch(force) {
|
|
152
|
-
numInBatch--;
|
|
153
|
-
if (numInBatch <= 0 || force) {
|
|
154
|
-
if (isRunningBatch) {
|
|
155
|
-
// Don't want to run multiple endBatches recursively, so just note that an endBatch
|
|
156
|
-
// was delayed so that the top level endBatch will run endBatch again after it's done.
|
|
157
|
-
didDelayEndBatch = true;
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
if (timeout) {
|
|
161
|
-
clearTimeout(timeout);
|
|
162
|
-
timeout = undefined;
|
|
163
|
-
}
|
|
164
|
-
numInBatch = 0;
|
|
165
|
-
// Save batch locally and reset _batch first because a new batch could begin while looping over callbacks.
|
|
166
|
-
// This can happen with observableComputed for example.
|
|
167
|
-
const batch = _batch;
|
|
168
|
-
const after = _afterBatch;
|
|
169
|
-
_batch = [];
|
|
170
|
-
_batchMap = new Map();
|
|
171
|
-
_afterBatch = [];
|
|
172
|
-
isRunningBatch = true;
|
|
173
|
-
for (let i = 0; i < batch.length; i++) {
|
|
174
|
-
const b = batch[i];
|
|
175
|
-
if (isFunction(b)) {
|
|
176
|
-
b();
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
const { cb } = b;
|
|
180
|
-
cb(b.params);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
for (let i = 0; i < after.length; i++) {
|
|
184
|
-
after[i]();
|
|
185
|
-
}
|
|
186
|
-
isRunningBatch = false;
|
|
187
|
-
if (didDelayEndBatch) {
|
|
188
|
-
didDelayEndBatch = false;
|
|
189
|
-
endBatch(true);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
function afterBatch(fn) {
|
|
195
|
-
if (numInBatch > 0) {
|
|
196
|
-
_afterBatch.push(fn);
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
fn();
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
54
|
let trackCount = 0;
|
|
204
55
|
const trackingQueue = [];
|
|
205
56
|
const tracking = {
|
|
@@ -331,6 +182,206 @@ function findIDKey(obj, node) {
|
|
|
331
182
|
return idKey;
|
|
332
183
|
}
|
|
333
184
|
|
|
185
|
+
let timeout;
|
|
186
|
+
let numInBatch = 0;
|
|
187
|
+
let isRunningBatch = false;
|
|
188
|
+
let didDelayEndBatch = false;
|
|
189
|
+
let _afterBatch = [];
|
|
190
|
+
let _batchMap = new Map();
|
|
191
|
+
function onActionTimeout() {
|
|
192
|
+
if (_batchMap.size > 0) {
|
|
193
|
+
if (process.env.NODE_ENV === 'development') {
|
|
194
|
+
console.error('Forcibly completing observableBatcher because end() was never called. This may be due to an uncaught error between begin() and end().');
|
|
195
|
+
}
|
|
196
|
+
endBatch(/*force*/ true);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function createPreviousHandlerInner(value, changes) {
|
|
200
|
+
// Clones the current state and inject the previous data at the changed path
|
|
201
|
+
let clone = value ? JSON.parse(JSON.stringify(value)) : {};
|
|
202
|
+
for (let i = 0; i < changes.length; i++) {
|
|
203
|
+
const { path, prevAtPath } = changes[i];
|
|
204
|
+
let o = clone;
|
|
205
|
+
if (path.length > 0) {
|
|
206
|
+
let i;
|
|
207
|
+
for (i = 0; i < path.length - 1; i++) {
|
|
208
|
+
o = o[path[i]];
|
|
209
|
+
}
|
|
210
|
+
o[path[i]] = prevAtPath;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
clone = prevAtPath;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return clone;
|
|
217
|
+
}
|
|
218
|
+
function createPreviousHandler(value, changes) {
|
|
219
|
+
// Create a function that generates the previous state
|
|
220
|
+
// We don't want to always do this because cloning is expensive
|
|
221
|
+
// so it's better to run on demand.
|
|
222
|
+
return function () {
|
|
223
|
+
return createPreviousHandlerInner(value, changes);
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function notify(node, value, prev, level, whenOptimizedOnlyIf) {
|
|
227
|
+
// Run immediate listeners if there are any
|
|
228
|
+
const changesInBatch = new Map();
|
|
229
|
+
computeChangesRecursive(changesInBatch, node, value, [], [], value, prev,
|
|
230
|
+
/*immediate*/ true, level, whenOptimizedOnlyIf);
|
|
231
|
+
batchNotifyChanges(changesInBatch, /*immediate*/ true);
|
|
232
|
+
// Update the current batch
|
|
233
|
+
const existing = _batchMap.get(node);
|
|
234
|
+
if (existing) {
|
|
235
|
+
existing.value = value;
|
|
236
|
+
// TODO: level, whenOptimizedOnlyIf
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
_batchMap.set(node, { value, prev, level, whenOptimizedOnlyIf });
|
|
240
|
+
}
|
|
241
|
+
// If not in a batch run it immediately
|
|
242
|
+
if (numInBatch <= 0) {
|
|
243
|
+
runBatch();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function computeChangesAtNode(changesInBatch, node, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf) {
|
|
247
|
+
// If there are listeners at this node compute the changes that need to be run
|
|
248
|
+
if (immediate ? node.listenersImmediate : node.listeners) {
|
|
249
|
+
const change = {
|
|
250
|
+
path,
|
|
251
|
+
pathTypes,
|
|
252
|
+
valueAtPath,
|
|
253
|
+
prevAtPath,
|
|
254
|
+
};
|
|
255
|
+
const changeInBatch = changesInBatch.get(node);
|
|
256
|
+
// If the node itself has been changed then we can ignore all the child changes
|
|
257
|
+
if (changeInBatch && path.length > 0) {
|
|
258
|
+
changeInBatch.changes.push(change);
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
changesInBatch.set(node, {
|
|
262
|
+
level,
|
|
263
|
+
value,
|
|
264
|
+
whenOptimizedOnlyIf,
|
|
265
|
+
changes: [change],
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
function computeChangesRecursive(changesInBatch, node, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf) {
|
|
271
|
+
// Do the compute at this node
|
|
272
|
+
computeChangesAtNode(changesInBatch, node, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf);
|
|
273
|
+
// If not root notify up through parents
|
|
274
|
+
if (node.parent) {
|
|
275
|
+
const parent = node.parent;
|
|
276
|
+
if (parent) {
|
|
277
|
+
const parentValue = getNodeValue(parent);
|
|
278
|
+
computeChangesRecursive(changesInBatch, parent, parentValue, [node.key].concat(path), [(isArray(value) ? 'array' : 'object')].concat(pathTypes), valueAtPath, prevAtPath, immediate, level + 1, whenOptimizedOnlyIf);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function batchNotifyChanges(changesInBatch, immediate) {
|
|
283
|
+
// For each change in the batch, notify all of the listeners
|
|
284
|
+
changesInBatch.forEach(({ changes, level, value, whenOptimizedOnlyIf }, node) => {
|
|
285
|
+
const listeners = immediate ? node.listenersImmediate : node.listeners;
|
|
286
|
+
if (listeners) {
|
|
287
|
+
let listenerParams;
|
|
288
|
+
// Need to convert to an array here instead of using a for...of loop because listeners can change while iterating
|
|
289
|
+
const arr = Array.from(listeners);
|
|
290
|
+
for (let i = 0; i < arr.length; i++) {
|
|
291
|
+
const listenerFn = arr[i];
|
|
292
|
+
const { track, noArgs, listener } = listenerFn;
|
|
293
|
+
const ok = track === true || track === 'shallow'
|
|
294
|
+
? level <= 0
|
|
295
|
+
: track === 'optimize'
|
|
296
|
+
? whenOptimizedOnlyIf && level <= 0
|
|
297
|
+
: true;
|
|
298
|
+
// Notify if listener is not shallow or if this is the first level
|
|
299
|
+
if (ok) {
|
|
300
|
+
// Create listenerParams if not already created
|
|
301
|
+
if (!noArgs && !listenerParams) {
|
|
302
|
+
listenerParams = {
|
|
303
|
+
value,
|
|
304
|
+
getPrevious: createPreviousHandler(value, changes),
|
|
305
|
+
changes,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
listener(listenerParams);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
function runBatch() {
|
|
315
|
+
const map = _batchMap;
|
|
316
|
+
_batchMap = new Map();
|
|
317
|
+
const changesInBatch = new Map();
|
|
318
|
+
// First compute all of the changes at each node. It's important to do this first before
|
|
319
|
+
// running all the notifications because createPreviousHandler depends on knowing
|
|
320
|
+
// all of the changes happening at the node.
|
|
321
|
+
map.forEach(({ value, prev, level, whenOptimizedOnlyIf }, node) => {
|
|
322
|
+
computeChangesRecursive(changesInBatch, node, value, [], [], value, prev, false, level, whenOptimizedOnlyIf);
|
|
323
|
+
});
|
|
324
|
+
// Once all changes are computed, notify all listeners for each node with the computed changes.
|
|
325
|
+
batchNotifyChanges(changesInBatch, false);
|
|
326
|
+
}
|
|
327
|
+
function batch(fn, onComplete) {
|
|
328
|
+
if (onComplete) {
|
|
329
|
+
_afterBatch.push(onComplete);
|
|
330
|
+
}
|
|
331
|
+
beginBatch();
|
|
332
|
+
try {
|
|
333
|
+
fn();
|
|
334
|
+
}
|
|
335
|
+
finally {
|
|
336
|
+
endBatch();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
function beginBatch() {
|
|
340
|
+
numInBatch++;
|
|
341
|
+
if (!timeout) {
|
|
342
|
+
timeout = setTimeout(onActionTimeout, 0);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function endBatch(force) {
|
|
346
|
+
numInBatch--;
|
|
347
|
+
if (numInBatch <= 0 || force) {
|
|
348
|
+
if (isRunningBatch) {
|
|
349
|
+
// Don't want to run multiple endBatches recursively, so just note that an endBatch
|
|
350
|
+
// was delayed so that the top level endBatch will run endBatch again after it's done.
|
|
351
|
+
didDelayEndBatch = true;
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
if (timeout) {
|
|
355
|
+
clearTimeout(timeout);
|
|
356
|
+
timeout = undefined;
|
|
357
|
+
}
|
|
358
|
+
numInBatch = 0;
|
|
359
|
+
// Save batch locally and reset _batch first because a new batch could begin while looping over callbacks.
|
|
360
|
+
// This can happen with observableComputed for example.
|
|
361
|
+
const after = _afterBatch;
|
|
362
|
+
_afterBatch = [];
|
|
363
|
+
isRunningBatch = true;
|
|
364
|
+
runBatch();
|
|
365
|
+
isRunningBatch = false;
|
|
366
|
+
if (didDelayEndBatch) {
|
|
367
|
+
didDelayEndBatch = false;
|
|
368
|
+
endBatch(true);
|
|
369
|
+
}
|
|
370
|
+
for (let i = 0; i < after.length; i++) {
|
|
371
|
+
after[i]();
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
function afterBatch(fn) {
|
|
377
|
+
if (numInBatch > 0) {
|
|
378
|
+
_afterBatch.push(fn);
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
fn();
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
334
385
|
function isObservable(obs) {
|
|
335
386
|
return obs && !!obs[symbolIsObservable];
|
|
336
387
|
}
|
|
@@ -480,69 +531,23 @@ function isObservableValueReady(value) {
|
|
|
480
531
|
return !!value && ((!isObject(value) && !isArray(value)) || !isEmpty(value));
|
|
481
532
|
}
|
|
482
533
|
|
|
483
|
-
function doNotify(node, value, path, pathTypes, valueAtPath, prevAtPath, level, whenOptimizedOnlyIf) {
|
|
484
|
-
const listeners = node.listeners;
|
|
485
|
-
if (listeners) {
|
|
486
|
-
let listenerParams;
|
|
487
|
-
// Need to convert to an array here instead of using a for...of loop because listeners can change while iterating
|
|
488
|
-
const arr = Array.from(listeners);
|
|
489
|
-
for (let i = 0; i < arr.length; i++) {
|
|
490
|
-
const listenerFn = arr[i];
|
|
491
|
-
const { track, noArgs, immediate, listener } = listenerFn;
|
|
492
|
-
const ok = track === true || track === 'shallow'
|
|
493
|
-
? level <= 0
|
|
494
|
-
: track === 'optimize'
|
|
495
|
-
? whenOptimizedOnlyIf && level <= 0
|
|
496
|
-
: true;
|
|
497
|
-
// Notify if listener is not shallow or if this is the first level
|
|
498
|
-
if (ok) {
|
|
499
|
-
if (!noArgs && !listenerParams) {
|
|
500
|
-
listenerParams = {
|
|
501
|
-
value,
|
|
502
|
-
changes: [
|
|
503
|
-
{
|
|
504
|
-
path,
|
|
505
|
-
pathTypes,
|
|
506
|
-
valueAtPath,
|
|
507
|
-
prevAtPath,
|
|
508
|
-
},
|
|
509
|
-
],
|
|
510
|
-
};
|
|
511
|
-
}
|
|
512
|
-
batchNotify(noArgs ? listener : { cb: listener, params: listenerParams }, immediate);
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
function _notifyParents(node, value, path, pathTypes, valueAtPath, prevAtPath, level, whenOptimizedOnlyIf) {
|
|
518
|
-
// Do the notify
|
|
519
|
-
doNotify(node, value, path, pathTypes, valueAtPath, prevAtPath, level, whenOptimizedOnlyIf);
|
|
520
|
-
// If not root notify up through parents
|
|
521
|
-
if (node.parent) {
|
|
522
|
-
const parent = node.parent;
|
|
523
|
-
if (parent) {
|
|
524
|
-
const parentValue = getNodeValue(parent);
|
|
525
|
-
_notifyParents(parent, parentValue, [node.key].concat(path), [(isArray(value) ? 'array' : 'object')].concat(pathTypes), valueAtPath, prevAtPath, level + 1, whenOptimizedOnlyIf);
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
function notify(node, value, prev, level, whenOptimizedOnlyIf) {
|
|
530
|
-
// Notify self and up through parents
|
|
531
|
-
_notifyParents(node, value, [], [], value, prev, level, whenOptimizedOnlyIf);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
534
|
function onChange(node, callback, options, noArgs) {
|
|
535
|
-
|
|
535
|
+
const { trackingType, initial, immediate } = options || {};
|
|
536
|
+
let listeners = immediate ? node.listenersImmediate : node.listeners;
|
|
536
537
|
if (!listeners) {
|
|
537
|
-
|
|
538
|
+
listeners = new Set();
|
|
539
|
+
if (immediate) {
|
|
540
|
+
node.listenersImmediate = listeners;
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
node.listeners = listeners;
|
|
544
|
+
}
|
|
538
545
|
}
|
|
539
546
|
checkActivate(node);
|
|
540
|
-
const { trackingType, initial, immediate } = options || {};
|
|
541
547
|
const listener = {
|
|
542
548
|
listener: callback,
|
|
543
549
|
track: trackingType,
|
|
544
550
|
noArgs,
|
|
545
|
-
immediate: immediate,
|
|
546
551
|
};
|
|
547
552
|
listeners.add(listener);
|
|
548
553
|
let parent = node.parent;
|
|
@@ -610,7 +615,7 @@ ObservablePrimitiveClass.prototype.set = function (value) {
|
|
|
610
615
|
const root = this._node.root;
|
|
611
616
|
const prev = root._;
|
|
612
617
|
root._ = value;
|
|
613
|
-
|
|
618
|
+
notify(this._node, value, prev, 0);
|
|
614
619
|
return this;
|
|
615
620
|
};
|
|
616
621
|
ObservablePrimitiveClass.prototype.toggle = function () {
|
|
@@ -623,6 +628,10 @@ ObservablePrimitiveClass.prototype.toggle = function () {
|
|
|
623
628
|
}
|
|
624
629
|
return !value;
|
|
625
630
|
};
|
|
631
|
+
ObservablePrimitiveClass.prototype.delete = function () {
|
|
632
|
+
this.set(undefined);
|
|
633
|
+
return this;
|
|
634
|
+
};
|
|
626
635
|
// Listener
|
|
627
636
|
ObservablePrimitiveClass.prototype.onChange = function (cb, options, noArgs) {
|
|
628
637
|
return onChange(this._node, cb, options, noArgs);
|
|
@@ -685,8 +694,8 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
685
694
|
if ((isObject(obj) && obj[symbolOpaque]) || (isObject(prevValue) && prevValue[symbolOpaque])) {
|
|
686
695
|
const isDiff = obj !== prevValue;
|
|
687
696
|
if (isDiff) {
|
|
688
|
-
if (parent.listeners) {
|
|
689
|
-
|
|
697
|
+
if (parent.listeners || parent.listenersImmediate) {
|
|
698
|
+
notify(parent, obj, prevValue, 0);
|
|
690
699
|
}
|
|
691
700
|
}
|
|
692
701
|
return isDiff;
|
|
@@ -747,8 +756,8 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
747
756
|
if (!isPrimitive(prev)) {
|
|
748
757
|
updateNodes(child, undefined, prev);
|
|
749
758
|
}
|
|
750
|
-
if (child.listeners) {
|
|
751
|
-
|
|
759
|
+
if (child.listeners || child.listenersImmediate) {
|
|
760
|
+
notify(child, undefined, prev, 0);
|
|
752
761
|
}
|
|
753
762
|
}
|
|
754
763
|
}
|
|
@@ -815,8 +824,8 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
815
824
|
// Or if the position changed in an array whose length did not change
|
|
816
825
|
// But do not notify child if the parent is an array with changing length -
|
|
817
826
|
// the array's listener will cover it
|
|
818
|
-
if (child.listeners) {
|
|
819
|
-
|
|
827
|
+
if (child.listeners || child.listenersImmediate) {
|
|
828
|
+
notify(child, value, prev, 0, !isArrDiff);
|
|
820
829
|
}
|
|
821
830
|
}
|
|
822
831
|
}
|
|
@@ -1183,10 +1192,12 @@ function observe(selectorOrRun, reactionOrOptions, options) {
|
|
|
1183
1192
|
e.onCleanupReaction();
|
|
1184
1193
|
e.onCleanupReaction = undefined;
|
|
1185
1194
|
}
|
|
1195
|
+
// Call the reaction if there is one and the value changed
|
|
1186
1196
|
if (reaction && (e.num > 0 || !selectorOrRun[symbolIsEvent]) && e.previous !== e.value) {
|
|
1187
1197
|
reaction(e);
|
|
1188
|
-
e.previous = e.value;
|
|
1189
1198
|
}
|
|
1199
|
+
// Update the previous value
|
|
1200
|
+
e.previous = e.value;
|
|
1190
1201
|
// Increment the counter
|
|
1191
1202
|
e.num++;
|
|
1192
1203
|
endBatch();
|
|
@@ -1254,12 +1265,12 @@ function event() {
|
|
|
1254
1265
|
};
|
|
1255
1266
|
}
|
|
1256
1267
|
|
|
1257
|
-
function
|
|
1268
|
+
function _when(predicate, effect, checkReady) {
|
|
1258
1269
|
let value;
|
|
1259
1270
|
// Create a wrapping fn that calls the effect if predicate returns true
|
|
1260
1271
|
function run(e) {
|
|
1261
1272
|
const ret = computeSelector(predicate);
|
|
1262
|
-
if (isObservableValueReady(ret)) {
|
|
1273
|
+
if (checkReady ? isObservableValueReady(ret) : ret) {
|
|
1263
1274
|
value = ret;
|
|
1264
1275
|
// If value is truthy then run the effect
|
|
1265
1276
|
effect === null || effect === void 0 ? void 0 : effect(ret);
|
|
@@ -1267,14 +1278,15 @@ function when(predicate, effect) {
|
|
|
1267
1278
|
e.cancel = true;
|
|
1268
1279
|
}
|
|
1269
1280
|
}
|
|
1270
|
-
//
|
|
1281
|
+
// Run in an observe
|
|
1271
1282
|
observe(run);
|
|
1272
|
-
// If first run resulted in a truthy value just return it
|
|
1283
|
+
// If first run resulted in a truthy value just return it.
|
|
1273
1284
|
// It will have set e.cancel so no need to dispose
|
|
1274
1285
|
if (value !== undefined) {
|
|
1275
1286
|
return Promise.resolve(value);
|
|
1276
1287
|
}
|
|
1277
1288
|
else {
|
|
1289
|
+
// Wrap it in a promise
|
|
1278
1290
|
const promise = new Promise((resolve) => {
|
|
1279
1291
|
if (effect) {
|
|
1280
1292
|
const originalEffect = effect;
|
|
@@ -1290,6 +1302,12 @@ function when(predicate, effect) {
|
|
|
1290
1302
|
return promise;
|
|
1291
1303
|
}
|
|
1292
1304
|
}
|
|
1305
|
+
function when(predicate, effect) {
|
|
1306
|
+
return _when(predicate, effect, false);
|
|
1307
|
+
}
|
|
1308
|
+
function whenReady(predicate, effect) {
|
|
1309
|
+
return _when(predicate, effect, true);
|
|
1310
|
+
}
|
|
1293
1311
|
|
|
1294
1312
|
const internal = {
|
|
1295
1313
|
getNode,
|
|
@@ -1344,4 +1362,5 @@ exports.symbolIsObservable = symbolIsObservable;
|
|
|
1344
1362
|
exports.tracking = tracking;
|
|
1345
1363
|
exports.updateTracking = updateTracking;
|
|
1346
1364
|
exports.when = when;
|
|
1365
|
+
exports.whenReady = whenReady;
|
|
1347
1366
|
//# sourceMappingURL=index.js.map
|