named-properties-window.js
3.44 KB
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
"use strict";
const hasOwnProp = Object.prototype.hasOwnProperty;
const namedPropertiesTracker = require("../named-properties-tracker");
const NODE_TYPE = require("./node-type");
const HTMLCollection = require("./generated/HTMLCollection");
const { treeOrderSorter } = require("../utils");
const idlUtils = require("./generated/utils");
function isNamedPropertyElement(element) {
// (for the name attribute)
// use hasOwnProperty to make sure contentWindow comes from the prototype,
// and is not set directly on the node by a script.
if ("contentWindow" in element && !hasOwnProp.call(element, "contentWindow")) {
return true;
}
switch (element.nodeName) {
case "A":
case "AREA":
case "EMBED":
case "FORM":
case "FRAMESET":
case "IMG":
case "OBJECT":
return true;
default:
return false;
}
}
function namedPropertyResolver(window, name, values) {
function getResult() {
const results = [];
for (const node of values().keys()) {
if (node.nodeType !== NODE_TYPE.ELEMENT_NODE) {
continue;
}
if (node.getAttribute("id") === name) {
results.push(node);
} else if (node.getAttribute("name") === name && isNamedPropertyElement(node)) {
results.push(node);
}
}
results.sort(treeOrderSorter);
return results;
}
const document = window._document;
const objects = HTMLCollection.create([], {
element: idlUtils.implForWrapper(document.documentElement),
query: getResult
});
const { length } = objects;
for (let i = 0; i < length; ++i) {
const node = objects[i];
if ("contentWindow" in node && !hasOwnProp.call(node, "contentWindow") &&
node.getAttribute("name") === name) {
return node.contentWindow;
}
}
if (length === 0) {
return undefined;
}
if (length === 1) {
return objects[0];
}
return objects;
}
exports.initializeWindow = function (window, windowProxy) {
namedPropertiesTracker.create(window, windowProxy, namedPropertyResolver.bind(null));
};
exports.elementAttributeModified = function (element, name, value, oldValue) {
if (!element._attached) {
return;
}
const useName = isNamedPropertyElement(element);
if (name === "id" || (name === "name" && useName)) {
const tracker = namedPropertiesTracker.get(element._ownerDocument._global);
// (tracker will be null if the document has no Window)
if (tracker) {
if (name === "id" && (!useName || element.getAttribute("name") !== oldValue)) {
tracker.untrack(oldValue, element);
}
if (name === "name" && element.getAttribute("id") !== oldValue) {
tracker.untrack(oldValue, element);
}
tracker.track(value, element);
}
}
};
exports.nodeAttachedToDocument = function (node) {
if (node.nodeType !== NODE_TYPE.ELEMENT_NODE) {
return;
}
const tracker = namedPropertiesTracker.get(node._ownerDocument._global);
if (!tracker) {
return;
}
tracker.track(node.getAttribute("id"), node);
if (isNamedPropertyElement(node)) {
tracker.track(node.getAttribute("name"), node);
}
};
exports.nodeDetachedFromDocument = function (node) {
if (node.nodeType !== NODE_TYPE.ELEMENT_NODE) {
return;
}
const tracker = namedPropertiesTracker.get(node._ownerDocument._global);
if (!tracker) {
return;
}
tracker.untrack(node.getAttribute("id"), node);
if (isNamedPropertyElement(node)) {
tracker.untrack(node.getAttribute("name"), node);
}
};