@whitesev/utils 2.6.8 → 2.7.0
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/dist/index.amd.js +1173 -901
- package/dist/index.amd.js.map +1 -1
- package/dist/index.cjs.js +1173 -901
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1173 -901
- package/dist/index.esm.js.map +1 -1
- package/dist/index.iife.js +1173 -901
- package/dist/index.iife.js.map +1 -1
- package/dist/index.system.js +1173 -901
- package/dist/index.system.js.map +1 -1
- package/dist/index.umd.js +1173 -901
- package/dist/index.umd.js.map +1 -1
- package/dist/types/src/CommonUtil.d.ts +109 -0
- package/dist/types/src/DOMUtils.d.ts +95 -0
- package/dist/types/src/Utils.d.ts +14 -10
- package/dist/types/src/ajaxHooker/ajaxHooker.d.ts +1 -1
- package/package.json +11 -8
- package/src/CommonUtil.ts +302 -0
- package/src/DOMUtils.ts +287 -0
- package/src/Dictionary.ts +2 -2
- package/src/Hooks.ts +11 -12
- package/src/Httpx.ts +22 -16
- package/src/LockFunction.ts +4 -7
- package/src/Progress.ts +2 -2
- package/src/TryCatch.ts +6 -9
- package/src/Utils.ts +23 -216
- package/src/UtilsGMCookie.ts +7 -7
- package/src/UtilsGMMenu.ts +2 -2
- package/src/ajaxHooker/ajaxHooker.js +536 -554
|
@@ -1,187 +1,187 @@
|
|
|
1
|
+
// ==UserScript==
|
|
1
2
|
// @name ajaxHooker
|
|
2
3
|
// @author cxxjackie
|
|
3
|
-
// @version 1.4.
|
|
4
|
-
// @updateLog 修复头条、抖音部分站点下this引用错误的问题。
|
|
4
|
+
// @version 1.4.6
|
|
5
5
|
// @supportURL https://bbs.tampermonkey.net.cn/thread-3284-1-1.html
|
|
6
|
+
// @license GNU LGPL-3.0
|
|
7
|
+
// ==/UserScript==
|
|
6
8
|
|
|
7
|
-
export const
|
|
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
|
-
console.error(err);
|
|
54
|
-
}
|
|
9
|
+
export const ajaxHooker = function () {
|
|
10
|
+
"use strict";
|
|
11
|
+
const version = "1.4.6";
|
|
12
|
+
const hookInst = {
|
|
13
|
+
hookFns: [],
|
|
14
|
+
filters: [],
|
|
15
|
+
};
|
|
16
|
+
const win = window.unsafeWindow || document.defaultView || window;
|
|
17
|
+
let winAh = win.__ajaxHooker;
|
|
18
|
+
const resProto = win.Response.prototype;
|
|
19
|
+
const xhrResponses = ["response", "responseText", "responseXML"];
|
|
20
|
+
const fetchResponses = ["arrayBuffer", "blob", "formData", "json", "text"];
|
|
21
|
+
const fetchInitProps = [
|
|
22
|
+
"method",
|
|
23
|
+
"headers",
|
|
24
|
+
"body",
|
|
25
|
+
"mode",
|
|
26
|
+
"credentials",
|
|
27
|
+
"cache",
|
|
28
|
+
"redirect",
|
|
29
|
+
"referrer",
|
|
30
|
+
"referrerPolicy",
|
|
31
|
+
"integrity",
|
|
32
|
+
"keepalive",
|
|
33
|
+
"signal",
|
|
34
|
+
"priority",
|
|
35
|
+
];
|
|
36
|
+
const xhrAsyncEvents = ["readystatechange", "load", "loadend"];
|
|
37
|
+
const getType = {}.toString.call.bind({}.toString);
|
|
38
|
+
const getDescriptor = Object.getOwnPropertyDescriptor.bind(Object);
|
|
39
|
+
const emptyFn = () => {};
|
|
40
|
+
const errorFn = (e) => console.error(e);
|
|
41
|
+
function isThenable(obj) {
|
|
42
|
+
return (
|
|
43
|
+
obj &&
|
|
44
|
+
["object", "function"].includes(typeof obj) &&
|
|
45
|
+
typeof obj.then === "function"
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
function catchError(fn, ...args) {
|
|
49
|
+
try {
|
|
50
|
+
const result = fn(...args);
|
|
51
|
+
if (isThenable(result)) return result.then(null, errorFn);
|
|
52
|
+
return result;
|
|
53
|
+
} catch (err) {
|
|
54
|
+
console.error(err);
|
|
55
55
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
}
|
|
57
|
+
function defineProp(obj, prop, getter, setter) {
|
|
58
|
+
Object.defineProperty(obj, prop, {
|
|
59
|
+
configurable: true,
|
|
60
|
+
enumerable: true,
|
|
61
|
+
get: getter,
|
|
62
|
+
set: setter,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function readonly(obj, prop, value = obj[prop]) {
|
|
66
|
+
defineProp(obj, prop, () => value, emptyFn);
|
|
67
|
+
}
|
|
68
|
+
function writable(obj, prop, value = obj[prop]) {
|
|
69
|
+
Object.defineProperty(obj, prop, {
|
|
70
|
+
configurable: true,
|
|
71
|
+
enumerable: true,
|
|
72
|
+
writable: true,
|
|
73
|
+
value: value,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function parseHeaders(obj) {
|
|
77
|
+
const headers = {};
|
|
78
|
+
switch (getType(obj)) {
|
|
79
|
+
case "[object String]":
|
|
80
|
+
for (const line of obj.trim().split(/[\r\n]+/)) {
|
|
81
|
+
const [header, value] = line.split(/(?<=^[^:]+)\s*:\s*/);
|
|
82
|
+
if (!value) continue;
|
|
83
|
+
const lheader = header.toLowerCase();
|
|
84
|
+
headers[lheader] =
|
|
85
|
+
lheader in headers ? `${headers[lheader]}, ${value}` : value;
|
|
86
|
+
}
|
|
87
|
+
break;
|
|
88
|
+
case "[object Headers]":
|
|
89
|
+
for (const [key, val] of obj) {
|
|
90
|
+
headers[key] = val;
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
case "[object Object]":
|
|
94
|
+
return { ...obj };
|
|
63
95
|
}
|
|
64
|
-
|
|
65
|
-
|
|
96
|
+
return headers;
|
|
97
|
+
}
|
|
98
|
+
function stopImmediatePropagation() {
|
|
99
|
+
this.ajaxHooker_isStopped = true;
|
|
100
|
+
}
|
|
101
|
+
class SyncThenable {
|
|
102
|
+
then(fn) {
|
|
103
|
+
fn && fn();
|
|
104
|
+
return new SyncThenable();
|
|
66
105
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
value: value,
|
|
73
|
-
});
|
|
106
|
+
}
|
|
107
|
+
class AHRequest {
|
|
108
|
+
constructor(request) {
|
|
109
|
+
this.request = request;
|
|
110
|
+
this.requestClone = { ...this.request };
|
|
74
111
|
}
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
headers[key] = val;
|
|
112
|
+
shouldFilter(filters) {
|
|
113
|
+
const { type, url, method, async } = this.request;
|
|
114
|
+
return (
|
|
115
|
+
filters.length &&
|
|
116
|
+
!filters.find((obj) => {
|
|
117
|
+
switch (true) {
|
|
118
|
+
case obj.type && obj.type !== type:
|
|
119
|
+
case getType(obj.url) === "[object String]" &&
|
|
120
|
+
!url.includes(obj.url):
|
|
121
|
+
case getType(obj.url) === "[object RegExp]" && !obj.url.test(url):
|
|
122
|
+
case obj.method &&
|
|
123
|
+
obj.method.toUpperCase() !== method.toUpperCase():
|
|
124
|
+
case "async" in obj && obj.async !== async:
|
|
125
|
+
return false;
|
|
90
126
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
return headers;
|
|
96
|
-
}
|
|
97
|
-
function stopImmediatePropagation() {
|
|
98
|
-
this.ajaxHooker_isStopped = true;
|
|
127
|
+
return true;
|
|
128
|
+
})
|
|
129
|
+
);
|
|
99
130
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
131
|
+
waitForRequestKeys() {
|
|
132
|
+
const requestKeys = ["url", "method", "abort", "headers", "data"];
|
|
133
|
+
if (!this.request.async) {
|
|
134
|
+
win.__ajaxHooker.hookInsts.forEach(({ hookFns, filters }) => {
|
|
135
|
+
if (this.shouldFilter(filters)) return;
|
|
136
|
+
hookFns.forEach((fn) => {
|
|
137
|
+
if (getType(fn) === "[object Function]")
|
|
138
|
+
catchError(fn, this.request);
|
|
139
|
+
});
|
|
140
|
+
requestKeys.forEach((key) => {
|
|
141
|
+
if (isThenable(this.request[key]))
|
|
142
|
+
this.request[key] = this.requestClone[key];
|
|
143
|
+
});
|
|
144
|
+
});
|
|
103
145
|
return new SyncThenable();
|
|
104
146
|
}
|
|
147
|
+
const promises = [];
|
|
148
|
+
win.__ajaxHooker.hookInsts.forEach(({ hookFns, filters }) => {
|
|
149
|
+
if (this.shouldFilter(filters)) return;
|
|
150
|
+
promises.push(
|
|
151
|
+
Promise.all(hookFns.map((fn) => catchError(fn, this.request))).then(
|
|
152
|
+
() =>
|
|
153
|
+
Promise.all(
|
|
154
|
+
requestKeys.map((key) =>
|
|
155
|
+
Promise.resolve(this.request[key]).then(
|
|
156
|
+
(val) => (this.request[key] = val),
|
|
157
|
+
() => (this.request[key] = this.requestClone[key])
|
|
158
|
+
)
|
|
159
|
+
)
|
|
160
|
+
)
|
|
161
|
+
)
|
|
162
|
+
);
|
|
163
|
+
});
|
|
164
|
+
return Promise.all(promises);
|
|
105
165
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
this.request
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
case getType(obj.url) === "[object String]" &&
|
|
119
|
-
!url.includes(obj.url):
|
|
120
|
-
case getType(obj.url) === "[object RegExp]" && !obj.url.test(url):
|
|
121
|
-
case obj.method &&
|
|
122
|
-
obj.method.toUpperCase() !== method.toUpperCase():
|
|
123
|
-
case "async" in obj && obj.async !== async:
|
|
124
|
-
return false;
|
|
166
|
+
waitForResponseKeys(response) {
|
|
167
|
+
const responseKeys =
|
|
168
|
+
this.request.type === "xhr" ? xhrResponses : fetchResponses;
|
|
169
|
+
if (!this.request.async) {
|
|
170
|
+
if (getType(this.request.response) === "[object Function]") {
|
|
171
|
+
catchError(this.request.response, response);
|
|
172
|
+
responseKeys.forEach((key) => {
|
|
173
|
+
if (
|
|
174
|
+
"get" in getDescriptor(response, key) ||
|
|
175
|
+
isThenable(response[key])
|
|
176
|
+
) {
|
|
177
|
+
delete response[key];
|
|
125
178
|
}
|
|
126
|
-
return true;
|
|
127
|
-
})
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
waitForRequestKeys() {
|
|
131
|
-
const requestKeys = ["url", "method", "abort", "headers", "data"];
|
|
132
|
-
if (!this.request.async) {
|
|
133
|
-
win.__ajaxHooker.hookInsts.forEach(({ hookFns, filters }) => {
|
|
134
|
-
if (this.shouldFilter(filters)) return;
|
|
135
|
-
hookFns.forEach((fn) => {
|
|
136
|
-
if (getType(fn) === "[object Function]")
|
|
137
|
-
catchError(fn, this.request);
|
|
138
|
-
});
|
|
139
|
-
requestKeys.forEach((key) => {
|
|
140
|
-
if (isThenable(this.request[key]))
|
|
141
|
-
this.request[key] = this.requestClone[key];
|
|
142
|
-
});
|
|
143
179
|
});
|
|
144
|
-
return new SyncThenable();
|
|
145
180
|
}
|
|
146
|
-
|
|
147
|
-
win.__ajaxHooker.hookInsts.forEach(({ hookFns, filters }) => {
|
|
148
|
-
if (this.shouldFilter(filters)) return;
|
|
149
|
-
promises.push(
|
|
150
|
-
Promise.all(hookFns.map((fn) => catchError(fn, this.request))).then(
|
|
151
|
-
() =>
|
|
152
|
-
Promise.all(
|
|
153
|
-
requestKeys.map((key) =>
|
|
154
|
-
Promise.resolve(this.request[key]).then(
|
|
155
|
-
(val) => (this.request[key] = val),
|
|
156
|
-
() => (this.request[key] = this.requestClone[key])
|
|
157
|
-
)
|
|
158
|
-
)
|
|
159
|
-
)
|
|
160
|
-
)
|
|
161
|
-
);
|
|
162
|
-
});
|
|
163
|
-
return Promise.all(promises);
|
|
181
|
+
return new SyncThenable();
|
|
164
182
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
this.request.type === "xhr" ? xhrResponses : fetchResponses;
|
|
168
|
-
if (!this.request.async) {
|
|
169
|
-
if (getType(this.request.response) === "[object Function]") {
|
|
170
|
-
catchError(this.request.response, response);
|
|
171
|
-
responseKeys.forEach((key) => {
|
|
172
|
-
if (
|
|
173
|
-
"get" in getDescriptor(response, key) ||
|
|
174
|
-
isThenable(response[key])
|
|
175
|
-
) {
|
|
176
|
-
delete response[key];
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
return new SyncThenable();
|
|
181
|
-
}
|
|
182
|
-
return Promise.resolve(
|
|
183
|
-
catchError(this.request.response, response)
|
|
184
|
-
).then(() =>
|
|
183
|
+
return Promise.resolve(catchError(this.request.response, response)).then(
|
|
184
|
+
() =>
|
|
185
185
|
Promise.all(
|
|
186
186
|
responseKeys.map((key) => {
|
|
187
187
|
const descriptor = getDescriptor(response, key);
|
|
@@ -195,422 +195,404 @@ export const AjaxHooker = function () {
|
|
|
195
195
|
}
|
|
196
196
|
})
|
|
197
197
|
)
|
|
198
|
-
|
|
199
|
-
}
|
|
198
|
+
);
|
|
200
199
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const ah = target.__ajaxHooker;
|
|
212
|
-
if (ah && ah.proxyProps) {
|
|
213
|
-
if (prop in ah.proxyProps) {
|
|
214
|
-
const pDescriptor = ah.proxyProps[prop];
|
|
215
|
-
if ("get" in pDescriptor) return pDescriptor.get();
|
|
216
|
-
if (typeof pDescriptor.value === "function")
|
|
217
|
-
return pDescriptor.value.bind(ah);
|
|
218
|
-
return pDescriptor.value;
|
|
219
|
-
}
|
|
220
|
-
if (typeof target[prop] === "function")
|
|
221
|
-
return target[prop].bind(target);
|
|
222
|
-
}
|
|
200
|
+
}
|
|
201
|
+
const proxyHandler = {
|
|
202
|
+
get(target, prop) {
|
|
203
|
+
const descriptor = getDescriptor(target, prop);
|
|
204
|
+
if (
|
|
205
|
+
descriptor &&
|
|
206
|
+
!descriptor.configurable &&
|
|
207
|
+
!descriptor.writable &&
|
|
208
|
+
!descriptor.get
|
|
209
|
+
)
|
|
223
210
|
return target[prop];
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
if (
|
|
228
|
-
descriptor &&
|
|
229
|
-
!descriptor.configurable &&
|
|
230
|
-
!descriptor.writable &&
|
|
231
|
-
!descriptor.set
|
|
232
|
-
)
|
|
233
|
-
return true;
|
|
234
|
-
const ah = target.__ajaxHooker;
|
|
235
|
-
if (ah && ah.proxyProps && prop in ah.proxyProps) {
|
|
211
|
+
const ah = target.__ajaxHooker;
|
|
212
|
+
if (ah && ah.proxyProps) {
|
|
213
|
+
if (prop in ah.proxyProps) {
|
|
236
214
|
const pDescriptor = ah.proxyProps[prop];
|
|
237
|
-
pDescriptor.
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
target[prop] = value;
|
|
242
|
-
}
|
|
243
|
-
return true;
|
|
244
|
-
},
|
|
245
|
-
};
|
|
246
|
-
class XhrHooker {
|
|
247
|
-
constructor(xhr) {
|
|
248
|
-
const ah = this;
|
|
249
|
-
Object.assign(ah, {
|
|
250
|
-
originalXhr: xhr,
|
|
251
|
-
proxyXhr: new Proxy(xhr, proxyHandler),
|
|
252
|
-
resThenable: new SyncThenable(),
|
|
253
|
-
proxyProps: {},
|
|
254
|
-
proxyEvents: {},
|
|
255
|
-
});
|
|
256
|
-
xhr.addEventListener("readystatechange", (e) => {
|
|
257
|
-
if (
|
|
258
|
-
ah.proxyXhr.readyState === 4 &&
|
|
259
|
-
ah.request &&
|
|
260
|
-
typeof ah.request.response === "function"
|
|
261
|
-
) {
|
|
262
|
-
const response = {
|
|
263
|
-
finalUrl: ah.proxyXhr.responseURL,
|
|
264
|
-
status: ah.proxyXhr.status,
|
|
265
|
-
responseHeaders: parseHeaders(
|
|
266
|
-
ah.proxyXhr.getAllResponseHeaders()
|
|
267
|
-
),
|
|
268
|
-
};
|
|
269
|
-
const tempValues = {};
|
|
270
|
-
for (const key of xhrResponses) {
|
|
271
|
-
try {
|
|
272
|
-
tempValues[key] = ah.originalXhr[key];
|
|
273
|
-
} catch (err) {}
|
|
274
|
-
defineProp(
|
|
275
|
-
response,
|
|
276
|
-
key,
|
|
277
|
-
() => {
|
|
278
|
-
return (response[key] = tempValues[key]);
|
|
279
|
-
},
|
|
280
|
-
(val) => {
|
|
281
|
-
delete response[key];
|
|
282
|
-
response[key] = val;
|
|
283
|
-
}
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
ah.resThenable = new AHRequest(ah.request)
|
|
287
|
-
.waitForResponseKeys(response)
|
|
288
|
-
.then(() => {
|
|
289
|
-
for (const key of xhrResponses) {
|
|
290
|
-
ah.proxyProps[key] = {
|
|
291
|
-
get: () => {
|
|
292
|
-
if (!(key in response)) response[key] = tempValues[key];
|
|
293
|
-
return response[key];
|
|
294
|
-
},
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
ah.dispatchEvent(e);
|
|
300
|
-
});
|
|
301
|
-
xhr.addEventListener("load", (e) => ah.dispatchEvent(e));
|
|
302
|
-
xhr.addEventListener("loadend", (e) => ah.dispatchEvent(e));
|
|
303
|
-
for (const evt of xhrAsyncEvents) {
|
|
304
|
-
const onEvt = "on" + evt;
|
|
305
|
-
ah.proxyProps[onEvt] = {
|
|
306
|
-
get: () => ah.proxyEvents[onEvt] || null,
|
|
307
|
-
set: (val) => ah.addEvent(onEvt, val),
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
for (const method of [
|
|
311
|
-
"setRequestHeader",
|
|
312
|
-
"addEventListener",
|
|
313
|
-
"removeEventListener",
|
|
314
|
-
"open",
|
|
315
|
-
"send",
|
|
316
|
-
]) {
|
|
317
|
-
ah.proxyProps[method] = { value: ah[method] };
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
toJSON() {} // Converting circular structure to JSON
|
|
321
|
-
addEvent(type, event) {
|
|
322
|
-
if (type.startsWith("on")) {
|
|
323
|
-
this.proxyEvents[type] = typeof event === "function" ? event : null;
|
|
324
|
-
} else {
|
|
325
|
-
if (typeof event === "object" && event !== null)
|
|
326
|
-
event = event.handleEvent;
|
|
327
|
-
if (typeof event !== "function") return;
|
|
328
|
-
this.proxyEvents[type] = this.proxyEvents[type] || new Set();
|
|
329
|
-
this.proxyEvents[type].add(event);
|
|
215
|
+
if ("get" in pDescriptor) return pDescriptor.get();
|
|
216
|
+
if (typeof pDescriptor.value === "function")
|
|
217
|
+
return pDescriptor.value.bind(ah);
|
|
218
|
+
return pDescriptor.value;
|
|
330
219
|
}
|
|
220
|
+
if (typeof target[prop] === "function")
|
|
221
|
+
return target[prop].bind(target);
|
|
331
222
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
223
|
+
return target[prop];
|
|
224
|
+
},
|
|
225
|
+
set(target, prop, value) {
|
|
226
|
+
const descriptor = getDescriptor(target, prop);
|
|
227
|
+
if (
|
|
228
|
+
descriptor &&
|
|
229
|
+
!descriptor.configurable &&
|
|
230
|
+
!descriptor.writable &&
|
|
231
|
+
!descriptor.set
|
|
232
|
+
)
|
|
233
|
+
return true;
|
|
234
|
+
const ah = target.__ajaxHooker;
|
|
235
|
+
if (ah && ah.proxyProps && prop in ah.proxyProps) {
|
|
236
|
+
const pDescriptor = ah.proxyProps[prop];
|
|
237
|
+
pDescriptor.set ? pDescriptor.set(value) : (pDescriptor.value = value);
|
|
238
|
+
} else {
|
|
239
|
+
target[prop] = value;
|
|
340
240
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
241
|
+
return true;
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
class XhrHooker {
|
|
245
|
+
constructor(xhr) {
|
|
246
|
+
const ah = this;
|
|
247
|
+
Object.assign(ah, {
|
|
248
|
+
originalXhr: xhr,
|
|
249
|
+
proxyXhr: new Proxy(xhr, proxyHandler),
|
|
250
|
+
resThenable: new SyncThenable(),
|
|
251
|
+
proxyProps: {},
|
|
252
|
+
proxyEvents: {},
|
|
253
|
+
});
|
|
254
|
+
xhr.addEventListener("readystatechange", (e) => {
|
|
255
|
+
if (
|
|
256
|
+
ah.proxyXhr.readyState === 4 &&
|
|
257
|
+
ah.request &&
|
|
258
|
+
typeof ah.request.response === "function"
|
|
259
|
+
) {
|
|
260
|
+
const response = {
|
|
261
|
+
finalUrl: ah.proxyXhr.responseURL,
|
|
262
|
+
status: ah.proxyXhr.status,
|
|
263
|
+
responseHeaders: parseHeaders(ah.proxyXhr.getAllResponseHeaders()),
|
|
264
|
+
};
|
|
265
|
+
const tempValues = {};
|
|
266
|
+
for (const key of xhrResponses) {
|
|
267
|
+
try {
|
|
268
|
+
tempValues[key] = ah.originalXhr[key];
|
|
269
|
+
} catch (err) {}
|
|
270
|
+
defineProp(
|
|
271
|
+
response,
|
|
272
|
+
key,
|
|
273
|
+
() => {
|
|
274
|
+
return (response[key] = tempValues[key]);
|
|
275
|
+
},
|
|
276
|
+
(val) => {
|
|
277
|
+
delete response[key];
|
|
278
|
+
response[key] = val;
|
|
279
|
+
}
|
|
349
280
|
);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
281
|
+
}
|
|
282
|
+
ah.resThenable = new AHRequest(ah.request)
|
|
283
|
+
.waitForResponseKeys(response)
|
|
284
|
+
.then(() => {
|
|
285
|
+
for (const key of xhrResponses) {
|
|
286
|
+
ah.proxyProps[key] = {
|
|
287
|
+
get: () => {
|
|
288
|
+
if (!(key in response)) response[key] = tempValues[key];
|
|
289
|
+
return response[key];
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
ah.dispatchEvent(e);
|
|
296
|
+
});
|
|
297
|
+
xhr.addEventListener("load", (e) => ah.dispatchEvent(e));
|
|
298
|
+
xhr.addEventListener("loadend", (e) => ah.dispatchEvent(e));
|
|
299
|
+
for (const evt of xhrAsyncEvents) {
|
|
300
|
+
const onEvt = "on" + evt;
|
|
301
|
+
ah.proxyProps[onEvt] = {
|
|
302
|
+
get: () => ah.proxyEvents[onEvt] || null,
|
|
303
|
+
set: (val) => ah.addEvent(onEvt, val),
|
|
304
|
+
};
|
|
354
305
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
306
|
+
for (const method of [
|
|
307
|
+
"setRequestHeader",
|
|
308
|
+
"addEventListener",
|
|
309
|
+
"removeEventListener",
|
|
310
|
+
"open",
|
|
311
|
+
"send",
|
|
312
|
+
]) {
|
|
313
|
+
ah.proxyProps[method] = { value: ah[method] };
|
|
361
314
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
315
|
+
}
|
|
316
|
+
toJSON() {} // Converting circular structure to JSON
|
|
317
|
+
addEvent(type, event) {
|
|
318
|
+
if (type.startsWith("on")) {
|
|
319
|
+
this.proxyEvents[type] = typeof event === "function" ? event : null;
|
|
320
|
+
} else {
|
|
321
|
+
if (typeof event === "object" && event !== null)
|
|
322
|
+
event = event.handleEvent;
|
|
323
|
+
if (typeof event !== "function") return;
|
|
324
|
+
this.proxyEvents[type] = this.proxyEvents[type] || new Set();
|
|
325
|
+
this.proxyEvents[type].add(event);
|
|
368
326
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
327
|
+
}
|
|
328
|
+
removeEvent(type, event) {
|
|
329
|
+
if (type.startsWith("on")) {
|
|
330
|
+
this.proxyEvents[type] = null;
|
|
331
|
+
} else {
|
|
332
|
+
if (typeof event === "object" && event !== null)
|
|
333
|
+
event = event.handleEvent;
|
|
334
|
+
this.proxyEvents[type] && this.proxyEvents[type].delete(event);
|
|
375
335
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
};
|
|
387
|
-
this.openArgs = args;
|
|
388
|
-
this.resThenable = new SyncThenable();
|
|
389
|
-
[
|
|
390
|
-
"responseURL",
|
|
391
|
-
"readyState",
|
|
392
|
-
"status",
|
|
393
|
-
"statusText",
|
|
394
|
-
...xhrResponses,
|
|
395
|
-
].forEach((key) => {
|
|
396
|
-
delete this.proxyProps[key];
|
|
336
|
+
}
|
|
337
|
+
dispatchEvent(e) {
|
|
338
|
+
e.stopImmediatePropagation = stopImmediatePropagation;
|
|
339
|
+
defineProp(e, "target", () => this.proxyXhr);
|
|
340
|
+
defineProp(e, "currentTarget", () => this.proxyXhr);
|
|
341
|
+
this.proxyEvents[e.type] &&
|
|
342
|
+
this.proxyEvents[e.type].forEach((fn) => {
|
|
343
|
+
this.resThenable.then(
|
|
344
|
+
() => !e.ajaxHooker_isStopped && fn.call(this.proxyXhr, e)
|
|
345
|
+
);
|
|
397
346
|
});
|
|
398
|
-
|
|
347
|
+
if (e.ajaxHooker_isStopped) return;
|
|
348
|
+
const onEvent = this.proxyEvents["on" + e.type];
|
|
349
|
+
onEvent && this.resThenable.then(onEvent.bind(this.proxyXhr, e));
|
|
350
|
+
}
|
|
351
|
+
setRequestHeader(header, value) {
|
|
352
|
+
this.originalXhr.setRequestHeader(header, value);
|
|
353
|
+
if (!this.request) return;
|
|
354
|
+
const headers = this.request.headers;
|
|
355
|
+
headers[header] =
|
|
356
|
+
header in headers ? `${headers[header]}, ${value}` : value;
|
|
357
|
+
}
|
|
358
|
+
addEventListener(...args) {
|
|
359
|
+
if (xhrAsyncEvents.includes(args[0])) {
|
|
360
|
+
this.addEvent(args[0], args[1]);
|
|
361
|
+
} else {
|
|
362
|
+
this.originalXhr.addEventListener(...args);
|
|
399
363
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
new AHRequest(request).waitForRequestKeys().then(() => {
|
|
407
|
-
if (request.abort) {
|
|
408
|
-
if (typeof request.response === "function") {
|
|
409
|
-
Object.assign(ah.proxyProps, {
|
|
410
|
-
responseURL: { value: request.url },
|
|
411
|
-
readyState: { value: 4 },
|
|
412
|
-
status: { value: 200 },
|
|
413
|
-
statusText: { value: "OK" },
|
|
414
|
-
});
|
|
415
|
-
xhrAsyncEvents.forEach((evt) =>
|
|
416
|
-
xhr.dispatchEvent(new Event(evt))
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
} else {
|
|
420
|
-
xhr.open(
|
|
421
|
-
request.method,
|
|
422
|
-
request.url,
|
|
423
|
-
request.async,
|
|
424
|
-
...ah.openArgs
|
|
425
|
-
);
|
|
426
|
-
for (const header in request.headers) {
|
|
427
|
-
xhr.setRequestHeader(header, request.headers[header]);
|
|
428
|
-
}
|
|
429
|
-
xhr.send(request.data);
|
|
430
|
-
}
|
|
431
|
-
});
|
|
364
|
+
}
|
|
365
|
+
removeEventListener(...args) {
|
|
366
|
+
if (xhrAsyncEvents.includes(args[0])) {
|
|
367
|
+
this.removeEvent(args[0], args[1]);
|
|
368
|
+
} else {
|
|
369
|
+
this.originalXhr.removeEventListener(...args);
|
|
432
370
|
}
|
|
433
371
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
372
|
+
open(method, url, async = true, ...args) {
|
|
373
|
+
this.request = {
|
|
374
|
+
type: "xhr",
|
|
375
|
+
url: url.toString(),
|
|
376
|
+
method: method.toUpperCase(),
|
|
377
|
+
abort: false,
|
|
378
|
+
headers: {},
|
|
379
|
+
data: null,
|
|
380
|
+
response: null,
|
|
381
|
+
async: !!async,
|
|
382
|
+
};
|
|
383
|
+
this.openArgs = args;
|
|
384
|
+
this.resThenable = new SyncThenable();
|
|
385
|
+
[
|
|
386
|
+
"responseURL",
|
|
387
|
+
"readyState",
|
|
388
|
+
"status",
|
|
389
|
+
"statusText",
|
|
390
|
+
...xhrResponses,
|
|
391
|
+
].forEach((key) => {
|
|
392
|
+
delete this.proxyProps[key];
|
|
393
|
+
});
|
|
394
|
+
return this.originalXhr.open(method, url, async, ...args);
|
|
440
395
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
const init = {};
|
|
449
|
-
if (getType(url) === "[object Request]") {
|
|
450
|
-
for (const prop of fetchInitProps) init[prop] = url[prop];
|
|
451
|
-
if (url.body) init.body = await url.arrayBuffer();
|
|
452
|
-
url = url.url;
|
|
453
|
-
}
|
|
454
|
-
url = url.toString();
|
|
455
|
-
Object.assign(init, options);
|
|
456
|
-
init.method = init.method || "GET";
|
|
457
|
-
init.headers = init.headers || {};
|
|
458
|
-
const request = {
|
|
459
|
-
type: "fetch",
|
|
460
|
-
url: url,
|
|
461
|
-
method: init.method.toUpperCase(),
|
|
462
|
-
abort: false,
|
|
463
|
-
headers: parseHeaders(init.headers),
|
|
464
|
-
data: init.body,
|
|
465
|
-
response: null,
|
|
466
|
-
async: true,
|
|
467
|
-
};
|
|
468
|
-
const req = new AHRequest(request);
|
|
469
|
-
await req.waitForRequestKeys();
|
|
396
|
+
send(data) {
|
|
397
|
+
const ah = this;
|
|
398
|
+
const xhr = ah.originalXhr;
|
|
399
|
+
const request = ah.request;
|
|
400
|
+
if (!request) return xhr.send(data);
|
|
401
|
+
request.data = data;
|
|
402
|
+
new AHRequest(request).waitForRequestKeys().then(() => {
|
|
470
403
|
if (request.abort) {
|
|
471
404
|
if (typeof request.response === "function") {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
await req.waitForResponseKeys(response);
|
|
478
|
-
const key = fetchResponses.find((k) => k in response);
|
|
479
|
-
let val = response[key];
|
|
480
|
-
if (key === "json" && typeof val === "object") {
|
|
481
|
-
val = catchError(JSON.stringify.bind(JSON), val);
|
|
482
|
-
}
|
|
483
|
-
const res = new Response(val, {
|
|
484
|
-
status: 200,
|
|
485
|
-
statusText: "OK",
|
|
405
|
+
Object.assign(ah.proxyProps, {
|
|
406
|
+
responseURL: { value: request.url },
|
|
407
|
+
readyState: { value: 4 },
|
|
408
|
+
status: { value: 200 },
|
|
409
|
+
statusText: { value: "OK" },
|
|
486
410
|
});
|
|
487
|
-
|
|
488
|
-
defineProp(res, "url", () => request.url);
|
|
489
|
-
resolve(res);
|
|
490
|
-
} else {
|
|
491
|
-
reject(new DOMException("aborted", "AbortError"));
|
|
411
|
+
xhrAsyncEvents.forEach((evt) => xhr.dispatchEvent(new Event(evt)));
|
|
492
412
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
init.body = request.data;
|
|
498
|
-
winAh.realFetch.call(win, request.url, init).then((res) => {
|
|
499
|
-
if (typeof request.response === "function") {
|
|
500
|
-
const response = {
|
|
501
|
-
finalUrl: res.url,
|
|
502
|
-
status: res.status,
|
|
503
|
-
responseHeaders: parseHeaders(res.headers),
|
|
504
|
-
};
|
|
505
|
-
fetchResponses.forEach(
|
|
506
|
-
(key) =>
|
|
507
|
-
(res[key] = function () {
|
|
508
|
-
if (key in response) return Promise.resolve(response[key]);
|
|
509
|
-
return resProto[key].call(this).then((val) => {
|
|
510
|
-
response[key] = val;
|
|
511
|
-
return req
|
|
512
|
-
.waitForResponseKeys(response)
|
|
513
|
-
.then(() => (key in response ? response[key] : val));
|
|
514
|
-
});
|
|
515
|
-
})
|
|
516
|
-
);
|
|
413
|
+
} else {
|
|
414
|
+
xhr.open(request.method, request.url, request.async, ...ah.openArgs);
|
|
415
|
+
for (const header in request.headers) {
|
|
416
|
+
xhr.setRequestHeader(header, request.headers[header]);
|
|
517
417
|
}
|
|
518
|
-
|
|
519
|
-
}
|
|
418
|
+
xhr.send(request.data);
|
|
419
|
+
}
|
|
520
420
|
});
|
|
521
421
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
return res;
|
|
527
|
-
}
|
|
528
|
-
winAh = win.__ajaxHooker = winAh || {
|
|
529
|
-
version,
|
|
530
|
-
fakeXHR,
|
|
531
|
-
fakeFetch,
|
|
532
|
-
fakeFetchClone,
|
|
533
|
-
realXHR: win.XMLHttpRequest,
|
|
534
|
-
realFetch: win.fetch,
|
|
535
|
-
realFetchClone: resProto.clone,
|
|
536
|
-
hookInsts: new Set(),
|
|
537
|
-
};
|
|
538
|
-
if (winAh.version !== version)
|
|
422
|
+
}
|
|
423
|
+
function fakeXHR() {
|
|
424
|
+
const xhr = new winAh.realXHR();
|
|
425
|
+
if ("__ajaxHooker" in xhr)
|
|
539
426
|
console.warn("检测到不同版本的ajaxHooker,可能发生冲突!");
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
427
|
+
xhr.__ajaxHooker = new XhrHooker(xhr);
|
|
428
|
+
return xhr.__ajaxHooker.proxyXhr;
|
|
429
|
+
}
|
|
430
|
+
fakeXHR.prototype = win.XMLHttpRequest.prototype;
|
|
431
|
+
Object.keys(win.XMLHttpRequest).forEach(
|
|
432
|
+
(key) => (fakeXHR[key] = win.XMLHttpRequest[key])
|
|
433
|
+
);
|
|
434
|
+
function fakeFetch(url, options = {}) {
|
|
435
|
+
if (!url) return winAh.realFetch.call(win, url, options);
|
|
436
|
+
return new Promise(async (resolve, reject) => {
|
|
437
|
+
const init = {};
|
|
438
|
+
if (getType(url) === "[object Request]") {
|
|
439
|
+
for (const prop of fetchInitProps) init[prop] = url[prop];
|
|
440
|
+
if (url.body) init.body = await url.arrayBuffer();
|
|
441
|
+
url = url.url;
|
|
442
|
+
}
|
|
443
|
+
url = url.toString();
|
|
444
|
+
Object.assign(init, options);
|
|
445
|
+
init.method = init.method || "GET";
|
|
446
|
+
init.headers = init.headers || {};
|
|
447
|
+
const request = {
|
|
448
|
+
type: "fetch",
|
|
449
|
+
url: url,
|
|
450
|
+
method: init.method.toUpperCase(),
|
|
451
|
+
abort: false,
|
|
452
|
+
headers: parseHeaders(init.headers),
|
|
453
|
+
data: init.body,
|
|
454
|
+
response: null,
|
|
455
|
+
async: true,
|
|
456
|
+
};
|
|
457
|
+
const req = new AHRequest(request);
|
|
458
|
+
await req.waitForRequestKeys();
|
|
459
|
+
if (request.abort) {
|
|
460
|
+
if (typeof request.response === "function") {
|
|
461
|
+
const response = {
|
|
462
|
+
finalUrl: request.url,
|
|
463
|
+
status: 200,
|
|
464
|
+
responseHeaders: {},
|
|
465
|
+
};
|
|
466
|
+
await req.waitForResponseKeys(response);
|
|
467
|
+
const key = fetchResponses.find((k) => k in response);
|
|
468
|
+
let val = response[key];
|
|
469
|
+
if (key === "json" && typeof val === "object") {
|
|
470
|
+
val = catchError(JSON.stringify.bind(JSON), val);
|
|
471
|
+
}
|
|
472
|
+
const res = new Response(val, {
|
|
473
|
+
status: 200,
|
|
474
|
+
statusText: "OK",
|
|
475
|
+
});
|
|
476
|
+
defineProp(res, "type", () => "basic");
|
|
477
|
+
defineProp(res, "url", () => request.url);
|
|
478
|
+
resolve(res);
|
|
479
|
+
} else {
|
|
480
|
+
reject(new DOMException("aborted", "AbortError"));
|
|
553
481
|
}
|
|
554
|
-
return
|
|
482
|
+
return;
|
|
555
483
|
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
484
|
+
init.method = request.method;
|
|
485
|
+
init.headers = request.headers;
|
|
486
|
+
init.body = request.data;
|
|
487
|
+
winAh.realFetch.call(win, request.url, init).then((res) => {
|
|
488
|
+
if (typeof request.response === "function") {
|
|
489
|
+
const response = {
|
|
490
|
+
finalUrl: res.url,
|
|
491
|
+
status: res.status,
|
|
492
|
+
responseHeaders: parseHeaders(res.headers),
|
|
493
|
+
};
|
|
494
|
+
fetchResponses.forEach(
|
|
495
|
+
(key) =>
|
|
496
|
+
(res[key] = function () {
|
|
497
|
+
if (key in response) return Promise.resolve(response[key]);
|
|
498
|
+
return resProto[key].call(this).then((val) => {
|
|
499
|
+
response[key] = val;
|
|
500
|
+
return req
|
|
501
|
+
.waitForResponseKeys(response)
|
|
502
|
+
.then(() => (key in response ? response[key] : val));
|
|
503
|
+
});
|
|
504
|
+
})
|
|
505
|
+
);
|
|
563
506
|
}
|
|
564
|
-
|
|
507
|
+
resolve(res);
|
|
508
|
+
}, reject);
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
function fakeFetchClone() {
|
|
512
|
+
const descriptors = Object.getOwnPropertyDescriptors(this);
|
|
513
|
+
const res = winAh.realFetchClone.call(this);
|
|
514
|
+
Object.defineProperties(res, descriptors);
|
|
515
|
+
return res;
|
|
516
|
+
}
|
|
517
|
+
winAh = win.__ajaxHooker = winAh || {
|
|
518
|
+
version,
|
|
519
|
+
fakeXHR,
|
|
520
|
+
fakeFetch,
|
|
521
|
+
fakeFetchClone,
|
|
522
|
+
realXHR: win.XMLHttpRequest,
|
|
523
|
+
realFetch: win.fetch,
|
|
524
|
+
realFetchClone: resProto.clone,
|
|
525
|
+
hookInsts: new Set(),
|
|
526
|
+
};
|
|
527
|
+
if (winAh.version !== version)
|
|
528
|
+
console.warn("检测到不同版本的ajaxHooker,可能发生冲突!");
|
|
529
|
+
win.XMLHttpRequest = winAh.fakeXHR;
|
|
530
|
+
win.fetch = winAh.fakeFetch;
|
|
531
|
+
resProto.clone = winAh.fakeFetchClone;
|
|
532
|
+
winAh.hookInsts.add(hookInst);
|
|
533
|
+
// 针对头条、抖音 secsdk.umd.js 的兼容性处理
|
|
534
|
+
class AHFunction extends Function {
|
|
535
|
+
call(thisArg, ...args) {
|
|
536
|
+
if (
|
|
537
|
+
thisArg &&
|
|
538
|
+
thisArg.__ajaxHooker &&
|
|
539
|
+
thisArg.__ajaxHooker.proxyXhr === thisArg
|
|
540
|
+
) {
|
|
541
|
+
thisArg = thisArg.__ajaxHooker.originalXhr;
|
|
565
542
|
}
|
|
543
|
+
return Reflect.apply(this, thisArg, args);
|
|
566
544
|
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
);
|
|
576
|
-
Object.setPrototypeOf(
|
|
577
|
-
csrf.nativeXMLHttpRequestSend,
|
|
578
|
-
AHFunction.prototype
|
|
579
|
-
);
|
|
545
|
+
apply(thisArg, args) {
|
|
546
|
+
if (
|
|
547
|
+
thisArg &&
|
|
548
|
+
thisArg.__ajaxHooker &&
|
|
549
|
+
thisArg.__ajaxHooker.proxyXhr === thisArg
|
|
550
|
+
) {
|
|
551
|
+
thisArg = thisArg.__ajaxHooker.originalXhr;
|
|
552
|
+
}
|
|
553
|
+
return Reflect.apply(this, thisArg, args || []);
|
|
580
554
|
}
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
555
|
+
}
|
|
556
|
+
function hookSecsdk(csrf) {
|
|
557
|
+
Object.setPrototypeOf(
|
|
558
|
+
csrf.nativeXMLHttpRequestSetRequestHeader,
|
|
559
|
+
AHFunction.prototype
|
|
560
|
+
);
|
|
561
|
+
Object.setPrototypeOf(csrf.nativeXMLHttpRequestOpen, AHFunction.prototype);
|
|
562
|
+
Object.setPrototypeOf(csrf.nativeXMLHttpRequestSend, AHFunction.prototype);
|
|
563
|
+
}
|
|
564
|
+
if (win.secsdk) {
|
|
565
|
+
if (win.secsdk.csrf && win.secsdk.csrf.nativeXMLHttpRequestOpen)
|
|
566
|
+
hookSecsdk(win.secsdk.csrf);
|
|
567
|
+
} else {
|
|
568
|
+
defineProp(win, "secsdk", emptyFn, (secsdk) => {
|
|
569
|
+
delete win.secsdk;
|
|
570
|
+
win.secsdk = secsdk;
|
|
571
|
+
defineProp(secsdk, "csrf", emptyFn, (csrf) => {
|
|
572
|
+
delete secsdk.csrf;
|
|
573
|
+
secsdk.csrf = csrf;
|
|
574
|
+
if (csrf.nativeXMLHttpRequestOpen) hookSecsdk(csrf);
|
|
593
575
|
});
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
}
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
return {
|
|
579
|
+
hook: (fn) => hookInst.hookFns.push(fn),
|
|
580
|
+
filter: (arr) => {
|
|
581
|
+
if (Array.isArray(arr)) hookInst.filters = arr;
|
|
582
|
+
},
|
|
583
|
+
protect: () => {
|
|
584
|
+
readonly(win, "XMLHttpRequest", winAh.fakeXHR);
|
|
585
|
+
readonly(win, "fetch", winAh.fakeFetch);
|
|
586
|
+
readonly(resProto, "clone", winAh.fakeFetchClone);
|
|
587
|
+
},
|
|
588
|
+
unhook: () => {
|
|
589
|
+
winAh.hookInsts.delete(hookInst);
|
|
590
|
+
if (!winAh.hookInsts.size) {
|
|
591
|
+
writable(win, "XMLHttpRequest", winAh.realXHR);
|
|
592
|
+
writable(win, "fetch", winAh.realFetch);
|
|
593
|
+
writable(resProto, "clone", winAh.realFetchClone);
|
|
594
|
+
delete win.__ajaxHooker;
|
|
595
|
+
}
|
|
596
|
+
},
|
|
597
|
+
};
|
|
616
598
|
};
|