@microsoft/fast-element 2.0.0-beta.17 → 2.0.0-beta.19
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/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 +24 -31
- 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 +50 -119
- 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 +39 -13
- package/dist/dts/templating/view.d.ts +2 -2
- package/dist/dts/utilities.d.ts +39 -0
- package/dist/esm/components/attributes.js +1 -1
- package/dist/esm/components/fast-definitions.js +2 -2
- 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/interfaces.js +45 -0
- package/dist/esm/observation/observable.js +3 -3
- package/dist/esm/observation/update-queue.js +2 -2
- package/dist/esm/platform.js +1 -1
- package/dist/esm/polyfills.js +3 -7
- package/dist/esm/templating/binding-signal.js +3 -2
- package/dist/esm/templating/binding-two-way.js +3 -2
- package/dist/esm/templating/binding.js +31 -54
- package/dist/esm/templating/compiler.js +31 -38
- package/dist/esm/templating/dangerous-html.js +23 -0
- package/dist/esm/templating/html-directive.js +38 -135
- 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 +81 -56
- 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 +190 -147
- package/dist/fast-element.debug.js +756 -388
- package/dist/fast-element.debug.min.js +1 -1
- package/dist/fast-element.js +727 -362
- package/dist/fast-element.min.js +1 -1
- package/dist/fast-element.untrimmed.d.ts +190 -147
- package/docs/api-report.md +66 -56
- package/package.json +5 -1
- package/dist/dts/templating/dom.d.ts +0 -41
- package/dist/esm/templating/dom.js +0 -49
package/dist/fast-element.js
CHANGED
|
@@ -1,10 +1,70 @@
|
|
|
1
|
+
let kernelMode;
|
|
2
|
+
const kernelAttr = "fast-kernel";
|
|
3
|
+
try {
|
|
4
|
+
if (document.currentScript) {
|
|
5
|
+
kernelMode = document.currentScript.getAttribute(kernelAttr);
|
|
6
|
+
}
|
|
7
|
+
else {
|
|
8
|
+
const scripts = document.getElementsByTagName("script");
|
|
9
|
+
const currentScript = scripts[scripts.length - 1];
|
|
10
|
+
kernelMode = currentScript.getAttribute(kernelAttr);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
catch (e) {
|
|
14
|
+
kernelMode = "isolate";
|
|
15
|
+
}
|
|
16
|
+
let KernelServiceId;
|
|
17
|
+
switch (kernelMode) {
|
|
18
|
+
case "share": // share the kernel across major versions
|
|
19
|
+
KernelServiceId = Object.freeze({
|
|
20
|
+
updateQueue: 1,
|
|
21
|
+
observable: 2,
|
|
22
|
+
contextEvent: 3,
|
|
23
|
+
elementRegistry: 4,
|
|
24
|
+
});
|
|
25
|
+
break;
|
|
26
|
+
case "share-v2": // only share the kernel with other v2 instances
|
|
27
|
+
KernelServiceId = Object.freeze({
|
|
28
|
+
updateQueue: 1.2,
|
|
29
|
+
observable: 2.2,
|
|
30
|
+
contextEvent: 3.2,
|
|
31
|
+
elementRegistry: 4.2,
|
|
32
|
+
});
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
// fully isolate the kernel from all other FAST instances
|
|
36
|
+
const postfix = `-${Math.random().toString(36).substring(2, 8)}`;
|
|
37
|
+
KernelServiceId = Object.freeze({
|
|
38
|
+
updateQueue: `1.2${postfix}`,
|
|
39
|
+
observable: `2.2${postfix}`,
|
|
40
|
+
contextEvent: `3.2${postfix}`,
|
|
41
|
+
elementRegistry: `4.2${postfix}`,
|
|
42
|
+
});
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
48
|
+
const isFunction = (object) => typeof object === "function";
|
|
49
|
+
/**
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
|
+
const isString = (object) => typeof object === "string";
|
|
53
|
+
/**
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
const noop = () => void 0;
|
|
57
|
+
|
|
58
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
1
59
|
(function ensureGlobalThis() {
|
|
2
60
|
if (typeof globalThis !== "undefined") {
|
|
3
61
|
// We're running in a modern environment.
|
|
4
62
|
return;
|
|
5
63
|
}
|
|
64
|
+
// @ts-ignore
|
|
6
65
|
if (typeof global !== "undefined") {
|
|
7
66
|
// We're running in NodeJS
|
|
67
|
+
// @ts-ignore
|
|
8
68
|
global.globalThis = global;
|
|
9
69
|
}
|
|
10
70
|
else if (typeof self !== "undefined") {
|
|
@@ -22,14 +82,8 @@
|
|
|
22
82
|
result.globalThis = result;
|
|
23
83
|
}
|
|
24
84
|
})();
|
|
25
|
-
// API-only Polyfill for trustedTypes
|
|
26
|
-
if (!globalThis.trustedTypes) {
|
|
27
|
-
globalThis.trustedTypes = {
|
|
28
|
-
createPolicy: (n, r) => r,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
85
|
|
|
32
|
-
// ensure FAST global - duplicated
|
|
86
|
+
// ensure FAST global - duplicated debug.ts
|
|
33
87
|
const propConfig = {
|
|
34
88
|
configurable: false,
|
|
35
89
|
enumerable: false,
|
|
@@ -117,24 +171,11 @@ function createMetadataLocator() {
|
|
|
117
171
|
};
|
|
118
172
|
}
|
|
119
173
|
|
|
120
|
-
/**
|
|
121
|
-
* @internal
|
|
122
|
-
*/
|
|
123
|
-
const isFunction = (object) => typeof object === "function";
|
|
124
|
-
/**
|
|
125
|
-
* @internal
|
|
126
|
-
*/
|
|
127
|
-
const isString = (object) => typeof object === "string";
|
|
128
|
-
/**
|
|
129
|
-
* @internal
|
|
130
|
-
*/
|
|
131
|
-
const noop = () => void 0;
|
|
132
|
-
|
|
133
174
|
/**
|
|
134
175
|
* The default UpdateQueue.
|
|
135
176
|
* @public
|
|
136
177
|
*/
|
|
137
|
-
const Updates = FAST.getById(
|
|
178
|
+
const Updates = FAST.getById(KernelServiceId.updateQueue, () => {
|
|
138
179
|
const tasks = [];
|
|
139
180
|
const pendingErrors = [];
|
|
140
181
|
const rAF = globalThis.requestAnimationFrame;
|
|
@@ -196,6 +237,456 @@ const Updates = FAST.getById(1 /* KernelServiceId.updateQueue */, () => {
|
|
|
196
237
|
});
|
|
197
238
|
});
|
|
198
239
|
|
|
240
|
+
/**
|
|
241
|
+
* The type of HTML aspect to target.
|
|
242
|
+
* @public
|
|
243
|
+
*/
|
|
244
|
+
const DOMAspect = Object.freeze({
|
|
245
|
+
/**
|
|
246
|
+
* Not aspected.
|
|
247
|
+
*/
|
|
248
|
+
none: 0,
|
|
249
|
+
/**
|
|
250
|
+
* An attribute.
|
|
251
|
+
*/
|
|
252
|
+
attribute: 1,
|
|
253
|
+
/**
|
|
254
|
+
* A boolean attribute.
|
|
255
|
+
*/
|
|
256
|
+
booleanAttribute: 2,
|
|
257
|
+
/**
|
|
258
|
+
* A property.
|
|
259
|
+
*/
|
|
260
|
+
property: 3,
|
|
261
|
+
/**
|
|
262
|
+
* Content
|
|
263
|
+
*/
|
|
264
|
+
content: 4,
|
|
265
|
+
/**
|
|
266
|
+
* A token list.
|
|
267
|
+
*/
|
|
268
|
+
tokenList: 5,
|
|
269
|
+
/**
|
|
270
|
+
* An event.
|
|
271
|
+
*/
|
|
272
|
+
event: 6,
|
|
273
|
+
});
|
|
274
|
+
const createHTML$1 = html => html;
|
|
275
|
+
const fastTrustedType = globalThis.trustedTypes
|
|
276
|
+
? globalThis.trustedTypes.createPolicy("fast-html", { createHTML: createHTML$1 })
|
|
277
|
+
: { createHTML: createHTML$1 };
|
|
278
|
+
let defaultPolicy = Object.freeze({
|
|
279
|
+
createHTML(value) {
|
|
280
|
+
return fastTrustedType.createHTML(value);
|
|
281
|
+
},
|
|
282
|
+
protect(tagName, aspect, aspectName, sink) {
|
|
283
|
+
return sink;
|
|
284
|
+
},
|
|
285
|
+
});
|
|
286
|
+
const fastPolicy = defaultPolicy;
|
|
287
|
+
/**
|
|
288
|
+
* Common DOM APIs.
|
|
289
|
+
* @public
|
|
290
|
+
*/
|
|
291
|
+
const DOM = Object.freeze({
|
|
292
|
+
/**
|
|
293
|
+
* @deprecated
|
|
294
|
+
* Use Updates.enqueue().
|
|
295
|
+
*/
|
|
296
|
+
queueUpdate: Updates.enqueue,
|
|
297
|
+
/**
|
|
298
|
+
* @deprecated
|
|
299
|
+
* Use Updates.next()
|
|
300
|
+
*/
|
|
301
|
+
nextUpdate: Updates.next,
|
|
302
|
+
/**
|
|
303
|
+
* @deprecated
|
|
304
|
+
* Use Updates.process()
|
|
305
|
+
*/
|
|
306
|
+
processUpdates: Updates.process,
|
|
307
|
+
/**
|
|
308
|
+
* Gets the dom policy used by the templating system.
|
|
309
|
+
*/
|
|
310
|
+
get policy() {
|
|
311
|
+
return defaultPolicy;
|
|
312
|
+
},
|
|
313
|
+
/**
|
|
314
|
+
* Sets the dom policy used by the templating system.
|
|
315
|
+
* @param policy - The policy to set.
|
|
316
|
+
* @remarks
|
|
317
|
+
* This API can only be called once, for security reasons. It should be
|
|
318
|
+
* called by the application developer at the start of their program.
|
|
319
|
+
*/
|
|
320
|
+
setPolicy(value) {
|
|
321
|
+
if (defaultPolicy !== fastPolicy) {
|
|
322
|
+
throw FAST.error(1201 /* Message.onlySetDOMPolicyOnce */);
|
|
323
|
+
}
|
|
324
|
+
defaultPolicy = value;
|
|
325
|
+
},
|
|
326
|
+
/**
|
|
327
|
+
* Sets an attribute value on an element.
|
|
328
|
+
* @param element - The element to set the attribute value on.
|
|
329
|
+
* @param attributeName - The attribute name to set.
|
|
330
|
+
* @param value - The value of the attribute to set.
|
|
331
|
+
* @remarks
|
|
332
|
+
* If the value is `null` or `undefined`, the attribute is removed, otherwise
|
|
333
|
+
* it is set to the provided value using the standard `setAttribute` API.
|
|
334
|
+
*/
|
|
335
|
+
setAttribute(element, attributeName, value) {
|
|
336
|
+
value === null || value === undefined
|
|
337
|
+
? element.removeAttribute(attributeName)
|
|
338
|
+
: element.setAttribute(attributeName, value);
|
|
339
|
+
},
|
|
340
|
+
/**
|
|
341
|
+
* Sets a boolean attribute value.
|
|
342
|
+
* @param element - The element to set the boolean attribute value on.
|
|
343
|
+
* @param attributeName - The attribute name to set.
|
|
344
|
+
* @param value - The value of the attribute to set.
|
|
345
|
+
* @remarks
|
|
346
|
+
* If the value is true, the attribute is added; otherwise it is removed.
|
|
347
|
+
*/
|
|
348
|
+
setBooleanAttribute(element, attributeName, value) {
|
|
349
|
+
value
|
|
350
|
+
? element.setAttribute(attributeName, "")
|
|
351
|
+
: element.removeAttribute(attributeName);
|
|
352
|
+
},
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
function safeURL(tagName, aspect, aspectName, sink) {
|
|
356
|
+
return (target, name, value, ...rest) => {
|
|
357
|
+
if (isString(value)) {
|
|
358
|
+
value = value.replace("javascript:", "");
|
|
359
|
+
}
|
|
360
|
+
sink(target, name, value, ...rest);
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
function block(tagName, aspect, aspectName, sink) {
|
|
364
|
+
throw new Error(`${aspectName} on ${tagName !== null && tagName !== void 0 ? tagName : "text"} is blocked by the current DOMPolicy.`);
|
|
365
|
+
}
|
|
366
|
+
const defaultDOMElementGuards = {
|
|
367
|
+
a: {
|
|
368
|
+
[DOMAspect.attribute]: {
|
|
369
|
+
href: safeURL,
|
|
370
|
+
},
|
|
371
|
+
[DOMAspect.property]: {
|
|
372
|
+
href: safeURL,
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
area: {
|
|
376
|
+
[DOMAspect.attribute]: {
|
|
377
|
+
href: safeURL,
|
|
378
|
+
},
|
|
379
|
+
[DOMAspect.property]: {
|
|
380
|
+
href: safeURL,
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
button: {
|
|
384
|
+
[DOMAspect.attribute]: {
|
|
385
|
+
formaction: safeURL,
|
|
386
|
+
},
|
|
387
|
+
[DOMAspect.property]: {
|
|
388
|
+
formAction: safeURL,
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
embed: {
|
|
392
|
+
[DOMAspect.attribute]: {
|
|
393
|
+
src: block,
|
|
394
|
+
},
|
|
395
|
+
[DOMAspect.property]: {
|
|
396
|
+
src: block,
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
form: {
|
|
400
|
+
[DOMAspect.attribute]: {
|
|
401
|
+
action: safeURL,
|
|
402
|
+
},
|
|
403
|
+
[DOMAspect.property]: {
|
|
404
|
+
action: safeURL,
|
|
405
|
+
},
|
|
406
|
+
},
|
|
407
|
+
frame: {
|
|
408
|
+
[DOMAspect.attribute]: {
|
|
409
|
+
src: safeURL,
|
|
410
|
+
},
|
|
411
|
+
[DOMAspect.property]: {
|
|
412
|
+
src: safeURL,
|
|
413
|
+
},
|
|
414
|
+
},
|
|
415
|
+
iframe: {
|
|
416
|
+
[DOMAspect.attribute]: {
|
|
417
|
+
src: safeURL,
|
|
418
|
+
},
|
|
419
|
+
[DOMAspect.property]: {
|
|
420
|
+
src: safeURL,
|
|
421
|
+
srcdoc: block,
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
input: {
|
|
425
|
+
[DOMAspect.attribute]: {
|
|
426
|
+
formaction: safeURL,
|
|
427
|
+
},
|
|
428
|
+
[DOMAspect.property]: {
|
|
429
|
+
formAction: safeURL,
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
link: {
|
|
433
|
+
[DOMAspect.attribute]: {
|
|
434
|
+
href: block,
|
|
435
|
+
},
|
|
436
|
+
[DOMAspect.property]: {
|
|
437
|
+
href: block,
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
object: {
|
|
441
|
+
[DOMAspect.attribute]: {
|
|
442
|
+
codebase: block,
|
|
443
|
+
data: block,
|
|
444
|
+
},
|
|
445
|
+
[DOMAspect.property]: {
|
|
446
|
+
codeBase: block,
|
|
447
|
+
data: block,
|
|
448
|
+
},
|
|
449
|
+
},
|
|
450
|
+
script: {
|
|
451
|
+
[DOMAspect.attribute]: {
|
|
452
|
+
src: block,
|
|
453
|
+
text: block,
|
|
454
|
+
},
|
|
455
|
+
[DOMAspect.property]: {
|
|
456
|
+
src: block,
|
|
457
|
+
text: block,
|
|
458
|
+
innerText: block,
|
|
459
|
+
textContent: block,
|
|
460
|
+
},
|
|
461
|
+
},
|
|
462
|
+
style: {
|
|
463
|
+
[DOMAspect.property]: {
|
|
464
|
+
innerText: block,
|
|
465
|
+
textContent: block,
|
|
466
|
+
},
|
|
467
|
+
},
|
|
468
|
+
};
|
|
469
|
+
const blockedEvents = {
|
|
470
|
+
onabort: block,
|
|
471
|
+
onauxclick: block,
|
|
472
|
+
onbeforeinput: block,
|
|
473
|
+
onbeforematch: block,
|
|
474
|
+
onblur: block,
|
|
475
|
+
oncancel: block,
|
|
476
|
+
oncanplay: block,
|
|
477
|
+
oncanplaythrough: block,
|
|
478
|
+
onchange: block,
|
|
479
|
+
onclick: block,
|
|
480
|
+
onclose: block,
|
|
481
|
+
oncontextlost: block,
|
|
482
|
+
oncontextmenu: block,
|
|
483
|
+
oncontextrestored: block,
|
|
484
|
+
oncopy: block,
|
|
485
|
+
oncuechange: block,
|
|
486
|
+
oncut: block,
|
|
487
|
+
ondblclick: block,
|
|
488
|
+
ondrag: block,
|
|
489
|
+
ondragend: block,
|
|
490
|
+
ondragenter: block,
|
|
491
|
+
ondragleave: block,
|
|
492
|
+
ondragover: block,
|
|
493
|
+
ondragstart: block,
|
|
494
|
+
ondrop: block,
|
|
495
|
+
ondurationchange: block,
|
|
496
|
+
onemptied: block,
|
|
497
|
+
onended: block,
|
|
498
|
+
onerror: block,
|
|
499
|
+
onfocus: block,
|
|
500
|
+
onformdata: block,
|
|
501
|
+
oninput: block,
|
|
502
|
+
oninvalid: block,
|
|
503
|
+
onkeydown: block,
|
|
504
|
+
onkeypress: block,
|
|
505
|
+
onkeyup: block,
|
|
506
|
+
onload: block,
|
|
507
|
+
onloadeddata: block,
|
|
508
|
+
onloadedmetadata: block,
|
|
509
|
+
onloadstart: block,
|
|
510
|
+
onmousedown: block,
|
|
511
|
+
onmouseenter: block,
|
|
512
|
+
onmouseleave: block,
|
|
513
|
+
onmousemove: block,
|
|
514
|
+
onmouseout: block,
|
|
515
|
+
onmouseover: block,
|
|
516
|
+
onmouseup: block,
|
|
517
|
+
onpaste: block,
|
|
518
|
+
onpause: block,
|
|
519
|
+
onplay: block,
|
|
520
|
+
onplaying: block,
|
|
521
|
+
onprogress: block,
|
|
522
|
+
onratechange: block,
|
|
523
|
+
onreset: block,
|
|
524
|
+
onresize: block,
|
|
525
|
+
onscroll: block,
|
|
526
|
+
onsecuritypolicyviolation: block,
|
|
527
|
+
onseeked: block,
|
|
528
|
+
onseeking: block,
|
|
529
|
+
onselect: block,
|
|
530
|
+
onslotchange: block,
|
|
531
|
+
onstalled: block,
|
|
532
|
+
onsubmit: block,
|
|
533
|
+
onsuspend: block,
|
|
534
|
+
ontimeupdate: block,
|
|
535
|
+
ontoggle: block,
|
|
536
|
+
onvolumechange: block,
|
|
537
|
+
onwaiting: block,
|
|
538
|
+
onwebkitanimationend: block,
|
|
539
|
+
onwebkitanimationiteration: block,
|
|
540
|
+
onwebkitanimationstart: block,
|
|
541
|
+
onwebkittransitionend: block,
|
|
542
|
+
onwheel: block,
|
|
543
|
+
};
|
|
544
|
+
const defaultDOMGuards = {
|
|
545
|
+
elements: defaultDOMElementGuards,
|
|
546
|
+
aspects: {
|
|
547
|
+
[DOMAspect.attribute]: Object.assign({}, blockedEvents),
|
|
548
|
+
[DOMAspect.property]: Object.assign({ innerHTML: block }, blockedEvents),
|
|
549
|
+
[DOMAspect.event]: Object.assign({}, blockedEvents),
|
|
550
|
+
},
|
|
551
|
+
};
|
|
552
|
+
function createDomSinkGuards(config, defaults) {
|
|
553
|
+
const result = {};
|
|
554
|
+
for (const name in defaults) {
|
|
555
|
+
const overrideValue = config[name];
|
|
556
|
+
const defaultValue = defaults[name];
|
|
557
|
+
switch (overrideValue) {
|
|
558
|
+
case null:
|
|
559
|
+
// remove the default
|
|
560
|
+
break;
|
|
561
|
+
case undefined:
|
|
562
|
+
// keep the default
|
|
563
|
+
result[name] = defaultValue;
|
|
564
|
+
break;
|
|
565
|
+
default:
|
|
566
|
+
// override the default
|
|
567
|
+
result[name] = overrideValue;
|
|
568
|
+
break;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
// add any new sinks that were not overrides
|
|
572
|
+
for (const name in config) {
|
|
573
|
+
if (!(name in result)) {
|
|
574
|
+
result[name] = config[name];
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
return Object.freeze(result);
|
|
578
|
+
}
|
|
579
|
+
function createDOMAspectGuards(config, defaults) {
|
|
580
|
+
const result = {};
|
|
581
|
+
for (const aspect in defaults) {
|
|
582
|
+
const overrideValue = config[aspect];
|
|
583
|
+
const defaultValue = defaults[aspect];
|
|
584
|
+
switch (overrideValue) {
|
|
585
|
+
case null:
|
|
586
|
+
// remove the default
|
|
587
|
+
break;
|
|
588
|
+
case undefined:
|
|
589
|
+
// keep the default
|
|
590
|
+
result[aspect] = createDomSinkGuards(defaultValue, {});
|
|
591
|
+
break;
|
|
592
|
+
default:
|
|
593
|
+
// override the default
|
|
594
|
+
result[aspect] = createDomSinkGuards(overrideValue, defaultValue);
|
|
595
|
+
break;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
// add any new aspect guards that were not overrides
|
|
599
|
+
for (const aspect in config) {
|
|
600
|
+
if (!(aspect in result)) {
|
|
601
|
+
result[aspect] = createDomSinkGuards(config[aspect], {});
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
return Object.freeze(result);
|
|
605
|
+
}
|
|
606
|
+
function createElementGuards(config, defaults) {
|
|
607
|
+
const result = {};
|
|
608
|
+
for (const tag in defaults) {
|
|
609
|
+
const overrideValue = config[tag];
|
|
610
|
+
const defaultValue = defaults[tag];
|
|
611
|
+
switch (overrideValue) {
|
|
612
|
+
case null:
|
|
613
|
+
// remove the default
|
|
614
|
+
break;
|
|
615
|
+
case undefined:
|
|
616
|
+
// keep the default
|
|
617
|
+
result[tag] = createDOMAspectGuards(overrideValue, {});
|
|
618
|
+
break;
|
|
619
|
+
default:
|
|
620
|
+
// override the default aspects
|
|
621
|
+
result[tag] = createDOMAspectGuards(overrideValue, defaultValue);
|
|
622
|
+
break;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
// Add any new element guards that were not overrides
|
|
626
|
+
for (const tag in config) {
|
|
627
|
+
if (!(tag in result)) {
|
|
628
|
+
result[tag] = createDOMAspectGuards(config[tag], {});
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return Object.freeze(result);
|
|
632
|
+
}
|
|
633
|
+
function createDOMGuards(config, defaults) {
|
|
634
|
+
return Object.freeze({
|
|
635
|
+
elements: config.elements
|
|
636
|
+
? createElementGuards(config.elements, defaults.elements)
|
|
637
|
+
: defaults.elements,
|
|
638
|
+
aspects: config.aspects
|
|
639
|
+
? createDOMAspectGuards(config.aspects, defaults.aspects)
|
|
640
|
+
: defaults.aspects,
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
function createTrustedType() {
|
|
644
|
+
const createHTML = html => html;
|
|
645
|
+
return globalThis.trustedTypes
|
|
646
|
+
? globalThis.trustedTypes.createPolicy("fast-html", { createHTML })
|
|
647
|
+
: { createHTML };
|
|
648
|
+
}
|
|
649
|
+
function tryGuard(aspectGuards, tagName, aspect, aspectName, sink) {
|
|
650
|
+
const sinkGuards = aspectGuards[aspect];
|
|
651
|
+
if (sinkGuards) {
|
|
652
|
+
const guard = sinkGuards[aspectName];
|
|
653
|
+
if (guard) {
|
|
654
|
+
return guard(tagName, aspect, aspectName, sink);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
const DOMPolicy = Object.freeze({
|
|
659
|
+
/**
|
|
660
|
+
* Creates a new DOM Policy object.
|
|
661
|
+
* @param options The options to use in creating the policy.
|
|
662
|
+
* @returns The newly created DOMPolicy.
|
|
663
|
+
*/
|
|
664
|
+
create(options = {}) {
|
|
665
|
+
var _a, _b;
|
|
666
|
+
const trustedType = (_a = options.trustedType) !== null && _a !== void 0 ? _a : createTrustedType();
|
|
667
|
+
const guards = createDOMGuards((_b = options.guards) !== null && _b !== void 0 ? _b : {}, defaultDOMGuards);
|
|
668
|
+
return Object.freeze({
|
|
669
|
+
createHTML(value) {
|
|
670
|
+
return trustedType.createHTML(value);
|
|
671
|
+
},
|
|
672
|
+
protect(tagName, aspect, aspectName, sink) {
|
|
673
|
+
var _a;
|
|
674
|
+
// Check for element-specific guards.
|
|
675
|
+
const key = (tagName !== null && tagName !== void 0 ? tagName : "").toLowerCase();
|
|
676
|
+
const elementGuards = guards.elements[key];
|
|
677
|
+
if (elementGuards) {
|
|
678
|
+
const guard = tryGuard(elementGuards, tagName, aspect, aspectName, sink);
|
|
679
|
+
if (guard) {
|
|
680
|
+
return guard;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
// Check for guards applicable to all nodes.
|
|
684
|
+
return ((_a = tryGuard(guards.aspects, tagName, aspect, aspectName, sink)) !== null && _a !== void 0 ? _a : sink);
|
|
685
|
+
},
|
|
686
|
+
});
|
|
687
|
+
},
|
|
688
|
+
});
|
|
689
|
+
|
|
199
690
|
/**
|
|
200
691
|
* An implementation of {@link Notifier} that efficiently keeps track of
|
|
201
692
|
* subscribers interested in a specific change notification on an
|
|
@@ -380,7 +871,7 @@ const SourceLifetime = Object.freeze({
|
|
|
380
871
|
* Common Observable APIs.
|
|
381
872
|
* @public
|
|
382
873
|
*/
|
|
383
|
-
const Observable = FAST.getById(
|
|
874
|
+
const Observable = FAST.getById(KernelServiceId.observable, () => {
|
|
384
875
|
const queueUpdate = Updates.enqueue;
|
|
385
876
|
const volatileRegex = /(:|&&|\|\||if)/;
|
|
386
877
|
const notifierLookup = new WeakMap();
|
|
@@ -651,7 +1142,7 @@ function volatile(target, name, descriptor) {
|
|
|
651
1142
|
},
|
|
652
1143
|
});
|
|
653
1144
|
}
|
|
654
|
-
const contextEvent = FAST.getById(
|
|
1145
|
+
const contextEvent = FAST.getById(KernelServiceId.contextEvent, () => {
|
|
655
1146
|
let current = null;
|
|
656
1147
|
return {
|
|
657
1148
|
get() {
|
|
@@ -1482,55 +1973,6 @@ css.partial = (strings, ...values) => {
|
|
|
1482
1973
|
*/
|
|
1483
1974
|
const cssPartial = css.partial;
|
|
1484
1975
|
|
|
1485
|
-
/**
|
|
1486
|
-
* Common DOM APIs.
|
|
1487
|
-
* @public
|
|
1488
|
-
*/
|
|
1489
|
-
const DOM = Object.freeze({
|
|
1490
|
-
/**
|
|
1491
|
-
* @deprecated
|
|
1492
|
-
* Use Updates.enqueue().
|
|
1493
|
-
*/
|
|
1494
|
-
queueUpdate: Updates.enqueue,
|
|
1495
|
-
/**
|
|
1496
|
-
* @deprecated
|
|
1497
|
-
* Use Updates.next()
|
|
1498
|
-
*/
|
|
1499
|
-
nextUpdate: Updates.next,
|
|
1500
|
-
/**
|
|
1501
|
-
* @deprecated
|
|
1502
|
-
* Use Updates.process()
|
|
1503
|
-
*/
|
|
1504
|
-
processUpdates: Updates.process,
|
|
1505
|
-
/**
|
|
1506
|
-
* Sets an attribute value on an element.
|
|
1507
|
-
* @param element - The element to set the attribute value on.
|
|
1508
|
-
* @param attributeName - The attribute name to set.
|
|
1509
|
-
* @param value - The value of the attribute to set.
|
|
1510
|
-
* @remarks
|
|
1511
|
-
* If the value is `null` or `undefined`, the attribute is removed, otherwise
|
|
1512
|
-
* it is set to the provided value using the standard `setAttribute` API.
|
|
1513
|
-
*/
|
|
1514
|
-
setAttribute(element, attributeName, value) {
|
|
1515
|
-
value === null || value === undefined
|
|
1516
|
-
? element.removeAttribute(attributeName)
|
|
1517
|
-
: element.setAttribute(attributeName, value);
|
|
1518
|
-
},
|
|
1519
|
-
/**
|
|
1520
|
-
* Sets a boolean attribute value.
|
|
1521
|
-
* @param element - The element to set the boolean attribute value on.
|
|
1522
|
-
* @param attributeName - The attribute name to set.
|
|
1523
|
-
* @param value - The value of the attribute to set.
|
|
1524
|
-
* @remarks
|
|
1525
|
-
* If the value is true, the attribute is added; otherwise it is removed.
|
|
1526
|
-
*/
|
|
1527
|
-
setBooleanAttribute(element, attributeName, value) {
|
|
1528
|
-
value
|
|
1529
|
-
? element.setAttribute(attributeName, "")
|
|
1530
|
-
: element.removeAttribute(attributeName);
|
|
1531
|
-
},
|
|
1532
|
-
});
|
|
1533
|
-
|
|
1534
1976
|
const marker = `fast-${Math.random().toString(36).substring(2, 8)}`;
|
|
1535
1977
|
const interpolationStart = `${marker}{`;
|
|
1536
1978
|
const interpolationEnd = `}${marker}`;
|
|
@@ -1607,67 +2049,6 @@ const Parser = Object.freeze({
|
|
|
1607
2049
|
},
|
|
1608
2050
|
});
|
|
1609
2051
|
|
|
1610
|
-
/**
|
|
1611
|
-
* Bridges between ViewBehaviors and HostBehaviors, enabling a host to
|
|
1612
|
-
* control ViewBehaviors.
|
|
1613
|
-
* @public
|
|
1614
|
-
*/
|
|
1615
|
-
const ViewBehaviorOrchestrator = Object.freeze({
|
|
1616
|
-
/**
|
|
1617
|
-
* Creates a ViewBehaviorOrchestrator.
|
|
1618
|
-
* @param source - The source to to associate behaviors with.
|
|
1619
|
-
* @returns A ViewBehaviorOrchestrator.
|
|
1620
|
-
*/
|
|
1621
|
-
create(source) {
|
|
1622
|
-
const behaviors = [];
|
|
1623
|
-
const targets = {};
|
|
1624
|
-
let unbindables = null;
|
|
1625
|
-
let isConnected = false;
|
|
1626
|
-
return {
|
|
1627
|
-
source,
|
|
1628
|
-
context: ExecutionContext.default,
|
|
1629
|
-
targets,
|
|
1630
|
-
get isBound() {
|
|
1631
|
-
return isConnected;
|
|
1632
|
-
},
|
|
1633
|
-
addBehaviorFactory(factory, target) {
|
|
1634
|
-
const nodeId = factory.nodeId || (factory.nodeId = nextId());
|
|
1635
|
-
factory.id || (factory.id = nextId());
|
|
1636
|
-
this.addTarget(nodeId, target);
|
|
1637
|
-
this.addBehavior(factory.createBehavior());
|
|
1638
|
-
},
|
|
1639
|
-
addTarget(nodeId, target) {
|
|
1640
|
-
targets[nodeId] = target;
|
|
1641
|
-
},
|
|
1642
|
-
addBehavior(behavior) {
|
|
1643
|
-
behaviors.push(behavior);
|
|
1644
|
-
if (isConnected) {
|
|
1645
|
-
behavior.bind(this);
|
|
1646
|
-
}
|
|
1647
|
-
},
|
|
1648
|
-
onUnbind(unbindable) {
|
|
1649
|
-
if (unbindables === null) {
|
|
1650
|
-
unbindables = [];
|
|
1651
|
-
}
|
|
1652
|
-
unbindables.push(unbindable);
|
|
1653
|
-
},
|
|
1654
|
-
connectedCallback(controller) {
|
|
1655
|
-
if (!isConnected) {
|
|
1656
|
-
isConnected = true;
|
|
1657
|
-
behaviors.forEach(x => x.bind(this));
|
|
1658
|
-
}
|
|
1659
|
-
},
|
|
1660
|
-
disconnectedCallback(controller) {
|
|
1661
|
-
if (isConnected) {
|
|
1662
|
-
isConnected = false;
|
|
1663
|
-
if (unbindables !== null) {
|
|
1664
|
-
unbindables.forEach(x => x.unbind(this));
|
|
1665
|
-
}
|
|
1666
|
-
}
|
|
1667
|
-
},
|
|
1668
|
-
};
|
|
1669
|
-
},
|
|
1670
|
-
});
|
|
1671
2052
|
const registry = createTypeRegistry();
|
|
1672
2053
|
/**
|
|
1673
2054
|
* Instructs the template engine to apply behavior to a node.
|
|
@@ -1695,67 +2076,6 @@ const HTMLDirective = Object.freeze({
|
|
|
1695
2076
|
registry.register(options);
|
|
1696
2077
|
return type;
|
|
1697
2078
|
},
|
|
1698
|
-
});
|
|
1699
|
-
/**
|
|
1700
|
-
* Decorator: Defines an HTMLDirective.
|
|
1701
|
-
* @param options - Provides options that specify the directive's application.
|
|
1702
|
-
* @public
|
|
1703
|
-
*/
|
|
1704
|
-
function htmlDirective(options) {
|
|
1705
|
-
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
1706
|
-
return function (type) {
|
|
1707
|
-
HTMLDirective.define(type, options);
|
|
1708
|
-
};
|
|
1709
|
-
}
|
|
1710
|
-
/**
|
|
1711
|
-
* Captures a binding expression along with related information and capabilities.
|
|
1712
|
-
*
|
|
1713
|
-
* @public
|
|
1714
|
-
*/
|
|
1715
|
-
class Binding {
|
|
1716
|
-
/**
|
|
1717
|
-
* Creates a binding.
|
|
1718
|
-
* @param evaluate - Evaluates the binding.
|
|
1719
|
-
* @param isVolatile - Indicates whether the binding is volatile.
|
|
1720
|
-
*/
|
|
1721
|
-
constructor(evaluate, isVolatile = false) {
|
|
1722
|
-
this.evaluate = evaluate;
|
|
1723
|
-
this.isVolatile = isVolatile;
|
|
1724
|
-
}
|
|
1725
|
-
}
|
|
1726
|
-
/**
|
|
1727
|
-
* The type of HTML aspect to target.
|
|
1728
|
-
* @public
|
|
1729
|
-
*/
|
|
1730
|
-
const Aspect = Object.freeze({
|
|
1731
|
-
/**
|
|
1732
|
-
* Not aspected.
|
|
1733
|
-
*/
|
|
1734
|
-
none: 0,
|
|
1735
|
-
/**
|
|
1736
|
-
* An attribute.
|
|
1737
|
-
*/
|
|
1738
|
-
attribute: 1,
|
|
1739
|
-
/**
|
|
1740
|
-
* A boolean attribute.
|
|
1741
|
-
*/
|
|
1742
|
-
booleanAttribute: 2,
|
|
1743
|
-
/**
|
|
1744
|
-
* A property.
|
|
1745
|
-
*/
|
|
1746
|
-
property: 3,
|
|
1747
|
-
/**
|
|
1748
|
-
* Content
|
|
1749
|
-
*/
|
|
1750
|
-
content: 4,
|
|
1751
|
-
/**
|
|
1752
|
-
* A token list.
|
|
1753
|
-
*/
|
|
1754
|
-
tokenList: 5,
|
|
1755
|
-
/**
|
|
1756
|
-
* An event.
|
|
1757
|
-
*/
|
|
1758
|
-
event: 6,
|
|
1759
2079
|
/**
|
|
1760
2080
|
*
|
|
1761
2081
|
* @param directive - The directive to assign the aspect to.
|
|
@@ -1763,9 +2083,9 @@ const Aspect = Object.freeze({
|
|
|
1763
2083
|
* @remarks
|
|
1764
2084
|
* If a falsy value is provided, then the content aspect will be assigned.
|
|
1765
2085
|
*/
|
|
1766
|
-
|
|
2086
|
+
assignAspect(directive, value) {
|
|
1767
2087
|
if (!value) {
|
|
1768
|
-
directive.aspectType =
|
|
2088
|
+
directive.aspectType = DOMAspect.content;
|
|
1769
2089
|
return;
|
|
1770
2090
|
}
|
|
1771
2091
|
directive.sourceAspect = value;
|
|
@@ -1774,24 +2094,53 @@ const Aspect = Object.freeze({
|
|
|
1774
2094
|
directive.targetAspect = value.substring(1);
|
|
1775
2095
|
directive.aspectType =
|
|
1776
2096
|
directive.targetAspect === "classList"
|
|
1777
|
-
?
|
|
1778
|
-
:
|
|
2097
|
+
? DOMAspect.tokenList
|
|
2098
|
+
: DOMAspect.property;
|
|
1779
2099
|
break;
|
|
1780
2100
|
case "?":
|
|
1781
2101
|
directive.targetAspect = value.substring(1);
|
|
1782
|
-
directive.aspectType =
|
|
2102
|
+
directive.aspectType = DOMAspect.booleanAttribute;
|
|
1783
2103
|
break;
|
|
1784
2104
|
case "@":
|
|
1785
2105
|
directive.targetAspect = value.substring(1);
|
|
1786
|
-
directive.aspectType =
|
|
2106
|
+
directive.aspectType = DOMAspect.event;
|
|
1787
2107
|
break;
|
|
1788
2108
|
default:
|
|
1789
2109
|
directive.targetAspect = value;
|
|
1790
|
-
directive.aspectType =
|
|
2110
|
+
directive.aspectType = DOMAspect.attribute;
|
|
1791
2111
|
break;
|
|
1792
2112
|
}
|
|
1793
2113
|
},
|
|
1794
2114
|
});
|
|
2115
|
+
/**
|
|
2116
|
+
* Decorator: Defines an HTMLDirective.
|
|
2117
|
+
* @param options - Provides options that specify the directive's application.
|
|
2118
|
+
* @public
|
|
2119
|
+
*/
|
|
2120
|
+
function htmlDirective(options) {
|
|
2121
|
+
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
2122
|
+
return function (type) {
|
|
2123
|
+
HTMLDirective.define(type, options);
|
|
2124
|
+
};
|
|
2125
|
+
}
|
|
2126
|
+
/**
|
|
2127
|
+
* Captures a binding expression along with related information and capabilities.
|
|
2128
|
+
*
|
|
2129
|
+
* @public
|
|
2130
|
+
*/
|
|
2131
|
+
class Binding {
|
|
2132
|
+
/**
|
|
2133
|
+
* Creates a binding.
|
|
2134
|
+
* @param evaluate - Evaluates the binding.
|
|
2135
|
+
* @param policy - The security policy to associate with this binding.
|
|
2136
|
+
* @param isVolatile - Indicates whether the binding is volatile.
|
|
2137
|
+
*/
|
|
2138
|
+
constructor(evaluate, policy, isVolatile = false) {
|
|
2139
|
+
this.evaluate = evaluate;
|
|
2140
|
+
this.policy = policy;
|
|
2141
|
+
this.isVolatile = isVolatile;
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
1795
2144
|
/**
|
|
1796
2145
|
* A base class used for attribute directives that don't need internal state.
|
|
1797
2146
|
* @public
|
|
@@ -1803,10 +2152,6 @@ class StatelessAttachedAttributeDirective {
|
|
|
1803
2152
|
*/
|
|
1804
2153
|
constructor(options) {
|
|
1805
2154
|
this.options = options;
|
|
1806
|
-
/**
|
|
1807
|
-
* The unique id of the factory.
|
|
1808
|
-
*/
|
|
1809
|
-
this.id = nextId();
|
|
1810
2155
|
/**
|
|
1811
2156
|
* Opts out of JSON stringification.
|
|
1812
2157
|
* @internal
|
|
@@ -1831,15 +2176,6 @@ class StatelessAttachedAttributeDirective {
|
|
|
1831
2176
|
}
|
|
1832
2177
|
}
|
|
1833
2178
|
|
|
1834
|
-
const createInnerHTMLBinding = globalThis.TrustedHTML
|
|
1835
|
-
? (binding) => (s, c) => {
|
|
1836
|
-
const value = binding(s, c);
|
|
1837
|
-
if (value instanceof TrustedHTML) {
|
|
1838
|
-
return value;
|
|
1839
|
-
}
|
|
1840
|
-
throw FAST.error(1202 /* Message.bindingInnerHTMLRequiresTrustedTypes */);
|
|
1841
|
-
}
|
|
1842
|
-
: (binding) => binding;
|
|
1843
2179
|
class OnChangeBinding extends Binding {
|
|
1844
2180
|
createObserver(_, subscriber) {
|
|
1845
2181
|
return Observable.binding(this.evaluate, subscriber, this.isVolatile);
|
|
@@ -1952,8 +2288,14 @@ function updateTokenList(target, aspect, value) {
|
|
|
1952
2288
|
}
|
|
1953
2289
|
}
|
|
1954
2290
|
}
|
|
1955
|
-
const
|
|
1956
|
-
|
|
2291
|
+
const sinkLookup = {
|
|
2292
|
+
[DOMAspect.attribute]: DOM.setAttribute,
|
|
2293
|
+
[DOMAspect.booleanAttribute]: DOM.setBooleanAttribute,
|
|
2294
|
+
[DOMAspect.property]: (t, a, v) => (t[a] = v),
|
|
2295
|
+
[DOMAspect.content]: updateContent,
|
|
2296
|
+
[DOMAspect.tokenList]: updateTokenList,
|
|
2297
|
+
[DOMAspect.event]: () => void 0,
|
|
2298
|
+
};
|
|
1957
2299
|
/**
|
|
1958
2300
|
* A directive that applies bindings.
|
|
1959
2301
|
* @public
|
|
@@ -1966,15 +2308,10 @@ class HTMLBindingDirective {
|
|
|
1966
2308
|
constructor(dataBinding) {
|
|
1967
2309
|
this.dataBinding = dataBinding;
|
|
1968
2310
|
this.updateTarget = null;
|
|
1969
|
-
/**
|
|
1970
|
-
* The unique id of the factory.
|
|
1971
|
-
*/
|
|
1972
|
-
this.id = nextId();
|
|
1973
2311
|
/**
|
|
1974
2312
|
* The type of aspect to target.
|
|
1975
2313
|
*/
|
|
1976
|
-
this.aspectType =
|
|
1977
|
-
this.data = `${this.id}-d`;
|
|
2314
|
+
this.aspectType = DOMAspect.content;
|
|
1978
2315
|
}
|
|
1979
2316
|
/**
|
|
1980
2317
|
* Creates HTML to be used within a template.
|
|
@@ -1987,45 +2324,28 @@ class HTMLBindingDirective {
|
|
|
1987
2324
|
* Creates a behavior.
|
|
1988
2325
|
*/
|
|
1989
2326
|
createBehavior() {
|
|
2327
|
+
var _a;
|
|
1990
2328
|
if (this.updateTarget === null) {
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
case 1:
|
|
1996
|
-
this.updateTarget = DOM.setAttribute;
|
|
1997
|
-
break;
|
|
1998
|
-
case 2:
|
|
1999
|
-
this.updateTarget = DOM.setBooleanAttribute;
|
|
2000
|
-
break;
|
|
2001
|
-
case 3:
|
|
2002
|
-
this.updateTarget = setProperty;
|
|
2003
|
-
break;
|
|
2004
|
-
case 4:
|
|
2005
|
-
this.updateTarget = updateContent;
|
|
2006
|
-
break;
|
|
2007
|
-
case 5:
|
|
2008
|
-
this.updateTarget = updateTokenList;
|
|
2009
|
-
break;
|
|
2010
|
-
case 6:
|
|
2011
|
-
this.updateTarget = eventTarget;
|
|
2012
|
-
break;
|
|
2013
|
-
default:
|
|
2014
|
-
throw FAST.error(1205 /* Message.unsupportedBindingBehavior */);
|
|
2329
|
+
const sink = sinkLookup[this.aspectType];
|
|
2330
|
+
const policy = (_a = this.dataBinding.policy) !== null && _a !== void 0 ? _a : this.policy;
|
|
2331
|
+
if (!sink) {
|
|
2332
|
+
throw FAST.error(1205 /* Message.unsupportedBindingBehavior */);
|
|
2015
2333
|
}
|
|
2334
|
+
this.data = `${this.id}-d`;
|
|
2335
|
+
this.updateTarget = policy.protect(this.targetTagName, this.aspectType, this.targetAspect, sink);
|
|
2016
2336
|
}
|
|
2017
2337
|
return this;
|
|
2018
2338
|
}
|
|
2019
2339
|
/** @internal */
|
|
2020
2340
|
bind(controller) {
|
|
2021
2341
|
var _a;
|
|
2022
|
-
const target = controller.targets[this.
|
|
2023
|
-
switch (this.
|
|
2024
|
-
case
|
|
2342
|
+
const target = controller.targets[this.targetNodeId];
|
|
2343
|
+
switch (this.aspectType) {
|
|
2344
|
+
case DOMAspect.event:
|
|
2025
2345
|
target[this.data] = controller;
|
|
2026
2346
|
target.addEventListener(this.targetAspect, this, this.dataBinding.options);
|
|
2027
2347
|
break;
|
|
2028
|
-
case
|
|
2348
|
+
case DOMAspect.content:
|
|
2029
2349
|
controller.onUnbind(this);
|
|
2030
2350
|
// intentional fall through
|
|
2031
2351
|
default:
|
|
@@ -2038,7 +2358,7 @@ class HTMLBindingDirective {
|
|
|
2038
2358
|
}
|
|
2039
2359
|
/** @internal */
|
|
2040
2360
|
unbind(controller) {
|
|
2041
|
-
const target = controller.targets[this.
|
|
2361
|
+
const target = controller.targets[this.targetNodeId];
|
|
2042
2362
|
const view = target.$fastView;
|
|
2043
2363
|
if (view !== void 0 && view.isComposed) {
|
|
2044
2364
|
view.unbind();
|
|
@@ -2068,21 +2388,23 @@ HTMLDirective.define(HTMLBindingDirective, { aspected: true });
|
|
|
2068
2388
|
/**
|
|
2069
2389
|
* Creates an standard binding.
|
|
2070
2390
|
* @param expression - The binding to refresh when changed.
|
|
2391
|
+
* @param policy - The security policy to associate with th binding.
|
|
2071
2392
|
* @param isVolatile - Indicates whether the binding is volatile or not.
|
|
2072
2393
|
* @returns A binding configuration.
|
|
2073
2394
|
* @public
|
|
2074
2395
|
*/
|
|
2075
|
-
function bind(expression, isVolatile = Observable.isVolatileBinding(expression)) {
|
|
2076
|
-
return new OnChangeBinding(expression, isVolatile);
|
|
2396
|
+
function bind(expression, policy, isVolatile = Observable.isVolatileBinding(expression)) {
|
|
2397
|
+
return new OnChangeBinding(expression, policy, isVolatile);
|
|
2077
2398
|
}
|
|
2078
2399
|
/**
|
|
2079
2400
|
* Creates a one time binding
|
|
2080
2401
|
* @param expression - The binding to refresh when signaled.
|
|
2402
|
+
* @param policy - The security policy to associate with th binding.
|
|
2081
2403
|
* @returns A binding configuration.
|
|
2082
2404
|
* @public
|
|
2083
2405
|
*/
|
|
2084
|
-
function oneTime(expression) {
|
|
2085
|
-
return new OneTimeBinding(expression);
|
|
2406
|
+
function oneTime(expression, policy) {
|
|
2407
|
+
return new OneTimeBinding(expression, policy);
|
|
2086
2408
|
}
|
|
2087
2409
|
/**
|
|
2088
2410
|
* Creates an event listener binding.
|
|
@@ -2092,7 +2414,7 @@ function oneTime(expression) {
|
|
|
2092
2414
|
* @public
|
|
2093
2415
|
*/
|
|
2094
2416
|
function listener(expression, options) {
|
|
2095
|
-
const config = new OnChangeBinding(expression
|
|
2417
|
+
const config = new OnChangeBinding(expression);
|
|
2096
2418
|
config.options = options;
|
|
2097
2419
|
return config;
|
|
2098
2420
|
}
|
|
@@ -2373,20 +2695,25 @@ const warningHost = new Proxy(document.createElement("div"), {
|
|
|
2373
2695
|
},
|
|
2374
2696
|
});
|
|
2375
2697
|
class CompilationContext {
|
|
2376
|
-
constructor(fragment, directives) {
|
|
2698
|
+
constructor(fragment, directives, policy) {
|
|
2377
2699
|
this.fragment = fragment;
|
|
2378
2700
|
this.directives = directives;
|
|
2701
|
+
this.policy = policy;
|
|
2379
2702
|
this.proto = null;
|
|
2380
2703
|
this.nodeIds = new Set();
|
|
2381
2704
|
this.descriptors = {};
|
|
2382
2705
|
this.factories = [];
|
|
2383
2706
|
}
|
|
2384
|
-
addFactory(factory, parentId, nodeId, targetIndex) {
|
|
2707
|
+
addFactory(factory, parentId, nodeId, targetIndex, tagName) {
|
|
2708
|
+
var _a, _b;
|
|
2385
2709
|
if (!this.nodeIds.has(nodeId)) {
|
|
2386
2710
|
this.nodeIds.add(nodeId);
|
|
2387
2711
|
this.addTargetDescriptor(parentId, nodeId, targetIndex);
|
|
2388
2712
|
}
|
|
2389
|
-
factory.
|
|
2713
|
+
factory.id = (_a = factory.id) !== null && _a !== void 0 ? _a : nextId();
|
|
2714
|
+
factory.targetNodeId = nodeId;
|
|
2715
|
+
factory.targetTagName = tagName;
|
|
2716
|
+
factory.policy = (_b = factory.policy) !== null && _b !== void 0 ? _b : this.policy;
|
|
2390
2717
|
this.factories.push(factory);
|
|
2391
2718
|
}
|
|
2392
2719
|
freeze() {
|
|
@@ -2439,19 +2766,19 @@ function compileAttributes(context, parentId, node, nodeId, nodeIndex, includeBa
|
|
|
2439
2766
|
let result = null;
|
|
2440
2767
|
if (parseResult === null) {
|
|
2441
2768
|
if (includeBasicValues) {
|
|
2442
|
-
result = new HTMLBindingDirective(oneTime(() => attrValue));
|
|
2443
|
-
|
|
2769
|
+
result = new HTMLBindingDirective(oneTime(() => attrValue, context.policy));
|
|
2770
|
+
HTMLDirective.assignAspect(result, attr.name);
|
|
2444
2771
|
}
|
|
2445
2772
|
}
|
|
2446
2773
|
else {
|
|
2447
2774
|
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
2448
|
-
result = Compiler.aggregate(parseResult);
|
|
2775
|
+
result = Compiler.aggregate(parseResult, context.policy);
|
|
2449
2776
|
}
|
|
2450
2777
|
if (result !== null) {
|
|
2451
2778
|
node.removeAttributeNode(attr);
|
|
2452
2779
|
i--;
|
|
2453
2780
|
ii--;
|
|
2454
|
-
context.addFactory(result, parentId, nodeId, nodeIndex);
|
|
2781
|
+
context.addFactory(result, parentId, nodeId, nodeIndex, node.tagName);
|
|
2455
2782
|
}
|
|
2456
2783
|
}
|
|
2457
2784
|
}
|
|
@@ -2476,8 +2803,8 @@ function compileContent(context, node, parentId, nodeId, nodeIndex) {
|
|
|
2476
2803
|
}
|
|
2477
2804
|
else {
|
|
2478
2805
|
currentNode.textContent = " ";
|
|
2479
|
-
|
|
2480
|
-
context.addFactory(currentPart, parentId, nodeId, nodeIndex);
|
|
2806
|
+
HTMLDirective.assignAspect(currentPart);
|
|
2807
|
+
context.addFactory(currentPart, parentId, nodeId, nodeIndex, null);
|
|
2481
2808
|
}
|
|
2482
2809
|
lastNode = currentNode;
|
|
2483
2810
|
}
|
|
@@ -2509,7 +2836,7 @@ function compileNode(context, parentId, node, nodeIndex) {
|
|
|
2509
2836
|
if (parts !== null) {
|
|
2510
2837
|
context.addFactory(
|
|
2511
2838
|
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
2512
|
-
Compiler.aggregate(parts), parentId, nodeId, nodeIndex);
|
|
2839
|
+
Compiler.aggregate(parts), parentId, nodeId, nodeIndex, null);
|
|
2513
2840
|
}
|
|
2514
2841
|
break;
|
|
2515
2842
|
}
|
|
@@ -2523,45 +2850,28 @@ function isMarker(node, directives) {
|
|
|
2523
2850
|
Parser.parse(node.data, directives) !== null);
|
|
2524
2851
|
}
|
|
2525
2852
|
const templateTag = "TEMPLATE";
|
|
2526
|
-
const policyOptions = { createHTML: html => html };
|
|
2527
|
-
let htmlPolicy = globalThis.trustedTypes
|
|
2528
|
-
? globalThis.trustedTypes.createPolicy("fast-html", policyOptions)
|
|
2529
|
-
: policyOptions;
|
|
2530
|
-
const fastHTMLPolicy = htmlPolicy;
|
|
2531
2853
|
/**
|
|
2532
2854
|
* Common APIs related to compilation.
|
|
2533
2855
|
* @public
|
|
2534
2856
|
*/
|
|
2535
2857
|
const Compiler = {
|
|
2536
|
-
/**
|
|
2537
|
-
* Sets the HTML trusted types policy used by the compiler.
|
|
2538
|
-
* @param policy - The policy to set for HTML.
|
|
2539
|
-
* @remarks
|
|
2540
|
-
* This API can only be called once, for security reasons. It should be
|
|
2541
|
-
* called by the application developer at the start of their program.
|
|
2542
|
-
*/
|
|
2543
|
-
setHTMLPolicy(policy) {
|
|
2544
|
-
if (htmlPolicy !== fastHTMLPolicy) {
|
|
2545
|
-
throw FAST.error(1201 /* Message.onlySetHTMLPolicyOnce */);
|
|
2546
|
-
}
|
|
2547
|
-
htmlPolicy = policy;
|
|
2548
|
-
},
|
|
2549
2858
|
/**
|
|
2550
2859
|
* Compiles a template and associated directives into a compilation
|
|
2551
2860
|
* result which can be used to create views.
|
|
2552
2861
|
* @param html - The html string or template element to compile.
|
|
2553
|
-
* @param
|
|
2862
|
+
* @param factories - The behavior factories referenced by the template.
|
|
2863
|
+
* @param policy - The security policy to compile the html with.
|
|
2554
2864
|
* @remarks
|
|
2555
2865
|
* The template that is provided for compilation is altered in-place
|
|
2556
2866
|
* and cannot be compiled again. If the original template must be preserved,
|
|
2557
2867
|
* it is recommended that you clone the original and pass the clone to this API.
|
|
2558
2868
|
* @public
|
|
2559
2869
|
*/
|
|
2560
|
-
compile(html,
|
|
2870
|
+
compile(html, factories, policy = DOM.policy) {
|
|
2561
2871
|
let template;
|
|
2562
2872
|
if (isString(html)) {
|
|
2563
2873
|
template = document.createElement(templateTag);
|
|
2564
|
-
template.innerHTML =
|
|
2874
|
+
template.innerHTML = policy.createHTML(html);
|
|
2565
2875
|
const fec = template.content.firstElementChild;
|
|
2566
2876
|
if (fec !== null && fec.tagName === templateTag) {
|
|
2567
2877
|
template = fec;
|
|
@@ -2572,18 +2882,18 @@ const Compiler = {
|
|
|
2572
2882
|
}
|
|
2573
2883
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=1111864
|
|
2574
2884
|
const fragment = document.adoptNode(template.content);
|
|
2575
|
-
const context = new CompilationContext(fragment,
|
|
2885
|
+
const context = new CompilationContext(fragment, factories, policy);
|
|
2576
2886
|
compileAttributes(context, "", template, /* host */ "h", 0, true);
|
|
2577
2887
|
if (
|
|
2578
2888
|
// If the first node in a fragment is a marker, that means it's an unstable first node,
|
|
2579
2889
|
// because something like a when, repeat, etc. could add nodes before the marker.
|
|
2580
2890
|
// To mitigate this, we insert a stable first node. However, if we insert a node,
|
|
2581
2891
|
// that will alter the result of the TreeWalker. So, we also need to offset the target index.
|
|
2582
|
-
isMarker(fragment.firstChild,
|
|
2892
|
+
isMarker(fragment.firstChild, factories) ||
|
|
2583
2893
|
// Or if there is only one node and a directive, it means the template's content
|
|
2584
2894
|
// is *only* the directive. In that case, HTMLView.dispose() misses any nodes inserted by
|
|
2585
2895
|
// the directive. Inserting a new node ensures proper disposal of nodes added by the directive.
|
|
2586
|
-
(fragment.childNodes.length === 1 && Object.keys(
|
|
2896
|
+
(fragment.childNodes.length === 1 && Object.keys(factories).length > 0)) {
|
|
2587
2897
|
fragment.insertBefore(document.createComment(""), fragment.firstChild);
|
|
2588
2898
|
}
|
|
2589
2899
|
compileChildren(context, fragment, /* root */ "r");
|
|
@@ -2602,15 +2912,17 @@ const Compiler = {
|
|
|
2602
2912
|
* Aggregates an array of strings and directives into a single directive.
|
|
2603
2913
|
* @param parts - A heterogeneous array of static strings interspersed with
|
|
2604
2914
|
* directives.
|
|
2915
|
+
* @param policy - The security policy to use with the aggregated bindings.
|
|
2605
2916
|
* @returns A single inline directive that aggregates the behavior of all the parts.
|
|
2606
2917
|
*/
|
|
2607
|
-
aggregate(parts) {
|
|
2918
|
+
aggregate(parts, policy = DOM.policy) {
|
|
2608
2919
|
if (parts.length === 1) {
|
|
2609
2920
|
return parts[0];
|
|
2610
2921
|
}
|
|
2611
2922
|
let sourceAspect;
|
|
2612
2923
|
let binding;
|
|
2613
2924
|
let isVolatile = false;
|
|
2925
|
+
let bindingPolicy = void 0;
|
|
2614
2926
|
const partCount = parts.length;
|
|
2615
2927
|
const finalParts = parts.map((x) => {
|
|
2616
2928
|
if (isString(x)) {
|
|
@@ -2619,6 +2931,7 @@ const Compiler = {
|
|
|
2619
2931
|
sourceAspect = x.sourceAspect || sourceAspect;
|
|
2620
2932
|
binding = x.dataBinding || binding;
|
|
2621
2933
|
isVolatile = isVolatile || x.dataBinding.isVolatile;
|
|
2934
|
+
bindingPolicy = bindingPolicy || x.dataBinding.policy;
|
|
2622
2935
|
return x.dataBinding.evaluate;
|
|
2623
2936
|
});
|
|
2624
2937
|
const expression = (scope, context) => {
|
|
@@ -2630,12 +2943,26 @@ const Compiler = {
|
|
|
2630
2943
|
};
|
|
2631
2944
|
binding.evaluate = expression;
|
|
2632
2945
|
binding.isVolatile = isVolatile;
|
|
2946
|
+
binding.policy = bindingPolicy !== null && bindingPolicy !== void 0 ? bindingPolicy : policy;
|
|
2633
2947
|
const directive = new HTMLBindingDirective(binding);
|
|
2634
|
-
|
|
2948
|
+
HTMLDirective.assignAspect(directive, sourceAspect);
|
|
2635
2949
|
return directive;
|
|
2636
2950
|
},
|
|
2637
2951
|
};
|
|
2638
2952
|
|
|
2953
|
+
// Much thanks to LitHTML for working this out!
|
|
2954
|
+
const lastAttributeNameRegex =
|
|
2955
|
+
/* eslint-disable-next-line no-control-regex */
|
|
2956
|
+
/([ \x09\x0a\x0c\x0d])([^\0-\x1F\x7F-\x9F "'>=/]+)([ \x09\x0a\x0c\x0d]*=[ \x09\x0a\x0c\x0d]*(?:[^ \x09\x0a\x0c\x0d"'`<>=]*|"[^"]*|'[^']*))$/;
|
|
2957
|
+
function createHTML(value, prevString, add, definition = HTMLDirective.getForInstance(value)) {
|
|
2958
|
+
if (definition.aspected) {
|
|
2959
|
+
const match = lastAttributeNameRegex.exec(prevString);
|
|
2960
|
+
if (match !== null) {
|
|
2961
|
+
HTMLDirective.assignAspect(value, match[2]);
|
|
2962
|
+
}
|
|
2963
|
+
}
|
|
2964
|
+
return value.createHTML(add);
|
|
2965
|
+
}
|
|
2639
2966
|
/**
|
|
2640
2967
|
* A template capable of creating HTMLView instances or rendering directly to DOM.
|
|
2641
2968
|
* @public
|
|
@@ -2645,8 +2972,10 @@ class ViewTemplate {
|
|
|
2645
2972
|
* Creates an instance of ViewTemplate.
|
|
2646
2973
|
* @param html - The html representing what this template will instantiate, including placeholders for directives.
|
|
2647
2974
|
* @param factories - The directives that will be connected to placeholders in the html.
|
|
2975
|
+
* @param policy - The security policy to use when compiling this template.
|
|
2648
2976
|
*/
|
|
2649
|
-
constructor(html, factories) {
|
|
2977
|
+
constructor(html, factories = {}, policy) {
|
|
2978
|
+
this.policy = policy;
|
|
2650
2979
|
this.result = null;
|
|
2651
2980
|
/**
|
|
2652
2981
|
* Opts out of JSON stringification.
|
|
@@ -2662,10 +2991,28 @@ class ViewTemplate {
|
|
|
2662
2991
|
*/
|
|
2663
2992
|
create(hostBindingTarget) {
|
|
2664
2993
|
if (this.result === null) {
|
|
2665
|
-
this.result = Compiler.compile(this.html, this.factories);
|
|
2994
|
+
this.result = Compiler.compile(this.html, this.factories, this.policy);
|
|
2666
2995
|
}
|
|
2667
2996
|
return this.result.createView(hostBindingTarget);
|
|
2668
2997
|
}
|
|
2998
|
+
/**
|
|
2999
|
+
* Sets the DOMPolicy for this template.
|
|
3000
|
+
* @param policy - The policy to associated with this template.
|
|
3001
|
+
* @returns The modified template instance.
|
|
3002
|
+
* @remarks
|
|
3003
|
+
* The DOMPolicy can only be set once for a template and cannot be
|
|
3004
|
+
* set after the template is compiled.
|
|
3005
|
+
*/
|
|
3006
|
+
withPolicy(policy) {
|
|
3007
|
+
if (this.result) {
|
|
3008
|
+
throw FAST.error(1208 /* Message.cannotSetTemplatePolicyAfterCompilation */);
|
|
3009
|
+
}
|
|
3010
|
+
if (this.policy) {
|
|
3011
|
+
throw FAST.error(1207 /* Message.onlySetTemplatePolicyOnce */);
|
|
3012
|
+
}
|
|
3013
|
+
this.policy = policy;
|
|
3014
|
+
return this;
|
|
3015
|
+
}
|
|
2669
3016
|
/**
|
|
2670
3017
|
* Creates an HTMLView from this template, binds it to the source, and then appends it to the host.
|
|
2671
3018
|
* @param source - The data source to bind the template to.
|
|
@@ -2679,17 +3026,47 @@ class ViewTemplate {
|
|
|
2679
3026
|
view.appendTo(host);
|
|
2680
3027
|
return view;
|
|
2681
3028
|
}
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
3029
|
+
/**
|
|
3030
|
+
* Creates a template based on a set of static strings and dynamic values.
|
|
3031
|
+
* @param strings - The static strings to create the template with.
|
|
3032
|
+
* @param values - The dynamic values to create the template with.
|
|
3033
|
+
* @param policy - The DOMPolicy to associated with the template.
|
|
3034
|
+
* @returns A ViewTemplate.
|
|
3035
|
+
* @remarks
|
|
3036
|
+
* This API should not be used directly under normal circumstances because constructing
|
|
3037
|
+
* a template in this way, if not done properly, can open up the application to XSS
|
|
3038
|
+
* attacks. When using this API, provide a strong DOMPolicy that can properly sanitize
|
|
3039
|
+
* and also be sure to manually sanitize all static strings particularly if they can
|
|
3040
|
+
* come from user input.
|
|
3041
|
+
*/
|
|
3042
|
+
static create(strings, values, policy) {
|
|
3043
|
+
let html = "";
|
|
3044
|
+
const factories = Object.create(null);
|
|
3045
|
+
const add = (factory) => {
|
|
3046
|
+
var _a;
|
|
3047
|
+
const id = (_a = factory.id) !== null && _a !== void 0 ? _a : (factory.id = nextId());
|
|
3048
|
+
factories[id] = factory;
|
|
3049
|
+
return id;
|
|
3050
|
+
};
|
|
3051
|
+
for (let i = 0, ii = strings.length - 1; i < ii; ++i) {
|
|
3052
|
+
const currentString = strings[i];
|
|
3053
|
+
let currentValue = values[i];
|
|
3054
|
+
let definition;
|
|
3055
|
+
html += currentString;
|
|
3056
|
+
if (isFunction(currentValue)) {
|
|
3057
|
+
currentValue = new HTMLBindingDirective(bind(currentValue));
|
|
3058
|
+
}
|
|
3059
|
+
else if (currentValue instanceof Binding) {
|
|
3060
|
+
currentValue = new HTMLBindingDirective(currentValue);
|
|
3061
|
+
}
|
|
3062
|
+
else if (!(definition = HTMLDirective.getForInstance(currentValue))) {
|
|
3063
|
+
const staticValue = currentValue;
|
|
3064
|
+
currentValue = new HTMLBindingDirective(oneTime(() => staticValue));
|
|
3065
|
+
}
|
|
3066
|
+
html += createHTML(currentValue, currentString, add, definition);
|
|
3067
|
+
}
|
|
3068
|
+
return new ViewTemplate(html + strings[strings.length - 1], factories, policy);
|
|
2691
3069
|
}
|
|
2692
|
-
return value.createHTML(add);
|
|
2693
3070
|
}
|
|
2694
3071
|
/**
|
|
2695
3072
|
* Transforms a template literal string into a ViewTemplate.
|
|
@@ -2701,49 +3078,10 @@ function createAspectedHTML(value, prevString, add) {
|
|
|
2701
3078
|
* @public
|
|
2702
3079
|
*/
|
|
2703
3080
|
function html(strings, ...values) {
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
const add = (factory) => {
|
|
2707
|
-
var _a;
|
|
2708
|
-
const id = (_a = factory.id) !== null && _a !== void 0 ? _a : (factory.id = nextId());
|
|
2709
|
-
factories[id] = factory;
|
|
2710
|
-
return id;
|
|
2711
|
-
};
|
|
2712
|
-
for (let i = 0, ii = strings.length - 1; i < ii; ++i) {
|
|
2713
|
-
const currentString = strings[i];
|
|
2714
|
-
const currentValue = values[i];
|
|
2715
|
-
let definition;
|
|
2716
|
-
html += currentString;
|
|
2717
|
-
if (isFunction(currentValue)) {
|
|
2718
|
-
html += createAspectedHTML(new HTMLBindingDirective(bind(currentValue)), currentString, add);
|
|
2719
|
-
}
|
|
2720
|
-
else if (isString(currentValue)) {
|
|
2721
|
-
const match = lastAttributeNameRegex.exec(currentString);
|
|
2722
|
-
if (match !== null) {
|
|
2723
|
-
const directive = new HTMLBindingDirective(oneTime(() => currentValue));
|
|
2724
|
-
Aspect.assign(directive, match[2]);
|
|
2725
|
-
html += directive.createHTML(add);
|
|
2726
|
-
}
|
|
2727
|
-
else {
|
|
2728
|
-
html += currentValue;
|
|
2729
|
-
}
|
|
2730
|
-
}
|
|
2731
|
-
else if (currentValue instanceof Binding) {
|
|
2732
|
-
html += createAspectedHTML(new HTMLBindingDirective(currentValue), currentString, add);
|
|
2733
|
-
}
|
|
2734
|
-
else if ((definition = HTMLDirective.getForInstance(currentValue)) === void 0) {
|
|
2735
|
-
html += createAspectedHTML(new HTMLBindingDirective(oneTime(() => currentValue)), currentString, add);
|
|
2736
|
-
}
|
|
2737
|
-
else {
|
|
2738
|
-
if (definition.aspected) {
|
|
2739
|
-
html += createAspectedHTML(currentValue, currentString, add);
|
|
2740
|
-
}
|
|
2741
|
-
else {
|
|
2742
|
-
html += currentValue.createHTML(add);
|
|
2743
|
-
}
|
|
2744
|
-
}
|
|
3081
|
+
if (Array.isArray(strings) && Array.isArray(strings.raw)) {
|
|
3082
|
+
return ViewTemplate.create(strings, values);
|
|
2745
3083
|
}
|
|
2746
|
-
|
|
3084
|
+
throw FAST.error(1206 /* Message.directCallToHTMLTagNotAllowed */);
|
|
2747
3085
|
}
|
|
2748
3086
|
|
|
2749
3087
|
/**
|
|
@@ -2756,7 +3094,7 @@ class RefDirective extends StatelessAttachedAttributeDirective {
|
|
|
2756
3094
|
* @param controller - The view controller that manages the lifecycle of this behavior.
|
|
2757
3095
|
*/
|
|
2758
3096
|
bind(controller) {
|
|
2759
|
-
controller.source[this.options] = controller.targets[this.
|
|
3097
|
+
controller.source[this.options] = controller.targets[this.targetNodeId];
|
|
2760
3098
|
}
|
|
2761
3099
|
}
|
|
2762
3100
|
HTMLDirective.define(RefDirective);
|
|
@@ -2830,7 +3168,7 @@ class RepeatBehavior {
|
|
|
2830
3168
|
* @param controller - The view controller that manages the lifecycle of this behavior.
|
|
2831
3169
|
*/
|
|
2832
3170
|
bind(controller) {
|
|
2833
|
-
this.location = controller.targets[this.directive.
|
|
3171
|
+
this.location = controller.targets[this.directive.targetNodeId];
|
|
2834
3172
|
this.controller = controller;
|
|
2835
3173
|
this.items = this.itemsBindingObserver.bind(controller);
|
|
2836
3174
|
this.template = this.templateBindingObserver.bind(controller);
|
|
@@ -3010,10 +3348,6 @@ class RepeatDirective {
|
|
|
3010
3348
|
this.dataBinding = dataBinding;
|
|
3011
3349
|
this.templateBinding = templateBinding;
|
|
3012
3350
|
this.options = options;
|
|
3013
|
-
/**
|
|
3014
|
-
* The unique id of the factory.
|
|
3015
|
-
*/
|
|
3016
|
-
this.id = nextId();
|
|
3017
3351
|
ArrayObserver.enable();
|
|
3018
3352
|
}
|
|
3019
3353
|
/**
|
|
@@ -3062,9 +3396,15 @@ const elements = (selector) => selector
|
|
|
3062
3396
|
* Internally used by the SlottedDirective and the ChildrenDirective.
|
|
3063
3397
|
*/
|
|
3064
3398
|
class NodeObservationDirective extends StatelessAttachedAttributeDirective {
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3399
|
+
/**
|
|
3400
|
+
* The unique id of the factory.
|
|
3401
|
+
*/
|
|
3402
|
+
get id() {
|
|
3403
|
+
return this._id;
|
|
3404
|
+
}
|
|
3405
|
+
set id(value) {
|
|
3406
|
+
this._id = value;
|
|
3407
|
+
this._controllerProperty = `${value}-c`;
|
|
3068
3408
|
}
|
|
3069
3409
|
/**
|
|
3070
3410
|
* Bind this behavior to the source.
|
|
@@ -3073,8 +3413,8 @@ class NodeObservationDirective extends StatelessAttachedAttributeDirective {
|
|
|
3073
3413
|
* @param targets - The targets that behaviors in a view can attach to.
|
|
3074
3414
|
*/
|
|
3075
3415
|
bind(controller) {
|
|
3076
|
-
const target = controller.targets[this.
|
|
3077
|
-
target[this.
|
|
3416
|
+
const target = controller.targets[this.targetNodeId];
|
|
3417
|
+
target[this._controllerProperty] = controller;
|
|
3078
3418
|
this.updateTarget(controller.source, this.computeNodes(target));
|
|
3079
3419
|
this.observe(target);
|
|
3080
3420
|
controller.onUnbind(this);
|
|
@@ -3086,10 +3426,10 @@ class NodeObservationDirective extends StatelessAttachedAttributeDirective {
|
|
|
3086
3426
|
* @param targets - The targets that behaviors in a view can attach to.
|
|
3087
3427
|
*/
|
|
3088
3428
|
unbind(controller) {
|
|
3089
|
-
const target = controller.targets[this.
|
|
3429
|
+
const target = controller.targets[this.targetNodeId];
|
|
3090
3430
|
this.updateTarget(controller.source, emptyArray);
|
|
3091
3431
|
this.disconnect(target);
|
|
3092
|
-
target[this.
|
|
3432
|
+
target[this._controllerProperty] = null;
|
|
3093
3433
|
}
|
|
3094
3434
|
/**
|
|
3095
3435
|
* Gets the data source for the target.
|
|
@@ -3097,7 +3437,7 @@ class NodeObservationDirective extends StatelessAttachedAttributeDirective {
|
|
|
3097
3437
|
* @returns The source.
|
|
3098
3438
|
*/
|
|
3099
3439
|
getSource(target) {
|
|
3100
|
-
return target[this.
|
|
3440
|
+
return target[this._controllerProperty].source;
|
|
3101
3441
|
}
|
|
3102
3442
|
/**
|
|
3103
3443
|
* Updates the source property with the computed nodes.
|
|
@@ -3238,6 +3578,29 @@ function children(propertyOrOptions) {
|
|
|
3238
3578
|
return new ChildrenDirective(propertyOrOptions);
|
|
3239
3579
|
}
|
|
3240
3580
|
|
|
3581
|
+
/**
|
|
3582
|
+
* A directive capable of injecting static HTML platform runtime protection.
|
|
3583
|
+
* @public
|
|
3584
|
+
*/
|
|
3585
|
+
class DangerousHTMLDirective {
|
|
3586
|
+
constructor(html) {
|
|
3587
|
+
this.html = html;
|
|
3588
|
+
}
|
|
3589
|
+
createHTML() {
|
|
3590
|
+
return this.html;
|
|
3591
|
+
}
|
|
3592
|
+
}
|
|
3593
|
+
HTMLDirective.define(DangerousHTMLDirective);
|
|
3594
|
+
/**
|
|
3595
|
+
* Injects static HTML without platform protection.
|
|
3596
|
+
* @param html - The html to injection.
|
|
3597
|
+
* @returns A DangerousHTMLDirective.
|
|
3598
|
+
* @public
|
|
3599
|
+
*/
|
|
3600
|
+
function dangerousHTML(html) {
|
|
3601
|
+
return new DangerousHTMLDirective(html);
|
|
3602
|
+
}
|
|
3603
|
+
|
|
3241
3604
|
const booleanMode = "boolean";
|
|
3242
3605
|
const reflectMode = "reflect";
|
|
3243
3606
|
/**
|
|
@@ -3436,7 +3799,7 @@ function attr(configOrTarget, prop) {
|
|
|
3436
3799
|
const defaultShadowOptions = { mode: "open" };
|
|
3437
3800
|
const defaultElementOptions = {};
|
|
3438
3801
|
const fastElementBaseTypes = new Set();
|
|
3439
|
-
const fastElementRegistry = FAST.getById(
|
|
3802
|
+
const fastElementRegistry = FAST.getById(KernelServiceId.elementRegistry, () => createTypeRegistry());
|
|
3440
3803
|
/**
|
|
3441
3804
|
* Defines metadata for a FASTElement.
|
|
3442
3805
|
* @public
|
|
@@ -4098,4 +4461,6 @@ function customElement(nameOrDef) {
|
|
|
4098
4461
|
};
|
|
4099
4462
|
}
|
|
4100
4463
|
|
|
4101
|
-
|
|
4464
|
+
DOM.setPolicy(DOMPolicy.create());
|
|
4465
|
+
|
|
4466
|
+
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 };
|