@microsoft/fast-element 2.0.0-beta.16 → 2.0.0-beta.18
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 +36 -0
- package/CHANGELOG.md +18 -1
- package/dist/dts/components/element-controller.d.ts +5 -0
- package/dist/dts/dom-policy.d.ts +68 -0
- package/dist/dts/dom.d.ts +116 -0
- package/dist/dts/index.d.ts +3 -2
- package/dist/dts/index.rollup.d.ts +0 -1
- package/dist/dts/index.rollup.debug.d.ts +0 -1
- package/dist/dts/interfaces.d.ts +15 -24
- package/dist/dts/polyfills.d.ts +0 -1
- package/dist/dts/templating/binding-signal.d.ts +3 -1
- package/dist/dts/templating/binding-two-way.d.ts +3 -1
- package/dist/dts/templating/binding.d.ts +16 -5
- package/dist/dts/templating/compiler.d.ts +11 -13
- package/dist/dts/templating/dangerous-html.d.ts +18 -0
- package/dist/dts/templating/html-directive.d.ts +54 -118
- package/dist/dts/templating/node-observation.d.ts +11 -1
- package/dist/dts/templating/ref.d.ts +4 -0
- package/dist/dts/templating/render.d.ts +30 -6
- package/dist/dts/templating/repeat.d.ts +1 -5
- package/dist/dts/templating/template.d.ts +44 -13
- package/dist/dts/templating/view.d.ts +8 -3
- package/dist/dts/testing/fakes.d.ts +1 -0
- package/dist/dts/utilities.d.ts +39 -0
- package/dist/esm/components/attributes.js +1 -1
- package/dist/esm/components/element-controller.js +6 -1
- package/dist/esm/debug.js +4 -1
- package/dist/esm/dom-policy.js +337 -0
- package/dist/esm/dom.js +117 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.rollup.debug.js +3 -1
- package/dist/esm/index.rollup.js +3 -1
- package/dist/esm/observation/observable.js +5 -1
- package/dist/esm/platform.js +1 -1
- package/dist/esm/polyfills.js +3 -7
- package/dist/esm/templating/binding-signal.js +9 -3
- package/dist/esm/templating/binding-two-way.js +9 -3
- package/dist/esm/templating/binding.js +40 -55
- package/dist/esm/templating/children.js +8 -4
- package/dist/esm/templating/compiler.js +31 -38
- package/dist/esm/templating/dangerous-html.js +23 -0
- package/dist/esm/templating/html-directive.js +42 -133
- package/dist/esm/templating/node-observation.js +14 -8
- package/dist/esm/templating/ref.js +1 -1
- package/dist/esm/templating/render.js +17 -6
- package/dist/esm/templating/repeat.js +2 -6
- package/dist/esm/templating/template.js +86 -56
- package/dist/esm/templating/view.js +6 -0
- package/dist/esm/testing/fakes.js +2 -0
- package/dist/esm/testing/fixture.js +1 -1
- package/dist/esm/utilities.js +68 -0
- package/dist/fast-element.api.json +1088 -608
- package/dist/fast-element.d.ts +194 -147
- package/dist/fast-element.debug.js +745 -381
- package/dist/fast-element.debug.min.js +1 -1
- package/dist/fast-element.js +716 -355
- package/dist/fast-element.min.js +1 -1
- package/dist/fast-element.untrimmed.d.ts +208 -145
- package/docs/api-report.md +74 -56
- package/package.json +5 -1
- package/yarn-error.log +177 -0
- package/dist/dts/templating/dom.d.ts +0 -41
- package/dist/esm/templating/dom.js +0 -49
|
@@ -1,34 +1,3 @@
|
|
|
1
|
-
(function ensureGlobalThis() {
|
|
2
|
-
if (typeof globalThis !== "undefined") {
|
|
3
|
-
// We're running in a modern environment.
|
|
4
|
-
return;
|
|
5
|
-
}
|
|
6
|
-
if (typeof global !== "undefined") {
|
|
7
|
-
// We're running in NodeJS
|
|
8
|
-
global.globalThis = global;
|
|
9
|
-
}
|
|
10
|
-
else if (typeof self !== "undefined") {
|
|
11
|
-
self.globalThis = self;
|
|
12
|
-
}
|
|
13
|
-
else if (typeof window !== "undefined") {
|
|
14
|
-
// We're running in the browser's main thread.
|
|
15
|
-
window.globalThis = window;
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
// Hopefully we never get here...
|
|
19
|
-
// Not all environments allow eval and Function. Use only as a last resort:
|
|
20
|
-
// eslint-disable-next-line no-new-func
|
|
21
|
-
const result = new Function("return this")();
|
|
22
|
-
result.globalThis = result;
|
|
23
|
-
}
|
|
24
|
-
})();
|
|
25
|
-
// API-only Polyfill for trustedTypes
|
|
26
|
-
if (!globalThis.trustedTypes) {
|
|
27
|
-
globalThis.trustedTypes = {
|
|
28
|
-
createPolicy: (n, r) => r,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
1
|
if (globalThis.FAST === void 0) {
|
|
33
2
|
Reflect.defineProperty(globalThis, "FAST", {
|
|
34
3
|
value: Object.create(null),
|
|
@@ -40,11 +9,14 @@ if (globalThis.FAST === void 0) {
|
|
|
40
9
|
const FAST$1 = globalThis.FAST;
|
|
41
10
|
const debugMessages = {
|
|
42
11
|
[1101 /* needsArrayObservation */]: "Must call enableArrayObservation before observing arrays.",
|
|
43
|
-
[1201 /*
|
|
12
|
+
[1201 /* onlySetDOMPolicyOnce */]: "The DOM Policy can only be set once.",
|
|
44
13
|
[1202 /* bindingInnerHTMLRequiresTrustedTypes */]: "To bind innerHTML, you must use a TrustedTypesPolicy.",
|
|
45
14
|
[1203 /* twoWayBindingRequiresObservables */]: "View=>Model update skipped. To use twoWay binding, the target property must be observable.",
|
|
46
15
|
[1204 /* hostBindingWithoutHost */]: "No host element is present. Cannot bind host with ${name}.",
|
|
47
16
|
[1205 /* unsupportedBindingBehavior */]: "The requested binding behavior is not supported by the binding engine.",
|
|
17
|
+
[1206 /* directCallToHTMLTagNotAllowed */]: "Calling html`` as a normal function invalidates the security guarantees provided by FAST.",
|
|
18
|
+
[1207 /* onlySetTemplatePolicyOnce */]: "The DOM Policy for an HTML template can only be set once.",
|
|
19
|
+
[1208 /* cannotSetTemplatePolicyAfterCompilation */]: "The DOM Policy cannot be set after a template is compiled.",
|
|
48
20
|
[1401 /* missingElementDefinition */]: "Missing FASTElement definition.",
|
|
49
21
|
[1501 /* noRegistrationForContext */]: "No registration for Context/Interface '${name}'.",
|
|
50
22
|
[1502 /* noFactoryForResolver */]: "Dependency injection resolver for '${key}' returned a null factory.",
|
|
@@ -90,7 +62,48 @@ Object.assign(FAST$1, {
|
|
|
90
62
|
},
|
|
91
63
|
});
|
|
92
64
|
|
|
93
|
-
|
|
65
|
+
/**
|
|
66
|
+
* @internal
|
|
67
|
+
*/
|
|
68
|
+
const isFunction = (object) => typeof object === "function";
|
|
69
|
+
/**
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
const isString = (object) => typeof object === "string";
|
|
73
|
+
/**
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
76
|
+
const noop = () => void 0;
|
|
77
|
+
|
|
78
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
79
|
+
(function ensureGlobalThis() {
|
|
80
|
+
if (typeof globalThis !== "undefined") {
|
|
81
|
+
// We're running in a modern environment.
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
// @ts-ignore
|
|
85
|
+
if (typeof global !== "undefined") {
|
|
86
|
+
// We're running in NodeJS
|
|
87
|
+
// @ts-ignore
|
|
88
|
+
global.globalThis = global;
|
|
89
|
+
}
|
|
90
|
+
else if (typeof self !== "undefined") {
|
|
91
|
+
self.globalThis = self;
|
|
92
|
+
}
|
|
93
|
+
else if (typeof window !== "undefined") {
|
|
94
|
+
// We're running in the browser's main thread.
|
|
95
|
+
window.globalThis = window;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
// Hopefully we never get here...
|
|
99
|
+
// Not all environments allow eval and Function. Use only as a last resort:
|
|
100
|
+
// eslint-disable-next-line no-new-func
|
|
101
|
+
const result = new Function("return this")();
|
|
102
|
+
result.globalThis = result;
|
|
103
|
+
}
|
|
104
|
+
})();
|
|
105
|
+
|
|
106
|
+
// ensure FAST global - duplicated debug.ts
|
|
94
107
|
const propConfig = {
|
|
95
108
|
configurable: false,
|
|
96
109
|
enumerable: false,
|
|
@@ -178,15 +191,6 @@ function createMetadataLocator() {
|
|
|
178
191
|
};
|
|
179
192
|
}
|
|
180
193
|
|
|
181
|
-
/**
|
|
182
|
-
* @internal
|
|
183
|
-
*/
|
|
184
|
-
const isFunction = (object) => typeof object === "function";
|
|
185
|
-
/**
|
|
186
|
-
* @internal
|
|
187
|
-
*/
|
|
188
|
-
const isString = (object) => typeof object === "string";
|
|
189
|
-
|
|
190
194
|
/**
|
|
191
195
|
* The default UpdateQueue.
|
|
192
196
|
* @public
|
|
@@ -253,6 +257,456 @@ const Updates = FAST.getById(1 /* KernelServiceId.updateQueue */, () => {
|
|
|
253
257
|
});
|
|
254
258
|
});
|
|
255
259
|
|
|
260
|
+
/**
|
|
261
|
+
* The type of HTML aspect to target.
|
|
262
|
+
* @public
|
|
263
|
+
*/
|
|
264
|
+
const DOMAspect = Object.freeze({
|
|
265
|
+
/**
|
|
266
|
+
* Not aspected.
|
|
267
|
+
*/
|
|
268
|
+
none: 0,
|
|
269
|
+
/**
|
|
270
|
+
* An attribute.
|
|
271
|
+
*/
|
|
272
|
+
attribute: 1,
|
|
273
|
+
/**
|
|
274
|
+
* A boolean attribute.
|
|
275
|
+
*/
|
|
276
|
+
booleanAttribute: 2,
|
|
277
|
+
/**
|
|
278
|
+
* A property.
|
|
279
|
+
*/
|
|
280
|
+
property: 3,
|
|
281
|
+
/**
|
|
282
|
+
* Content
|
|
283
|
+
*/
|
|
284
|
+
content: 4,
|
|
285
|
+
/**
|
|
286
|
+
* A token list.
|
|
287
|
+
*/
|
|
288
|
+
tokenList: 5,
|
|
289
|
+
/**
|
|
290
|
+
* An event.
|
|
291
|
+
*/
|
|
292
|
+
event: 6,
|
|
293
|
+
});
|
|
294
|
+
const createHTML$1 = html => html;
|
|
295
|
+
const fastTrustedType = globalThis.trustedTypes
|
|
296
|
+
? globalThis.trustedTypes.createPolicy("fast-html", { createHTML: createHTML$1 })
|
|
297
|
+
: { createHTML: createHTML$1 };
|
|
298
|
+
let defaultPolicy = Object.freeze({
|
|
299
|
+
createHTML(value) {
|
|
300
|
+
return fastTrustedType.createHTML(value);
|
|
301
|
+
},
|
|
302
|
+
protect(tagName, aspect, aspectName, sink) {
|
|
303
|
+
return sink;
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
const fastPolicy = defaultPolicy;
|
|
307
|
+
/**
|
|
308
|
+
* Common DOM APIs.
|
|
309
|
+
* @public
|
|
310
|
+
*/
|
|
311
|
+
const DOM = Object.freeze({
|
|
312
|
+
/**
|
|
313
|
+
* @deprecated
|
|
314
|
+
* Use Updates.enqueue().
|
|
315
|
+
*/
|
|
316
|
+
queueUpdate: Updates.enqueue,
|
|
317
|
+
/**
|
|
318
|
+
* @deprecated
|
|
319
|
+
* Use Updates.next()
|
|
320
|
+
*/
|
|
321
|
+
nextUpdate: Updates.next,
|
|
322
|
+
/**
|
|
323
|
+
* @deprecated
|
|
324
|
+
* Use Updates.process()
|
|
325
|
+
*/
|
|
326
|
+
processUpdates: Updates.process,
|
|
327
|
+
/**
|
|
328
|
+
* Gets the dom policy used by the templating system.
|
|
329
|
+
*/
|
|
330
|
+
get policy() {
|
|
331
|
+
return defaultPolicy;
|
|
332
|
+
},
|
|
333
|
+
/**
|
|
334
|
+
* Sets the dom policy used by the templating system.
|
|
335
|
+
* @param policy - The policy to set.
|
|
336
|
+
* @remarks
|
|
337
|
+
* This API can only be called once, for security reasons. It should be
|
|
338
|
+
* called by the application developer at the start of their program.
|
|
339
|
+
*/
|
|
340
|
+
setPolicy(value) {
|
|
341
|
+
if (defaultPolicy !== fastPolicy) {
|
|
342
|
+
throw FAST.error(1201 /* Message.onlySetDOMPolicyOnce */);
|
|
343
|
+
}
|
|
344
|
+
defaultPolicy = value;
|
|
345
|
+
},
|
|
346
|
+
/**
|
|
347
|
+
* Sets an attribute value on an element.
|
|
348
|
+
* @param element - The element to set the attribute value on.
|
|
349
|
+
* @param attributeName - The attribute name to set.
|
|
350
|
+
* @param value - The value of the attribute to set.
|
|
351
|
+
* @remarks
|
|
352
|
+
* If the value is `null` or `undefined`, the attribute is removed, otherwise
|
|
353
|
+
* it is set to the provided value using the standard `setAttribute` API.
|
|
354
|
+
*/
|
|
355
|
+
setAttribute(element, attributeName, value) {
|
|
356
|
+
value === null || value === undefined
|
|
357
|
+
? element.removeAttribute(attributeName)
|
|
358
|
+
: element.setAttribute(attributeName, value);
|
|
359
|
+
},
|
|
360
|
+
/**
|
|
361
|
+
* Sets a boolean attribute value.
|
|
362
|
+
* @param element - The element to set the boolean attribute value on.
|
|
363
|
+
* @param attributeName - The attribute name to set.
|
|
364
|
+
* @param value - The value of the attribute to set.
|
|
365
|
+
* @remarks
|
|
366
|
+
* If the value is true, the attribute is added; otherwise it is removed.
|
|
367
|
+
*/
|
|
368
|
+
setBooleanAttribute(element, attributeName, value) {
|
|
369
|
+
value
|
|
370
|
+
? element.setAttribute(attributeName, "")
|
|
371
|
+
: element.removeAttribute(attributeName);
|
|
372
|
+
},
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
function safeURL(tagName, aspect, aspectName, sink) {
|
|
376
|
+
return (target, name, value, ...rest) => {
|
|
377
|
+
if (isString(value)) {
|
|
378
|
+
value = value.replace("javascript:", "");
|
|
379
|
+
}
|
|
380
|
+
sink(target, name, value, ...rest);
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
function block(tagName, aspect, aspectName, sink) {
|
|
384
|
+
throw new Error(`${aspectName} on ${tagName !== null && tagName !== void 0 ? tagName : "text"} is blocked by the current DOMPolicy.`);
|
|
385
|
+
}
|
|
386
|
+
const defaultDOMElementGuards = {
|
|
387
|
+
a: {
|
|
388
|
+
[DOMAspect.attribute]: {
|
|
389
|
+
href: safeURL,
|
|
390
|
+
},
|
|
391
|
+
[DOMAspect.property]: {
|
|
392
|
+
href: safeURL,
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
area: {
|
|
396
|
+
[DOMAspect.attribute]: {
|
|
397
|
+
href: safeURL,
|
|
398
|
+
},
|
|
399
|
+
[DOMAspect.property]: {
|
|
400
|
+
href: safeURL,
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
button: {
|
|
404
|
+
[DOMAspect.attribute]: {
|
|
405
|
+
formaction: safeURL,
|
|
406
|
+
},
|
|
407
|
+
[DOMAspect.property]: {
|
|
408
|
+
formAction: safeURL,
|
|
409
|
+
},
|
|
410
|
+
},
|
|
411
|
+
embed: {
|
|
412
|
+
[DOMAspect.attribute]: {
|
|
413
|
+
src: block,
|
|
414
|
+
},
|
|
415
|
+
[DOMAspect.property]: {
|
|
416
|
+
src: block,
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
form: {
|
|
420
|
+
[DOMAspect.attribute]: {
|
|
421
|
+
action: safeURL,
|
|
422
|
+
},
|
|
423
|
+
[DOMAspect.property]: {
|
|
424
|
+
action: safeURL,
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
frame: {
|
|
428
|
+
[DOMAspect.attribute]: {
|
|
429
|
+
src: safeURL,
|
|
430
|
+
},
|
|
431
|
+
[DOMAspect.property]: {
|
|
432
|
+
src: safeURL,
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
iframe: {
|
|
436
|
+
[DOMAspect.attribute]: {
|
|
437
|
+
src: safeURL,
|
|
438
|
+
},
|
|
439
|
+
[DOMAspect.property]: {
|
|
440
|
+
src: safeURL,
|
|
441
|
+
srcdoc: block,
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
input: {
|
|
445
|
+
[DOMAspect.attribute]: {
|
|
446
|
+
formaction: safeURL,
|
|
447
|
+
},
|
|
448
|
+
[DOMAspect.property]: {
|
|
449
|
+
formAction: safeURL,
|
|
450
|
+
},
|
|
451
|
+
},
|
|
452
|
+
link: {
|
|
453
|
+
[DOMAspect.attribute]: {
|
|
454
|
+
href: block,
|
|
455
|
+
},
|
|
456
|
+
[DOMAspect.property]: {
|
|
457
|
+
href: block,
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
object: {
|
|
461
|
+
[DOMAspect.attribute]: {
|
|
462
|
+
codebase: block,
|
|
463
|
+
data: block,
|
|
464
|
+
},
|
|
465
|
+
[DOMAspect.property]: {
|
|
466
|
+
codeBase: block,
|
|
467
|
+
data: block,
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
script: {
|
|
471
|
+
[DOMAspect.attribute]: {
|
|
472
|
+
src: block,
|
|
473
|
+
text: block,
|
|
474
|
+
},
|
|
475
|
+
[DOMAspect.property]: {
|
|
476
|
+
src: block,
|
|
477
|
+
text: block,
|
|
478
|
+
innerText: block,
|
|
479
|
+
textContent: block,
|
|
480
|
+
},
|
|
481
|
+
},
|
|
482
|
+
style: {
|
|
483
|
+
[DOMAspect.property]: {
|
|
484
|
+
innerText: block,
|
|
485
|
+
textContent: block,
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
};
|
|
489
|
+
const blockedEvents = {
|
|
490
|
+
onabort: block,
|
|
491
|
+
onauxclick: block,
|
|
492
|
+
onbeforeinput: block,
|
|
493
|
+
onbeforematch: block,
|
|
494
|
+
onblur: block,
|
|
495
|
+
oncancel: block,
|
|
496
|
+
oncanplay: block,
|
|
497
|
+
oncanplaythrough: block,
|
|
498
|
+
onchange: block,
|
|
499
|
+
onclick: block,
|
|
500
|
+
onclose: block,
|
|
501
|
+
oncontextlost: block,
|
|
502
|
+
oncontextmenu: block,
|
|
503
|
+
oncontextrestored: block,
|
|
504
|
+
oncopy: block,
|
|
505
|
+
oncuechange: block,
|
|
506
|
+
oncut: block,
|
|
507
|
+
ondblclick: block,
|
|
508
|
+
ondrag: block,
|
|
509
|
+
ondragend: block,
|
|
510
|
+
ondragenter: block,
|
|
511
|
+
ondragleave: block,
|
|
512
|
+
ondragover: block,
|
|
513
|
+
ondragstart: block,
|
|
514
|
+
ondrop: block,
|
|
515
|
+
ondurationchange: block,
|
|
516
|
+
onemptied: block,
|
|
517
|
+
onended: block,
|
|
518
|
+
onerror: block,
|
|
519
|
+
onfocus: block,
|
|
520
|
+
onformdata: block,
|
|
521
|
+
oninput: block,
|
|
522
|
+
oninvalid: block,
|
|
523
|
+
onkeydown: block,
|
|
524
|
+
onkeypress: block,
|
|
525
|
+
onkeyup: block,
|
|
526
|
+
onload: block,
|
|
527
|
+
onloadeddata: block,
|
|
528
|
+
onloadedmetadata: block,
|
|
529
|
+
onloadstart: block,
|
|
530
|
+
onmousedown: block,
|
|
531
|
+
onmouseenter: block,
|
|
532
|
+
onmouseleave: block,
|
|
533
|
+
onmousemove: block,
|
|
534
|
+
onmouseout: block,
|
|
535
|
+
onmouseover: block,
|
|
536
|
+
onmouseup: block,
|
|
537
|
+
onpaste: block,
|
|
538
|
+
onpause: block,
|
|
539
|
+
onplay: block,
|
|
540
|
+
onplaying: block,
|
|
541
|
+
onprogress: block,
|
|
542
|
+
onratechange: block,
|
|
543
|
+
onreset: block,
|
|
544
|
+
onresize: block,
|
|
545
|
+
onscroll: block,
|
|
546
|
+
onsecuritypolicyviolation: block,
|
|
547
|
+
onseeked: block,
|
|
548
|
+
onseeking: block,
|
|
549
|
+
onselect: block,
|
|
550
|
+
onslotchange: block,
|
|
551
|
+
onstalled: block,
|
|
552
|
+
onsubmit: block,
|
|
553
|
+
onsuspend: block,
|
|
554
|
+
ontimeupdate: block,
|
|
555
|
+
ontoggle: block,
|
|
556
|
+
onvolumechange: block,
|
|
557
|
+
onwaiting: block,
|
|
558
|
+
onwebkitanimationend: block,
|
|
559
|
+
onwebkitanimationiteration: block,
|
|
560
|
+
onwebkitanimationstart: block,
|
|
561
|
+
onwebkittransitionend: block,
|
|
562
|
+
onwheel: block,
|
|
563
|
+
};
|
|
564
|
+
const defaultDOMGuards = {
|
|
565
|
+
elements: defaultDOMElementGuards,
|
|
566
|
+
aspects: {
|
|
567
|
+
[DOMAspect.attribute]: Object.assign({}, blockedEvents),
|
|
568
|
+
[DOMAspect.property]: Object.assign({ innerHTML: block }, blockedEvents),
|
|
569
|
+
[DOMAspect.event]: Object.assign({}, blockedEvents),
|
|
570
|
+
},
|
|
571
|
+
};
|
|
572
|
+
function createDomSinkGuards(config, defaults) {
|
|
573
|
+
const result = {};
|
|
574
|
+
for (const name in defaults) {
|
|
575
|
+
const overrideValue = config[name];
|
|
576
|
+
const defaultValue = defaults[name];
|
|
577
|
+
switch (overrideValue) {
|
|
578
|
+
case null:
|
|
579
|
+
// remove the default
|
|
580
|
+
break;
|
|
581
|
+
case undefined:
|
|
582
|
+
// keep the default
|
|
583
|
+
result[name] = defaultValue;
|
|
584
|
+
break;
|
|
585
|
+
default:
|
|
586
|
+
// override the default
|
|
587
|
+
result[name] = overrideValue;
|
|
588
|
+
break;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
// add any new sinks that were not overrides
|
|
592
|
+
for (const name in config) {
|
|
593
|
+
if (!(name in result)) {
|
|
594
|
+
result[name] = config[name];
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
return Object.freeze(result);
|
|
598
|
+
}
|
|
599
|
+
function createDOMAspectGuards(config, defaults) {
|
|
600
|
+
const result = {};
|
|
601
|
+
for (const aspect in defaults) {
|
|
602
|
+
const overrideValue = config[aspect];
|
|
603
|
+
const defaultValue = defaults[aspect];
|
|
604
|
+
switch (overrideValue) {
|
|
605
|
+
case null:
|
|
606
|
+
// remove the default
|
|
607
|
+
break;
|
|
608
|
+
case undefined:
|
|
609
|
+
// keep the default
|
|
610
|
+
result[aspect] = createDomSinkGuards(defaultValue, {});
|
|
611
|
+
break;
|
|
612
|
+
default:
|
|
613
|
+
// override the default
|
|
614
|
+
result[aspect] = createDomSinkGuards(overrideValue, defaultValue);
|
|
615
|
+
break;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
// add any new aspect guards that were not overrides
|
|
619
|
+
for (const aspect in config) {
|
|
620
|
+
if (!(aspect in result)) {
|
|
621
|
+
result[aspect] = createDomSinkGuards(config[aspect], {});
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
return Object.freeze(result);
|
|
625
|
+
}
|
|
626
|
+
function createElementGuards(config, defaults) {
|
|
627
|
+
const result = {};
|
|
628
|
+
for (const tag in defaults) {
|
|
629
|
+
const overrideValue = config[tag];
|
|
630
|
+
const defaultValue = defaults[tag];
|
|
631
|
+
switch (overrideValue) {
|
|
632
|
+
case null:
|
|
633
|
+
// remove the default
|
|
634
|
+
break;
|
|
635
|
+
case undefined:
|
|
636
|
+
// keep the default
|
|
637
|
+
result[tag] = createDOMAspectGuards(overrideValue, {});
|
|
638
|
+
break;
|
|
639
|
+
default:
|
|
640
|
+
// override the default aspects
|
|
641
|
+
result[tag] = createDOMAspectGuards(overrideValue, defaultValue);
|
|
642
|
+
break;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
// Add any new element guards that were not overrides
|
|
646
|
+
for (const tag in config) {
|
|
647
|
+
if (!(tag in result)) {
|
|
648
|
+
result[tag] = createDOMAspectGuards(config[tag], {});
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
return Object.freeze(result);
|
|
652
|
+
}
|
|
653
|
+
function createDOMGuards(config, defaults) {
|
|
654
|
+
return Object.freeze({
|
|
655
|
+
elements: config.elements
|
|
656
|
+
? createElementGuards(config.elements, defaults.elements)
|
|
657
|
+
: defaults.elements,
|
|
658
|
+
aspects: config.aspects
|
|
659
|
+
? createDOMAspectGuards(config.aspects, defaults.aspects)
|
|
660
|
+
: defaults.aspects,
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
function createTrustedType() {
|
|
664
|
+
const createHTML = html => html;
|
|
665
|
+
return globalThis.trustedTypes
|
|
666
|
+
? globalThis.trustedTypes.createPolicy("fast-html", { createHTML })
|
|
667
|
+
: { createHTML };
|
|
668
|
+
}
|
|
669
|
+
function tryGuard(aspectGuards, tagName, aspect, aspectName, sink) {
|
|
670
|
+
const sinkGuards = aspectGuards[aspect];
|
|
671
|
+
if (sinkGuards) {
|
|
672
|
+
const guard = sinkGuards[aspectName];
|
|
673
|
+
if (guard) {
|
|
674
|
+
return guard(tagName, aspect, aspectName, sink);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
const DOMPolicy = Object.freeze({
|
|
679
|
+
/**
|
|
680
|
+
* Creates a new DOM Policy object.
|
|
681
|
+
* @param options The options to use in creating the policy.
|
|
682
|
+
* @returns The newly created DOMPolicy.
|
|
683
|
+
*/
|
|
684
|
+
create(options = {}) {
|
|
685
|
+
var _a, _b;
|
|
686
|
+
const trustedType = (_a = options.trustedType) !== null && _a !== void 0 ? _a : createTrustedType();
|
|
687
|
+
const guards = createDOMGuards((_b = options.guards) !== null && _b !== void 0 ? _b : {}, defaultDOMGuards);
|
|
688
|
+
return Object.freeze({
|
|
689
|
+
createHTML(value) {
|
|
690
|
+
return trustedType.createHTML(value);
|
|
691
|
+
},
|
|
692
|
+
protect(tagName, aspect, aspectName, sink) {
|
|
693
|
+
var _a;
|
|
694
|
+
// Check for element-specific guards.
|
|
695
|
+
const key = (tagName !== null && tagName !== void 0 ? tagName : "").toLowerCase();
|
|
696
|
+
const elementGuards = guards.elements[key];
|
|
697
|
+
if (elementGuards) {
|
|
698
|
+
const guard = tryGuard(elementGuards, tagName, aspect, aspectName, sink);
|
|
699
|
+
if (guard) {
|
|
700
|
+
return guard;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
// Check for guards applicable to all nodes.
|
|
704
|
+
return ((_a = tryGuard(guards.aspects, tagName, aspect, aspectName, sink)) !== null && _a !== void 0 ? _a : sink);
|
|
705
|
+
},
|
|
706
|
+
});
|
|
707
|
+
},
|
|
708
|
+
});
|
|
709
|
+
|
|
256
710
|
/**
|
|
257
711
|
* An implementation of {@link Notifier} that efficiently keeps track of
|
|
258
712
|
* subscribers interested in a specific change notification on an
|
|
@@ -495,6 +949,10 @@ const Observable = FAST.getById(2 /* KernelServiceId.observable */, () => {
|
|
|
495
949
|
this.propertyName = void 0;
|
|
496
950
|
this.notifier = void 0;
|
|
497
951
|
this.next = void 0;
|
|
952
|
+
/**
|
|
953
|
+
* Opts out of JSON stringification.
|
|
954
|
+
*/
|
|
955
|
+
this.toJSON = noop;
|
|
498
956
|
}
|
|
499
957
|
setMode(isAsync) {
|
|
500
958
|
this.isAsync = this.needsQueue = isAsync;
|
|
@@ -1535,55 +1993,6 @@ css.partial = (strings, ...values) => {
|
|
|
1535
1993
|
*/
|
|
1536
1994
|
const cssPartial = css.partial;
|
|
1537
1995
|
|
|
1538
|
-
/**
|
|
1539
|
-
* Common DOM APIs.
|
|
1540
|
-
* @public
|
|
1541
|
-
*/
|
|
1542
|
-
const DOM = Object.freeze({
|
|
1543
|
-
/**
|
|
1544
|
-
* @deprecated
|
|
1545
|
-
* Use Updates.enqueue().
|
|
1546
|
-
*/
|
|
1547
|
-
queueUpdate: Updates.enqueue,
|
|
1548
|
-
/**
|
|
1549
|
-
* @deprecated
|
|
1550
|
-
* Use Updates.next()
|
|
1551
|
-
*/
|
|
1552
|
-
nextUpdate: Updates.next,
|
|
1553
|
-
/**
|
|
1554
|
-
* @deprecated
|
|
1555
|
-
* Use Updates.process()
|
|
1556
|
-
*/
|
|
1557
|
-
processUpdates: Updates.process,
|
|
1558
|
-
/**
|
|
1559
|
-
* Sets an attribute value on an element.
|
|
1560
|
-
* @param element - The element to set the attribute value on.
|
|
1561
|
-
* @param attributeName - The attribute name to set.
|
|
1562
|
-
* @param value - The value of the attribute to set.
|
|
1563
|
-
* @remarks
|
|
1564
|
-
* If the value is `null` or `undefined`, the attribute is removed, otherwise
|
|
1565
|
-
* it is set to the provided value using the standard `setAttribute` API.
|
|
1566
|
-
*/
|
|
1567
|
-
setAttribute(element, attributeName, value) {
|
|
1568
|
-
value === null || value === undefined
|
|
1569
|
-
? element.removeAttribute(attributeName)
|
|
1570
|
-
: element.setAttribute(attributeName, value);
|
|
1571
|
-
},
|
|
1572
|
-
/**
|
|
1573
|
-
* Sets a boolean attribute value.
|
|
1574
|
-
* @param element - The element to set the boolean attribute value on.
|
|
1575
|
-
* @param attributeName - The attribute name to set.
|
|
1576
|
-
* @param value - The value of the attribute to set.
|
|
1577
|
-
* @remarks
|
|
1578
|
-
* If the value is true, the attribute is added; otherwise it is removed.
|
|
1579
|
-
*/
|
|
1580
|
-
setBooleanAttribute(element, attributeName, value) {
|
|
1581
|
-
value
|
|
1582
|
-
? element.setAttribute(attributeName, "")
|
|
1583
|
-
: element.removeAttribute(attributeName);
|
|
1584
|
-
},
|
|
1585
|
-
});
|
|
1586
|
-
|
|
1587
1996
|
const marker = `fast-${Math.random().toString(36).substring(2, 8)}`;
|
|
1588
1997
|
const interpolationStart = `${marker}{`;
|
|
1589
1998
|
const interpolationEnd = `}${marker}`;
|
|
@@ -1660,67 +2069,6 @@ const Parser = Object.freeze({
|
|
|
1660
2069
|
},
|
|
1661
2070
|
});
|
|
1662
2071
|
|
|
1663
|
-
/**
|
|
1664
|
-
* Bridges between ViewBehaviors and HostBehaviors, enabling a host to
|
|
1665
|
-
* control ViewBehaviors.
|
|
1666
|
-
* @public
|
|
1667
|
-
*/
|
|
1668
|
-
const ViewBehaviorOrchestrator = Object.freeze({
|
|
1669
|
-
/**
|
|
1670
|
-
* Creates a ViewBehaviorOrchestrator.
|
|
1671
|
-
* @param source - The source to to associate behaviors with.
|
|
1672
|
-
* @returns A ViewBehaviorOrchestrator.
|
|
1673
|
-
*/
|
|
1674
|
-
create(source) {
|
|
1675
|
-
const behaviors = [];
|
|
1676
|
-
const targets = {};
|
|
1677
|
-
let unbindables = null;
|
|
1678
|
-
let isConnected = false;
|
|
1679
|
-
return {
|
|
1680
|
-
source,
|
|
1681
|
-
context: ExecutionContext.default,
|
|
1682
|
-
targets,
|
|
1683
|
-
get isBound() {
|
|
1684
|
-
return isConnected;
|
|
1685
|
-
},
|
|
1686
|
-
addBehaviorFactory(factory, target) {
|
|
1687
|
-
const nodeId = factory.nodeId || (factory.nodeId = nextId());
|
|
1688
|
-
factory.id || (factory.id = nextId());
|
|
1689
|
-
this.addTarget(nodeId, target);
|
|
1690
|
-
this.addBehavior(factory.createBehavior());
|
|
1691
|
-
},
|
|
1692
|
-
addTarget(nodeId, target) {
|
|
1693
|
-
targets[nodeId] = target;
|
|
1694
|
-
},
|
|
1695
|
-
addBehavior(behavior) {
|
|
1696
|
-
behaviors.push(behavior);
|
|
1697
|
-
if (isConnected) {
|
|
1698
|
-
behavior.bind(this);
|
|
1699
|
-
}
|
|
1700
|
-
},
|
|
1701
|
-
onUnbind(unbindable) {
|
|
1702
|
-
if (unbindables === null) {
|
|
1703
|
-
unbindables = [];
|
|
1704
|
-
}
|
|
1705
|
-
unbindables.push(unbindable);
|
|
1706
|
-
},
|
|
1707
|
-
connectedCallback(controller) {
|
|
1708
|
-
if (!isConnected) {
|
|
1709
|
-
isConnected = true;
|
|
1710
|
-
behaviors.forEach(x => x.bind(this));
|
|
1711
|
-
}
|
|
1712
|
-
},
|
|
1713
|
-
disconnectedCallback(controller) {
|
|
1714
|
-
if (isConnected) {
|
|
1715
|
-
isConnected = false;
|
|
1716
|
-
if (unbindables !== null) {
|
|
1717
|
-
unbindables.forEach(x => x.unbind(this));
|
|
1718
|
-
}
|
|
1719
|
-
}
|
|
1720
|
-
},
|
|
1721
|
-
};
|
|
1722
|
-
},
|
|
1723
|
-
});
|
|
1724
2072
|
const registry = createTypeRegistry();
|
|
1725
2073
|
/**
|
|
1726
2074
|
* Instructs the template engine to apply behavior to a node.
|
|
@@ -1748,67 +2096,6 @@ const HTMLDirective = Object.freeze({
|
|
|
1748
2096
|
registry.register(options);
|
|
1749
2097
|
return type;
|
|
1750
2098
|
},
|
|
1751
|
-
});
|
|
1752
|
-
/**
|
|
1753
|
-
* Decorator: Defines an HTMLDirective.
|
|
1754
|
-
* @param options - Provides options that specify the directive's application.
|
|
1755
|
-
* @public
|
|
1756
|
-
*/
|
|
1757
|
-
function htmlDirective(options) {
|
|
1758
|
-
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
1759
|
-
return function (type) {
|
|
1760
|
-
HTMLDirective.define(type, options);
|
|
1761
|
-
};
|
|
1762
|
-
}
|
|
1763
|
-
/**
|
|
1764
|
-
* Captures a binding expression along with related information and capabilities.
|
|
1765
|
-
*
|
|
1766
|
-
* @public
|
|
1767
|
-
*/
|
|
1768
|
-
class Binding {
|
|
1769
|
-
/**
|
|
1770
|
-
* Creates a binding.
|
|
1771
|
-
* @param evaluate - Evaluates the binding.
|
|
1772
|
-
* @param isVolatile - Indicates whether the binding is volatile.
|
|
1773
|
-
*/
|
|
1774
|
-
constructor(evaluate, isVolatile = false) {
|
|
1775
|
-
this.evaluate = evaluate;
|
|
1776
|
-
this.isVolatile = isVolatile;
|
|
1777
|
-
}
|
|
1778
|
-
}
|
|
1779
|
-
/**
|
|
1780
|
-
* The type of HTML aspect to target.
|
|
1781
|
-
* @public
|
|
1782
|
-
*/
|
|
1783
|
-
const Aspect = Object.freeze({
|
|
1784
|
-
/**
|
|
1785
|
-
* Not aspected.
|
|
1786
|
-
*/
|
|
1787
|
-
none: 0,
|
|
1788
|
-
/**
|
|
1789
|
-
* An attribute.
|
|
1790
|
-
*/
|
|
1791
|
-
attribute: 1,
|
|
1792
|
-
/**
|
|
1793
|
-
* A boolean attribute.
|
|
1794
|
-
*/
|
|
1795
|
-
booleanAttribute: 2,
|
|
1796
|
-
/**
|
|
1797
|
-
* A property.
|
|
1798
|
-
*/
|
|
1799
|
-
property: 3,
|
|
1800
|
-
/**
|
|
1801
|
-
* Content
|
|
1802
|
-
*/
|
|
1803
|
-
content: 4,
|
|
1804
|
-
/**
|
|
1805
|
-
* A token list.
|
|
1806
|
-
*/
|
|
1807
|
-
tokenList: 5,
|
|
1808
|
-
/**
|
|
1809
|
-
* An event.
|
|
1810
|
-
*/
|
|
1811
|
-
event: 6,
|
|
1812
2099
|
/**
|
|
1813
2100
|
*
|
|
1814
2101
|
* @param directive - The directive to assign the aspect to.
|
|
@@ -1816,9 +2103,9 @@ const Aspect = Object.freeze({
|
|
|
1816
2103
|
* @remarks
|
|
1817
2104
|
* If a falsy value is provided, then the content aspect will be assigned.
|
|
1818
2105
|
*/
|
|
1819
|
-
|
|
2106
|
+
assignAspect(directive, value) {
|
|
1820
2107
|
if (!value) {
|
|
1821
|
-
directive.aspectType =
|
|
2108
|
+
directive.aspectType = DOMAspect.content;
|
|
1822
2109
|
return;
|
|
1823
2110
|
}
|
|
1824
2111
|
directive.sourceAspect = value;
|
|
@@ -1827,24 +2114,53 @@ const Aspect = Object.freeze({
|
|
|
1827
2114
|
directive.targetAspect = value.substring(1);
|
|
1828
2115
|
directive.aspectType =
|
|
1829
2116
|
directive.targetAspect === "classList"
|
|
1830
|
-
?
|
|
1831
|
-
:
|
|
2117
|
+
? DOMAspect.tokenList
|
|
2118
|
+
: DOMAspect.property;
|
|
1832
2119
|
break;
|
|
1833
2120
|
case "?":
|
|
1834
2121
|
directive.targetAspect = value.substring(1);
|
|
1835
|
-
directive.aspectType =
|
|
2122
|
+
directive.aspectType = DOMAspect.booleanAttribute;
|
|
1836
2123
|
break;
|
|
1837
2124
|
case "@":
|
|
1838
2125
|
directive.targetAspect = value.substring(1);
|
|
1839
|
-
directive.aspectType =
|
|
2126
|
+
directive.aspectType = DOMAspect.event;
|
|
1840
2127
|
break;
|
|
1841
2128
|
default:
|
|
1842
2129
|
directive.targetAspect = value;
|
|
1843
|
-
directive.aspectType =
|
|
2130
|
+
directive.aspectType = DOMAspect.attribute;
|
|
1844
2131
|
break;
|
|
1845
2132
|
}
|
|
1846
2133
|
},
|
|
1847
2134
|
});
|
|
2135
|
+
/**
|
|
2136
|
+
* Decorator: Defines an HTMLDirective.
|
|
2137
|
+
* @param options - Provides options that specify the directive's application.
|
|
2138
|
+
* @public
|
|
2139
|
+
*/
|
|
2140
|
+
function htmlDirective(options) {
|
|
2141
|
+
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
2142
|
+
return function (type) {
|
|
2143
|
+
HTMLDirective.define(type, options);
|
|
2144
|
+
};
|
|
2145
|
+
}
|
|
2146
|
+
/**
|
|
2147
|
+
* Captures a binding expression along with related information and capabilities.
|
|
2148
|
+
*
|
|
2149
|
+
* @public
|
|
2150
|
+
*/
|
|
2151
|
+
class Binding {
|
|
2152
|
+
/**
|
|
2153
|
+
* Creates a binding.
|
|
2154
|
+
* @param evaluate - Evaluates the binding.
|
|
2155
|
+
* @param policy - The security policy to associate with this binding.
|
|
2156
|
+
* @param isVolatile - Indicates whether the binding is volatile.
|
|
2157
|
+
*/
|
|
2158
|
+
constructor(evaluate, policy, isVolatile = false) {
|
|
2159
|
+
this.evaluate = evaluate;
|
|
2160
|
+
this.policy = policy;
|
|
2161
|
+
this.isVolatile = isVolatile;
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
1848
2164
|
/**
|
|
1849
2165
|
* A base class used for attribute directives that don't need internal state.
|
|
1850
2166
|
* @public
|
|
@@ -1857,9 +2173,10 @@ class StatelessAttachedAttributeDirective {
|
|
|
1857
2173
|
constructor(options) {
|
|
1858
2174
|
this.options = options;
|
|
1859
2175
|
/**
|
|
1860
|
-
*
|
|
2176
|
+
* Opts out of JSON stringification.
|
|
2177
|
+
* @internal
|
|
1861
2178
|
*/
|
|
1862
|
-
this.
|
|
2179
|
+
this.toJSON = noop;
|
|
1863
2180
|
}
|
|
1864
2181
|
/**
|
|
1865
2182
|
* Creates a placeholder string based on the directive's index within the template.
|
|
@@ -1879,21 +2196,20 @@ class StatelessAttachedAttributeDirective {
|
|
|
1879
2196
|
}
|
|
1880
2197
|
}
|
|
1881
2198
|
|
|
1882
|
-
const createInnerHTMLBinding = globalThis.TrustedHTML
|
|
1883
|
-
? (binding) => (s, c) => {
|
|
1884
|
-
const value = binding(s, c);
|
|
1885
|
-
if (value instanceof TrustedHTML) {
|
|
1886
|
-
return value;
|
|
1887
|
-
}
|
|
1888
|
-
throw FAST.error(1202 /* Message.bindingInnerHTMLRequiresTrustedTypes */);
|
|
1889
|
-
}
|
|
1890
|
-
: (binding) => binding;
|
|
1891
2199
|
class OnChangeBinding extends Binding {
|
|
1892
2200
|
createObserver(_, subscriber) {
|
|
1893
2201
|
return Observable.binding(this.evaluate, subscriber, this.isVolatile);
|
|
1894
2202
|
}
|
|
1895
2203
|
}
|
|
1896
2204
|
class OneTimeBinding extends Binding {
|
|
2205
|
+
constructor() {
|
|
2206
|
+
super(...arguments);
|
|
2207
|
+
/**
|
|
2208
|
+
* Opts out of JSON stringification.
|
|
2209
|
+
* @internal
|
|
2210
|
+
*/
|
|
2211
|
+
this.toJSON = noop;
|
|
2212
|
+
}
|
|
1897
2213
|
createObserver() {
|
|
1898
2214
|
return this;
|
|
1899
2215
|
}
|
|
@@ -1992,8 +2308,14 @@ function updateTokenList(target, aspect, value) {
|
|
|
1992
2308
|
}
|
|
1993
2309
|
}
|
|
1994
2310
|
}
|
|
1995
|
-
const
|
|
1996
|
-
|
|
2311
|
+
const sinkLookup = {
|
|
2312
|
+
[DOMAspect.attribute]: DOM.setAttribute,
|
|
2313
|
+
[DOMAspect.booleanAttribute]: DOM.setBooleanAttribute,
|
|
2314
|
+
[DOMAspect.property]: (t, a, v) => (t[a] = v),
|
|
2315
|
+
[DOMAspect.content]: updateContent,
|
|
2316
|
+
[DOMAspect.tokenList]: updateTokenList,
|
|
2317
|
+
[DOMAspect.event]: () => void 0,
|
|
2318
|
+
};
|
|
1997
2319
|
/**
|
|
1998
2320
|
* A directive that applies bindings.
|
|
1999
2321
|
* @public
|
|
@@ -2006,15 +2328,10 @@ class HTMLBindingDirective {
|
|
|
2006
2328
|
constructor(dataBinding) {
|
|
2007
2329
|
this.dataBinding = dataBinding;
|
|
2008
2330
|
this.updateTarget = null;
|
|
2009
|
-
/**
|
|
2010
|
-
* The unique id of the factory.
|
|
2011
|
-
*/
|
|
2012
|
-
this.id = nextId();
|
|
2013
2331
|
/**
|
|
2014
2332
|
* The type of aspect to target.
|
|
2015
2333
|
*/
|
|
2016
|
-
this.aspectType =
|
|
2017
|
-
this.data = `${this.id}-d`;
|
|
2334
|
+
this.aspectType = DOMAspect.content;
|
|
2018
2335
|
}
|
|
2019
2336
|
/**
|
|
2020
2337
|
* Creates HTML to be used within a template.
|
|
@@ -2027,45 +2344,28 @@ class HTMLBindingDirective {
|
|
|
2027
2344
|
* Creates a behavior.
|
|
2028
2345
|
*/
|
|
2029
2346
|
createBehavior() {
|
|
2347
|
+
var _a;
|
|
2030
2348
|
if (this.updateTarget === null) {
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
case 1:
|
|
2036
|
-
this.updateTarget = DOM.setAttribute;
|
|
2037
|
-
break;
|
|
2038
|
-
case 2:
|
|
2039
|
-
this.updateTarget = DOM.setBooleanAttribute;
|
|
2040
|
-
break;
|
|
2041
|
-
case 3:
|
|
2042
|
-
this.updateTarget = setProperty;
|
|
2043
|
-
break;
|
|
2044
|
-
case 4:
|
|
2045
|
-
this.updateTarget = updateContent;
|
|
2046
|
-
break;
|
|
2047
|
-
case 5:
|
|
2048
|
-
this.updateTarget = updateTokenList;
|
|
2049
|
-
break;
|
|
2050
|
-
case 6:
|
|
2051
|
-
this.updateTarget = eventTarget;
|
|
2052
|
-
break;
|
|
2053
|
-
default:
|
|
2054
|
-
throw FAST.error(1205 /* Message.unsupportedBindingBehavior */);
|
|
2349
|
+
const sink = sinkLookup[this.aspectType];
|
|
2350
|
+
const policy = (_a = this.dataBinding.policy) !== null && _a !== void 0 ? _a : this.policy;
|
|
2351
|
+
if (!sink) {
|
|
2352
|
+
throw FAST.error(1205 /* Message.unsupportedBindingBehavior */);
|
|
2055
2353
|
}
|
|
2354
|
+
this.data = `${this.id}-d`;
|
|
2355
|
+
this.updateTarget = policy.protect(this.targetTagName, this.aspectType, this.targetAspect, sink);
|
|
2056
2356
|
}
|
|
2057
2357
|
return this;
|
|
2058
2358
|
}
|
|
2059
2359
|
/** @internal */
|
|
2060
2360
|
bind(controller) {
|
|
2061
2361
|
var _a;
|
|
2062
|
-
const target = controller.targets[this.
|
|
2063
|
-
switch (this.
|
|
2064
|
-
case
|
|
2362
|
+
const target = controller.targets[this.targetNodeId];
|
|
2363
|
+
switch (this.aspectType) {
|
|
2364
|
+
case DOMAspect.event:
|
|
2065
2365
|
target[this.data] = controller;
|
|
2066
2366
|
target.addEventListener(this.targetAspect, this, this.dataBinding.options);
|
|
2067
2367
|
break;
|
|
2068
|
-
case
|
|
2368
|
+
case DOMAspect.content:
|
|
2069
2369
|
controller.onUnbind(this);
|
|
2070
2370
|
// intentional fall through
|
|
2071
2371
|
default:
|
|
@@ -2078,7 +2378,7 @@ class HTMLBindingDirective {
|
|
|
2078
2378
|
}
|
|
2079
2379
|
/** @internal */
|
|
2080
2380
|
unbind(controller) {
|
|
2081
|
-
const target = controller.targets[this.
|
|
2381
|
+
const target = controller.targets[this.targetNodeId];
|
|
2082
2382
|
const view = target.$fastView;
|
|
2083
2383
|
if (view !== void 0 && view.isComposed) {
|
|
2084
2384
|
view.unbind();
|
|
@@ -2108,21 +2408,23 @@ HTMLDirective.define(HTMLBindingDirective, { aspected: true });
|
|
|
2108
2408
|
/**
|
|
2109
2409
|
* Creates an standard binding.
|
|
2110
2410
|
* @param expression - The binding to refresh when changed.
|
|
2411
|
+
* @param policy - The security policy to associate with th binding.
|
|
2111
2412
|
* @param isVolatile - Indicates whether the binding is volatile or not.
|
|
2112
2413
|
* @returns A binding configuration.
|
|
2113
2414
|
* @public
|
|
2114
2415
|
*/
|
|
2115
|
-
function bind(expression, isVolatile = Observable.isVolatileBinding(expression)) {
|
|
2116
|
-
return new OnChangeBinding(expression, isVolatile);
|
|
2416
|
+
function bind(expression, policy, isVolatile = Observable.isVolatileBinding(expression)) {
|
|
2417
|
+
return new OnChangeBinding(expression, policy, isVolatile);
|
|
2117
2418
|
}
|
|
2118
2419
|
/**
|
|
2119
2420
|
* Creates a one time binding
|
|
2120
2421
|
* @param expression - The binding to refresh when signaled.
|
|
2422
|
+
* @param policy - The security policy to associate with th binding.
|
|
2121
2423
|
* @returns A binding configuration.
|
|
2122
2424
|
* @public
|
|
2123
2425
|
*/
|
|
2124
|
-
function oneTime(expression) {
|
|
2125
|
-
return new OneTimeBinding(expression);
|
|
2426
|
+
function oneTime(expression, policy) {
|
|
2427
|
+
return new OneTimeBinding(expression, policy);
|
|
2126
2428
|
}
|
|
2127
2429
|
/**
|
|
2128
2430
|
* Creates an event listener binding.
|
|
@@ -2132,7 +2434,7 @@ function oneTime(expression) {
|
|
|
2132
2434
|
* @public
|
|
2133
2435
|
*/
|
|
2134
2436
|
function listener(expression, options) {
|
|
2135
|
-
const config = new OnChangeBinding(expression
|
|
2437
|
+
const config = new OnChangeBinding(expression);
|
|
2136
2438
|
config.options = options;
|
|
2137
2439
|
return config;
|
|
2138
2440
|
}
|
|
@@ -2201,6 +2503,11 @@ class HTMLView {
|
|
|
2201
2503
|
* The length of the current collection within a repeat context.
|
|
2202
2504
|
*/
|
|
2203
2505
|
this.length = 0;
|
|
2506
|
+
/**
|
|
2507
|
+
* Opts out of JSON stringification.
|
|
2508
|
+
* @internal
|
|
2509
|
+
*/
|
|
2510
|
+
this.toJSON = noop;
|
|
2204
2511
|
this.firstChild = fragment.firstChild;
|
|
2205
2512
|
this.lastChild = fragment.lastChild;
|
|
2206
2513
|
}
|
|
@@ -2408,20 +2715,25 @@ const warningHost = new Proxy(document.createElement("div"), {
|
|
|
2408
2715
|
},
|
|
2409
2716
|
});
|
|
2410
2717
|
class CompilationContext {
|
|
2411
|
-
constructor(fragment, directives) {
|
|
2718
|
+
constructor(fragment, directives, policy) {
|
|
2412
2719
|
this.fragment = fragment;
|
|
2413
2720
|
this.directives = directives;
|
|
2721
|
+
this.policy = policy;
|
|
2414
2722
|
this.proto = null;
|
|
2415
2723
|
this.nodeIds = new Set();
|
|
2416
2724
|
this.descriptors = {};
|
|
2417
2725
|
this.factories = [];
|
|
2418
2726
|
}
|
|
2419
|
-
addFactory(factory, parentId, nodeId, targetIndex) {
|
|
2727
|
+
addFactory(factory, parentId, nodeId, targetIndex, tagName) {
|
|
2728
|
+
var _a, _b;
|
|
2420
2729
|
if (!this.nodeIds.has(nodeId)) {
|
|
2421
2730
|
this.nodeIds.add(nodeId);
|
|
2422
2731
|
this.addTargetDescriptor(parentId, nodeId, targetIndex);
|
|
2423
2732
|
}
|
|
2424
|
-
factory.
|
|
2733
|
+
factory.id = (_a = factory.id) !== null && _a !== void 0 ? _a : nextId();
|
|
2734
|
+
factory.targetNodeId = nodeId;
|
|
2735
|
+
factory.targetTagName = tagName;
|
|
2736
|
+
factory.policy = (_b = factory.policy) !== null && _b !== void 0 ? _b : this.policy;
|
|
2425
2737
|
this.factories.push(factory);
|
|
2426
2738
|
}
|
|
2427
2739
|
freeze() {
|
|
@@ -2474,19 +2786,19 @@ function compileAttributes(context, parentId, node, nodeId, nodeIndex, includeBa
|
|
|
2474
2786
|
let result = null;
|
|
2475
2787
|
if (parseResult === null) {
|
|
2476
2788
|
if (includeBasicValues) {
|
|
2477
|
-
result = new HTMLBindingDirective(oneTime(() => attrValue));
|
|
2478
|
-
|
|
2789
|
+
result = new HTMLBindingDirective(oneTime(() => attrValue, context.policy));
|
|
2790
|
+
HTMLDirective.assignAspect(result, attr.name);
|
|
2479
2791
|
}
|
|
2480
2792
|
}
|
|
2481
2793
|
else {
|
|
2482
2794
|
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
2483
|
-
result = Compiler.aggregate(parseResult);
|
|
2795
|
+
result = Compiler.aggregate(parseResult, context.policy);
|
|
2484
2796
|
}
|
|
2485
2797
|
if (result !== null) {
|
|
2486
2798
|
node.removeAttributeNode(attr);
|
|
2487
2799
|
i--;
|
|
2488
2800
|
ii--;
|
|
2489
|
-
context.addFactory(result, parentId, nodeId, nodeIndex);
|
|
2801
|
+
context.addFactory(result, parentId, nodeId, nodeIndex, node.tagName);
|
|
2490
2802
|
}
|
|
2491
2803
|
}
|
|
2492
2804
|
}
|
|
@@ -2511,8 +2823,8 @@ function compileContent(context, node, parentId, nodeId, nodeIndex) {
|
|
|
2511
2823
|
}
|
|
2512
2824
|
else {
|
|
2513
2825
|
currentNode.textContent = " ";
|
|
2514
|
-
|
|
2515
|
-
context.addFactory(currentPart, parentId, nodeId, nodeIndex);
|
|
2826
|
+
HTMLDirective.assignAspect(currentPart);
|
|
2827
|
+
context.addFactory(currentPart, parentId, nodeId, nodeIndex, null);
|
|
2516
2828
|
}
|
|
2517
2829
|
lastNode = currentNode;
|
|
2518
2830
|
}
|
|
@@ -2544,7 +2856,7 @@ function compileNode(context, parentId, node, nodeIndex) {
|
|
|
2544
2856
|
if (parts !== null) {
|
|
2545
2857
|
context.addFactory(
|
|
2546
2858
|
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
2547
|
-
Compiler.aggregate(parts), parentId, nodeId, nodeIndex);
|
|
2859
|
+
Compiler.aggregate(parts), parentId, nodeId, nodeIndex, null);
|
|
2548
2860
|
}
|
|
2549
2861
|
break;
|
|
2550
2862
|
}
|
|
@@ -2558,45 +2870,28 @@ function isMarker(node, directives) {
|
|
|
2558
2870
|
Parser.parse(node.data, directives) !== null);
|
|
2559
2871
|
}
|
|
2560
2872
|
const templateTag = "TEMPLATE";
|
|
2561
|
-
const policyOptions = { createHTML: html => html };
|
|
2562
|
-
let htmlPolicy = globalThis.trustedTypes
|
|
2563
|
-
? globalThis.trustedTypes.createPolicy("fast-html", policyOptions)
|
|
2564
|
-
: policyOptions;
|
|
2565
|
-
const fastHTMLPolicy = htmlPolicy;
|
|
2566
2873
|
/**
|
|
2567
2874
|
* Common APIs related to compilation.
|
|
2568
2875
|
* @public
|
|
2569
2876
|
*/
|
|
2570
2877
|
const Compiler = {
|
|
2571
|
-
/**
|
|
2572
|
-
* Sets the HTML trusted types policy used by the compiler.
|
|
2573
|
-
* @param policy - The policy to set for HTML.
|
|
2574
|
-
* @remarks
|
|
2575
|
-
* This API can only be called once, for security reasons. It should be
|
|
2576
|
-
* called by the application developer at the start of their program.
|
|
2577
|
-
*/
|
|
2578
|
-
setHTMLPolicy(policy) {
|
|
2579
|
-
if (htmlPolicy !== fastHTMLPolicy) {
|
|
2580
|
-
throw FAST.error(1201 /* Message.onlySetHTMLPolicyOnce */);
|
|
2581
|
-
}
|
|
2582
|
-
htmlPolicy = policy;
|
|
2583
|
-
},
|
|
2584
2878
|
/**
|
|
2585
2879
|
* Compiles a template and associated directives into a compilation
|
|
2586
2880
|
* result which can be used to create views.
|
|
2587
2881
|
* @param html - The html string or template element to compile.
|
|
2588
|
-
* @param
|
|
2882
|
+
* @param factories - The behavior factories referenced by the template.
|
|
2883
|
+
* @param policy - The security policy to compile the html with.
|
|
2589
2884
|
* @remarks
|
|
2590
2885
|
* The template that is provided for compilation is altered in-place
|
|
2591
2886
|
* and cannot be compiled again. If the original template must be preserved,
|
|
2592
2887
|
* it is recommended that you clone the original and pass the clone to this API.
|
|
2593
2888
|
* @public
|
|
2594
2889
|
*/
|
|
2595
|
-
compile(html,
|
|
2890
|
+
compile(html, factories, policy = DOM.policy) {
|
|
2596
2891
|
let template;
|
|
2597
2892
|
if (isString(html)) {
|
|
2598
2893
|
template = document.createElement(templateTag);
|
|
2599
|
-
template.innerHTML =
|
|
2894
|
+
template.innerHTML = policy.createHTML(html);
|
|
2600
2895
|
const fec = template.content.firstElementChild;
|
|
2601
2896
|
if (fec !== null && fec.tagName === templateTag) {
|
|
2602
2897
|
template = fec;
|
|
@@ -2607,18 +2902,18 @@ const Compiler = {
|
|
|
2607
2902
|
}
|
|
2608
2903
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=1111864
|
|
2609
2904
|
const fragment = document.adoptNode(template.content);
|
|
2610
|
-
const context = new CompilationContext(fragment,
|
|
2905
|
+
const context = new CompilationContext(fragment, factories, policy);
|
|
2611
2906
|
compileAttributes(context, "", template, /* host */ "h", 0, true);
|
|
2612
2907
|
if (
|
|
2613
2908
|
// If the first node in a fragment is a marker, that means it's an unstable first node,
|
|
2614
2909
|
// because something like a when, repeat, etc. could add nodes before the marker.
|
|
2615
2910
|
// To mitigate this, we insert a stable first node. However, if we insert a node,
|
|
2616
2911
|
// that will alter the result of the TreeWalker. So, we also need to offset the target index.
|
|
2617
|
-
isMarker(fragment.firstChild,
|
|
2912
|
+
isMarker(fragment.firstChild, factories) ||
|
|
2618
2913
|
// Or if there is only one node and a directive, it means the template's content
|
|
2619
2914
|
// is *only* the directive. In that case, HTMLView.dispose() misses any nodes inserted by
|
|
2620
2915
|
// the directive. Inserting a new node ensures proper disposal of nodes added by the directive.
|
|
2621
|
-
(fragment.childNodes.length === 1 && Object.keys(
|
|
2916
|
+
(fragment.childNodes.length === 1 && Object.keys(factories).length > 0)) {
|
|
2622
2917
|
fragment.insertBefore(document.createComment(""), fragment.firstChild);
|
|
2623
2918
|
}
|
|
2624
2919
|
compileChildren(context, fragment, /* root */ "r");
|
|
@@ -2637,15 +2932,17 @@ const Compiler = {
|
|
|
2637
2932
|
* Aggregates an array of strings and directives into a single directive.
|
|
2638
2933
|
* @param parts - A heterogeneous array of static strings interspersed with
|
|
2639
2934
|
* directives.
|
|
2935
|
+
* @param policy - The security policy to use with the aggregated bindings.
|
|
2640
2936
|
* @returns A single inline directive that aggregates the behavior of all the parts.
|
|
2641
2937
|
*/
|
|
2642
|
-
aggregate(parts) {
|
|
2938
|
+
aggregate(parts, policy = DOM.policy) {
|
|
2643
2939
|
if (parts.length === 1) {
|
|
2644
2940
|
return parts[0];
|
|
2645
2941
|
}
|
|
2646
2942
|
let sourceAspect;
|
|
2647
2943
|
let binding;
|
|
2648
2944
|
let isVolatile = false;
|
|
2945
|
+
let bindingPolicy = void 0;
|
|
2649
2946
|
const partCount = parts.length;
|
|
2650
2947
|
const finalParts = parts.map((x) => {
|
|
2651
2948
|
if (isString(x)) {
|
|
@@ -2654,6 +2951,7 @@ const Compiler = {
|
|
|
2654
2951
|
sourceAspect = x.sourceAspect || sourceAspect;
|
|
2655
2952
|
binding = x.dataBinding || binding;
|
|
2656
2953
|
isVolatile = isVolatile || x.dataBinding.isVolatile;
|
|
2954
|
+
bindingPolicy = bindingPolicy || x.dataBinding.policy;
|
|
2657
2955
|
return x.dataBinding.evaluate;
|
|
2658
2956
|
});
|
|
2659
2957
|
const expression = (scope, context) => {
|
|
@@ -2665,12 +2963,26 @@ const Compiler = {
|
|
|
2665
2963
|
};
|
|
2666
2964
|
binding.evaluate = expression;
|
|
2667
2965
|
binding.isVolatile = isVolatile;
|
|
2966
|
+
binding.policy = bindingPolicy !== null && bindingPolicy !== void 0 ? bindingPolicy : policy;
|
|
2668
2967
|
const directive = new HTMLBindingDirective(binding);
|
|
2669
|
-
|
|
2968
|
+
HTMLDirective.assignAspect(directive, sourceAspect);
|
|
2670
2969
|
return directive;
|
|
2671
2970
|
},
|
|
2672
2971
|
};
|
|
2673
2972
|
|
|
2973
|
+
// Much thanks to LitHTML for working this out!
|
|
2974
|
+
const lastAttributeNameRegex =
|
|
2975
|
+
/* eslint-disable-next-line no-control-regex */
|
|
2976
|
+
/([ \x09\x0a\x0c\x0d])([^\0-\x1F\x7F-\x9F "'>=/]+)([ \x09\x0a\x0c\x0d]*=[ \x09\x0a\x0c\x0d]*(?:[^ \x09\x0a\x0c\x0d"'`<>=]*|"[^"]*|'[^']*))$/;
|
|
2977
|
+
function createHTML(value, prevString, add, definition = HTMLDirective.getForInstance(value)) {
|
|
2978
|
+
if (definition.aspected) {
|
|
2979
|
+
const match = lastAttributeNameRegex.exec(prevString);
|
|
2980
|
+
if (match !== null) {
|
|
2981
|
+
HTMLDirective.assignAspect(value, match[2]);
|
|
2982
|
+
}
|
|
2983
|
+
}
|
|
2984
|
+
return value.createHTML(add);
|
|
2985
|
+
}
|
|
2674
2986
|
/**
|
|
2675
2987
|
* A template capable of creating HTMLView instances or rendering directly to DOM.
|
|
2676
2988
|
* @public
|
|
@@ -2680,9 +2992,16 @@ class ViewTemplate {
|
|
|
2680
2992
|
* Creates an instance of ViewTemplate.
|
|
2681
2993
|
* @param html - The html representing what this template will instantiate, including placeholders for directives.
|
|
2682
2994
|
* @param factories - The directives that will be connected to placeholders in the html.
|
|
2995
|
+
* @param policy - The security policy to use when compiling this template.
|
|
2683
2996
|
*/
|
|
2684
|
-
constructor(html, factories) {
|
|
2997
|
+
constructor(html, factories = {}, policy) {
|
|
2998
|
+
this.policy = policy;
|
|
2685
2999
|
this.result = null;
|
|
3000
|
+
/**
|
|
3001
|
+
* Opts out of JSON stringification.
|
|
3002
|
+
* @internal
|
|
3003
|
+
*/
|
|
3004
|
+
this.toJSON = noop;
|
|
2686
3005
|
this.html = html;
|
|
2687
3006
|
this.factories = factories;
|
|
2688
3007
|
}
|
|
@@ -2692,10 +3011,28 @@ class ViewTemplate {
|
|
|
2692
3011
|
*/
|
|
2693
3012
|
create(hostBindingTarget) {
|
|
2694
3013
|
if (this.result === null) {
|
|
2695
|
-
this.result = Compiler.compile(this.html, this.factories);
|
|
3014
|
+
this.result = Compiler.compile(this.html, this.factories, this.policy);
|
|
2696
3015
|
}
|
|
2697
3016
|
return this.result.createView(hostBindingTarget);
|
|
2698
3017
|
}
|
|
3018
|
+
/**
|
|
3019
|
+
* Sets the DOMPolicy for this template.
|
|
3020
|
+
* @param policy - The policy to associated with this template.
|
|
3021
|
+
* @returns The modified template instance.
|
|
3022
|
+
* @remarks
|
|
3023
|
+
* The DOMPolicy can only be set once for a template and cannot be
|
|
3024
|
+
* set after the template is compiled.
|
|
3025
|
+
*/
|
|
3026
|
+
withPolicy(policy) {
|
|
3027
|
+
if (this.result) {
|
|
3028
|
+
throw FAST.error(1208 /* Message.cannotSetTemplatePolicyAfterCompilation */);
|
|
3029
|
+
}
|
|
3030
|
+
if (this.policy) {
|
|
3031
|
+
throw FAST.error(1207 /* Message.onlySetTemplatePolicyOnce */);
|
|
3032
|
+
}
|
|
3033
|
+
this.policy = policy;
|
|
3034
|
+
return this;
|
|
3035
|
+
}
|
|
2699
3036
|
/**
|
|
2700
3037
|
* Creates an HTMLView from this template, binds it to the source, and then appends it to the host.
|
|
2701
3038
|
* @param source - The data source to bind the template to.
|
|
@@ -2709,17 +3046,47 @@ class ViewTemplate {
|
|
|
2709
3046
|
view.appendTo(host);
|
|
2710
3047
|
return view;
|
|
2711
3048
|
}
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
3049
|
+
/**
|
|
3050
|
+
* Creates a template based on a set of static strings and dynamic values.
|
|
3051
|
+
* @param strings - The static strings to create the template with.
|
|
3052
|
+
* @param values - The dynamic values to create the template with.
|
|
3053
|
+
* @param policy - The DOMPolicy to associated with the template.
|
|
3054
|
+
* @returns A ViewTemplate.
|
|
3055
|
+
* @remarks
|
|
3056
|
+
* This API should not be used directly under normal circumstances because constructing
|
|
3057
|
+
* a template in this way, if not done properly, can open up the application to XSS
|
|
3058
|
+
* attacks. When using this API, provide a strong DOMPolicy that can properly sanitize
|
|
3059
|
+
* and also be sure to manually sanitize all static strings particularly if they can
|
|
3060
|
+
* come from user input.
|
|
3061
|
+
*/
|
|
3062
|
+
static create(strings, values, policy) {
|
|
3063
|
+
let html = "";
|
|
3064
|
+
const factories = Object.create(null);
|
|
3065
|
+
const add = (factory) => {
|
|
3066
|
+
var _a;
|
|
3067
|
+
const id = (_a = factory.id) !== null && _a !== void 0 ? _a : (factory.id = nextId());
|
|
3068
|
+
factories[id] = factory;
|
|
3069
|
+
return id;
|
|
3070
|
+
};
|
|
3071
|
+
for (let i = 0, ii = strings.length - 1; i < ii; ++i) {
|
|
3072
|
+
const currentString = strings[i];
|
|
3073
|
+
let currentValue = values[i];
|
|
3074
|
+
let definition;
|
|
3075
|
+
html += currentString;
|
|
3076
|
+
if (isFunction(currentValue)) {
|
|
3077
|
+
currentValue = new HTMLBindingDirective(bind(currentValue));
|
|
3078
|
+
}
|
|
3079
|
+
else if (currentValue instanceof Binding) {
|
|
3080
|
+
currentValue = new HTMLBindingDirective(currentValue);
|
|
3081
|
+
}
|
|
3082
|
+
else if (!(definition = HTMLDirective.getForInstance(currentValue))) {
|
|
3083
|
+
const staticValue = currentValue;
|
|
3084
|
+
currentValue = new HTMLBindingDirective(oneTime(() => staticValue));
|
|
3085
|
+
}
|
|
3086
|
+
html += createHTML(currentValue, currentString, add, definition);
|
|
3087
|
+
}
|
|
3088
|
+
return new ViewTemplate(html + strings[strings.length - 1], factories, policy);
|
|
2721
3089
|
}
|
|
2722
|
-
return value.createHTML(add);
|
|
2723
3090
|
}
|
|
2724
3091
|
/**
|
|
2725
3092
|
* Transforms a template literal string into a ViewTemplate.
|
|
@@ -2731,49 +3098,10 @@ function createAspectedHTML(value, prevString, add) {
|
|
|
2731
3098
|
* @public
|
|
2732
3099
|
*/
|
|
2733
3100
|
function html(strings, ...values) {
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
const add = (factory) => {
|
|
2737
|
-
var _a;
|
|
2738
|
-
const id = (_a = factory.id) !== null && _a !== void 0 ? _a : (factory.id = nextId());
|
|
2739
|
-
factories[id] = factory;
|
|
2740
|
-
return id;
|
|
2741
|
-
};
|
|
2742
|
-
for (let i = 0, ii = strings.length - 1; i < ii; ++i) {
|
|
2743
|
-
const currentString = strings[i];
|
|
2744
|
-
const currentValue = values[i];
|
|
2745
|
-
let definition;
|
|
2746
|
-
html += currentString;
|
|
2747
|
-
if (isFunction(currentValue)) {
|
|
2748
|
-
html += createAspectedHTML(new HTMLBindingDirective(bind(currentValue)), currentString, add);
|
|
2749
|
-
}
|
|
2750
|
-
else if (isString(currentValue)) {
|
|
2751
|
-
const match = lastAttributeNameRegex.exec(currentString);
|
|
2752
|
-
if (match !== null) {
|
|
2753
|
-
const directive = new HTMLBindingDirective(oneTime(() => currentValue));
|
|
2754
|
-
Aspect.assign(directive, match[2]);
|
|
2755
|
-
html += directive.createHTML(add);
|
|
2756
|
-
}
|
|
2757
|
-
else {
|
|
2758
|
-
html += currentValue;
|
|
2759
|
-
}
|
|
2760
|
-
}
|
|
2761
|
-
else if (currentValue instanceof Binding) {
|
|
2762
|
-
html += createAspectedHTML(new HTMLBindingDirective(currentValue), currentString, add);
|
|
2763
|
-
}
|
|
2764
|
-
else if ((definition = HTMLDirective.getForInstance(currentValue)) === void 0) {
|
|
2765
|
-
html += createAspectedHTML(new HTMLBindingDirective(oneTime(() => currentValue)), currentString, add);
|
|
2766
|
-
}
|
|
2767
|
-
else {
|
|
2768
|
-
if (definition.aspected) {
|
|
2769
|
-
html += createAspectedHTML(currentValue, currentString, add);
|
|
2770
|
-
}
|
|
2771
|
-
else {
|
|
2772
|
-
html += currentValue.createHTML(add);
|
|
2773
|
-
}
|
|
2774
|
-
}
|
|
3101
|
+
if (Array.isArray(strings) && Array.isArray(strings.raw)) {
|
|
3102
|
+
return ViewTemplate.create(strings, values);
|
|
2775
3103
|
}
|
|
2776
|
-
|
|
3104
|
+
throw FAST.error(1206 /* Message.directCallToHTMLTagNotAllowed */);
|
|
2777
3105
|
}
|
|
2778
3106
|
|
|
2779
3107
|
/**
|
|
@@ -2786,7 +3114,7 @@ class RefDirective extends StatelessAttachedAttributeDirective {
|
|
|
2786
3114
|
* @param controller - The view controller that manages the lifecycle of this behavior.
|
|
2787
3115
|
*/
|
|
2788
3116
|
bind(controller) {
|
|
2789
|
-
controller.source[this.options] = controller.targets[this.
|
|
3117
|
+
controller.source[this.options] = controller.targets[this.targetNodeId];
|
|
2790
3118
|
}
|
|
2791
3119
|
}
|
|
2792
3120
|
HTMLDirective.define(RefDirective);
|
|
@@ -2860,7 +3188,7 @@ class RepeatBehavior {
|
|
|
2860
3188
|
* @param controller - The view controller that manages the lifecycle of this behavior.
|
|
2861
3189
|
*/
|
|
2862
3190
|
bind(controller) {
|
|
2863
|
-
this.location = controller.targets[this.directive.
|
|
3191
|
+
this.location = controller.targets[this.directive.targetNodeId];
|
|
2864
3192
|
this.controller = controller;
|
|
2865
3193
|
this.items = this.itemsBindingObserver.bind(controller);
|
|
2866
3194
|
this.template = this.templateBindingObserver.bind(controller);
|
|
@@ -3040,10 +3368,6 @@ class RepeatDirective {
|
|
|
3040
3368
|
this.dataBinding = dataBinding;
|
|
3041
3369
|
this.templateBinding = templateBinding;
|
|
3042
3370
|
this.options = options;
|
|
3043
|
-
/**
|
|
3044
|
-
* The unique id of the factory.
|
|
3045
|
-
*/
|
|
3046
|
-
this.id = nextId();
|
|
3047
3371
|
ArrayObserver.enable();
|
|
3048
3372
|
}
|
|
3049
3373
|
/**
|
|
@@ -3092,9 +3416,15 @@ const elements = (selector) => selector
|
|
|
3092
3416
|
* Internally used by the SlottedDirective and the ChildrenDirective.
|
|
3093
3417
|
*/
|
|
3094
3418
|
class NodeObservationDirective extends StatelessAttachedAttributeDirective {
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3419
|
+
/**
|
|
3420
|
+
* The unique id of the factory.
|
|
3421
|
+
*/
|
|
3422
|
+
get id() {
|
|
3423
|
+
return this._id;
|
|
3424
|
+
}
|
|
3425
|
+
set id(value) {
|
|
3426
|
+
this._id = value;
|
|
3427
|
+
this._controllerProperty = `${value}-c`;
|
|
3098
3428
|
}
|
|
3099
3429
|
/**
|
|
3100
3430
|
* Bind this behavior to the source.
|
|
@@ -3103,8 +3433,8 @@ class NodeObservationDirective extends StatelessAttachedAttributeDirective {
|
|
|
3103
3433
|
* @param targets - The targets that behaviors in a view can attach to.
|
|
3104
3434
|
*/
|
|
3105
3435
|
bind(controller) {
|
|
3106
|
-
const target = controller.targets[this.
|
|
3107
|
-
target[this.
|
|
3436
|
+
const target = controller.targets[this.targetNodeId];
|
|
3437
|
+
target[this._controllerProperty] = controller;
|
|
3108
3438
|
this.updateTarget(controller.source, this.computeNodes(target));
|
|
3109
3439
|
this.observe(target);
|
|
3110
3440
|
controller.onUnbind(this);
|
|
@@ -3116,10 +3446,10 @@ class NodeObservationDirective extends StatelessAttachedAttributeDirective {
|
|
|
3116
3446
|
* @param targets - The targets that behaviors in a view can attach to.
|
|
3117
3447
|
*/
|
|
3118
3448
|
unbind(controller) {
|
|
3119
|
-
const target = controller.targets[this.
|
|
3449
|
+
const target = controller.targets[this.targetNodeId];
|
|
3120
3450
|
this.updateTarget(controller.source, emptyArray);
|
|
3121
3451
|
this.disconnect(target);
|
|
3122
|
-
target[this.
|
|
3452
|
+
target[this._controllerProperty] = null;
|
|
3123
3453
|
}
|
|
3124
3454
|
/**
|
|
3125
3455
|
* Gets the data source for the target.
|
|
@@ -3127,7 +3457,7 @@ class NodeObservationDirective extends StatelessAttachedAttributeDirective {
|
|
|
3127
3457
|
* @returns The source.
|
|
3128
3458
|
*/
|
|
3129
3459
|
getSource(target) {
|
|
3130
|
-
return target[this.
|
|
3460
|
+
return target[this._controllerProperty].source;
|
|
3131
3461
|
}
|
|
3132
3462
|
/**
|
|
3133
3463
|
* Updates the source property with the computed nodes.
|
|
@@ -3223,9 +3553,13 @@ class ChildrenDirective extends NodeObservationDirective {
|
|
|
3223
3553
|
* @param target - The target to observe.
|
|
3224
3554
|
*/
|
|
3225
3555
|
observe(target) {
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3556
|
+
let observer = target[this.observerProperty];
|
|
3557
|
+
if (!observer) {
|
|
3558
|
+
observer = new MutationObserver(this.handleEvent);
|
|
3559
|
+
observer.toJSON = noop;
|
|
3560
|
+
observer.target = target;
|
|
3561
|
+
target[this.observerProperty] = observer;
|
|
3562
|
+
}
|
|
3229
3563
|
observer.observe(target, this.options);
|
|
3230
3564
|
}
|
|
3231
3565
|
/**
|
|
@@ -3264,6 +3598,29 @@ function children(propertyOrOptions) {
|
|
|
3264
3598
|
return new ChildrenDirective(propertyOrOptions);
|
|
3265
3599
|
}
|
|
3266
3600
|
|
|
3601
|
+
/**
|
|
3602
|
+
* A directive capable of injecting static HTML platform runtime protection.
|
|
3603
|
+
* @public
|
|
3604
|
+
*/
|
|
3605
|
+
class DangerousHTMLDirective {
|
|
3606
|
+
constructor(html) {
|
|
3607
|
+
this.html = html;
|
|
3608
|
+
}
|
|
3609
|
+
createHTML() {
|
|
3610
|
+
return this.html;
|
|
3611
|
+
}
|
|
3612
|
+
}
|
|
3613
|
+
HTMLDirective.define(DangerousHTMLDirective);
|
|
3614
|
+
/**
|
|
3615
|
+
* Injects static HTML without platform protection.
|
|
3616
|
+
* @param html - The html to injection.
|
|
3617
|
+
* @returns A DangerousHTMLDirective.
|
|
3618
|
+
* @public
|
|
3619
|
+
*/
|
|
3620
|
+
function dangerousHTML(html) {
|
|
3621
|
+
return new DangerousHTMLDirective(html);
|
|
3622
|
+
}
|
|
3623
|
+
|
|
3267
3624
|
const booleanMode = "boolean";
|
|
3268
3625
|
const reflectMode = "reflect";
|
|
3269
3626
|
/**
|
|
@@ -3617,6 +3974,11 @@ class ElementController extends PropertyChangeNotifier {
|
|
|
3617
3974
|
* If `null` then the element is managing its own rendering.
|
|
3618
3975
|
*/
|
|
3619
3976
|
this.view = null;
|
|
3977
|
+
/**
|
|
3978
|
+
* Opts out of JSON stringification.
|
|
3979
|
+
* @internal
|
|
3980
|
+
*/
|
|
3981
|
+
this.toJSON = noop;
|
|
3620
3982
|
this.source = element;
|
|
3621
3983
|
this.definition = definition;
|
|
3622
3984
|
const shadowOptions = definition.shadowOptions;
|
|
@@ -4119,4 +4481,6 @@ function customElement(nameOrDef) {
|
|
|
4119
4481
|
};
|
|
4120
4482
|
}
|
|
4121
4483
|
|
|
4122
|
-
|
|
4484
|
+
DOM.setPolicy(DOMPolicy.create());
|
|
4485
|
+
|
|
4486
|
+
export { ArrayObserver, AttributeConfiguration, AttributeDefinition, Binding, CSSDirective, ChildrenDirective, Compiler, DOM, DOMAspect, DangerousHTMLDirective, ElementController, ElementStyles, ExecutionContext, FAST, FASTElement, FASTElementDefinition, HTMLBindingDirective, HTMLDirective, HTMLView, Markup, NodeObservationDirective, Observable, Parser, PropertyChangeNotifier, RefDirective, RepeatBehavior, RepeatDirective, SlottedDirective, SourceLifetime, Splice, SpliceStrategy, SpliceStrategySupport, StatelessAttachedAttributeDirective, SubscriberSet, Updates, ViewTemplate, attr, bind, booleanConverter, children, createMetadataLocator, createTypeRegistry, css, cssDirective, cssPartial, customElement, dangerousHTML, elements, emptyArray, html, htmlDirective, lengthOf, listener, normalizeBinding, nullableNumberConverter, observable, oneTime, ref, repeat, slotted, volatile, when };
|