@webqit/observer 2.0.7 → 2.1.1
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/.gitignore +3 -3
- package/LICENSE +20 -20
- package/README.md +425 -202
- package/dist/main.js +1 -1
- package/dist/main.js.map +3 -3
- package/package.json +68 -68
- package/src/actors.js +180 -176
- package/src/core/Descriptor.js +22 -22
- package/src/core/ListenerRegistration.js +61 -57
- package/src/core/ListenerRegistry.js +73 -70
- package/src/core/Registration.js +34 -34
- package/src/core/Registry.js +92 -92
- package/src/core/TrapsRegistration.js +34 -34
- package/src/core/TrapsRegistry.js +50 -50
- package/src/index.js +9 -9
- package/src/main.js +585 -561
- package/src/targets.browser.js +8 -8
- package/src/util.js +9 -7
- package/test/reactions.test.js +351 -352
- package/webpack.config.cjs +5 -5
package/src/main.js
CHANGED
|
@@ -1,561 +1,585 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import { _isObject, _isTypeObject, _isFunction, _getType } from '@webqit/util/js/index.js';
|
|
6
|
-
import { _from as _arrFrom } from '@webqit/util/arr/index.js';
|
|
7
|
-
import ListenerRegistry from './core/ListenerRegistry.js';
|
|
8
|
-
import TrapsRegistry from './core/TrapsRegistry.js';
|
|
9
|
-
import Descriptor from './core/Descriptor.js';
|
|
10
|
-
import { unproxy } from './actors.js';
|
|
11
|
-
import { _ } from './util.js';
|
|
12
|
-
|
|
13
|
-
/* ---------------SPECIAL APIs--------------- */
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Reduces a path array against handler.
|
|
17
|
-
*
|
|
18
|
-
* @param Array|Object target
|
|
19
|
-
* @param Array path
|
|
20
|
-
* @param Function receiver
|
|
21
|
-
* @param Function final
|
|
22
|
-
* @param Object params
|
|
23
|
-
*
|
|
24
|
-
* @example deep( object, [ segement1, segement2 ], observe, ( value, flags ) => {}, params );
|
|
25
|
-
*
|
|
26
|
-
* @return Any
|
|
27
|
-
*/
|
|
28
|
-
export function deep( target, path, receiver, final = x => x, params = {} ) {
|
|
29
|
-
return ( function eat( target, path,
|
|
30
|
-
const segment = path[
|
|
31
|
-
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* @param Array|Object target
|
|
133
|
-
* @param String|Number prop
|
|
134
|
-
* @param Function receiver
|
|
135
|
-
* @param Object params
|
|
136
|
-
*
|
|
137
|
-
* @return Any
|
|
138
|
-
*/
|
|
139
|
-
export function
|
|
140
|
-
return exec( target, '
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Performs a "
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* @param
|
|
148
|
-
* @param
|
|
149
|
-
*
|
|
150
|
-
* @
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* @param Object
|
|
162
|
-
*
|
|
163
|
-
* @
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* @param Object
|
|
175
|
-
*
|
|
176
|
-
* @
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
* @param
|
|
188
|
-
* @param
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
* @param
|
|
201
|
-
* @param
|
|
202
|
-
* @param
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
* @param
|
|
274
|
-
* @param
|
|
275
|
-
* @param
|
|
276
|
-
*
|
|
277
|
-
* @return
|
|
278
|
-
*/
|
|
279
|
-
export function
|
|
280
|
-
|
|
281
|
-
target
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
const descriptor =
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
326
|
-
// ---------
|
|
327
|
-
|
|
328
|
-
if (
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
*
|
|
360
|
-
*
|
|
361
|
-
* @param Object
|
|
362
|
-
* @param
|
|
363
|
-
* @param Object
|
|
364
|
-
*
|
|
365
|
-
* @
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
*
|
|
375
|
-
* @
|
|
376
|
-
*
|
|
377
|
-
* @param Object
|
|
378
|
-
*
|
|
379
|
-
* @
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
*/
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
/**
|
|
443
|
-
*
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
*
|
|
459
|
-
*
|
|
460
|
-
* @
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
*
|
|
473
|
-
*
|
|
474
|
-
*
|
|
475
|
-
* @
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
* @
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
*
|
|
518
|
-
* @
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
if ( arguments.length
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
function
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
*/
|
|
5
|
+
import { _isObject, _isTypeObject, _isFunction, _getType } from '@webqit/util/js/index.js';
|
|
6
|
+
import { _from as _arrFrom } from '@webqit/util/arr/index.js';
|
|
7
|
+
import ListenerRegistry from './core/ListenerRegistry.js';
|
|
8
|
+
import TrapsRegistry from './core/TrapsRegistry.js';
|
|
9
|
+
import Descriptor from './core/Descriptor.js';
|
|
10
|
+
import { unproxy } from './actors.js';
|
|
11
|
+
import { _, _await } from './util.js';
|
|
12
|
+
|
|
13
|
+
/* ---------------SPECIAL APIs--------------- */
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Reduces a path array against handler.
|
|
17
|
+
*
|
|
18
|
+
* @param Array|Object target
|
|
19
|
+
* @param Array path
|
|
20
|
+
* @param Function receiver
|
|
21
|
+
* @param Function final
|
|
22
|
+
* @param Object params
|
|
23
|
+
*
|
|
24
|
+
* @example deep( object, [ segement1, segement2 ], observe, ( value, flags ) => {}, params );
|
|
25
|
+
*
|
|
26
|
+
* @return Any
|
|
27
|
+
*/
|
|
28
|
+
export function deep( target, path, receiver, final = x => x, params = {} ) {
|
|
29
|
+
return ( function eat( target, path, $params ) {
|
|
30
|
+
const segment = path[ $params.level ];
|
|
31
|
+
const isLastSegment = $params.level === path.length - 1;
|
|
32
|
+
if ( target instanceof Descriptor && target.type !== 'get' ) {
|
|
33
|
+
// Always probe event-generated trees
|
|
34
|
+
$params = { ...$params, probe: 'always' };
|
|
35
|
+
} else if ( $params.probe !== 'always' ) {
|
|
36
|
+
// Probe until (before) last segment
|
|
37
|
+
$params = { ...$params, probe: !isLastSegment };
|
|
38
|
+
}
|
|
39
|
+
// ---------------
|
|
40
|
+
return receiver( target, segment, ( result, ...args ) => {
|
|
41
|
+
// -----------
|
|
42
|
+
const addTrail = desc => {
|
|
43
|
+
if ( !( desc instanceof Descriptor ) ) return;
|
|
44
|
+
desc.path = [ desc.key ];
|
|
45
|
+
if ( target instanceof Descriptor ) {
|
|
46
|
+
desc.path = target.path.concat( desc.key );
|
|
47
|
+
Object.defineProperty( desc, 'context', { get: () => target } );
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const advance = result => {
|
|
51
|
+
const $value = resolveObj( result/* a Descriptor who's value could be proxied */, false );
|
|
52
|
+
return _await( $value/* could be a promise */, $value => {
|
|
53
|
+
if ( result instanceof Descriptor ) {
|
|
54
|
+
result.value = $value; // Update to (fulfilled), unproxied, value
|
|
55
|
+
} else {
|
|
56
|
+
result = $value;
|
|
57
|
+
}
|
|
58
|
+
const flags = args[ 0 ] || {};
|
|
59
|
+
return eat( result, path, { ...$params, ...flags, level: $params.level + 1, } );
|
|
60
|
+
} );
|
|
61
|
+
};
|
|
62
|
+
// -----------
|
|
63
|
+
if ( isPropsList( segment ) && Array.isArray( result ) ) {
|
|
64
|
+
result.forEach( addTrail );
|
|
65
|
+
if ( isLastSegment ) return final( result, ...args );
|
|
66
|
+
return result.map( advance );
|
|
67
|
+
}
|
|
68
|
+
// -----------
|
|
69
|
+
addTrail( result );
|
|
70
|
+
if ( isLastSegment ) return final( result, ...args );
|
|
71
|
+
return advance( result );
|
|
72
|
+
// -----------
|
|
73
|
+
}, $params );
|
|
74
|
+
} )( target, path.slice( 0 ), { ...params, level: 0 } );
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Adds an observer to a target's registry.
|
|
79
|
+
*
|
|
80
|
+
* @param Array|Object target
|
|
81
|
+
* @param String|Object prop
|
|
82
|
+
* @param Function receiver
|
|
83
|
+
* @param Object params
|
|
84
|
+
*
|
|
85
|
+
* @return AbortController
|
|
86
|
+
*/
|
|
87
|
+
export function observe( target, prop, receiver, params = {} ) {
|
|
88
|
+
// ---------------
|
|
89
|
+
target = resolveObj( target, !params.level );
|
|
90
|
+
if ( _isFunction( arguments[ 1 ] ) ) {
|
|
91
|
+
[ , receiver, params = {} ] = arguments;
|
|
92
|
+
prop = Infinity;
|
|
93
|
+
}
|
|
94
|
+
if ( !_isFunction( receiver ) ) throw new Error( `Handler must be a function; "${ _getType( receiver ) }" given!` );
|
|
95
|
+
// ---------------
|
|
96
|
+
params = { ...params, descripted: true };
|
|
97
|
+
delete params.live;
|
|
98
|
+
if ( !_isTypeObject( target ) ) return params.probe && get( target, prop, receiver, params );
|
|
99
|
+
// ---------------
|
|
100
|
+
const emit = bind( target, prop, receiver, params );
|
|
101
|
+
if ( params.probe ) {
|
|
102
|
+
return get( target, prop, emit, params );
|
|
103
|
+
}
|
|
104
|
+
return emit();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Adds an interceptor object to a target's registry.
|
|
109
|
+
*
|
|
110
|
+
* @param Array|Object target
|
|
111
|
+
* @param Object traps
|
|
112
|
+
* @param Object params
|
|
113
|
+
*
|
|
114
|
+
* @return AbortRegistry
|
|
115
|
+
*/
|
|
116
|
+
export function intercept( target, traps, params = {} ) {
|
|
117
|
+
// ---------------
|
|
118
|
+
target = resolveObj( target );
|
|
119
|
+
if ( !_isObject( traps ) ) {
|
|
120
|
+
[ /*target*/, /*type*/, /*handler*/, params = {} ] = arguments;
|
|
121
|
+
traps = { [ arguments[ 1 ] ]: arguments[ 2 ] };
|
|
122
|
+
}
|
|
123
|
+
// ---------------
|
|
124
|
+
return TrapsRegistry.getInstance( target, true, params.namespace ).addRegistration( { traps, params } );
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* ---------------QUERY APIs--------------- */
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Performs a "getOwnPropertyDescriptor" operation.
|
|
131
|
+
*
|
|
132
|
+
* @param Array|Object target
|
|
133
|
+
* @param String|Number prop
|
|
134
|
+
* @param Function receiver
|
|
135
|
+
* @param Object params
|
|
136
|
+
*
|
|
137
|
+
* @return Any
|
|
138
|
+
*/
|
|
139
|
+
export function getOwnPropertyDescriptor( target, prop, receiver = x => x, params = {} ) {
|
|
140
|
+
return exec( target, 'getOwnPropertyDescriptor', { key: prop }, receiver, params );
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Performs a "getOwnPropertyDescriptors" operation.
|
|
145
|
+
* @note this isn't part of the standard Reflect API.
|
|
146
|
+
*
|
|
147
|
+
* @param Array|Object target
|
|
148
|
+
* @param String|Number prop
|
|
149
|
+
* @param Function receiver
|
|
150
|
+
* @param Object params
|
|
151
|
+
*
|
|
152
|
+
* @return Any
|
|
153
|
+
*/
|
|
154
|
+
export function getOwnPropertyDescriptors( target, prop, receiver = x => x, params = {} ) {
|
|
155
|
+
return exec( target, 'getOwnPropertyDescriptors', { key: prop }, receiver, params );
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Performs a "getPrototypeOf" operation.
|
|
160
|
+
*
|
|
161
|
+
* @param Array|Object target
|
|
162
|
+
* @param Function receiver
|
|
163
|
+
* @param Object params
|
|
164
|
+
*
|
|
165
|
+
* @return Any
|
|
166
|
+
*/
|
|
167
|
+
export function getPrototypeOf( target, receiver = x => x, params = {} ) {
|
|
168
|
+
return exec( target, 'getPrototypeOf', {}, receiver, params );
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Performs a "isExtensible" operation.
|
|
173
|
+
*
|
|
174
|
+
* @param Array|Object target
|
|
175
|
+
* @param Function receiver
|
|
176
|
+
* @param Object params
|
|
177
|
+
*
|
|
178
|
+
* @return Any
|
|
179
|
+
*/
|
|
180
|
+
export function isExtensible( target, receiver = x => x, params = {} ) {
|
|
181
|
+
return exec( target, 'isExtensible', {}, receiver, params );
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Performs a "ownKeys" operation.
|
|
186
|
+
*
|
|
187
|
+
* @param Array|Object target
|
|
188
|
+
* @param Function receiver
|
|
189
|
+
* @param Object params
|
|
190
|
+
*
|
|
191
|
+
* @return Any
|
|
192
|
+
*/
|
|
193
|
+
export function ownKeys( target, receiver = x => x, params = {} ) {
|
|
194
|
+
return exec( target, 'ownKeys', {}, receiver, params );
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Performs an operation of the given "type".
|
|
199
|
+
*
|
|
200
|
+
* @param Array|Object target
|
|
201
|
+
* @param String|Number prop
|
|
202
|
+
* @param Function receiver
|
|
203
|
+
* @param Object params
|
|
204
|
+
*
|
|
205
|
+
* @return Any
|
|
206
|
+
*/
|
|
207
|
+
export function has( target, prop, receiver = x => x, params = {} ) {
|
|
208
|
+
return exec( target, 'has', { key: prop }, receiver, params );
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Performs a get operation.
|
|
213
|
+
*
|
|
214
|
+
* @param Array|Object target
|
|
215
|
+
* @param String|Number prop
|
|
216
|
+
* @param Function receiver
|
|
217
|
+
* @param Object params
|
|
218
|
+
*
|
|
219
|
+
* @return Any
|
|
220
|
+
*/
|
|
221
|
+
export function get( target, prop, receiver = x => x, params = {} ) {
|
|
222
|
+
// ---------------
|
|
223
|
+
let isLive;
|
|
224
|
+
target = resolveObj( target, !params.level );
|
|
225
|
+
if ( _isObject( receiver ) ) { [ params, receiver ] = [ receiver, x => x ]; }
|
|
226
|
+
else if ( params.live ) { isLive = true; }
|
|
227
|
+
// ---------------
|
|
228
|
+
return resolveProps( target, prop, props => {
|
|
229
|
+
const related = [ ...props ];
|
|
230
|
+
return ( function next( results, _props, _done ) {
|
|
231
|
+
if ( !_props.length ) return _done( results );
|
|
232
|
+
const prop = _props.shift();
|
|
233
|
+
// ---------
|
|
234
|
+
function defaultGet( descriptor, value = undefined ) {
|
|
235
|
+
const _next = value => ( descriptor.value = value, next( results.concat( params.live || params.descripted ? descriptor : value ), _props, _done ) );
|
|
236
|
+
if ( arguments.length > 1 ) return _next( value );
|
|
237
|
+
const accessorizedProps = _( target, 'accessorizedProps', false );
|
|
238
|
+
const accessorization = accessorizedProps && accessorizedProps.get( descriptor.key + '' );
|
|
239
|
+
if ( accessorization && accessorization.intact() ) {
|
|
240
|
+
return _next( accessorization.getValue() );
|
|
241
|
+
}
|
|
242
|
+
return _next( Reflect.get( target, descriptor.key, ...( params.receiver ? [ params.receiver ] : [] ) ) );
|
|
243
|
+
}
|
|
244
|
+
// ---------
|
|
245
|
+
const descriptor = new Descriptor( target, {
|
|
246
|
+
type: 'get',
|
|
247
|
+
key: prop,
|
|
248
|
+
value: undefined,
|
|
249
|
+
related,
|
|
250
|
+
} );
|
|
251
|
+
if ( !_isTypeObject( target ) ) return next( results.concat( params.live || params.descripted ? descriptor : undefined ), _props, _done );
|
|
252
|
+
const listenerRegistry = TrapsRegistry.getInstance( target, false, params.namespace );
|
|
253
|
+
if ( listenerRegistry ) {
|
|
254
|
+
return listenerRegistry.emit( descriptor, defaultGet );
|
|
255
|
+
}
|
|
256
|
+
return defaultGet( descriptor );
|
|
257
|
+
} )( [], props.slice( 0 ), results => {
|
|
258
|
+
const result_s = isPropsList( prop/*original*/ ) ? results : results[ 0 ];
|
|
259
|
+
if ( isLive && _isTypeObject( target ) ) {
|
|
260
|
+
const emit = bind( target, prop, receiver, params );
|
|
261
|
+
return emit( result_s );
|
|
262
|
+
}
|
|
263
|
+
return receiver( result_s );
|
|
264
|
+
} );
|
|
265
|
+
} );
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/* ---------------MUTATION APIs--------------- */
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Performs a batch operation.
|
|
272
|
+
*
|
|
273
|
+
* @param Object target
|
|
274
|
+
* @param Function callback
|
|
275
|
+
* @param Object params
|
|
276
|
+
*
|
|
277
|
+
* @return Void
|
|
278
|
+
*/
|
|
279
|
+
export function batch( target, callback, params = {} ) {
|
|
280
|
+
target = resolveObj( target );
|
|
281
|
+
return ListenerRegistry.getInstance( target, true, params.namespace ).batch( callback );
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Performs a set operation.
|
|
286
|
+
*
|
|
287
|
+
* @param Object target
|
|
288
|
+
* @param String|Number prop
|
|
289
|
+
* @param Any value
|
|
290
|
+
* @param Function receiver
|
|
291
|
+
* @param Object params
|
|
292
|
+
* @param Bool def
|
|
293
|
+
*
|
|
294
|
+
* @return Any
|
|
295
|
+
*/
|
|
296
|
+
export function set( target, prop, value, receiver = x => x, params = {}, def = false ) {
|
|
297
|
+
// ---------------
|
|
298
|
+
target = resolveObj( target );
|
|
299
|
+
let entries = [ [ prop, value ] ];
|
|
300
|
+
if ( _isObject( prop ) ) {
|
|
301
|
+
[ /*target*/, /*hash*/, receiver = x => x, params = {}, def = false ] = arguments;
|
|
302
|
+
entries = Object.entries( prop );
|
|
303
|
+
}
|
|
304
|
+
if ( _isObject( receiver ) ) { [ def, params, receiver ] = [ typeof params === 'boolean' ? params : false, receiver, x => x ]; }
|
|
305
|
+
// ---------------
|
|
306
|
+
const related = entries.map( ( [ prop ] ) => prop );
|
|
307
|
+
return ( function next( descriptors, entries, _done ) {
|
|
308
|
+
if ( !entries.length ) return _done( descriptors );
|
|
309
|
+
const [ prop, value ] = entries.shift();
|
|
310
|
+
// ---------
|
|
311
|
+
function defaultSet( descriptor, status = undefined ) {
|
|
312
|
+
const _next = status => ( descriptor.status = status, next( descriptors.concat( descriptor ), entries, _done ) );
|
|
313
|
+
if ( arguments.length > 1 ) return _next( descriptor, status );
|
|
314
|
+
const accessorizedProps = _( target, 'accessorizedProps', false );
|
|
315
|
+
const accessorization = accessorizedProps && accessorizedProps.get( descriptor.key + '' );
|
|
316
|
+
if ( descriptor.type === 'defineProperty' ) {
|
|
317
|
+
if ( accessorization && !accessorization.restore() ) _next( false );
|
|
318
|
+
Object.defineProperty( target, descriptor.key, descriptor.value );
|
|
319
|
+
return _next( true );
|
|
320
|
+
}
|
|
321
|
+
if ( accessorization && accessorization.intact() ) {
|
|
322
|
+
return _next( accessorization.setValue( descriptor.value ) );
|
|
323
|
+
}
|
|
324
|
+
return _next( Reflect.set( target, descriptor.key, descriptor.value ) );
|
|
325
|
+
}
|
|
326
|
+
// ---------
|
|
327
|
+
function exec( isUpdate, oldValue ) {
|
|
328
|
+
if ( params.diff && value === oldValue ) return next( descriptors, entries, _done );
|
|
329
|
+
const descriptor = new Descriptor( target, {
|
|
330
|
+
type: def ? 'defineProperty' : 'set',
|
|
331
|
+
key: prop,
|
|
332
|
+
value,
|
|
333
|
+
isUpdate,
|
|
334
|
+
oldValue,
|
|
335
|
+
related: [ ...related ],
|
|
336
|
+
detail: params.detail,
|
|
337
|
+
} );
|
|
338
|
+
const listenerRegistry = TrapsRegistry.getInstance( target, false, params.namespace );
|
|
339
|
+
return listenerRegistry
|
|
340
|
+
? listenerRegistry.emit( descriptor, defaultSet )
|
|
341
|
+
: defaultSet( descriptor );
|
|
342
|
+
}
|
|
343
|
+
// ---------
|
|
344
|
+
return has( target, prop, exists => {
|
|
345
|
+
if ( !exists ) return exec( exists );
|
|
346
|
+
return get( target, prop, oldValue => exec( exists, oldValue ), params );
|
|
347
|
+
}, params );
|
|
348
|
+
// ---------
|
|
349
|
+
} )( [], entries.slice( 0 ), descriptors => {
|
|
350
|
+
const listenerRegistry = ListenerRegistry.getInstance( target, false, params.namespace );
|
|
351
|
+
if ( listenerRegistry ) listenerRegistry.emit( descriptors );
|
|
352
|
+
return receiver(
|
|
353
|
+
isPropsList( prop/*original*/ ) ? descriptors.map( opr => opr.status ) : descriptors[ 0 ]?.status
|
|
354
|
+
);
|
|
355
|
+
} );
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Performs a defineProperty operation.
|
|
360
|
+
*
|
|
361
|
+
* @param Object target
|
|
362
|
+
* @param String|Number prop
|
|
363
|
+
* @param Object descriptor
|
|
364
|
+
* @param Function receiver
|
|
365
|
+
* @param Object params
|
|
366
|
+
*
|
|
367
|
+
* @return Any
|
|
368
|
+
*/
|
|
369
|
+
export function defineProperty( target, prop, descriptor, receiver = x => x, params = {} ) {
|
|
370
|
+
return set( target, prop, descriptor, receiver, params, true/*def*/ );
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Performs a defineProperties operation.
|
|
375
|
+
* @note this isn't part of the standard Reflect API.
|
|
376
|
+
*
|
|
377
|
+
* @param Object target
|
|
378
|
+
* @param Object descriptors
|
|
379
|
+
* @param Function receiver
|
|
380
|
+
* @param Object params
|
|
381
|
+
*
|
|
382
|
+
* @return Any
|
|
383
|
+
*/
|
|
384
|
+
export function defineProperties( target, descriptors, receiver = x => x, params = {} ) {
|
|
385
|
+
return set( target, descriptors, receiver, params, true/*def*/ );
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Performs a delete operation.
|
|
390
|
+
*
|
|
391
|
+
* @param Object target
|
|
392
|
+
* @param String|Number prop
|
|
393
|
+
* @param Function receiver
|
|
394
|
+
* @param Object params
|
|
395
|
+
*
|
|
396
|
+
* @return Any
|
|
397
|
+
*/
|
|
398
|
+
export function deleteProperty( target, prop, receiver = x => x, params = {} ) {
|
|
399
|
+
// ---------------
|
|
400
|
+
target = resolveObj( target );
|
|
401
|
+
if ( _isObject( receiver ) ) { [ params, receiver ] = [ receiver, x => x ]; }
|
|
402
|
+
// ---------------
|
|
403
|
+
const props = _arrFrom( prop ), related = [ ...props ];
|
|
404
|
+
return ( function next( descriptors, props, _done ) {
|
|
405
|
+
if ( !props.length ) return _done( descriptors );
|
|
406
|
+
const prop = props.shift();
|
|
407
|
+
// ---------
|
|
408
|
+
function defaultDel( descriptor, status = undefined ) {
|
|
409
|
+
const _next = status => ( descriptor.status = status, next( descriptors.concat( descriptor ), props, _done ) );
|
|
410
|
+
if ( arguments.length > 1 ) return _next( descriptor, status );
|
|
411
|
+
const accessorizedProps = _( target, 'accessorizedProps', false );
|
|
412
|
+
const accessorization = accessorizedProps && accessorizedProps.get( descriptor.key + '' );
|
|
413
|
+
if ( accessorization && !accessorization.restore() ) _next( false );
|
|
414
|
+
return _next( Reflect.deleteProperty( target, descriptor.key ) );
|
|
415
|
+
}
|
|
416
|
+
// ---------
|
|
417
|
+
function exec( oldValue ) {
|
|
418
|
+
const descriptor = new Descriptor( target, {
|
|
419
|
+
type: 'deleteProperty',
|
|
420
|
+
key: prop,
|
|
421
|
+
oldValue,
|
|
422
|
+
related: [ ...related ],
|
|
423
|
+
detail: params.detail,
|
|
424
|
+
} );
|
|
425
|
+
const listenerRegistry = TrapsRegistry.getInstance( target, false, params.namespace );
|
|
426
|
+
return listenerRegistry
|
|
427
|
+
? listenerRegistry.emit( descriptor, defaultDel )
|
|
428
|
+
: defaultDel( descriptor );
|
|
429
|
+
}
|
|
430
|
+
// ---------
|
|
431
|
+
return get( target, prop, exec, params );
|
|
432
|
+
// ---------
|
|
433
|
+
} )( [], props.slice( 0 ), descriptors => {
|
|
434
|
+
const listenerRegistry = ListenerRegistry.getInstance( target, false, params.namespace );
|
|
435
|
+
if ( listenerRegistry ) listenerRegistry.emit( descriptors );
|
|
436
|
+
return receiver(
|
|
437
|
+
isPropsList( prop/*original*/ ) ? descriptors.map( opr => opr.status ) : descriptors[ 0 ].status
|
|
438
|
+
);
|
|
439
|
+
} );
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* @alias deleteProperty()
|
|
444
|
+
*/
|
|
445
|
+
export function deleteProperties( target, props, receiver = x => x, params = {} ) {
|
|
446
|
+
return deleteProperty( ...arguments );
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/* ---------------EFFECT APIs--------------- */
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Performs a "construct" operation.
|
|
453
|
+
*
|
|
454
|
+
* @param Array|Object target
|
|
455
|
+
* @param Array argumentsList
|
|
456
|
+
* @param Object newTarget
|
|
457
|
+
* @param Function receiver
|
|
458
|
+
* @param Object params
|
|
459
|
+
*
|
|
460
|
+
* @return Any
|
|
461
|
+
*/
|
|
462
|
+
export function construct( target, argumentsList, newTarget = null, receiver = x => x, params = {} ) {
|
|
463
|
+
return exec( target, 'construct', arguments.length > 2 ? { argumentsList, newTarget } : { argumentsList }, receiver, params );
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Performs an "apply" operation.
|
|
468
|
+
*
|
|
469
|
+
* @param Array|Object target
|
|
470
|
+
* @param Any thisArgument
|
|
471
|
+
* @param Array argumentsList
|
|
472
|
+
* @param Function receiver
|
|
473
|
+
* @param Object params
|
|
474
|
+
*
|
|
475
|
+
* @return Any
|
|
476
|
+
*/
|
|
477
|
+
export function apply( target, thisArgument, argumentsList, receiver = x => x, params = {} ) {
|
|
478
|
+
return exec( target, 'apply', { thisArgument, argumentsList }, receiver, params );
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Performs a "setPrototypeOf" operation.
|
|
483
|
+
*
|
|
484
|
+
* @param Array|Object target
|
|
485
|
+
* @param Anyr proto
|
|
486
|
+
* @param Function receiver
|
|
487
|
+
* @param Object params
|
|
488
|
+
*
|
|
489
|
+
* @return Any
|
|
490
|
+
*/
|
|
491
|
+
export function setPrototypeOf( target, proto, receiver = x => x, params = {} ) {
|
|
492
|
+
return exec( target, 'setPrototypeOf', { proto }, receiver, params );
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Performs a "preventExtension" operation.
|
|
497
|
+
*
|
|
498
|
+
* @param Array|Object target
|
|
499
|
+
* @param Function receiver
|
|
500
|
+
* @param Object params
|
|
501
|
+
*
|
|
502
|
+
* @return Any
|
|
503
|
+
*/
|
|
504
|
+
export function preventExtensions( target, receiver = x => x, params = {} ) {
|
|
505
|
+
return exec( target, 'preventExtensions', {}, receiver, params );
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/* ---------------HELPER APIs--------------- */
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Adds an observer to a target's registry.
|
|
512
|
+
*
|
|
513
|
+
* @param Array|Object target
|
|
514
|
+
* @param String|Object prop
|
|
515
|
+
* @param Function receiver
|
|
516
|
+
* @param Object params
|
|
517
|
+
*
|
|
518
|
+
* @return Function: AbortController
|
|
519
|
+
*/
|
|
520
|
+
function bind( target, prop, receiver, params = {} ) {
|
|
521
|
+
let controller;
|
|
522
|
+
if ( !params.signal ) {
|
|
523
|
+
controller = new AbortController;
|
|
524
|
+
params = { ...params, signal: controller.signal };
|
|
525
|
+
}
|
|
526
|
+
const listenerRegistry = ListenerRegistry.getInstance( target, true, params.namespace );
|
|
527
|
+
return function emit( descriptor_s, prevRegistration = null ) {
|
|
528
|
+
prevRegistration?.remove();
|
|
529
|
+
const registrationNext = listenerRegistry.addRegistration( prop, emit, params );
|
|
530
|
+
const flags = { signal: registrationNext.signal, };
|
|
531
|
+
if ( arguments.length ) {
|
|
532
|
+
receiver( descriptor_s, flags );
|
|
533
|
+
}
|
|
534
|
+
return controller;
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Performs an operation of the given "type".
|
|
540
|
+
*
|
|
541
|
+
* @param Array|Object target
|
|
542
|
+
* @param String type
|
|
543
|
+
* @param Object payload
|
|
544
|
+
* @param Function receiver
|
|
545
|
+
* @param Object params
|
|
546
|
+
*
|
|
547
|
+
* @return Any
|
|
548
|
+
*/
|
|
549
|
+
function exec( target, type, payload = {}, receiver = x => x, params = {} ) {
|
|
550
|
+
// ---------
|
|
551
|
+
target = resolveObj( target );
|
|
552
|
+
if ( _isObject( receiver ) ) { [ params, receiver ] = [ receiver, x => x ]; }
|
|
553
|
+
// ---------
|
|
554
|
+
function defaultExec( descriptor, result ) {
|
|
555
|
+
if ( arguments.length > 1 ) return receiver( result );
|
|
556
|
+
return receiver( Reflect[ type ]( target, ...Object.values( payload ) ) );
|
|
557
|
+
}
|
|
558
|
+
// ---------
|
|
559
|
+
const descriptor = new Descriptor( target, { type, ...payload } );
|
|
560
|
+
const listenerRegistry = TrapsRegistry.getInstance( target, false, params.namespace );
|
|
561
|
+
if ( listenerRegistry ) {
|
|
562
|
+
return listenerRegistry.emit( descriptor, defaultExec );
|
|
563
|
+
}
|
|
564
|
+
return defaultExec( descriptor );
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// Asks if prop is a multi-result field
|
|
568
|
+
function isPropsList( prop ) {
|
|
569
|
+
return prop === Infinity || Array.isArray( prop );
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Resolves obj down to it's self
|
|
573
|
+
function resolveObj( obj, assert = true ) {
|
|
574
|
+
if ( ( !obj || !_isTypeObject( obj ) ) && assert ) throw new Error( `Object must be of type object or array! "${ _getType( obj ) }" given.` );
|
|
575
|
+
if ( obj instanceof Descriptor ) {
|
|
576
|
+
obj = obj.value;
|
|
577
|
+
}
|
|
578
|
+
return obj && unproxy( obj );
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// Resolves prop down to actual keys
|
|
582
|
+
function resolveProps( obj, prop, receiver ) {
|
|
583
|
+
if ( prop === Infinity ) return ownKeys( obj, receiver );
|
|
584
|
+
return receiver( _arrFrom( prop ) );
|
|
585
|
+
}
|