Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
titaniumnetwork-dev
GitHub Repository: titaniumnetwork-dev/Ultraviolet
Path: blob/main/src/client/dom/document.js
305 views
1
import EventEmitter from "events";
2
import HookEvent from "../hook.js";
3
4
/**
5
* @typedef {import('../index').default} UVClient
6
*/
7
8
class DocumentHook extends EventEmitter {
9
/**
10
*
11
* @param {UVClient} ctx
12
*/
13
constructor(ctx) {
14
super();
15
this.ctx = ctx;
16
this.window = ctx.window;
17
this.document = this.window.document;
18
this.Document = this.window.Document || {};
19
this.DOMParser = this.window.DOMParser || {};
20
this.docProto = this.Document.prototype || {};
21
this.domProto = this.DOMParser.prototype || {};
22
this.title = ctx.nativeMethods.getOwnPropertyDescriptor(
23
this.docProto,
24
"title"
25
);
26
this.cookie = ctx.nativeMethods.getOwnPropertyDescriptor(
27
this.docProto,
28
"cookie"
29
);
30
this.referrer = ctx.nativeMethods.getOwnPropertyDescriptor(
31
this.docProto,
32
"referrer"
33
);
34
this.domain = ctx.nativeMethods.getOwnPropertyDescriptor(
35
this.docProto,
36
"domain"
37
);
38
this.documentURI = ctx.nativeMethods.getOwnPropertyDescriptor(
39
this.docProto,
40
"documentURI"
41
);
42
this.write = this.docProto.write;
43
this.writeln = this.docProto.writeln;
44
this.querySelector = this.docProto.querySelector;
45
this.querySelectorAll = this.docProto.querySelectorAll;
46
this.parseFromString = this.domProto.parseFromString;
47
this.URL = ctx.nativeMethods.getOwnPropertyDescriptor(this.docProto, "URL");
48
}
49
overrideParseFromString() {
50
this.ctx.override(
51
this.domProto,
52
"parseFromString",
53
(target, that, args) => {
54
if (2 > args.length) return target.apply(that, args);
55
let [string, type] = args;
56
57
const event = new HookEvent({ string, type }, target, that);
58
this.emit("parseFromString", event);
59
60
if (event.intercepted) return event.returnValue;
61
return event.target.call(
62
event.that,
63
event.data.string,
64
event.data.type
65
);
66
}
67
);
68
}
69
overrideQuerySelector() {
70
this.ctx.override(this.docProto, "querySelector", (target, that, args) => {
71
if (!args.length) return target.apply(that, args);
72
let [selectors] = args;
73
74
const event = new HookEvent({ selectors }, target, that);
75
this.emit("querySelector", event);
76
77
if (event.intercepted) return event.returnValue;
78
return event.target.call(event.that, event.data.selectors);
79
});
80
}
81
overrideDomain() {
82
this.ctx.overrideDescriptor(this.docProto, "domain", {
83
get: (target, that) => {
84
const event = new HookEvent({ value: target.call(that) }, target, that);
85
this.emit("getDomain", event);
86
87
if (event.intercepted) return event.returnValue;
88
return event.data.value;
89
},
90
set: (target, that, [val]) => {
91
const event = new HookEvent({ value: val }, target, that);
92
this.emit("setDomain", event);
93
94
if (event.intercepted) return event.returnValue;
95
return event.target.call(event.that, event.data.value);
96
},
97
});
98
}
99
overrideReferrer() {
100
this.ctx.overrideDescriptor(this.docProto, "referrer", {
101
get: (target, that) => {
102
const event = new HookEvent({ value: target.call(that) }, target, that);
103
this.emit("referrer", event);
104
105
if (event.intercepted) return event.returnValue;
106
return event.data.value;
107
},
108
});
109
}
110
overrideCreateTreeWalker() {
111
this.ctx.override(
112
this.docProto,
113
"createTreeWalker",
114
(target, that, args) => {
115
if (!args.length) return target.apply(that, args);
116
let [root, show = 0xffffffff, filter, expandEntityReferences] = args;
117
118
const event = new HookEvent(
119
{ root, show, filter, expandEntityReferences },
120
target,
121
that
122
);
123
this.emit("createTreeWalker", event);
124
125
if (event.intercepted) return event.returnValue;
126
return event.target.call(
127
event.that,
128
event.data.root,
129
event.data.show,
130
event.data.filter,
131
event.data.expandEntityReferences
132
);
133
}
134
);
135
}
136
overrideWrite() {
137
this.ctx.override(this.docProto, "write", (target, that, args) => {
138
if (!args.length) return target.apply(that, args);
139
let [...html] = args;
140
141
const event = new HookEvent({ html }, target, that);
142
this.emit("write", event);
143
144
if (event.intercepted) return event.returnValue;
145
return event.target.apply(event.that, event.data.html);
146
});
147
this.ctx.override(this.docProto, "writeln", (target, that, args) => {
148
if (!args.length) return target.apply(that, args);
149
let [...html] = args;
150
151
const event = new HookEvent({ html }, target, that);
152
this.emit("writeln", event);
153
154
if (event.intercepted) return event.returnValue;
155
return event.target.apply(event.that, event.data.html);
156
});
157
}
158
overrideDocumentURI() {
159
this.ctx.overrideDescriptor(this.docProto, "documentURI", {
160
get: (target, that) => {
161
const event = new HookEvent({ value: target.call(that) }, target, that);
162
this.emit("documentURI", event);
163
164
if (event.intercepted) return event.returnValue;
165
return event.data.value;
166
},
167
});
168
}
169
overrideURL() {
170
this.ctx.overrideDescriptor(this.docProto, "URL", {
171
get: (target, that) => {
172
const event = new HookEvent({ value: target.call(that) }, target, that);
173
this.emit("url", event);
174
175
if (event.intercepted) return event.returnValue;
176
return event.data.value;
177
},
178
});
179
}
180
overrideCookie() {
181
this.ctx.overrideDescriptor(this.docProto, "cookie", {
182
get: (target, that) => {
183
const event = new HookEvent({ value: target.call(that) }, target, that);
184
this.emit("getCookie", event);
185
186
if (event.intercepted) return event.returnValue;
187
return event.data.value;
188
},
189
set: (target, that, [value]) => {
190
const event = new HookEvent({ value }, target, that);
191
this.emit("setCookie", event);
192
193
if (event.intercepted) return event.returnValue;
194
return event.target.call(event.that, event.data.value);
195
},
196
});
197
}
198
overrideTitle() {
199
this.ctx.overrideDescriptor(this.docProto, "title", {
200
get: (target, that) => {
201
const event = new HookEvent({ value: target.call(that) }, target, that);
202
this.emit("getTitle", event);
203
204
if (event.intercepted) return event.returnValue;
205
return event.data.value;
206
},
207
set: (target, that, [value]) => {
208
const event = new HookEvent({ value }, target, that);
209
this.emit("setTitle", event);
210
211
if (event.intercepted) return event.returnValue;
212
return event.target.call(event.that, event.data.value);
213
},
214
});
215
}
216
}
217
218
export default DocumentHook;
219
220