@microsoft/fast-element 1.7.0 → 1.8.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/CHANGELOG.json +46 -1
- package/CHANGELOG.md +26 -2
- package/dist/dts/components/fast-definitions.d.ts +2 -2
- package/dist/dts/dom.d.ts +2 -2
- package/dist/dts/observation/observable.d.ts +50 -49
- package/dist/dts/platform.d.ts +37 -0
- package/dist/esm/components/fast-definitions.js +28 -11
- package/dist/esm/dom.js +54 -49
- package/dist/esm/observation/array-observer.js +28 -16
- package/dist/esm/observation/observable.js +242 -234
- package/dist/esm/platform.js +23 -0
- package/dist/esm/templating/binding.js +3 -3
- package/dist/fast-element.api.json +43 -48
- package/dist/fast-element.d.ts +53 -13
- package/dist/fast-element.js +450 -359
- package/dist/fast-element.min.js +1 -1
- package/docs/api-report.md +39 -12
- package/package.json +1 -1
package/dist/fast-element.js
CHANGED
|
@@ -41,6 +41,41 @@ if ($global.trustedTypes === void 0) {
|
|
|
41
41
|
createPolicy: (n, r) => r
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
|
+
|
|
45
|
+
const propConfig = {
|
|
46
|
+
configurable: false,
|
|
47
|
+
enumerable: false,
|
|
48
|
+
writable: false
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
if ($global.FAST === void 0) {
|
|
52
|
+
Reflect.defineProperty($global, "FAST", Object.assign({
|
|
53
|
+
value: Object.create(null)
|
|
54
|
+
}, propConfig));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The FAST global.
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
const FAST = $global.FAST;
|
|
63
|
+
|
|
64
|
+
if (FAST.getById === void 0) {
|
|
65
|
+
const storage = Object.create(null);
|
|
66
|
+
Reflect.defineProperty(FAST, "getById", Object.assign({
|
|
67
|
+
value(id, initialize) {
|
|
68
|
+
let found = storage[id];
|
|
69
|
+
|
|
70
|
+
if (found === void 0) {
|
|
71
|
+
found = initialize ? storage[id] = initialize() : null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return found;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
}, propConfig));
|
|
78
|
+
}
|
|
44
79
|
/**
|
|
45
80
|
* A readonly, empty array.
|
|
46
81
|
* @remarks
|
|
@@ -52,33 +87,75 @@ if ($global.trustedTypes === void 0) {
|
|
|
52
87
|
|
|
53
88
|
const emptyArray = Object.freeze([]);
|
|
54
89
|
|
|
55
|
-
const updateQueue =
|
|
56
|
-
/*
|
|
90
|
+
const updateQueue = $global.FAST.getById(1
|
|
91
|
+
/* updateQueue */
|
|
92
|
+
, () => {
|
|
93
|
+
const tasks = [];
|
|
94
|
+
const pendingErrors = [];
|
|
57
95
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
96
|
+
function throwFirstError() {
|
|
97
|
+
if (pendingErrors.length) {
|
|
98
|
+
throw pendingErrors.shift();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function tryRunTask(task) {
|
|
103
|
+
try {
|
|
104
|
+
task.call();
|
|
105
|
+
} catch (error) {
|
|
106
|
+
pendingErrors.push(error);
|
|
107
|
+
setTimeout(throwFirstError, 0);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
62
110
|
|
|
63
|
-
|
|
111
|
+
function process() {
|
|
112
|
+
const capacity = 1024;
|
|
113
|
+
let index = 0;
|
|
114
|
+
|
|
115
|
+
while (index < tasks.length) {
|
|
116
|
+
tryRunTask(tasks[index]);
|
|
117
|
+
index++; // Prevent leaking memory for long chains of recursive calls to `DOM.queueUpdate`.
|
|
118
|
+
// If we call `DOM.queueUpdate` within a task scheduled by `DOM.queueUpdate`, the queue will
|
|
119
|
+
// grow, but to avoid an O(n) walk for every task we execute, we don't
|
|
120
|
+
// shift tasks off the queue after they have been executed.
|
|
121
|
+
// Instead, we periodically shift 1024 tasks off the queue.
|
|
122
|
+
|
|
123
|
+
if (index > capacity) {
|
|
124
|
+
// Manually shift all values starting at the index back to the
|
|
125
|
+
// beginning of the queue.
|
|
126
|
+
for (let scan = 0, newLength = tasks.length - index; scan < newLength; scan++) {
|
|
127
|
+
tasks[scan] = tasks[scan + index];
|
|
128
|
+
}
|
|
64
129
|
|
|
65
|
-
|
|
130
|
+
tasks.length -= index;
|
|
131
|
+
index = 0;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
66
134
|
|
|
67
|
-
|
|
68
|
-
if (pendingErrors.length) {
|
|
69
|
-
throw pendingErrors.shift();
|
|
135
|
+
tasks.length = 0;
|
|
70
136
|
}
|
|
71
|
-
}
|
|
72
137
|
|
|
73
|
-
function
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
138
|
+
function enqueue(callable) {
|
|
139
|
+
if (tasks.length < 1) {
|
|
140
|
+
$global.requestAnimationFrame(process);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
tasks.push(callable);
|
|
79
144
|
}
|
|
80
|
-
}
|
|
81
145
|
|
|
146
|
+
return Object.freeze({
|
|
147
|
+
enqueue,
|
|
148
|
+
process
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
/* eslint-disable */
|
|
152
|
+
|
|
153
|
+
const fastHTMLPolicy = $global.trustedTypes.createPolicy("fast-html", {
|
|
154
|
+
createHTML: html => html
|
|
155
|
+
});
|
|
156
|
+
/* eslint-enable */
|
|
157
|
+
|
|
158
|
+
let htmlPolicy = fastHTMLPolicy;
|
|
82
159
|
const marker = `fast-${Math.random().toString(36).substring(2, 8)}`;
|
|
83
160
|
/** @internal */
|
|
84
161
|
|
|
@@ -176,13 +253,7 @@ const DOM = Object.freeze({
|
|
|
176
253
|
* Schedules DOM update work in the next async batch.
|
|
177
254
|
* @param callable - The callable function or object to queue.
|
|
178
255
|
*/
|
|
179
|
-
queueUpdate
|
|
180
|
-
if (updateQueue.length < 1) {
|
|
181
|
-
window.requestAnimationFrame(DOM.processUpdates);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
updateQueue.push(callable);
|
|
185
|
-
},
|
|
256
|
+
queueUpdate: updateQueue.enqueue,
|
|
186
257
|
|
|
187
258
|
/**
|
|
188
259
|
* Immediately processes all work previously scheduled
|
|
@@ -191,40 +262,13 @@ const DOM = Object.freeze({
|
|
|
191
262
|
* This also forces nextUpdate promises
|
|
192
263
|
* to resolve.
|
|
193
264
|
*/
|
|
194
|
-
processUpdates
|
|
195
|
-
const capacity = 1024;
|
|
196
|
-
let index = 0;
|
|
197
|
-
|
|
198
|
-
while (index < updateQueue.length) {
|
|
199
|
-
tryRunTask(updateQueue[index]);
|
|
200
|
-
index++; // Prevent leaking memory for long chains of recursive calls to `DOM.queueUpdate`.
|
|
201
|
-
// If we call `DOM.queueUpdate` within a task scheduled by `DOM.queueUpdate`, the queue will
|
|
202
|
-
// grow, but to avoid an O(n) walk for every task we execute, we don't
|
|
203
|
-
// shift tasks off the queue after they have been executed.
|
|
204
|
-
// Instead, we periodically shift 1024 tasks off the queue.
|
|
205
|
-
|
|
206
|
-
if (index > capacity) {
|
|
207
|
-
// Manually shift all values starting at the index back to the
|
|
208
|
-
// beginning of the queue.
|
|
209
|
-
for (let scan = 0, newLength = updateQueue.length - index; scan < newLength; scan++) {
|
|
210
|
-
updateQueue[scan] = updateQueue[scan + index];
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
updateQueue.length -= index;
|
|
214
|
-
index = 0;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
updateQueue.length = 0;
|
|
219
|
-
},
|
|
265
|
+
processUpdates: updateQueue.process,
|
|
220
266
|
|
|
221
267
|
/**
|
|
222
268
|
* Resolves with the next DOM update.
|
|
223
269
|
*/
|
|
224
270
|
nextUpdate() {
|
|
225
|
-
return new Promise(
|
|
226
|
-
DOM.queueUpdate(resolve);
|
|
227
|
-
});
|
|
271
|
+
return new Promise(updateQueue.enqueue);
|
|
228
272
|
},
|
|
229
273
|
|
|
230
274
|
/**
|
|
@@ -484,69 +528,25 @@ class PropertyChangeNotifier {
|
|
|
484
528
|
|
|
485
529
|
}
|
|
486
530
|
|
|
487
|
-
const volatileRegex = /(:|&&|\|\||if)/;
|
|
488
|
-
const notifierLookup = new WeakMap();
|
|
489
|
-
const accessorLookup = new WeakMap();
|
|
490
|
-
let watcher = void 0;
|
|
491
|
-
|
|
492
|
-
let createArrayObserver = array => {
|
|
493
|
-
throw new Error("Must call enableArrayObservation before observing arrays.");
|
|
494
|
-
};
|
|
495
|
-
|
|
496
|
-
class DefaultObservableAccessor {
|
|
497
|
-
constructor(name) {
|
|
498
|
-
this.name = name;
|
|
499
|
-
this.field = `_${name}`;
|
|
500
|
-
this.callback = `${name}Changed`;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
getValue(source) {
|
|
504
|
-
if (watcher !== void 0) {
|
|
505
|
-
watcher.watch(source, this.name);
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
return source[this.field];
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
setValue(source, newValue) {
|
|
512
|
-
const field = this.field;
|
|
513
|
-
const oldValue = source[field];
|
|
514
|
-
|
|
515
|
-
if (oldValue !== newValue) {
|
|
516
|
-
source[field] = newValue;
|
|
517
|
-
const callback = source[this.callback];
|
|
518
|
-
|
|
519
|
-
if (typeof callback === "function") {
|
|
520
|
-
callback.call(source, oldValue, newValue);
|
|
521
|
-
}
|
|
522
|
-
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
getNotifier(source).notify(this.name);
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
}
|
|
530
531
|
/**
|
|
531
532
|
* Common Observable APIs.
|
|
532
533
|
* @public
|
|
533
534
|
*/
|
|
534
535
|
|
|
536
|
+
const Observable = FAST.getById(2
|
|
537
|
+
/* observable */
|
|
538
|
+
, () => {
|
|
539
|
+
const volatileRegex = /(:|&&|\|\||if)/;
|
|
540
|
+
const notifierLookup = new WeakMap();
|
|
541
|
+
const accessorLookup = new WeakMap();
|
|
542
|
+
const queueUpdate = DOM.queueUpdate;
|
|
543
|
+
let watcher = void 0;
|
|
544
|
+
|
|
545
|
+
let createArrayObserver = array => {
|
|
546
|
+
throw new Error("Must call enableArrayObservation before observing arrays.");
|
|
547
|
+
};
|
|
535
548
|
|
|
536
|
-
|
|
537
|
-
/**
|
|
538
|
-
* @internal
|
|
539
|
-
* @param factory - The factory used to create array observers.
|
|
540
|
-
*/
|
|
541
|
-
setArrayObserverFactory(factory) {
|
|
542
|
-
createArrayObserver = factory;
|
|
543
|
-
},
|
|
544
|
-
|
|
545
|
-
/**
|
|
546
|
-
* Gets a notifier for an object or Array.
|
|
547
|
-
* @param source - The object or Array to get the notifier for.
|
|
548
|
-
*/
|
|
549
|
-
getNotifier(source) {
|
|
549
|
+
function getNotifier(source) {
|
|
550
550
|
let found = source.$fastController || notifierLookup.get(source);
|
|
551
551
|
|
|
552
552
|
if (found === void 0) {
|
|
@@ -558,68 +558,9 @@ const Observable = Object.freeze({
|
|
|
558
558
|
}
|
|
559
559
|
|
|
560
560
|
return found;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
/**
|
|
564
|
-
* Records a property change for a source object.
|
|
565
|
-
* @param source - The object to record the change against.
|
|
566
|
-
* @param propertyName - The property to track as changed.
|
|
567
|
-
*/
|
|
568
|
-
track(source, propertyName) {
|
|
569
|
-
if (watcher !== void 0) {
|
|
570
|
-
watcher.watch(source, propertyName);
|
|
571
|
-
}
|
|
572
|
-
},
|
|
573
|
-
|
|
574
|
-
/**
|
|
575
|
-
* Notifies watchers that the currently executing property getter or function is volatile
|
|
576
|
-
* with respect to its observable dependencies.
|
|
577
|
-
*/
|
|
578
|
-
trackVolatile() {
|
|
579
|
-
if (watcher !== void 0) {
|
|
580
|
-
watcher.needsRefresh = true;
|
|
581
|
-
}
|
|
582
|
-
},
|
|
583
|
-
|
|
584
|
-
/**
|
|
585
|
-
* Notifies subscribers of a source object of changes.
|
|
586
|
-
* @param source - the object to notify of changes.
|
|
587
|
-
* @param args - The change args to pass to subscribers.
|
|
588
|
-
*/
|
|
589
|
-
notify(source, args) {
|
|
590
|
-
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
591
|
-
getNotifier(source).notify(args);
|
|
592
|
-
},
|
|
593
|
-
|
|
594
|
-
/**
|
|
595
|
-
* Defines an observable property on an object or prototype.
|
|
596
|
-
* @param target - The target object to define the observable on.
|
|
597
|
-
* @param nameOrAccessor - The name of the property to define as observable;
|
|
598
|
-
* or a custom accessor that specifies the property name and accessor implementation.
|
|
599
|
-
*/
|
|
600
|
-
defineProperty(target, nameOrAccessor) {
|
|
601
|
-
if (typeof nameOrAccessor === "string") {
|
|
602
|
-
nameOrAccessor = new DefaultObservableAccessor(nameOrAccessor);
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
this.getAccessors(target).push(nameOrAccessor);
|
|
606
|
-
Reflect.defineProperty(target, nameOrAccessor.name, {
|
|
607
|
-
enumerable: true,
|
|
608
|
-
get: function () {
|
|
609
|
-
return nameOrAccessor.getValue(this);
|
|
610
|
-
},
|
|
611
|
-
set: function (newValue) {
|
|
612
|
-
nameOrAccessor.setValue(this, newValue);
|
|
613
|
-
}
|
|
614
|
-
});
|
|
615
|
-
},
|
|
561
|
+
}
|
|
616
562
|
|
|
617
|
-
|
|
618
|
-
* Finds all the observable accessors defined on the target,
|
|
619
|
-
* including its prototype chain.
|
|
620
|
-
* @param target - The target object to search for accessor on.
|
|
621
|
-
*/
|
|
622
|
-
getAccessors(target) {
|
|
563
|
+
function getAccessors(target) {
|
|
623
564
|
let accessors = accessorLookup.get(target);
|
|
624
565
|
|
|
625
566
|
if (accessors === void 0) {
|
|
@@ -640,33 +581,253 @@ const Observable = Object.freeze({
|
|
|
640
581
|
}
|
|
641
582
|
|
|
642
583
|
return accessors;
|
|
643
|
-
}
|
|
584
|
+
}
|
|
644
585
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
586
|
+
class DefaultObservableAccessor {
|
|
587
|
+
constructor(name) {
|
|
588
|
+
this.name = name;
|
|
589
|
+
this.field = `_${name}`;
|
|
590
|
+
this.callback = `${name}Changed`;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
getValue(source) {
|
|
594
|
+
if (watcher !== void 0) {
|
|
595
|
+
watcher.watch(source, this.name);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
return source[this.field];
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
setValue(source, newValue) {
|
|
602
|
+
const field = this.field;
|
|
603
|
+
const oldValue = source[field];
|
|
604
|
+
|
|
605
|
+
if (oldValue !== newValue) {
|
|
606
|
+
source[field] = newValue;
|
|
607
|
+
const callback = source[this.callback];
|
|
608
|
+
|
|
609
|
+
if (typeof callback === "function") {
|
|
610
|
+
callback.call(source, oldValue, newValue);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
getNotifier(source).notify(this.name);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
656
616
|
|
|
657
|
-
/**
|
|
658
|
-
* Determines whether a binding expression is volatile and needs to have its dependency list re-evaluated
|
|
659
|
-
* on every evaluation of the value.
|
|
660
|
-
* @param binding - The binding to inspect.
|
|
661
|
-
*/
|
|
662
|
-
isVolatileBinding(binding) {
|
|
663
|
-
return volatileRegex.test(binding.toString());
|
|
664
617
|
}
|
|
665
618
|
|
|
619
|
+
class BindingObserverImplementation extends SubscriberSet {
|
|
620
|
+
constructor(binding, initialSubscriber, isVolatileBinding = false) {
|
|
621
|
+
super(binding, initialSubscriber);
|
|
622
|
+
this.binding = binding;
|
|
623
|
+
this.isVolatileBinding = isVolatileBinding;
|
|
624
|
+
this.needsRefresh = true;
|
|
625
|
+
this.needsQueue = true;
|
|
626
|
+
this.first = this;
|
|
627
|
+
this.last = null;
|
|
628
|
+
this.propertySource = void 0;
|
|
629
|
+
this.propertyName = void 0;
|
|
630
|
+
this.notifier = void 0;
|
|
631
|
+
this.next = void 0;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
observe(source, context) {
|
|
635
|
+
if (this.needsRefresh && this.last !== null) {
|
|
636
|
+
this.disconnect();
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
const previousWatcher = watcher;
|
|
640
|
+
watcher = this.needsRefresh ? this : void 0;
|
|
641
|
+
this.needsRefresh = this.isVolatileBinding;
|
|
642
|
+
const result = this.binding(source, context);
|
|
643
|
+
watcher = previousWatcher;
|
|
644
|
+
return result;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
disconnect() {
|
|
648
|
+
if (this.last !== null) {
|
|
649
|
+
let current = this.first;
|
|
650
|
+
|
|
651
|
+
while (current !== void 0) {
|
|
652
|
+
current.notifier.unsubscribe(this, current.propertyName);
|
|
653
|
+
current = current.next;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
this.last = null;
|
|
657
|
+
this.needsRefresh = this.needsQueue = true;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
watch(propertySource, propertyName) {
|
|
662
|
+
const prev = this.last;
|
|
663
|
+
const notifier = getNotifier(propertySource);
|
|
664
|
+
const current = prev === null ? this.first : {};
|
|
665
|
+
current.propertySource = propertySource;
|
|
666
|
+
current.propertyName = propertyName;
|
|
667
|
+
current.notifier = notifier;
|
|
668
|
+
notifier.subscribe(this, propertyName);
|
|
669
|
+
|
|
670
|
+
if (prev !== null) {
|
|
671
|
+
if (!this.needsRefresh) {
|
|
672
|
+
// Declaring the variable prior to assignment below circumvents
|
|
673
|
+
// a bug in Angular's optimization process causing infinite recursion
|
|
674
|
+
// of this watch() method. Details https://github.com/microsoft/fast/issues/4969
|
|
675
|
+
let prevValue;
|
|
676
|
+
watcher = void 0;
|
|
677
|
+
/* eslint-disable-next-line */
|
|
678
|
+
|
|
679
|
+
prevValue = prev.propertySource[prev.propertyName];
|
|
680
|
+
watcher = this;
|
|
681
|
+
|
|
682
|
+
if (propertySource === prevValue) {
|
|
683
|
+
this.needsRefresh = true;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
prev.next = current;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
this.last = current;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
handleChange() {
|
|
694
|
+
if (this.needsQueue) {
|
|
695
|
+
this.needsQueue = false;
|
|
696
|
+
queueUpdate(this);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
call() {
|
|
701
|
+
if (this.last !== null) {
|
|
702
|
+
this.needsQueue = true;
|
|
703
|
+
this.notify(this);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
records() {
|
|
708
|
+
let next = this.first;
|
|
709
|
+
return {
|
|
710
|
+
next: () => {
|
|
711
|
+
const current = next;
|
|
712
|
+
|
|
713
|
+
if (current === undefined) {
|
|
714
|
+
return {
|
|
715
|
+
value: void 0,
|
|
716
|
+
done: true
|
|
717
|
+
};
|
|
718
|
+
} else {
|
|
719
|
+
next = next.next;
|
|
720
|
+
return {
|
|
721
|
+
value: current,
|
|
722
|
+
done: false
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
},
|
|
726
|
+
[Symbol.iterator]: function () {
|
|
727
|
+
return this;
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
return Object.freeze({
|
|
735
|
+
/**
|
|
736
|
+
* @internal
|
|
737
|
+
* @param factory - The factory used to create array observers.
|
|
738
|
+
*/
|
|
739
|
+
setArrayObserverFactory(factory) {
|
|
740
|
+
createArrayObserver = factory;
|
|
741
|
+
},
|
|
742
|
+
|
|
743
|
+
/**
|
|
744
|
+
* Gets a notifier for an object or Array.
|
|
745
|
+
* @param source - The object or Array to get the notifier for.
|
|
746
|
+
*/
|
|
747
|
+
getNotifier,
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Records a property change for a source object.
|
|
751
|
+
* @param source - The object to record the change against.
|
|
752
|
+
* @param propertyName - The property to track as changed.
|
|
753
|
+
*/
|
|
754
|
+
track(source, propertyName) {
|
|
755
|
+
if (watcher !== void 0) {
|
|
756
|
+
watcher.watch(source, propertyName);
|
|
757
|
+
}
|
|
758
|
+
},
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
* Notifies watchers that the currently executing property getter or function is volatile
|
|
762
|
+
* with respect to its observable dependencies.
|
|
763
|
+
*/
|
|
764
|
+
trackVolatile() {
|
|
765
|
+
if (watcher !== void 0) {
|
|
766
|
+
watcher.needsRefresh = true;
|
|
767
|
+
}
|
|
768
|
+
},
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* Notifies subscribers of a source object of changes.
|
|
772
|
+
* @param source - the object to notify of changes.
|
|
773
|
+
* @param args - The change args to pass to subscribers.
|
|
774
|
+
*/
|
|
775
|
+
notify(source, args) {
|
|
776
|
+
getNotifier(source).notify(args);
|
|
777
|
+
},
|
|
778
|
+
|
|
779
|
+
/**
|
|
780
|
+
* Defines an observable property on an object or prototype.
|
|
781
|
+
* @param target - The target object to define the observable on.
|
|
782
|
+
* @param nameOrAccessor - The name of the property to define as observable;
|
|
783
|
+
* or a custom accessor that specifies the property name and accessor implementation.
|
|
784
|
+
*/
|
|
785
|
+
defineProperty(target, nameOrAccessor) {
|
|
786
|
+
if (typeof nameOrAccessor === "string") {
|
|
787
|
+
nameOrAccessor = new DefaultObservableAccessor(nameOrAccessor);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
getAccessors(target).push(nameOrAccessor);
|
|
791
|
+
Reflect.defineProperty(target, nameOrAccessor.name, {
|
|
792
|
+
enumerable: true,
|
|
793
|
+
get: function () {
|
|
794
|
+
return nameOrAccessor.getValue(this);
|
|
795
|
+
},
|
|
796
|
+
set: function (newValue) {
|
|
797
|
+
nameOrAccessor.setValue(this, newValue);
|
|
798
|
+
}
|
|
799
|
+
});
|
|
800
|
+
},
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Finds all the observable accessors defined on the target,
|
|
804
|
+
* including its prototype chain.
|
|
805
|
+
* @param target - The target object to search for accessor on.
|
|
806
|
+
*/
|
|
807
|
+
getAccessors,
|
|
808
|
+
|
|
809
|
+
/**
|
|
810
|
+
* Creates a {@link BindingObserver} that can watch the
|
|
811
|
+
* provided {@link Binding} for changes.
|
|
812
|
+
* @param binding - The binding to observe.
|
|
813
|
+
* @param initialSubscriber - An initial subscriber to changes in the binding value.
|
|
814
|
+
* @param isVolatileBinding - Indicates whether the binding's dependency list must be re-evaluated on every value evaluation.
|
|
815
|
+
*/
|
|
816
|
+
binding(binding, initialSubscriber, isVolatileBinding = this.isVolatileBinding(binding)) {
|
|
817
|
+
return new BindingObserverImplementation(binding, initialSubscriber, isVolatileBinding);
|
|
818
|
+
},
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* Determines whether a binding expression is volatile and needs to have its dependency list re-evaluated
|
|
822
|
+
* on every evaluation of the value.
|
|
823
|
+
* @param binding - The binding to inspect.
|
|
824
|
+
*/
|
|
825
|
+
isVolatileBinding(binding) {
|
|
826
|
+
return volatileRegex.test(binding.toString());
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
});
|
|
666
830
|
});
|
|
667
|
-
const getNotifier = Observable.getNotifier;
|
|
668
|
-
const trackVolatile = Observable.trackVolatile;
|
|
669
|
-
const queueUpdate = DOM.queueUpdate;
|
|
670
831
|
/**
|
|
671
832
|
* Decorator: Defines an observable property on the target.
|
|
672
833
|
* @param target - The target to define the observable on.
|
|
@@ -688,20 +849,26 @@ function observable(target, nameOrAccessor) {
|
|
|
688
849
|
function volatile(target, name, descriptor) {
|
|
689
850
|
return Object.assign({}, descriptor, {
|
|
690
851
|
get: function () {
|
|
691
|
-
trackVolatile();
|
|
852
|
+
Observable.trackVolatile();
|
|
692
853
|
return descriptor.get.apply(this);
|
|
693
854
|
}
|
|
694
855
|
});
|
|
695
856
|
}
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
857
|
+
const contextEvent = FAST.getById(3
|
|
858
|
+
/* contextEvent */
|
|
859
|
+
, () => {
|
|
860
|
+
let current = null;
|
|
861
|
+
return {
|
|
862
|
+
get() {
|
|
863
|
+
return current;
|
|
864
|
+
},
|
|
701
865
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
}
|
|
866
|
+
set(event) {
|
|
867
|
+
current = event;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
};
|
|
871
|
+
});
|
|
705
872
|
/**
|
|
706
873
|
* Provides additional contextual information available to behaviors and expressions.
|
|
707
874
|
* @public
|
|
@@ -735,7 +902,7 @@ class ExecutionContext {
|
|
|
735
902
|
|
|
736
903
|
|
|
737
904
|
get event() {
|
|
738
|
-
return
|
|
905
|
+
return contextEvent.get();
|
|
739
906
|
}
|
|
740
907
|
/**
|
|
741
908
|
* Indicates whether the current item within a repeat context
|
|
@@ -782,6 +949,16 @@ class ExecutionContext {
|
|
|
782
949
|
get isLast() {
|
|
783
950
|
return this.index === this.length - 1;
|
|
784
951
|
}
|
|
952
|
+
/**
|
|
953
|
+
* Sets the event for the current execution context.
|
|
954
|
+
* @param event - The event to set.
|
|
955
|
+
* @internal
|
|
956
|
+
*/
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
static setEvent(event) {
|
|
960
|
+
contextEvent.set(event);
|
|
961
|
+
}
|
|
785
962
|
|
|
786
963
|
}
|
|
787
964
|
Observable.defineProperty(ExecutionContext.prototype, "index");
|
|
@@ -793,127 +970,6 @@ Observable.defineProperty(ExecutionContext.prototype, "length");
|
|
|
793
970
|
|
|
794
971
|
const defaultExecutionContext = Object.seal(new ExecutionContext());
|
|
795
972
|
|
|
796
|
-
class BindingObserverImplementation extends SubscriberSet {
|
|
797
|
-
constructor(binding, initialSubscriber, isVolatileBinding = false) {
|
|
798
|
-
super(binding, initialSubscriber);
|
|
799
|
-
this.binding = binding;
|
|
800
|
-
this.isVolatileBinding = isVolatileBinding;
|
|
801
|
-
this.needsRefresh = true;
|
|
802
|
-
this.needsQueue = true;
|
|
803
|
-
this.first = this;
|
|
804
|
-
this.last = null;
|
|
805
|
-
this.propertySource = void 0;
|
|
806
|
-
this.propertyName = void 0;
|
|
807
|
-
this.notifier = void 0;
|
|
808
|
-
this.next = void 0;
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
observe(source, context) {
|
|
812
|
-
if (this.needsRefresh && this.last !== null) {
|
|
813
|
-
this.disconnect();
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
const previousWatcher = watcher;
|
|
817
|
-
watcher = this.needsRefresh ? this : void 0;
|
|
818
|
-
this.needsRefresh = this.isVolatileBinding;
|
|
819
|
-
const result = this.binding(source, context);
|
|
820
|
-
watcher = previousWatcher;
|
|
821
|
-
return result;
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
disconnect() {
|
|
825
|
-
if (this.last !== null) {
|
|
826
|
-
let current = this.first;
|
|
827
|
-
|
|
828
|
-
while (current !== void 0) {
|
|
829
|
-
current.notifier.unsubscribe(this, current.propertyName);
|
|
830
|
-
current = current.next;
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
this.last = null;
|
|
834
|
-
this.needsRefresh = this.needsQueue = true;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
/** @internal */
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
watch(propertySource, propertyName) {
|
|
841
|
-
const prev = this.last;
|
|
842
|
-
const notifier = getNotifier(propertySource);
|
|
843
|
-
const current = prev === null ? this.first : {};
|
|
844
|
-
current.propertySource = propertySource;
|
|
845
|
-
current.propertyName = propertyName;
|
|
846
|
-
current.notifier = notifier;
|
|
847
|
-
notifier.subscribe(this, propertyName);
|
|
848
|
-
|
|
849
|
-
if (prev !== null) {
|
|
850
|
-
if (!this.needsRefresh) {
|
|
851
|
-
// Declaring the variable prior to assignment below circumvents
|
|
852
|
-
// a bug in Angular's optimization process causing infinite recursion
|
|
853
|
-
// of this watch() method. Details https://github.com/microsoft/fast/issues/4969
|
|
854
|
-
let prevValue;
|
|
855
|
-
watcher = void 0;
|
|
856
|
-
/* eslint-disable-next-line */
|
|
857
|
-
|
|
858
|
-
prevValue = prev.propertySource[prev.propertyName];
|
|
859
|
-
watcher = this;
|
|
860
|
-
|
|
861
|
-
if (propertySource === prevValue) {
|
|
862
|
-
this.needsRefresh = true;
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
prev.next = current;
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
this.last = current;
|
|
870
|
-
}
|
|
871
|
-
/** @internal */
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
handleChange() {
|
|
875
|
-
if (this.needsQueue) {
|
|
876
|
-
this.needsQueue = false;
|
|
877
|
-
queueUpdate(this);
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
/** @internal */
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
call() {
|
|
884
|
-
if (this.last !== null) {
|
|
885
|
-
this.needsQueue = true;
|
|
886
|
-
this.notify(this);
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
records() {
|
|
891
|
-
let next = this.first;
|
|
892
|
-
return {
|
|
893
|
-
next: () => {
|
|
894
|
-
const current = next;
|
|
895
|
-
|
|
896
|
-
if (current === undefined) {
|
|
897
|
-
return {
|
|
898
|
-
value: void 0,
|
|
899
|
-
done: true
|
|
900
|
-
};
|
|
901
|
-
} else {
|
|
902
|
-
next = next.next;
|
|
903
|
-
return {
|
|
904
|
-
value: current,
|
|
905
|
-
done: false
|
|
906
|
-
};
|
|
907
|
-
}
|
|
908
|
-
},
|
|
909
|
-
[Symbol.iterator]: function () {
|
|
910
|
-
return this;
|
|
911
|
-
}
|
|
912
|
-
};
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
}
|
|
916
|
-
|
|
917
973
|
/**
|
|
918
974
|
* Instructs the template engine to apply behavior to a node.
|
|
919
975
|
* @public
|
|
@@ -1276,9 +1332,9 @@ class BindingBehavior {
|
|
|
1276
1332
|
|
|
1277
1333
|
|
|
1278
1334
|
handleEvent(event) {
|
|
1279
|
-
|
|
1335
|
+
ExecutionContext.setEvent(event);
|
|
1280
1336
|
const result = this.binding(this.source, this.context);
|
|
1281
|
-
|
|
1337
|
+
ExecutionContext.setEvent(null);
|
|
1282
1338
|
|
|
1283
1339
|
if (result !== true) {
|
|
1284
1340
|
event.preventDefault();
|
|
@@ -2274,7 +2330,26 @@ const defaultShadowOptions = {
|
|
|
2274
2330
|
mode: "open"
|
|
2275
2331
|
};
|
|
2276
2332
|
const defaultElementOptions = {};
|
|
2277
|
-
const
|
|
2333
|
+
const fastRegistry = FAST.getById(4
|
|
2334
|
+
/* elementRegistry */
|
|
2335
|
+
, () => {
|
|
2336
|
+
const typeToDefinition = new Map();
|
|
2337
|
+
return Object.freeze({
|
|
2338
|
+
register(definition) {
|
|
2339
|
+
if (typeToDefinition.has(definition.type)) {
|
|
2340
|
+
return false;
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2343
|
+
typeToDefinition.set(definition.type, definition);
|
|
2344
|
+
return true;
|
|
2345
|
+
},
|
|
2346
|
+
|
|
2347
|
+
getByType(key) {
|
|
2348
|
+
return typeToDefinition.get(key);
|
|
2349
|
+
}
|
|
2350
|
+
|
|
2351
|
+
});
|
|
2352
|
+
});
|
|
2278
2353
|
/**
|
|
2279
2354
|
* Defines metadata for a FASTElement.
|
|
2280
2355
|
* @public
|
|
@@ -2317,6 +2392,14 @@ class FASTElementDefinition {
|
|
|
2317
2392
|
this.elementOptions = nameOrConfig.elementOptions === void 0 ? defaultElementOptions : Object.assign(Object.assign({}, defaultElementOptions), nameOrConfig.elementOptions);
|
|
2318
2393
|
this.styles = nameOrConfig.styles === void 0 ? void 0 : Array.isArray(nameOrConfig.styles) ? ElementStyles.create(nameOrConfig.styles) : nameOrConfig.styles instanceof ElementStyles ? nameOrConfig.styles : ElementStyles.create([nameOrConfig.styles]);
|
|
2319
2394
|
}
|
|
2395
|
+
/**
|
|
2396
|
+
* Indicates if this element has been defined in at least one registry.
|
|
2397
|
+
*/
|
|
2398
|
+
|
|
2399
|
+
|
|
2400
|
+
get isDefined() {
|
|
2401
|
+
return !!fastRegistry.getByType(this.type);
|
|
2402
|
+
}
|
|
2320
2403
|
/**
|
|
2321
2404
|
* Defines a custom element based on this definition.
|
|
2322
2405
|
* @param registry - The element registry to define the element in.
|
|
@@ -2326,7 +2409,7 @@ class FASTElementDefinition {
|
|
|
2326
2409
|
define(registry = customElements) {
|
|
2327
2410
|
const type = this.type;
|
|
2328
2411
|
|
|
2329
|
-
if (
|
|
2412
|
+
if (fastRegistry.register(this)) {
|
|
2330
2413
|
const attributes = this.attributes;
|
|
2331
2414
|
const proto = type.prototype;
|
|
2332
2415
|
|
|
@@ -2338,8 +2421,6 @@ class FASTElementDefinition {
|
|
|
2338
2421
|
value: this.observedAttributes,
|
|
2339
2422
|
enumerable: true
|
|
2340
2423
|
});
|
|
2341
|
-
fastDefinitions.set(type, this);
|
|
2342
|
-
this.isDefined = true;
|
|
2343
2424
|
}
|
|
2344
2425
|
|
|
2345
2426
|
if (!registry.get(this.name)) {
|
|
@@ -2348,17 +2429,14 @@ class FASTElementDefinition {
|
|
|
2348
2429
|
|
|
2349
2430
|
return this;
|
|
2350
2431
|
}
|
|
2351
|
-
/**
|
|
2352
|
-
* Gets the element definition associated with the specified type.
|
|
2353
|
-
* @param type - The custom element type to retrieve the definition for.
|
|
2354
|
-
*/
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
static forType(type) {
|
|
2358
|
-
return fastDefinitions.get(type);
|
|
2359
|
-
}
|
|
2360
2432
|
|
|
2361
2433
|
}
|
|
2434
|
+
/**
|
|
2435
|
+
* Gets the element definition associated with the specified type.
|
|
2436
|
+
* @param type - The custom element type to retrieve the definition for.
|
|
2437
|
+
*/
|
|
2438
|
+
|
|
2439
|
+
FASTElementDefinition.forType = fastRegistry.getByType;
|
|
2362
2440
|
|
|
2363
2441
|
const shadowRoots = new WeakMap();
|
|
2364
2442
|
const defaultEventOptions = {
|
|
@@ -3434,7 +3512,10 @@ class ArrayObserver extends SubscriberSet {
|
|
|
3434
3512
|
this.splices = void 0;
|
|
3435
3513
|
this.needsQueue = true;
|
|
3436
3514
|
this.call = this.flush;
|
|
3437
|
-
source
|
|
3515
|
+
Reflect.defineProperty(source, "$fastController", {
|
|
3516
|
+
value: this,
|
|
3517
|
+
enumerable: false
|
|
3518
|
+
});
|
|
3438
3519
|
}
|
|
3439
3520
|
|
|
3440
3521
|
addSplice(splice) {
|
|
@@ -3498,16 +3579,26 @@ function enableArrayObservation() {
|
|
|
3498
3579
|
Observable.setArrayObserverFactory(collection => {
|
|
3499
3580
|
return new ArrayObserver(collection);
|
|
3500
3581
|
});
|
|
3501
|
-
const
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3582
|
+
const proto = Array.prototype; // Don't patch Array if it has already been patched
|
|
3583
|
+
// by another copy of fast-element.
|
|
3584
|
+
|
|
3585
|
+
if (proto.$fastPatch) {
|
|
3586
|
+
return;
|
|
3587
|
+
}
|
|
3588
|
+
|
|
3589
|
+
Reflect.defineProperty(proto, "$fastPatch", {
|
|
3590
|
+
value: 1,
|
|
3591
|
+
enumerable: false
|
|
3592
|
+
});
|
|
3593
|
+
const pop = proto.pop;
|
|
3594
|
+
const push = proto.push;
|
|
3595
|
+
const reverse = proto.reverse;
|
|
3596
|
+
const shift = proto.shift;
|
|
3597
|
+
const sort = proto.sort;
|
|
3598
|
+
const splice = proto.splice;
|
|
3599
|
+
const unshift = proto.unshift;
|
|
3600
|
+
|
|
3601
|
+
proto.pop = function () {
|
|
3511
3602
|
const notEmpty = this.length > 0;
|
|
3512
3603
|
const methodCallResult = pop.apply(this, arguments);
|
|
3513
3604
|
const o = this.$fastController;
|
|
@@ -3519,7 +3610,7 @@ function enableArrayObservation() {
|
|
|
3519
3610
|
return methodCallResult;
|
|
3520
3611
|
};
|
|
3521
3612
|
|
|
3522
|
-
|
|
3613
|
+
proto.push = function () {
|
|
3523
3614
|
const methodCallResult = push.apply(this, arguments);
|
|
3524
3615
|
const o = this.$fastController;
|
|
3525
3616
|
|
|
@@ -3530,7 +3621,7 @@ function enableArrayObservation() {
|
|
|
3530
3621
|
return methodCallResult;
|
|
3531
3622
|
};
|
|
3532
3623
|
|
|
3533
|
-
|
|
3624
|
+
proto.reverse = function () {
|
|
3534
3625
|
let oldArray;
|
|
3535
3626
|
const o = this.$fastController;
|
|
3536
3627
|
|
|
@@ -3548,7 +3639,7 @@ function enableArrayObservation() {
|
|
|
3548
3639
|
return methodCallResult;
|
|
3549
3640
|
};
|
|
3550
3641
|
|
|
3551
|
-
|
|
3642
|
+
proto.shift = function () {
|
|
3552
3643
|
const notEmpty = this.length > 0;
|
|
3553
3644
|
const methodCallResult = shift.apply(this, arguments);
|
|
3554
3645
|
const o = this.$fastController;
|
|
@@ -3560,7 +3651,7 @@ function enableArrayObservation() {
|
|
|
3560
3651
|
return methodCallResult;
|
|
3561
3652
|
};
|
|
3562
3653
|
|
|
3563
|
-
|
|
3654
|
+
proto.sort = function () {
|
|
3564
3655
|
let oldArray;
|
|
3565
3656
|
const o = this.$fastController;
|
|
3566
3657
|
|
|
@@ -3578,7 +3669,7 @@ function enableArrayObservation() {
|
|
|
3578
3669
|
return methodCallResult;
|
|
3579
3670
|
};
|
|
3580
3671
|
|
|
3581
|
-
|
|
3672
|
+
proto.splice = function () {
|
|
3582
3673
|
const methodCallResult = splice.apply(this, arguments);
|
|
3583
3674
|
const o = this.$fastController;
|
|
3584
3675
|
|
|
@@ -3589,7 +3680,7 @@ function enableArrayObservation() {
|
|
|
3589
3680
|
return methodCallResult;
|
|
3590
3681
|
};
|
|
3591
3682
|
|
|
3592
|
-
|
|
3683
|
+
proto.unshift = function () {
|
|
3593
3684
|
const methodCallResult = unshift.apply(this, arguments);
|
|
3594
3685
|
const o = this.$fastController;
|
|
3595
3686
|
|
|
@@ -4150,4 +4241,4 @@ function children(propertyOrOptions) {
|
|
|
4150
4241
|
return new AttachedBehaviorHTMLDirective("fast-children", ChildrenBehavior, propertyOrOptions);
|
|
4151
4242
|
}
|
|
4152
4243
|
|
|
4153
|
-
export { $global, AttachedBehaviorHTMLDirective, AttributeDefinition, BindingBehavior, CSSDirective, ChildrenBehavior, Controller, DOM, ElementStyles, ExecutionContext, FASTElement, FASTElementDefinition, HTMLBindingDirective, HTMLDirective, HTMLView, Observable, PropertyChangeNotifier, RefBehavior, RepeatBehavior, RepeatDirective, SlottedBehavior, SubscriberSet, TargetedHTMLDirective, ViewTemplate, attr, booleanConverter, children, compileTemplate, css, cssPartial, customElement, defaultExecutionContext, elements, emptyArray, enableArrayObservation, html, nullableNumberConverter, observable, ref, repeat,
|
|
4244
|
+
export { $global, AttachedBehaviorHTMLDirective, AttributeDefinition, BindingBehavior, CSSDirective, ChildrenBehavior, Controller, DOM, ElementStyles, ExecutionContext, FAST, FASTElement, FASTElementDefinition, HTMLBindingDirective, HTMLDirective, HTMLView, Observable, PropertyChangeNotifier, RefBehavior, RepeatBehavior, RepeatDirective, SlottedBehavior, SubscriberSet, TargetedHTMLDirective, ViewTemplate, attr, booleanConverter, children, compileTemplate, css, cssPartial, customElement, defaultExecutionContext, elements, emptyArray, enableArrayObservation, html, nullableNumberConverter, observable, ref, repeat, slotted, volatile, when };
|