@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
package/dist/fast-element.js
CHANGED
|
@@ -1,10 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal
|
|
3
|
+
*/
|
|
4
|
+
const isFunction = (object) => typeof object === "function";
|
|
5
|
+
/**
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
const isString = (object) => typeof object === "string";
|
|
9
|
+
/**
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
const noop = () => void 0;
|
|
13
|
+
|
|
14
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
1
15
|
(function ensureGlobalThis() {
|
|
2
16
|
if (typeof globalThis !== "undefined") {
|
|
3
17
|
// We're running in a modern environment.
|
|
4
18
|
return;
|
|
5
19
|
}
|
|
20
|
+
// @ts-ignore
|
|
6
21
|
if (typeof global !== "undefined") {
|
|
7
22
|
// We're running in NodeJS
|
|
23
|
+
// @ts-ignore
|
|
8
24
|
global.globalThis = global;
|
|
9
25
|
}
|
|
10
26
|
else if (typeof self !== "undefined") {
|
|
@@ -22,14 +38,8 @@
|
|
|
22
38
|
result.globalThis = result;
|
|
23
39
|
}
|
|
24
40
|
})();
|
|
25
|
-
// API-only Polyfill for trustedTypes
|
|
26
|
-
if (!globalThis.trustedTypes) {
|
|
27
|
-
globalThis.trustedTypes = {
|
|
28
|
-
createPolicy: (n, r) => r,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
41
|
|
|
32
|
-
// ensure FAST global - duplicated
|
|
42
|
+
// ensure FAST global - duplicated debug.ts
|
|
33
43
|
const propConfig = {
|
|
34
44
|
configurable: false,
|
|
35
45
|
enumerable: false,
|
|
@@ -117,15 +127,6 @@ function createMetadataLocator() {
|
|
|
117
127
|
};
|
|
118
128
|
}
|
|
119
129
|
|
|
120
|
-
/**
|
|
121
|
-
* @internal
|
|
122
|
-
*/
|
|
123
|
-
const isFunction = (object) => typeof object === "function";
|
|
124
|
-
/**
|
|
125
|
-
* @internal
|
|
126
|
-
*/
|
|
127
|
-
const isString = (object) => typeof object === "string";
|
|
128
|
-
|
|
129
130
|
/**
|
|
130
131
|
* The default UpdateQueue.
|
|
131
132
|
* @public
|
|
@@ -192,6 +193,456 @@ const Updates = FAST.getById(1 /* KernelServiceId.updateQueue */, () => {
|
|
|
192
193
|
});
|
|
193
194
|
});
|
|
194
195
|
|
|
196
|
+
/**
|
|
197
|
+
* The type of HTML aspect to target.
|
|
198
|
+
* @public
|
|
199
|
+
*/
|
|
200
|
+
const DOMAspect = Object.freeze({
|
|
201
|
+
/**
|
|
202
|
+
* Not aspected.
|
|
203
|
+
*/
|
|
204
|
+
none: 0,
|
|
205
|
+
/**
|
|
206
|
+
* An attribute.
|
|
207
|
+
*/
|
|
208
|
+
attribute: 1,
|
|
209
|
+
/**
|
|
210
|
+
* A boolean attribute.
|
|
211
|
+
*/
|
|
212
|
+
booleanAttribute: 2,
|
|
213
|
+
/**
|
|
214
|
+
* A property.
|
|
215
|
+
*/
|
|
216
|
+
property: 3,
|
|
217
|
+
/**
|
|
218
|
+
* Content
|
|
219
|
+
*/
|
|
220
|
+
content: 4,
|
|
221
|
+
/**
|
|
222
|
+
* A token list.
|
|
223
|
+
*/
|
|
224
|
+
tokenList: 5,
|
|
225
|
+
/**
|
|
226
|
+
* An event.
|
|
227
|
+
*/
|
|
228
|
+
event: 6,
|
|
229
|
+
});
|
|
230
|
+
const createHTML$1 = html => html;
|
|
231
|
+
const fastTrustedType = globalThis.trustedTypes
|
|
232
|
+
? globalThis.trustedTypes.createPolicy("fast-html", { createHTML: createHTML$1 })
|
|
233
|
+
: { createHTML: createHTML$1 };
|
|
234
|
+
let defaultPolicy = Object.freeze({
|
|
235
|
+
createHTML(value) {
|
|
236
|
+
return fastTrustedType.createHTML(value);
|
|
237
|
+
},
|
|
238
|
+
protect(tagName, aspect, aspectName, sink) {
|
|
239
|
+
return sink;
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
const fastPolicy = defaultPolicy;
|
|
243
|
+
/**
|
|
244
|
+
* Common DOM APIs.
|
|
245
|
+
* @public
|
|
246
|
+
*/
|
|
247
|
+
const DOM = Object.freeze({
|
|
248
|
+
/**
|
|
249
|
+
* @deprecated
|
|
250
|
+
* Use Updates.enqueue().
|
|
251
|
+
*/
|
|
252
|
+
queueUpdate: Updates.enqueue,
|
|
253
|
+
/**
|
|
254
|
+
* @deprecated
|
|
255
|
+
* Use Updates.next()
|
|
256
|
+
*/
|
|
257
|
+
nextUpdate: Updates.next,
|
|
258
|
+
/**
|
|
259
|
+
* @deprecated
|
|
260
|
+
* Use Updates.process()
|
|
261
|
+
*/
|
|
262
|
+
processUpdates: Updates.process,
|
|
263
|
+
/**
|
|
264
|
+
* Gets the dom policy used by the templating system.
|
|
265
|
+
*/
|
|
266
|
+
get policy() {
|
|
267
|
+
return defaultPolicy;
|
|
268
|
+
},
|
|
269
|
+
/**
|
|
270
|
+
* Sets the dom policy used by the templating system.
|
|
271
|
+
* @param policy - The policy to set.
|
|
272
|
+
* @remarks
|
|
273
|
+
* This API can only be called once, for security reasons. It should be
|
|
274
|
+
* called by the application developer at the start of their program.
|
|
275
|
+
*/
|
|
276
|
+
setPolicy(value) {
|
|
277
|
+
if (defaultPolicy !== fastPolicy) {
|
|
278
|
+
throw FAST.error(1201 /* Message.onlySetDOMPolicyOnce */);
|
|
279
|
+
}
|
|
280
|
+
defaultPolicy = value;
|
|
281
|
+
},
|
|
282
|
+
/**
|
|
283
|
+
* Sets an attribute value on an element.
|
|
284
|
+
* @param element - The element to set the attribute value on.
|
|
285
|
+
* @param attributeName - The attribute name to set.
|
|
286
|
+
* @param value - The value of the attribute to set.
|
|
287
|
+
* @remarks
|
|
288
|
+
* If the value is `null` or `undefined`, the attribute is removed, otherwise
|
|
289
|
+
* it is set to the provided value using the standard `setAttribute` API.
|
|
290
|
+
*/
|
|
291
|
+
setAttribute(element, attributeName, value) {
|
|
292
|
+
value === null || value === undefined
|
|
293
|
+
? element.removeAttribute(attributeName)
|
|
294
|
+
: element.setAttribute(attributeName, value);
|
|
295
|
+
},
|
|
296
|
+
/**
|
|
297
|
+
* Sets a boolean attribute value.
|
|
298
|
+
* @param element - The element to set the boolean attribute value on.
|
|
299
|
+
* @param attributeName - The attribute name to set.
|
|
300
|
+
* @param value - The value of the attribute to set.
|
|
301
|
+
* @remarks
|
|
302
|
+
* If the value is true, the attribute is added; otherwise it is removed.
|
|
303
|
+
*/
|
|
304
|
+
setBooleanAttribute(element, attributeName, value) {
|
|
305
|
+
value
|
|
306
|
+
? element.setAttribute(attributeName, "")
|
|
307
|
+
: element.removeAttribute(attributeName);
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
function safeURL(tagName, aspect, aspectName, sink) {
|
|
312
|
+
return (target, name, value, ...rest) => {
|
|
313
|
+
if (isString(value)) {
|
|
314
|
+
value = value.replace("javascript:", "");
|
|
315
|
+
}
|
|
316
|
+
sink(target, name, value, ...rest);
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
function block(tagName, aspect, aspectName, sink) {
|
|
320
|
+
throw new Error(`${aspectName} on ${tagName !== null && tagName !== void 0 ? tagName : "text"} is blocked by the current DOMPolicy.`);
|
|
321
|
+
}
|
|
322
|
+
const defaultDOMElementGuards = {
|
|
323
|
+
a: {
|
|
324
|
+
[DOMAspect.attribute]: {
|
|
325
|
+
href: safeURL,
|
|
326
|
+
},
|
|
327
|
+
[DOMAspect.property]: {
|
|
328
|
+
href: safeURL,
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
area: {
|
|
332
|
+
[DOMAspect.attribute]: {
|
|
333
|
+
href: safeURL,
|
|
334
|
+
},
|
|
335
|
+
[DOMAspect.property]: {
|
|
336
|
+
href: safeURL,
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
button: {
|
|
340
|
+
[DOMAspect.attribute]: {
|
|
341
|
+
formaction: safeURL,
|
|
342
|
+
},
|
|
343
|
+
[DOMAspect.property]: {
|
|
344
|
+
formAction: safeURL,
|
|
345
|
+
},
|
|
346
|
+
},
|
|
347
|
+
embed: {
|
|
348
|
+
[DOMAspect.attribute]: {
|
|
349
|
+
src: block,
|
|
350
|
+
},
|
|
351
|
+
[DOMAspect.property]: {
|
|
352
|
+
src: block,
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
form: {
|
|
356
|
+
[DOMAspect.attribute]: {
|
|
357
|
+
action: safeURL,
|
|
358
|
+
},
|
|
359
|
+
[DOMAspect.property]: {
|
|
360
|
+
action: safeURL,
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
frame: {
|
|
364
|
+
[DOMAspect.attribute]: {
|
|
365
|
+
src: safeURL,
|
|
366
|
+
},
|
|
367
|
+
[DOMAspect.property]: {
|
|
368
|
+
src: safeURL,
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
iframe: {
|
|
372
|
+
[DOMAspect.attribute]: {
|
|
373
|
+
src: safeURL,
|
|
374
|
+
},
|
|
375
|
+
[DOMAspect.property]: {
|
|
376
|
+
src: safeURL,
|
|
377
|
+
srcdoc: block,
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
input: {
|
|
381
|
+
[DOMAspect.attribute]: {
|
|
382
|
+
formaction: safeURL,
|
|
383
|
+
},
|
|
384
|
+
[DOMAspect.property]: {
|
|
385
|
+
formAction: safeURL,
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
link: {
|
|
389
|
+
[DOMAspect.attribute]: {
|
|
390
|
+
href: block,
|
|
391
|
+
},
|
|
392
|
+
[DOMAspect.property]: {
|
|
393
|
+
href: block,
|
|
394
|
+
},
|
|
395
|
+
},
|
|
396
|
+
object: {
|
|
397
|
+
[DOMAspect.attribute]: {
|
|
398
|
+
codebase: block,
|
|
399
|
+
data: block,
|
|
400
|
+
},
|
|
401
|
+
[DOMAspect.property]: {
|
|
402
|
+
codeBase: block,
|
|
403
|
+
data: block,
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
script: {
|
|
407
|
+
[DOMAspect.attribute]: {
|
|
408
|
+
src: block,
|
|
409
|
+
text: block,
|
|
410
|
+
},
|
|
411
|
+
[DOMAspect.property]: {
|
|
412
|
+
src: block,
|
|
413
|
+
text: block,
|
|
414
|
+
innerText: block,
|
|
415
|
+
textContent: block,
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
style: {
|
|
419
|
+
[DOMAspect.property]: {
|
|
420
|
+
innerText: block,
|
|
421
|
+
textContent: block,
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
};
|
|
425
|
+
const blockedEvents = {
|
|
426
|
+
onabort: block,
|
|
427
|
+
onauxclick: block,
|
|
428
|
+
onbeforeinput: block,
|
|
429
|
+
onbeforematch: block,
|
|
430
|
+
onblur: block,
|
|
431
|
+
oncancel: block,
|
|
432
|
+
oncanplay: block,
|
|
433
|
+
oncanplaythrough: block,
|
|
434
|
+
onchange: block,
|
|
435
|
+
onclick: block,
|
|
436
|
+
onclose: block,
|
|
437
|
+
oncontextlost: block,
|
|
438
|
+
oncontextmenu: block,
|
|
439
|
+
oncontextrestored: block,
|
|
440
|
+
oncopy: block,
|
|
441
|
+
oncuechange: block,
|
|
442
|
+
oncut: block,
|
|
443
|
+
ondblclick: block,
|
|
444
|
+
ondrag: block,
|
|
445
|
+
ondragend: block,
|
|
446
|
+
ondragenter: block,
|
|
447
|
+
ondragleave: block,
|
|
448
|
+
ondragover: block,
|
|
449
|
+
ondragstart: block,
|
|
450
|
+
ondrop: block,
|
|
451
|
+
ondurationchange: block,
|
|
452
|
+
onemptied: block,
|
|
453
|
+
onended: block,
|
|
454
|
+
onerror: block,
|
|
455
|
+
onfocus: block,
|
|
456
|
+
onformdata: block,
|
|
457
|
+
oninput: block,
|
|
458
|
+
oninvalid: block,
|
|
459
|
+
onkeydown: block,
|
|
460
|
+
onkeypress: block,
|
|
461
|
+
onkeyup: block,
|
|
462
|
+
onload: block,
|
|
463
|
+
onloadeddata: block,
|
|
464
|
+
onloadedmetadata: block,
|
|
465
|
+
onloadstart: block,
|
|
466
|
+
onmousedown: block,
|
|
467
|
+
onmouseenter: block,
|
|
468
|
+
onmouseleave: block,
|
|
469
|
+
onmousemove: block,
|
|
470
|
+
onmouseout: block,
|
|
471
|
+
onmouseover: block,
|
|
472
|
+
onmouseup: block,
|
|
473
|
+
onpaste: block,
|
|
474
|
+
onpause: block,
|
|
475
|
+
onplay: block,
|
|
476
|
+
onplaying: block,
|
|
477
|
+
onprogress: block,
|
|
478
|
+
onratechange: block,
|
|
479
|
+
onreset: block,
|
|
480
|
+
onresize: block,
|
|
481
|
+
onscroll: block,
|
|
482
|
+
onsecuritypolicyviolation: block,
|
|
483
|
+
onseeked: block,
|
|
484
|
+
onseeking: block,
|
|
485
|
+
onselect: block,
|
|
486
|
+
onslotchange: block,
|
|
487
|
+
onstalled: block,
|
|
488
|
+
onsubmit: block,
|
|
489
|
+
onsuspend: block,
|
|
490
|
+
ontimeupdate: block,
|
|
491
|
+
ontoggle: block,
|
|
492
|
+
onvolumechange: block,
|
|
493
|
+
onwaiting: block,
|
|
494
|
+
onwebkitanimationend: block,
|
|
495
|
+
onwebkitanimationiteration: block,
|
|
496
|
+
onwebkitanimationstart: block,
|
|
497
|
+
onwebkittransitionend: block,
|
|
498
|
+
onwheel: block,
|
|
499
|
+
};
|
|
500
|
+
const defaultDOMGuards = {
|
|
501
|
+
elements: defaultDOMElementGuards,
|
|
502
|
+
aspects: {
|
|
503
|
+
[DOMAspect.attribute]: Object.assign({}, blockedEvents),
|
|
504
|
+
[DOMAspect.property]: Object.assign({ innerHTML: block }, blockedEvents),
|
|
505
|
+
[DOMAspect.event]: Object.assign({}, blockedEvents),
|
|
506
|
+
},
|
|
507
|
+
};
|
|
508
|
+
function createDomSinkGuards(config, defaults) {
|
|
509
|
+
const result = {};
|
|
510
|
+
for (const name in defaults) {
|
|
511
|
+
const overrideValue = config[name];
|
|
512
|
+
const defaultValue = defaults[name];
|
|
513
|
+
switch (overrideValue) {
|
|
514
|
+
case null:
|
|
515
|
+
// remove the default
|
|
516
|
+
break;
|
|
517
|
+
case undefined:
|
|
518
|
+
// keep the default
|
|
519
|
+
result[name] = defaultValue;
|
|
520
|
+
break;
|
|
521
|
+
default:
|
|
522
|
+
// override the default
|
|
523
|
+
result[name] = overrideValue;
|
|
524
|
+
break;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
// add any new sinks that were not overrides
|
|
528
|
+
for (const name in config) {
|
|
529
|
+
if (!(name in result)) {
|
|
530
|
+
result[name] = config[name];
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
return Object.freeze(result);
|
|
534
|
+
}
|
|
535
|
+
function createDOMAspectGuards(config, defaults) {
|
|
536
|
+
const result = {};
|
|
537
|
+
for (const aspect in defaults) {
|
|
538
|
+
const overrideValue = config[aspect];
|
|
539
|
+
const defaultValue = defaults[aspect];
|
|
540
|
+
switch (overrideValue) {
|
|
541
|
+
case null:
|
|
542
|
+
// remove the default
|
|
543
|
+
break;
|
|
544
|
+
case undefined:
|
|
545
|
+
// keep the default
|
|
546
|
+
result[aspect] = createDomSinkGuards(defaultValue, {});
|
|
547
|
+
break;
|
|
548
|
+
default:
|
|
549
|
+
// override the default
|
|
550
|
+
result[aspect] = createDomSinkGuards(overrideValue, defaultValue);
|
|
551
|
+
break;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
// add any new aspect guards that were not overrides
|
|
555
|
+
for (const aspect in config) {
|
|
556
|
+
if (!(aspect in result)) {
|
|
557
|
+
result[aspect] = createDomSinkGuards(config[aspect], {});
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return Object.freeze(result);
|
|
561
|
+
}
|
|
562
|
+
function createElementGuards(config, defaults) {
|
|
563
|
+
const result = {};
|
|
564
|
+
for (const tag in defaults) {
|
|
565
|
+
const overrideValue = config[tag];
|
|
566
|
+
const defaultValue = defaults[tag];
|
|
567
|
+
switch (overrideValue) {
|
|
568
|
+
case null:
|
|
569
|
+
// remove the default
|
|
570
|
+
break;
|
|
571
|
+
case undefined:
|
|
572
|
+
// keep the default
|
|
573
|
+
result[tag] = createDOMAspectGuards(overrideValue, {});
|
|
574
|
+
break;
|
|
575
|
+
default:
|
|
576
|
+
// override the default aspects
|
|
577
|
+
result[tag] = createDOMAspectGuards(overrideValue, defaultValue);
|
|
578
|
+
break;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
// Add any new element guards that were not overrides
|
|
582
|
+
for (const tag in config) {
|
|
583
|
+
if (!(tag in result)) {
|
|
584
|
+
result[tag] = createDOMAspectGuards(config[tag], {});
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
return Object.freeze(result);
|
|
588
|
+
}
|
|
589
|
+
function createDOMGuards(config, defaults) {
|
|
590
|
+
return Object.freeze({
|
|
591
|
+
elements: config.elements
|
|
592
|
+
? createElementGuards(config.elements, defaults.elements)
|
|
593
|
+
: defaults.elements,
|
|
594
|
+
aspects: config.aspects
|
|
595
|
+
? createDOMAspectGuards(config.aspects, defaults.aspects)
|
|
596
|
+
: defaults.aspects,
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
function createTrustedType() {
|
|
600
|
+
const createHTML = html => html;
|
|
601
|
+
return globalThis.trustedTypes
|
|
602
|
+
? globalThis.trustedTypes.createPolicy("fast-html", { createHTML })
|
|
603
|
+
: { createHTML };
|
|
604
|
+
}
|
|
605
|
+
function tryGuard(aspectGuards, tagName, aspect, aspectName, sink) {
|
|
606
|
+
const sinkGuards = aspectGuards[aspect];
|
|
607
|
+
if (sinkGuards) {
|
|
608
|
+
const guard = sinkGuards[aspectName];
|
|
609
|
+
if (guard) {
|
|
610
|
+
return guard(tagName, aspect, aspectName, sink);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
const DOMPolicy = Object.freeze({
|
|
615
|
+
/**
|
|
616
|
+
* Creates a new DOM Policy object.
|
|
617
|
+
* @param options The options to use in creating the policy.
|
|
618
|
+
* @returns The newly created DOMPolicy.
|
|
619
|
+
*/
|
|
620
|
+
create(options = {}) {
|
|
621
|
+
var _a, _b;
|
|
622
|
+
const trustedType = (_a = options.trustedType) !== null && _a !== void 0 ? _a : createTrustedType();
|
|
623
|
+
const guards = createDOMGuards((_b = options.guards) !== null && _b !== void 0 ? _b : {}, defaultDOMGuards);
|
|
624
|
+
return Object.freeze({
|
|
625
|
+
createHTML(value) {
|
|
626
|
+
return trustedType.createHTML(value);
|
|
627
|
+
},
|
|
628
|
+
protect(tagName, aspect, aspectName, sink) {
|
|
629
|
+
var _a;
|
|
630
|
+
// Check for element-specific guards.
|
|
631
|
+
const key = (tagName !== null && tagName !== void 0 ? tagName : "").toLowerCase();
|
|
632
|
+
const elementGuards = guards.elements[key];
|
|
633
|
+
if (elementGuards) {
|
|
634
|
+
const guard = tryGuard(elementGuards, tagName, aspect, aspectName, sink);
|
|
635
|
+
if (guard) {
|
|
636
|
+
return guard;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
// Check for guards applicable to all nodes.
|
|
640
|
+
return ((_a = tryGuard(guards.aspects, tagName, aspect, aspectName, sink)) !== null && _a !== void 0 ? _a : sink);
|
|
641
|
+
},
|
|
642
|
+
});
|
|
643
|
+
},
|
|
644
|
+
});
|
|
645
|
+
|
|
195
646
|
/**
|
|
196
647
|
* An implementation of {@link Notifier} that efficiently keeps track of
|
|
197
648
|
* subscribers interested in a specific change notification on an
|
|
@@ -434,6 +885,10 @@ const Observable = FAST.getById(2 /* KernelServiceId.observable */, () => {
|
|
|
434
885
|
this.propertyName = void 0;
|
|
435
886
|
this.notifier = void 0;
|
|
436
887
|
this.next = void 0;
|
|
888
|
+
/**
|
|
889
|
+
* Opts out of JSON stringification.
|
|
890
|
+
*/
|
|
891
|
+
this.toJSON = noop;
|
|
437
892
|
}
|
|
438
893
|
setMode(isAsync) {
|
|
439
894
|
this.isAsync = this.needsQueue = isAsync;
|
|
@@ -1474,55 +1929,6 @@ css.partial = (strings, ...values) => {
|
|
|
1474
1929
|
*/
|
|
1475
1930
|
const cssPartial = css.partial;
|
|
1476
1931
|
|
|
1477
|
-
/**
|
|
1478
|
-
* Common DOM APIs.
|
|
1479
|
-
* @public
|
|
1480
|
-
*/
|
|
1481
|
-
const DOM = Object.freeze({
|
|
1482
|
-
/**
|
|
1483
|
-
* @deprecated
|
|
1484
|
-
* Use Updates.enqueue().
|
|
1485
|
-
*/
|
|
1486
|
-
queueUpdate: Updates.enqueue,
|
|
1487
|
-
/**
|
|
1488
|
-
* @deprecated
|
|
1489
|
-
* Use Updates.next()
|
|
1490
|
-
*/
|
|
1491
|
-
nextUpdate: Updates.next,
|
|
1492
|
-
/**
|
|
1493
|
-
* @deprecated
|
|
1494
|
-
* Use Updates.process()
|
|
1495
|
-
*/
|
|
1496
|
-
processUpdates: Updates.process,
|
|
1497
|
-
/**
|
|
1498
|
-
* Sets an attribute value on an element.
|
|
1499
|
-
* @param element - The element to set the attribute value on.
|
|
1500
|
-
* @param attributeName - The attribute name to set.
|
|
1501
|
-
* @param value - The value of the attribute to set.
|
|
1502
|
-
* @remarks
|
|
1503
|
-
* If the value is `null` or `undefined`, the attribute is removed, otherwise
|
|
1504
|
-
* it is set to the provided value using the standard `setAttribute` API.
|
|
1505
|
-
*/
|
|
1506
|
-
setAttribute(element, attributeName, value) {
|
|
1507
|
-
value === null || value === undefined
|
|
1508
|
-
? element.removeAttribute(attributeName)
|
|
1509
|
-
: element.setAttribute(attributeName, value);
|
|
1510
|
-
},
|
|
1511
|
-
/**
|
|
1512
|
-
* Sets a boolean attribute value.
|
|
1513
|
-
* @param element - The element to set the boolean attribute value on.
|
|
1514
|
-
* @param attributeName - The attribute name to set.
|
|
1515
|
-
* @param value - The value of the attribute to set.
|
|
1516
|
-
* @remarks
|
|
1517
|
-
* If the value is true, the attribute is added; otherwise it is removed.
|
|
1518
|
-
*/
|
|
1519
|
-
setBooleanAttribute(element, attributeName, value) {
|
|
1520
|
-
value
|
|
1521
|
-
? element.setAttribute(attributeName, "")
|
|
1522
|
-
: element.removeAttribute(attributeName);
|
|
1523
|
-
},
|
|
1524
|
-
});
|
|
1525
|
-
|
|
1526
1932
|
const marker = `fast-${Math.random().toString(36).substring(2, 8)}`;
|
|
1527
1933
|
const interpolationStart = `${marker}{`;
|
|
1528
1934
|
const interpolationEnd = `}${marker}`;
|
|
@@ -1599,67 +2005,6 @@ const Parser = Object.freeze({
|
|
|
1599
2005
|
},
|
|
1600
2006
|
});
|
|
1601
2007
|
|
|
1602
|
-
/**
|
|
1603
|
-
* Bridges between ViewBehaviors and HostBehaviors, enabling a host to
|
|
1604
|
-
* control ViewBehaviors.
|
|
1605
|
-
* @public
|
|
1606
|
-
*/
|
|
1607
|
-
const ViewBehaviorOrchestrator = Object.freeze({
|
|
1608
|
-
/**
|
|
1609
|
-
* Creates a ViewBehaviorOrchestrator.
|
|
1610
|
-
* @param source - The source to to associate behaviors with.
|
|
1611
|
-
* @returns A ViewBehaviorOrchestrator.
|
|
1612
|
-
*/
|
|
1613
|
-
create(source) {
|
|
1614
|
-
const behaviors = [];
|
|
1615
|
-
const targets = {};
|
|
1616
|
-
let unbindables = null;
|
|
1617
|
-
let isConnected = false;
|
|
1618
|
-
return {
|
|
1619
|
-
source,
|
|
1620
|
-
context: ExecutionContext.default,
|
|
1621
|
-
targets,
|
|
1622
|
-
get isBound() {
|
|
1623
|
-
return isConnected;
|
|
1624
|
-
},
|
|
1625
|
-
addBehaviorFactory(factory, target) {
|
|
1626
|
-
const nodeId = factory.nodeId || (factory.nodeId = nextId());
|
|
1627
|
-
factory.id || (factory.id = nextId());
|
|
1628
|
-
this.addTarget(nodeId, target);
|
|
1629
|
-
this.addBehavior(factory.createBehavior());
|
|
1630
|
-
},
|
|
1631
|
-
addTarget(nodeId, target) {
|
|
1632
|
-
targets[nodeId] = target;
|
|
1633
|
-
},
|
|
1634
|
-
addBehavior(behavior) {
|
|
1635
|
-
behaviors.push(behavior);
|
|
1636
|
-
if (isConnected) {
|
|
1637
|
-
behavior.bind(this);
|
|
1638
|
-
}
|
|
1639
|
-
},
|
|
1640
|
-
onUnbind(unbindable) {
|
|
1641
|
-
if (unbindables === null) {
|
|
1642
|
-
unbindables = [];
|
|
1643
|
-
}
|
|
1644
|
-
unbindables.push(unbindable);
|
|
1645
|
-
},
|
|
1646
|
-
connectedCallback(controller) {
|
|
1647
|
-
if (!isConnected) {
|
|
1648
|
-
isConnected = true;
|
|
1649
|
-
behaviors.forEach(x => x.bind(this));
|
|
1650
|
-
}
|
|
1651
|
-
},
|
|
1652
|
-
disconnectedCallback(controller) {
|
|
1653
|
-
if (isConnected) {
|
|
1654
|
-
isConnected = false;
|
|
1655
|
-
if (unbindables !== null) {
|
|
1656
|
-
unbindables.forEach(x => x.unbind(this));
|
|
1657
|
-
}
|
|
1658
|
-
}
|
|
1659
|
-
},
|
|
1660
|
-
};
|
|
1661
|
-
},
|
|
1662
|
-
});
|
|
1663
2008
|
const registry = createTypeRegistry();
|
|
1664
2009
|
/**
|
|
1665
2010
|
* Instructs the template engine to apply behavior to a node.
|
|
@@ -1687,67 +2032,6 @@ const HTMLDirective = Object.freeze({
|
|
|
1687
2032
|
registry.register(options);
|
|
1688
2033
|
return type;
|
|
1689
2034
|
},
|
|
1690
|
-
});
|
|
1691
|
-
/**
|
|
1692
|
-
* Decorator: Defines an HTMLDirective.
|
|
1693
|
-
* @param options - Provides options that specify the directive's application.
|
|
1694
|
-
* @public
|
|
1695
|
-
*/
|
|
1696
|
-
function htmlDirective(options) {
|
|
1697
|
-
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
1698
|
-
return function (type) {
|
|
1699
|
-
HTMLDirective.define(type, options);
|
|
1700
|
-
};
|
|
1701
|
-
}
|
|
1702
|
-
/**
|
|
1703
|
-
* Captures a binding expression along with related information and capabilities.
|
|
1704
|
-
*
|
|
1705
|
-
* @public
|
|
1706
|
-
*/
|
|
1707
|
-
class Binding {
|
|
1708
|
-
/**
|
|
1709
|
-
* Creates a binding.
|
|
1710
|
-
* @param evaluate - Evaluates the binding.
|
|
1711
|
-
* @param isVolatile - Indicates whether the binding is volatile.
|
|
1712
|
-
*/
|
|
1713
|
-
constructor(evaluate, isVolatile = false) {
|
|
1714
|
-
this.evaluate = evaluate;
|
|
1715
|
-
this.isVolatile = isVolatile;
|
|
1716
|
-
}
|
|
1717
|
-
}
|
|
1718
|
-
/**
|
|
1719
|
-
* The type of HTML aspect to target.
|
|
1720
|
-
* @public
|
|
1721
|
-
*/
|
|
1722
|
-
const Aspect = Object.freeze({
|
|
1723
|
-
/**
|
|
1724
|
-
* Not aspected.
|
|
1725
|
-
*/
|
|
1726
|
-
none: 0,
|
|
1727
|
-
/**
|
|
1728
|
-
* An attribute.
|
|
1729
|
-
*/
|
|
1730
|
-
attribute: 1,
|
|
1731
|
-
/**
|
|
1732
|
-
* A boolean attribute.
|
|
1733
|
-
*/
|
|
1734
|
-
booleanAttribute: 2,
|
|
1735
|
-
/**
|
|
1736
|
-
* A property.
|
|
1737
|
-
*/
|
|
1738
|
-
property: 3,
|
|
1739
|
-
/**
|
|
1740
|
-
* Content
|
|
1741
|
-
*/
|
|
1742
|
-
content: 4,
|
|
1743
|
-
/**
|
|
1744
|
-
* A token list.
|
|
1745
|
-
*/
|
|
1746
|
-
tokenList: 5,
|
|
1747
|
-
/**
|
|
1748
|
-
* An event.
|
|
1749
|
-
*/
|
|
1750
|
-
event: 6,
|
|
1751
2035
|
/**
|
|
1752
2036
|
*
|
|
1753
2037
|
* @param directive - The directive to assign the aspect to.
|
|
@@ -1755,9 +2039,9 @@ const Aspect = Object.freeze({
|
|
|
1755
2039
|
* @remarks
|
|
1756
2040
|
* If a falsy value is provided, then the content aspect will be assigned.
|
|
1757
2041
|
*/
|
|
1758
|
-
|
|
2042
|
+
assignAspect(directive, value) {
|
|
1759
2043
|
if (!value) {
|
|
1760
|
-
directive.aspectType =
|
|
2044
|
+
directive.aspectType = DOMAspect.content;
|
|
1761
2045
|
return;
|
|
1762
2046
|
}
|
|
1763
2047
|
directive.sourceAspect = value;
|
|
@@ -1766,24 +2050,53 @@ const Aspect = Object.freeze({
|
|
|
1766
2050
|
directive.targetAspect = value.substring(1);
|
|
1767
2051
|
directive.aspectType =
|
|
1768
2052
|
directive.targetAspect === "classList"
|
|
1769
|
-
?
|
|
1770
|
-
:
|
|
2053
|
+
? DOMAspect.tokenList
|
|
2054
|
+
: DOMAspect.property;
|
|
1771
2055
|
break;
|
|
1772
2056
|
case "?":
|
|
1773
2057
|
directive.targetAspect = value.substring(1);
|
|
1774
|
-
directive.aspectType =
|
|
2058
|
+
directive.aspectType = DOMAspect.booleanAttribute;
|
|
1775
2059
|
break;
|
|
1776
2060
|
case "@":
|
|
1777
2061
|
directive.targetAspect = value.substring(1);
|
|
1778
|
-
directive.aspectType =
|
|
2062
|
+
directive.aspectType = DOMAspect.event;
|
|
1779
2063
|
break;
|
|
1780
2064
|
default:
|
|
1781
2065
|
directive.targetAspect = value;
|
|
1782
|
-
directive.aspectType =
|
|
2066
|
+
directive.aspectType = DOMAspect.attribute;
|
|
1783
2067
|
break;
|
|
1784
2068
|
}
|
|
1785
2069
|
},
|
|
1786
2070
|
});
|
|
2071
|
+
/**
|
|
2072
|
+
* Decorator: Defines an HTMLDirective.
|
|
2073
|
+
* @param options - Provides options that specify the directive's application.
|
|
2074
|
+
* @public
|
|
2075
|
+
*/
|
|
2076
|
+
function htmlDirective(options) {
|
|
2077
|
+
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
2078
|
+
return function (type) {
|
|
2079
|
+
HTMLDirective.define(type, options);
|
|
2080
|
+
};
|
|
2081
|
+
}
|
|
2082
|
+
/**
|
|
2083
|
+
* Captures a binding expression along with related information and capabilities.
|
|
2084
|
+
*
|
|
2085
|
+
* @public
|
|
2086
|
+
*/
|
|
2087
|
+
class Binding {
|
|
2088
|
+
/**
|
|
2089
|
+
* Creates a binding.
|
|
2090
|
+
* @param evaluate - Evaluates the binding.
|
|
2091
|
+
* @param policy - The security policy to associate with this binding.
|
|
2092
|
+
* @param isVolatile - Indicates whether the binding is volatile.
|
|
2093
|
+
*/
|
|
2094
|
+
constructor(evaluate, policy, isVolatile = false) {
|
|
2095
|
+
this.evaluate = evaluate;
|
|
2096
|
+
this.policy = policy;
|
|
2097
|
+
this.isVolatile = isVolatile;
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
1787
2100
|
/**
|
|
1788
2101
|
* A base class used for attribute directives that don't need internal state.
|
|
1789
2102
|
* @public
|
|
@@ -1796,9 +2109,10 @@ class StatelessAttachedAttributeDirective {
|
|
|
1796
2109
|
constructor(options) {
|
|
1797
2110
|
this.options = options;
|
|
1798
2111
|
/**
|
|
1799
|
-
*
|
|
2112
|
+
* Opts out of JSON stringification.
|
|
2113
|
+
* @internal
|
|
1800
2114
|
*/
|
|
1801
|
-
this.
|
|
2115
|
+
this.toJSON = noop;
|
|
1802
2116
|
}
|
|
1803
2117
|
/**
|
|
1804
2118
|
* Creates a placeholder string based on the directive's index within the template.
|
|
@@ -1818,21 +2132,20 @@ class StatelessAttachedAttributeDirective {
|
|
|
1818
2132
|
}
|
|
1819
2133
|
}
|
|
1820
2134
|
|
|
1821
|
-
const createInnerHTMLBinding = globalThis.TrustedHTML
|
|
1822
|
-
? (binding) => (s, c) => {
|
|
1823
|
-
const value = binding(s, c);
|
|
1824
|
-
if (value instanceof TrustedHTML) {
|
|
1825
|
-
return value;
|
|
1826
|
-
}
|
|
1827
|
-
throw FAST.error(1202 /* Message.bindingInnerHTMLRequiresTrustedTypes */);
|
|
1828
|
-
}
|
|
1829
|
-
: (binding) => binding;
|
|
1830
2135
|
class OnChangeBinding extends Binding {
|
|
1831
2136
|
createObserver(_, subscriber) {
|
|
1832
2137
|
return Observable.binding(this.evaluate, subscriber, this.isVolatile);
|
|
1833
2138
|
}
|
|
1834
2139
|
}
|
|
1835
2140
|
class OneTimeBinding extends Binding {
|
|
2141
|
+
constructor() {
|
|
2142
|
+
super(...arguments);
|
|
2143
|
+
/**
|
|
2144
|
+
* Opts out of JSON stringification.
|
|
2145
|
+
* @internal
|
|
2146
|
+
*/
|
|
2147
|
+
this.toJSON = noop;
|
|
2148
|
+
}
|
|
1836
2149
|
createObserver() {
|
|
1837
2150
|
return this;
|
|
1838
2151
|
}
|
|
@@ -1931,8 +2244,14 @@ function updateTokenList(target, aspect, value) {
|
|
|
1931
2244
|
}
|
|
1932
2245
|
}
|
|
1933
2246
|
}
|
|
1934
|
-
const
|
|
1935
|
-
|
|
2247
|
+
const sinkLookup = {
|
|
2248
|
+
[DOMAspect.attribute]: DOM.setAttribute,
|
|
2249
|
+
[DOMAspect.booleanAttribute]: DOM.setBooleanAttribute,
|
|
2250
|
+
[DOMAspect.property]: (t, a, v) => (t[a] = v),
|
|
2251
|
+
[DOMAspect.content]: updateContent,
|
|
2252
|
+
[DOMAspect.tokenList]: updateTokenList,
|
|
2253
|
+
[DOMAspect.event]: () => void 0,
|
|
2254
|
+
};
|
|
1936
2255
|
/**
|
|
1937
2256
|
* A directive that applies bindings.
|
|
1938
2257
|
* @public
|
|
@@ -1945,15 +2264,10 @@ class HTMLBindingDirective {
|
|
|
1945
2264
|
constructor(dataBinding) {
|
|
1946
2265
|
this.dataBinding = dataBinding;
|
|
1947
2266
|
this.updateTarget = null;
|
|
1948
|
-
/**
|
|
1949
|
-
* The unique id of the factory.
|
|
1950
|
-
*/
|
|
1951
|
-
this.id = nextId();
|
|
1952
2267
|
/**
|
|
1953
2268
|
* The type of aspect to target.
|
|
1954
2269
|
*/
|
|
1955
|
-
this.aspectType =
|
|
1956
|
-
this.data = `${this.id}-d`;
|
|
2270
|
+
this.aspectType = DOMAspect.content;
|
|
1957
2271
|
}
|
|
1958
2272
|
/**
|
|
1959
2273
|
* Creates HTML to be used within a template.
|
|
@@ -1966,45 +2280,28 @@ class HTMLBindingDirective {
|
|
|
1966
2280
|
* Creates a behavior.
|
|
1967
2281
|
*/
|
|
1968
2282
|
createBehavior() {
|
|
2283
|
+
var _a;
|
|
1969
2284
|
if (this.updateTarget === null) {
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
case 1:
|
|
1975
|
-
this.updateTarget = DOM.setAttribute;
|
|
1976
|
-
break;
|
|
1977
|
-
case 2:
|
|
1978
|
-
this.updateTarget = DOM.setBooleanAttribute;
|
|
1979
|
-
break;
|
|
1980
|
-
case 3:
|
|
1981
|
-
this.updateTarget = setProperty;
|
|
1982
|
-
break;
|
|
1983
|
-
case 4:
|
|
1984
|
-
this.updateTarget = updateContent;
|
|
1985
|
-
break;
|
|
1986
|
-
case 5:
|
|
1987
|
-
this.updateTarget = updateTokenList;
|
|
1988
|
-
break;
|
|
1989
|
-
case 6:
|
|
1990
|
-
this.updateTarget = eventTarget;
|
|
1991
|
-
break;
|
|
1992
|
-
default:
|
|
1993
|
-
throw FAST.error(1205 /* Message.unsupportedBindingBehavior */);
|
|
2285
|
+
const sink = sinkLookup[this.aspectType];
|
|
2286
|
+
const policy = (_a = this.dataBinding.policy) !== null && _a !== void 0 ? _a : this.policy;
|
|
2287
|
+
if (!sink) {
|
|
2288
|
+
throw FAST.error(1205 /* Message.unsupportedBindingBehavior */);
|
|
1994
2289
|
}
|
|
2290
|
+
this.data = `${this.id}-d`;
|
|
2291
|
+
this.updateTarget = policy.protect(this.targetTagName, this.aspectType, this.targetAspect, sink);
|
|
1995
2292
|
}
|
|
1996
2293
|
return this;
|
|
1997
2294
|
}
|
|
1998
2295
|
/** @internal */
|
|
1999
2296
|
bind(controller) {
|
|
2000
2297
|
var _a;
|
|
2001
|
-
const target = controller.targets[this.
|
|
2002
|
-
switch (this.
|
|
2003
|
-
case
|
|
2298
|
+
const target = controller.targets[this.targetNodeId];
|
|
2299
|
+
switch (this.aspectType) {
|
|
2300
|
+
case DOMAspect.event:
|
|
2004
2301
|
target[this.data] = controller;
|
|
2005
2302
|
target.addEventListener(this.targetAspect, this, this.dataBinding.options);
|
|
2006
2303
|
break;
|
|
2007
|
-
case
|
|
2304
|
+
case DOMAspect.content:
|
|
2008
2305
|
controller.onUnbind(this);
|
|
2009
2306
|
// intentional fall through
|
|
2010
2307
|
default:
|
|
@@ -2017,7 +2314,7 @@ class HTMLBindingDirective {
|
|
|
2017
2314
|
}
|
|
2018
2315
|
/** @internal */
|
|
2019
2316
|
unbind(controller) {
|
|
2020
|
-
const target = controller.targets[this.
|
|
2317
|
+
const target = controller.targets[this.targetNodeId];
|
|
2021
2318
|
const view = target.$fastView;
|
|
2022
2319
|
if (view !== void 0 && view.isComposed) {
|
|
2023
2320
|
view.unbind();
|
|
@@ -2047,21 +2344,23 @@ HTMLDirective.define(HTMLBindingDirective, { aspected: true });
|
|
|
2047
2344
|
/**
|
|
2048
2345
|
* Creates an standard binding.
|
|
2049
2346
|
* @param expression - The binding to refresh when changed.
|
|
2347
|
+
* @param policy - The security policy to associate with th binding.
|
|
2050
2348
|
* @param isVolatile - Indicates whether the binding is volatile or not.
|
|
2051
2349
|
* @returns A binding configuration.
|
|
2052
2350
|
* @public
|
|
2053
2351
|
*/
|
|
2054
|
-
function bind(expression, isVolatile = Observable.isVolatileBinding(expression)) {
|
|
2055
|
-
return new OnChangeBinding(expression, isVolatile);
|
|
2352
|
+
function bind(expression, policy, isVolatile = Observable.isVolatileBinding(expression)) {
|
|
2353
|
+
return new OnChangeBinding(expression, policy, isVolatile);
|
|
2056
2354
|
}
|
|
2057
2355
|
/**
|
|
2058
2356
|
* Creates a one time binding
|
|
2059
2357
|
* @param expression - The binding to refresh when signaled.
|
|
2358
|
+
* @param policy - The security policy to associate with th binding.
|
|
2060
2359
|
* @returns A binding configuration.
|
|
2061
2360
|
* @public
|
|
2062
2361
|
*/
|
|
2063
|
-
function oneTime(expression) {
|
|
2064
|
-
return new OneTimeBinding(expression);
|
|
2362
|
+
function oneTime(expression, policy) {
|
|
2363
|
+
return new OneTimeBinding(expression, policy);
|
|
2065
2364
|
}
|
|
2066
2365
|
/**
|
|
2067
2366
|
* Creates an event listener binding.
|
|
@@ -2071,7 +2370,7 @@ function oneTime(expression) {
|
|
|
2071
2370
|
* @public
|
|
2072
2371
|
*/
|
|
2073
2372
|
function listener(expression, options) {
|
|
2074
|
-
const config = new OnChangeBinding(expression
|
|
2373
|
+
const config = new OnChangeBinding(expression);
|
|
2075
2374
|
config.options = options;
|
|
2076
2375
|
return config;
|
|
2077
2376
|
}
|
|
@@ -2140,6 +2439,11 @@ class HTMLView {
|
|
|
2140
2439
|
* The length of the current collection within a repeat context.
|
|
2141
2440
|
*/
|
|
2142
2441
|
this.length = 0;
|
|
2442
|
+
/**
|
|
2443
|
+
* Opts out of JSON stringification.
|
|
2444
|
+
* @internal
|
|
2445
|
+
*/
|
|
2446
|
+
this.toJSON = noop;
|
|
2143
2447
|
this.firstChild = fragment.firstChild;
|
|
2144
2448
|
this.lastChild = fragment.lastChild;
|
|
2145
2449
|
}
|
|
@@ -2347,20 +2651,25 @@ const warningHost = new Proxy(document.createElement("div"), {
|
|
|
2347
2651
|
},
|
|
2348
2652
|
});
|
|
2349
2653
|
class CompilationContext {
|
|
2350
|
-
constructor(fragment, directives) {
|
|
2654
|
+
constructor(fragment, directives, policy) {
|
|
2351
2655
|
this.fragment = fragment;
|
|
2352
2656
|
this.directives = directives;
|
|
2657
|
+
this.policy = policy;
|
|
2353
2658
|
this.proto = null;
|
|
2354
2659
|
this.nodeIds = new Set();
|
|
2355
2660
|
this.descriptors = {};
|
|
2356
2661
|
this.factories = [];
|
|
2357
2662
|
}
|
|
2358
|
-
addFactory(factory, parentId, nodeId, targetIndex) {
|
|
2663
|
+
addFactory(factory, parentId, nodeId, targetIndex, tagName) {
|
|
2664
|
+
var _a, _b;
|
|
2359
2665
|
if (!this.nodeIds.has(nodeId)) {
|
|
2360
2666
|
this.nodeIds.add(nodeId);
|
|
2361
2667
|
this.addTargetDescriptor(parentId, nodeId, targetIndex);
|
|
2362
2668
|
}
|
|
2363
|
-
factory.
|
|
2669
|
+
factory.id = (_a = factory.id) !== null && _a !== void 0 ? _a : nextId();
|
|
2670
|
+
factory.targetNodeId = nodeId;
|
|
2671
|
+
factory.targetTagName = tagName;
|
|
2672
|
+
factory.policy = (_b = factory.policy) !== null && _b !== void 0 ? _b : this.policy;
|
|
2364
2673
|
this.factories.push(factory);
|
|
2365
2674
|
}
|
|
2366
2675
|
freeze() {
|
|
@@ -2413,19 +2722,19 @@ function compileAttributes(context, parentId, node, nodeId, nodeIndex, includeBa
|
|
|
2413
2722
|
let result = null;
|
|
2414
2723
|
if (parseResult === null) {
|
|
2415
2724
|
if (includeBasicValues) {
|
|
2416
|
-
result = new HTMLBindingDirective(oneTime(() => attrValue));
|
|
2417
|
-
|
|
2725
|
+
result = new HTMLBindingDirective(oneTime(() => attrValue, context.policy));
|
|
2726
|
+
HTMLDirective.assignAspect(result, attr.name);
|
|
2418
2727
|
}
|
|
2419
2728
|
}
|
|
2420
2729
|
else {
|
|
2421
2730
|
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
2422
|
-
result = Compiler.aggregate(parseResult);
|
|
2731
|
+
result = Compiler.aggregate(parseResult, context.policy);
|
|
2423
2732
|
}
|
|
2424
2733
|
if (result !== null) {
|
|
2425
2734
|
node.removeAttributeNode(attr);
|
|
2426
2735
|
i--;
|
|
2427
2736
|
ii--;
|
|
2428
|
-
context.addFactory(result, parentId, nodeId, nodeIndex);
|
|
2737
|
+
context.addFactory(result, parentId, nodeId, nodeIndex, node.tagName);
|
|
2429
2738
|
}
|
|
2430
2739
|
}
|
|
2431
2740
|
}
|
|
@@ -2450,8 +2759,8 @@ function compileContent(context, node, parentId, nodeId, nodeIndex) {
|
|
|
2450
2759
|
}
|
|
2451
2760
|
else {
|
|
2452
2761
|
currentNode.textContent = " ";
|
|
2453
|
-
|
|
2454
|
-
context.addFactory(currentPart, parentId, nodeId, nodeIndex);
|
|
2762
|
+
HTMLDirective.assignAspect(currentPart);
|
|
2763
|
+
context.addFactory(currentPart, parentId, nodeId, nodeIndex, null);
|
|
2455
2764
|
}
|
|
2456
2765
|
lastNode = currentNode;
|
|
2457
2766
|
}
|
|
@@ -2483,7 +2792,7 @@ function compileNode(context, parentId, node, nodeIndex) {
|
|
|
2483
2792
|
if (parts !== null) {
|
|
2484
2793
|
context.addFactory(
|
|
2485
2794
|
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
2486
|
-
Compiler.aggregate(parts), parentId, nodeId, nodeIndex);
|
|
2795
|
+
Compiler.aggregate(parts), parentId, nodeId, nodeIndex, null);
|
|
2487
2796
|
}
|
|
2488
2797
|
break;
|
|
2489
2798
|
}
|
|
@@ -2497,45 +2806,28 @@ function isMarker(node, directives) {
|
|
|
2497
2806
|
Parser.parse(node.data, directives) !== null);
|
|
2498
2807
|
}
|
|
2499
2808
|
const templateTag = "TEMPLATE";
|
|
2500
|
-
const policyOptions = { createHTML: html => html };
|
|
2501
|
-
let htmlPolicy = globalThis.trustedTypes
|
|
2502
|
-
? globalThis.trustedTypes.createPolicy("fast-html", policyOptions)
|
|
2503
|
-
: policyOptions;
|
|
2504
|
-
const fastHTMLPolicy = htmlPolicy;
|
|
2505
2809
|
/**
|
|
2506
2810
|
* Common APIs related to compilation.
|
|
2507
2811
|
* @public
|
|
2508
2812
|
*/
|
|
2509
2813
|
const Compiler = {
|
|
2510
|
-
/**
|
|
2511
|
-
* Sets the HTML trusted types policy used by the compiler.
|
|
2512
|
-
* @param policy - The policy to set for HTML.
|
|
2513
|
-
* @remarks
|
|
2514
|
-
* This API can only be called once, for security reasons. It should be
|
|
2515
|
-
* called by the application developer at the start of their program.
|
|
2516
|
-
*/
|
|
2517
|
-
setHTMLPolicy(policy) {
|
|
2518
|
-
if (htmlPolicy !== fastHTMLPolicy) {
|
|
2519
|
-
throw FAST.error(1201 /* Message.onlySetHTMLPolicyOnce */);
|
|
2520
|
-
}
|
|
2521
|
-
htmlPolicy = policy;
|
|
2522
|
-
},
|
|
2523
2814
|
/**
|
|
2524
2815
|
* Compiles a template and associated directives into a compilation
|
|
2525
2816
|
* result which can be used to create views.
|
|
2526
2817
|
* @param html - The html string or template element to compile.
|
|
2527
|
-
* @param
|
|
2818
|
+
* @param factories - The behavior factories referenced by the template.
|
|
2819
|
+
* @param policy - The security policy to compile the html with.
|
|
2528
2820
|
* @remarks
|
|
2529
2821
|
* The template that is provided for compilation is altered in-place
|
|
2530
2822
|
* and cannot be compiled again. If the original template must be preserved,
|
|
2531
2823
|
* it is recommended that you clone the original and pass the clone to this API.
|
|
2532
2824
|
* @public
|
|
2533
2825
|
*/
|
|
2534
|
-
compile(html,
|
|
2826
|
+
compile(html, factories, policy = DOM.policy) {
|
|
2535
2827
|
let template;
|
|
2536
2828
|
if (isString(html)) {
|
|
2537
2829
|
template = document.createElement(templateTag);
|
|
2538
|
-
template.innerHTML =
|
|
2830
|
+
template.innerHTML = policy.createHTML(html);
|
|
2539
2831
|
const fec = template.content.firstElementChild;
|
|
2540
2832
|
if (fec !== null && fec.tagName === templateTag) {
|
|
2541
2833
|
template = fec;
|
|
@@ -2546,18 +2838,18 @@ const Compiler = {
|
|
|
2546
2838
|
}
|
|
2547
2839
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=1111864
|
|
2548
2840
|
const fragment = document.adoptNode(template.content);
|
|
2549
|
-
const context = new CompilationContext(fragment,
|
|
2841
|
+
const context = new CompilationContext(fragment, factories, policy);
|
|
2550
2842
|
compileAttributes(context, "", template, /* host */ "h", 0, true);
|
|
2551
2843
|
if (
|
|
2552
2844
|
// If the first node in a fragment is a marker, that means it's an unstable first node,
|
|
2553
2845
|
// because something like a when, repeat, etc. could add nodes before the marker.
|
|
2554
2846
|
// To mitigate this, we insert a stable first node. However, if we insert a node,
|
|
2555
2847
|
// that will alter the result of the TreeWalker. So, we also need to offset the target index.
|
|
2556
|
-
isMarker(fragment.firstChild,
|
|
2848
|
+
isMarker(fragment.firstChild, factories) ||
|
|
2557
2849
|
// Or if there is only one node and a directive, it means the template's content
|
|
2558
2850
|
// is *only* the directive. In that case, HTMLView.dispose() misses any nodes inserted by
|
|
2559
2851
|
// the directive. Inserting a new node ensures proper disposal of nodes added by the directive.
|
|
2560
|
-
(fragment.childNodes.length === 1 && Object.keys(
|
|
2852
|
+
(fragment.childNodes.length === 1 && Object.keys(factories).length > 0)) {
|
|
2561
2853
|
fragment.insertBefore(document.createComment(""), fragment.firstChild);
|
|
2562
2854
|
}
|
|
2563
2855
|
compileChildren(context, fragment, /* root */ "r");
|
|
@@ -2576,15 +2868,17 @@ const Compiler = {
|
|
|
2576
2868
|
* Aggregates an array of strings and directives into a single directive.
|
|
2577
2869
|
* @param parts - A heterogeneous array of static strings interspersed with
|
|
2578
2870
|
* directives.
|
|
2871
|
+
* @param policy - The security policy to use with the aggregated bindings.
|
|
2579
2872
|
* @returns A single inline directive that aggregates the behavior of all the parts.
|
|
2580
2873
|
*/
|
|
2581
|
-
aggregate(parts) {
|
|
2874
|
+
aggregate(parts, policy = DOM.policy) {
|
|
2582
2875
|
if (parts.length === 1) {
|
|
2583
2876
|
return parts[0];
|
|
2584
2877
|
}
|
|
2585
2878
|
let sourceAspect;
|
|
2586
2879
|
let binding;
|
|
2587
2880
|
let isVolatile = false;
|
|
2881
|
+
let bindingPolicy = void 0;
|
|
2588
2882
|
const partCount = parts.length;
|
|
2589
2883
|
const finalParts = parts.map((x) => {
|
|
2590
2884
|
if (isString(x)) {
|
|
@@ -2593,6 +2887,7 @@ const Compiler = {
|
|
|
2593
2887
|
sourceAspect = x.sourceAspect || sourceAspect;
|
|
2594
2888
|
binding = x.dataBinding || binding;
|
|
2595
2889
|
isVolatile = isVolatile || x.dataBinding.isVolatile;
|
|
2890
|
+
bindingPolicy = bindingPolicy || x.dataBinding.policy;
|
|
2596
2891
|
return x.dataBinding.evaluate;
|
|
2597
2892
|
});
|
|
2598
2893
|
const expression = (scope, context) => {
|
|
@@ -2604,12 +2899,26 @@ const Compiler = {
|
|
|
2604
2899
|
};
|
|
2605
2900
|
binding.evaluate = expression;
|
|
2606
2901
|
binding.isVolatile = isVolatile;
|
|
2902
|
+
binding.policy = bindingPolicy !== null && bindingPolicy !== void 0 ? bindingPolicy : policy;
|
|
2607
2903
|
const directive = new HTMLBindingDirective(binding);
|
|
2608
|
-
|
|
2904
|
+
HTMLDirective.assignAspect(directive, sourceAspect);
|
|
2609
2905
|
return directive;
|
|
2610
2906
|
},
|
|
2611
2907
|
};
|
|
2612
2908
|
|
|
2909
|
+
// Much thanks to LitHTML for working this out!
|
|
2910
|
+
const lastAttributeNameRegex =
|
|
2911
|
+
/* eslint-disable-next-line no-control-regex */
|
|
2912
|
+
/([ \x09\x0a\x0c\x0d])([^\0-\x1F\x7F-\x9F "'>=/]+)([ \x09\x0a\x0c\x0d]*=[ \x09\x0a\x0c\x0d]*(?:[^ \x09\x0a\x0c\x0d"'`<>=]*|"[^"]*|'[^']*))$/;
|
|
2913
|
+
function createHTML(value, prevString, add, definition = HTMLDirective.getForInstance(value)) {
|
|
2914
|
+
if (definition.aspected) {
|
|
2915
|
+
const match = lastAttributeNameRegex.exec(prevString);
|
|
2916
|
+
if (match !== null) {
|
|
2917
|
+
HTMLDirective.assignAspect(value, match[2]);
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
return value.createHTML(add);
|
|
2921
|
+
}
|
|
2613
2922
|
/**
|
|
2614
2923
|
* A template capable of creating HTMLView instances or rendering directly to DOM.
|
|
2615
2924
|
* @public
|
|
@@ -2619,9 +2928,16 @@ class ViewTemplate {
|
|
|
2619
2928
|
* Creates an instance of ViewTemplate.
|
|
2620
2929
|
* @param html - The html representing what this template will instantiate, including placeholders for directives.
|
|
2621
2930
|
* @param factories - The directives that will be connected to placeholders in the html.
|
|
2931
|
+
* @param policy - The security policy to use when compiling this template.
|
|
2622
2932
|
*/
|
|
2623
|
-
constructor(html, factories) {
|
|
2933
|
+
constructor(html, factories = {}, policy) {
|
|
2934
|
+
this.policy = policy;
|
|
2624
2935
|
this.result = null;
|
|
2936
|
+
/**
|
|
2937
|
+
* Opts out of JSON stringification.
|
|
2938
|
+
* @internal
|
|
2939
|
+
*/
|
|
2940
|
+
this.toJSON = noop;
|
|
2625
2941
|
this.html = html;
|
|
2626
2942
|
this.factories = factories;
|
|
2627
2943
|
}
|
|
@@ -2631,10 +2947,28 @@ class ViewTemplate {
|
|
|
2631
2947
|
*/
|
|
2632
2948
|
create(hostBindingTarget) {
|
|
2633
2949
|
if (this.result === null) {
|
|
2634
|
-
this.result = Compiler.compile(this.html, this.factories);
|
|
2950
|
+
this.result = Compiler.compile(this.html, this.factories, this.policy);
|
|
2635
2951
|
}
|
|
2636
2952
|
return this.result.createView(hostBindingTarget);
|
|
2637
2953
|
}
|
|
2954
|
+
/**
|
|
2955
|
+
* Sets the DOMPolicy for this template.
|
|
2956
|
+
* @param policy - The policy to associated with this template.
|
|
2957
|
+
* @returns The modified template instance.
|
|
2958
|
+
* @remarks
|
|
2959
|
+
* The DOMPolicy can only be set once for a template and cannot be
|
|
2960
|
+
* set after the template is compiled.
|
|
2961
|
+
*/
|
|
2962
|
+
withPolicy(policy) {
|
|
2963
|
+
if (this.result) {
|
|
2964
|
+
throw FAST.error(1208 /* Message.cannotSetTemplatePolicyAfterCompilation */);
|
|
2965
|
+
}
|
|
2966
|
+
if (this.policy) {
|
|
2967
|
+
throw FAST.error(1207 /* Message.onlySetTemplatePolicyOnce */);
|
|
2968
|
+
}
|
|
2969
|
+
this.policy = policy;
|
|
2970
|
+
return this;
|
|
2971
|
+
}
|
|
2638
2972
|
/**
|
|
2639
2973
|
* Creates an HTMLView from this template, binds it to the source, and then appends it to the host.
|
|
2640
2974
|
* @param source - The data source to bind the template to.
|
|
@@ -2648,17 +2982,47 @@ class ViewTemplate {
|
|
|
2648
2982
|
view.appendTo(host);
|
|
2649
2983
|
return view;
|
|
2650
2984
|
}
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2985
|
+
/**
|
|
2986
|
+
* Creates a template based on a set of static strings and dynamic values.
|
|
2987
|
+
* @param strings - The static strings to create the template with.
|
|
2988
|
+
* @param values - The dynamic values to create the template with.
|
|
2989
|
+
* @param policy - The DOMPolicy to associated with the template.
|
|
2990
|
+
* @returns A ViewTemplate.
|
|
2991
|
+
* @remarks
|
|
2992
|
+
* This API should not be used directly under normal circumstances because constructing
|
|
2993
|
+
* a template in this way, if not done properly, can open up the application to XSS
|
|
2994
|
+
* attacks. When using this API, provide a strong DOMPolicy that can properly sanitize
|
|
2995
|
+
* and also be sure to manually sanitize all static strings particularly if they can
|
|
2996
|
+
* come from user input.
|
|
2997
|
+
*/
|
|
2998
|
+
static create(strings, values, policy) {
|
|
2999
|
+
let html = "";
|
|
3000
|
+
const factories = Object.create(null);
|
|
3001
|
+
const add = (factory) => {
|
|
3002
|
+
var _a;
|
|
3003
|
+
const id = (_a = factory.id) !== null && _a !== void 0 ? _a : (factory.id = nextId());
|
|
3004
|
+
factories[id] = factory;
|
|
3005
|
+
return id;
|
|
3006
|
+
};
|
|
3007
|
+
for (let i = 0, ii = strings.length - 1; i < ii; ++i) {
|
|
3008
|
+
const currentString = strings[i];
|
|
3009
|
+
let currentValue = values[i];
|
|
3010
|
+
let definition;
|
|
3011
|
+
html += currentString;
|
|
3012
|
+
if (isFunction(currentValue)) {
|
|
3013
|
+
currentValue = new HTMLBindingDirective(bind(currentValue));
|
|
3014
|
+
}
|
|
3015
|
+
else if (currentValue instanceof Binding) {
|
|
3016
|
+
currentValue = new HTMLBindingDirective(currentValue);
|
|
3017
|
+
}
|
|
3018
|
+
else if (!(definition = HTMLDirective.getForInstance(currentValue))) {
|
|
3019
|
+
const staticValue = currentValue;
|
|
3020
|
+
currentValue = new HTMLBindingDirective(oneTime(() => staticValue));
|
|
3021
|
+
}
|
|
3022
|
+
html += createHTML(currentValue, currentString, add, definition);
|
|
3023
|
+
}
|
|
3024
|
+
return new ViewTemplate(html + strings[strings.length - 1], factories, policy);
|
|
2660
3025
|
}
|
|
2661
|
-
return value.createHTML(add);
|
|
2662
3026
|
}
|
|
2663
3027
|
/**
|
|
2664
3028
|
* Transforms a template literal string into a ViewTemplate.
|
|
@@ -2670,49 +3034,10 @@ function createAspectedHTML(value, prevString, add) {
|
|
|
2670
3034
|
* @public
|
|
2671
3035
|
*/
|
|
2672
3036
|
function html(strings, ...values) {
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
const add = (factory) => {
|
|
2676
|
-
var _a;
|
|
2677
|
-
const id = (_a = factory.id) !== null && _a !== void 0 ? _a : (factory.id = nextId());
|
|
2678
|
-
factories[id] = factory;
|
|
2679
|
-
return id;
|
|
2680
|
-
};
|
|
2681
|
-
for (let i = 0, ii = strings.length - 1; i < ii; ++i) {
|
|
2682
|
-
const currentString = strings[i];
|
|
2683
|
-
const currentValue = values[i];
|
|
2684
|
-
let definition;
|
|
2685
|
-
html += currentString;
|
|
2686
|
-
if (isFunction(currentValue)) {
|
|
2687
|
-
html += createAspectedHTML(new HTMLBindingDirective(bind(currentValue)), currentString, add);
|
|
2688
|
-
}
|
|
2689
|
-
else if (isString(currentValue)) {
|
|
2690
|
-
const match = lastAttributeNameRegex.exec(currentString);
|
|
2691
|
-
if (match !== null) {
|
|
2692
|
-
const directive = new HTMLBindingDirective(oneTime(() => currentValue));
|
|
2693
|
-
Aspect.assign(directive, match[2]);
|
|
2694
|
-
html += directive.createHTML(add);
|
|
2695
|
-
}
|
|
2696
|
-
else {
|
|
2697
|
-
html += currentValue;
|
|
2698
|
-
}
|
|
2699
|
-
}
|
|
2700
|
-
else if (currentValue instanceof Binding) {
|
|
2701
|
-
html += createAspectedHTML(new HTMLBindingDirective(currentValue), currentString, add);
|
|
2702
|
-
}
|
|
2703
|
-
else if ((definition = HTMLDirective.getForInstance(currentValue)) === void 0) {
|
|
2704
|
-
html += createAspectedHTML(new HTMLBindingDirective(oneTime(() => currentValue)), currentString, add);
|
|
2705
|
-
}
|
|
2706
|
-
else {
|
|
2707
|
-
if (definition.aspected) {
|
|
2708
|
-
html += createAspectedHTML(currentValue, currentString, add);
|
|
2709
|
-
}
|
|
2710
|
-
else {
|
|
2711
|
-
html += currentValue.createHTML(add);
|
|
2712
|
-
}
|
|
2713
|
-
}
|
|
3037
|
+
if (Array.isArray(strings) && Array.isArray(strings.raw)) {
|
|
3038
|
+
return ViewTemplate.create(strings, values);
|
|
2714
3039
|
}
|
|
2715
|
-
|
|
3040
|
+
throw FAST.error(1206 /* Message.directCallToHTMLTagNotAllowed */);
|
|
2716
3041
|
}
|
|
2717
3042
|
|
|
2718
3043
|
/**
|
|
@@ -2725,7 +3050,7 @@ class RefDirective extends StatelessAttachedAttributeDirective {
|
|
|
2725
3050
|
* @param controller - The view controller that manages the lifecycle of this behavior.
|
|
2726
3051
|
*/
|
|
2727
3052
|
bind(controller) {
|
|
2728
|
-
controller.source[this.options] = controller.targets[this.
|
|
3053
|
+
controller.source[this.options] = controller.targets[this.targetNodeId];
|
|
2729
3054
|
}
|
|
2730
3055
|
}
|
|
2731
3056
|
HTMLDirective.define(RefDirective);
|
|
@@ -2799,7 +3124,7 @@ class RepeatBehavior {
|
|
|
2799
3124
|
* @param controller - The view controller that manages the lifecycle of this behavior.
|
|
2800
3125
|
*/
|
|
2801
3126
|
bind(controller) {
|
|
2802
|
-
this.location = controller.targets[this.directive.
|
|
3127
|
+
this.location = controller.targets[this.directive.targetNodeId];
|
|
2803
3128
|
this.controller = controller;
|
|
2804
3129
|
this.items = this.itemsBindingObserver.bind(controller);
|
|
2805
3130
|
this.template = this.templateBindingObserver.bind(controller);
|
|
@@ -2979,10 +3304,6 @@ class RepeatDirective {
|
|
|
2979
3304
|
this.dataBinding = dataBinding;
|
|
2980
3305
|
this.templateBinding = templateBinding;
|
|
2981
3306
|
this.options = options;
|
|
2982
|
-
/**
|
|
2983
|
-
* The unique id of the factory.
|
|
2984
|
-
*/
|
|
2985
|
-
this.id = nextId();
|
|
2986
3307
|
ArrayObserver.enable();
|
|
2987
3308
|
}
|
|
2988
3309
|
/**
|
|
@@ -3031,9 +3352,15 @@ const elements = (selector) => selector
|
|
|
3031
3352
|
* Internally used by the SlottedDirective and the ChildrenDirective.
|
|
3032
3353
|
*/
|
|
3033
3354
|
class NodeObservationDirective extends StatelessAttachedAttributeDirective {
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3355
|
+
/**
|
|
3356
|
+
* The unique id of the factory.
|
|
3357
|
+
*/
|
|
3358
|
+
get id() {
|
|
3359
|
+
return this._id;
|
|
3360
|
+
}
|
|
3361
|
+
set id(value) {
|
|
3362
|
+
this._id = value;
|
|
3363
|
+
this._controllerProperty = `${value}-c`;
|
|
3037
3364
|
}
|
|
3038
3365
|
/**
|
|
3039
3366
|
* Bind this behavior to the source.
|
|
@@ -3042,8 +3369,8 @@ class NodeObservationDirective extends StatelessAttachedAttributeDirective {
|
|
|
3042
3369
|
* @param targets - The targets that behaviors in a view can attach to.
|
|
3043
3370
|
*/
|
|
3044
3371
|
bind(controller) {
|
|
3045
|
-
const target = controller.targets[this.
|
|
3046
|
-
target[this.
|
|
3372
|
+
const target = controller.targets[this.targetNodeId];
|
|
3373
|
+
target[this._controllerProperty] = controller;
|
|
3047
3374
|
this.updateTarget(controller.source, this.computeNodes(target));
|
|
3048
3375
|
this.observe(target);
|
|
3049
3376
|
controller.onUnbind(this);
|
|
@@ -3055,10 +3382,10 @@ class NodeObservationDirective extends StatelessAttachedAttributeDirective {
|
|
|
3055
3382
|
* @param targets - The targets that behaviors in a view can attach to.
|
|
3056
3383
|
*/
|
|
3057
3384
|
unbind(controller) {
|
|
3058
|
-
const target = controller.targets[this.
|
|
3385
|
+
const target = controller.targets[this.targetNodeId];
|
|
3059
3386
|
this.updateTarget(controller.source, emptyArray);
|
|
3060
3387
|
this.disconnect(target);
|
|
3061
|
-
target[this.
|
|
3388
|
+
target[this._controllerProperty] = null;
|
|
3062
3389
|
}
|
|
3063
3390
|
/**
|
|
3064
3391
|
* Gets the data source for the target.
|
|
@@ -3066,7 +3393,7 @@ class NodeObservationDirective extends StatelessAttachedAttributeDirective {
|
|
|
3066
3393
|
* @returns The source.
|
|
3067
3394
|
*/
|
|
3068
3395
|
getSource(target) {
|
|
3069
|
-
return target[this.
|
|
3396
|
+
return target[this._controllerProperty].source;
|
|
3070
3397
|
}
|
|
3071
3398
|
/**
|
|
3072
3399
|
* Updates the source property with the computed nodes.
|
|
@@ -3162,9 +3489,13 @@ class ChildrenDirective extends NodeObservationDirective {
|
|
|
3162
3489
|
* @param target - The target to observe.
|
|
3163
3490
|
*/
|
|
3164
3491
|
observe(target) {
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3492
|
+
let observer = target[this.observerProperty];
|
|
3493
|
+
if (!observer) {
|
|
3494
|
+
observer = new MutationObserver(this.handleEvent);
|
|
3495
|
+
observer.toJSON = noop;
|
|
3496
|
+
observer.target = target;
|
|
3497
|
+
target[this.observerProperty] = observer;
|
|
3498
|
+
}
|
|
3168
3499
|
observer.observe(target, this.options);
|
|
3169
3500
|
}
|
|
3170
3501
|
/**
|
|
@@ -3203,6 +3534,29 @@ function children(propertyOrOptions) {
|
|
|
3203
3534
|
return new ChildrenDirective(propertyOrOptions);
|
|
3204
3535
|
}
|
|
3205
3536
|
|
|
3537
|
+
/**
|
|
3538
|
+
* A directive capable of injecting static HTML platform runtime protection.
|
|
3539
|
+
* @public
|
|
3540
|
+
*/
|
|
3541
|
+
class DangerousHTMLDirective {
|
|
3542
|
+
constructor(html) {
|
|
3543
|
+
this.html = html;
|
|
3544
|
+
}
|
|
3545
|
+
createHTML() {
|
|
3546
|
+
return this.html;
|
|
3547
|
+
}
|
|
3548
|
+
}
|
|
3549
|
+
HTMLDirective.define(DangerousHTMLDirective);
|
|
3550
|
+
/**
|
|
3551
|
+
* Injects static HTML without platform protection.
|
|
3552
|
+
* @param html - The html to injection.
|
|
3553
|
+
* @returns A DangerousHTMLDirective.
|
|
3554
|
+
* @public
|
|
3555
|
+
*/
|
|
3556
|
+
function dangerousHTML(html) {
|
|
3557
|
+
return new DangerousHTMLDirective(html);
|
|
3558
|
+
}
|
|
3559
|
+
|
|
3206
3560
|
const booleanMode = "boolean";
|
|
3207
3561
|
const reflectMode = "reflect";
|
|
3208
3562
|
/**
|
|
@@ -3556,6 +3910,11 @@ class ElementController extends PropertyChangeNotifier {
|
|
|
3556
3910
|
* If `null` then the element is managing its own rendering.
|
|
3557
3911
|
*/
|
|
3558
3912
|
this.view = null;
|
|
3913
|
+
/**
|
|
3914
|
+
* Opts out of JSON stringification.
|
|
3915
|
+
* @internal
|
|
3916
|
+
*/
|
|
3917
|
+
this.toJSON = noop;
|
|
3559
3918
|
this.source = element;
|
|
3560
3919
|
this.definition = definition;
|
|
3561
3920
|
const shadowOptions = definition.shadowOptions;
|
|
@@ -4058,4 +4417,6 @@ function customElement(nameOrDef) {
|
|
|
4058
4417
|
};
|
|
4059
4418
|
}
|
|
4060
4419
|
|
|
4061
|
-
|
|
4420
|
+
DOM.setPolicy(DOMPolicy.create());
|
|
4421
|
+
|
|
4422
|
+
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 };
|