-
Notifications
You must be signed in to change notification settings - Fork 9
/
utils.js
121 lines (96 loc) · 2.96 KB
/
utils.js
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
const {tagName, nodeType, slice, Array, parse, stringify,
Node, Document, DocumentFragment, Element, ShadowRoot, getContentWindow,
getDefaultView, getOwnerDocument, stringToLowerCase,
} = require('./natives');
const shadows = new Array();
function isShadow(node) {
return shadows.includes(node);
}
function isTrustedHTML(node) {
const replacer = (k, v) => (!k && node === v) ? v : ''; // avoid own props
// normal nodes will parse into objects whereas trusted htmls into strings
return typeof parse(stringify(node, replacer)) === 'string';
}
function getPrototype(node) {
if (isShadow(node)) {
return ShadowRoot;
}
switch (nodeType(node)) {
case Node.prototype.DOCUMENT_NODE:
return Document;
case Node.prototype.DOCUMENT_FRAGMENT_NODE:
return DocumentFragment;
default:
return Element;
}
}
function isTagFramable(t) {
const tag = stringToLowerCase(t);
return tag === 'iframe' || tag === 'frame' || tag === 'object' || tag === 'embed';
}
function getFrameTag(element) {
if (!element || typeof element !== 'object') {
return null;
}
if (nodeType(element) !== Element.prototype.ELEMENT_NODE) {
return null;
}
if (isShadow(element)) {
return null;
}
const tag = tagName(element);
if (!isTagFramable(tag)) {
return null;
}
return tag;
}
function toArray(item) {
if (!Array.isArray(item)) {
item = new Array(item);
}
return item;
}
function getContentWindowOfFrame(iframe) {
return getContentWindow(iframe, getFrameTag(iframe));
}
function getOwnerWindowOfNode(iframe) {
return getDefaultView(getOwnerDocument(iframe));
}
function canNodeRunQuerySelector(node) {
if (isShadow(node)) {
return true;
}
const type = nodeType(node);
return (
type === Element.prototype.ELEMENT_NODE ||
type === Element.prototype.DOCUMENT_FRAGMENT_NODE ||
type === Element.prototype.DOCUMENT_NODE
);
}
function getFramesArray(element, includingParent) {
const frames = new Array();
if (null === element || typeof element !== 'object') {
return frames;
}
if (isTrustedHTML(element) || !canNodeRunQuerySelector(element)) {
return frames;
}
const querySelectorAll = getPrototype(element).prototype.querySelectorAll;
const list = querySelectorAll.call(element, 'iframe,frame,object,embed');
fillArrayUniques(frames, slice(list));
if (includingParent) {
fillArrayUniques(frames, toArray(element));
}
return frames;
}
function fillArrayUniques(arr, items) {
let isArrUpdated = false;
for (let i = 0; i < items.length; i++) {
if (!arr.includes(items[i])) {
arr.push(items[i]);
isArrUpdated = true;
}
}
return isArrUpdated;
}
module.exports = {toArray, isTagFramable, getOwnerWindowOfNode, getContentWindowOfFrame, getFramesArray, getFrameTag, shadows};