-
-
Notifications
You must be signed in to change notification settings - Fork 179
/
HTMLIFrameElementNamedNodeMap.ts
123 lines (109 loc) · 3.35 KB
/
HTMLIFrameElementNamedNodeMap.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import Attr from '../attr/Attr.js';
import Element from '../element/Element.js';
import HTMLElementNamedNodeMap from '../html-element/HTMLElementNamedNodeMap.js';
import HTMLIFrameElementPageLoader from './HTMLIFrameElementPageLoader.js';
import * as PropertySymbol from '../../PropertySymbol.js';
import DOMTokenList from '../../dom-token-list/DOMTokenList.js';
const SANDBOX_FLAGS = [
'allow-downloads',
'allow-forms',
'allow-modals',
'allow-orientation-lock',
'allow-pointer-lock',
'allow-popups',
'allow-popups-to-escape-sandbox',
'allow-presentation',
'allow-same-origin',
'allow-scripts',
'allow-top-navigation',
'allow-top-navigation-by-user-activation',
'allow-top-navigation-to-custom-protocols'
];
/**
* Named Node Map.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap
*/
export default class HTMLIFrameElementNamedNodeMap extends HTMLElementNamedNodeMap {
#pageLoader: HTMLIFrameElementPageLoader;
/**
* Constructor.
*
* @param ownerElement Owner element.
* @param pageLoader
*/
constructor(ownerElement: Element, pageLoader: HTMLIFrameElementPageLoader) {
super(ownerElement);
this.#pageLoader = pageLoader;
}
/**
* @override
*/
public override setNamedItem(item: Attr): Attr | null {
const replacedAttribute = super.setNamedItem(item);
if (item[PropertySymbol.name] === 'srcdoc') {
this.#pageLoader.loadPage();
}
// If the src attribute and the srcdoc attribute are both specified together, the srcdoc attribute takes priority.
if (
item[PropertySymbol.name] === 'src' &&
this[PropertySymbol.ownerElement][PropertySymbol.attributes]['srcdoc']?.value === undefined &&
item[PropertySymbol.value] &&
item[PropertySymbol.value] !== replacedAttribute?.[PropertySymbol.value]
) {
this.#pageLoader.loadPage();
}
if (item[PropertySymbol.name] === 'sandbox') {
if (!this[PropertySymbol.ownerElement][PropertySymbol.sandbox]) {
this[PropertySymbol.ownerElement][PropertySymbol.sandbox] = new DOMTokenList(
this[PropertySymbol.ownerElement],
'sandbox'
);
} else {
this[PropertySymbol.ownerElement][PropertySymbol.sandbox][PropertySymbol.updateIndices]();
}
this.#validateSandboxFlags();
}
return replacedAttribute || null;
}
/**
* @override
*/
public override [PropertySymbol.removeNamedItem](name: string): Attr | null {
const removedItem = super[PropertySymbol.removeNamedItem](name);
if (
removedItem &&
(removedItem[PropertySymbol.name] === 'srcdoc' || removedItem[PropertySymbol.name] === 'src')
) {
this.#pageLoader.loadPage();
}
return removedItem;
}
/**
*
* @param tokens
* @param vconsole
*/
#validateSandboxFlags(): void {
const window =
this[PropertySymbol.ownerElement][PropertySymbol.ownerDocument][PropertySymbol.ownerWindow];
const values = this[PropertySymbol.ownerElement][PropertySymbol.sandbox].values();
const invalidFlags: string[] = [];
for (const token of values) {
if (!SANDBOX_FLAGS.includes(token)) {
invalidFlags.push(token);
}
}
if (invalidFlags.length === 1) {
window.console.error(
`Error while parsing the 'sandbox' attribute: '${invalidFlags[0]}' is an invalid sandbox flag.`
);
} else if (invalidFlags.length > 1) {
window.console.error(
`Error while parsing the 'sandbox' attribute: '${invalidFlags.join(
`', '`
)}' are invalid sandbox flags.`
);
}
}
}