@whitesev/utils 1.4.0 → 1.4.2

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