@tarojs/plugin-http 3.7.0-alpha.2 → 3.7.0-alpha.22

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.js CHANGED
@@ -26,6 +26,21 @@ var index = (ctx, options) => {
26
26
  ((_b = options.disabledBlob) !== null && _b !== void 0 ? _b : true) && ((_d = args[0]).Blob || (_d.Blob = [runtimeAlias, 'Blob']));
27
27
  return args;
28
28
  });
29
+ if (ctx.initialConfig.compiler === 'webpack4' || (shared.isObject(ctx.initialConfig.compiler) && ctx.initialConfig.compiler.type === 'webpack4')) {
30
+ // taro webpack4 中, 未正确识别到 axios package.json 中的 browser 字段, 以致于打包进入了 node 相关的代码(https://github.com/axios/axios/blob/59eb99183546d822bc27e881f5dcd748daa04173/package.json#L128-L132)
31
+ const inAxiosReg = /(\/|\\)(node_modules)(\/|\\)(axios)(\/|\\)/;
32
+ chain.merge({
33
+ externals: [
34
+ (context, request, callback) => {
35
+ if (inAxiosReg.test(context) && request.includes('http.js')) {
36
+ // 将 http 适配器从源码里干掉 https://github.com/axios/axios/blob/59eb99183546d822bc27e881f5dcd748daa04173/lib/adapters/adapters.js#L2
37
+ return callback(null, 'var undefined');
38
+ }
39
+ callback();
40
+ }
41
+ ]
42
+ });
43
+ }
29
44
  }
30
45
  });
31
46
  ctx.registerMethod({
package/dist/runtime.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { document, Events } from '@tarojs/runtime';
1
+ import { document, Events, TaroEvent } from '@tarojs/runtime';
2
2
  declare class Cookie {
3
3
  #private;
4
4
  constructor();
@@ -41,6 +41,12 @@ declare class Cookie {
41
41
  */
42
42
  deserialize(str: any): void;
43
43
  }
44
+ interface XMLHttpRequestEvent extends TaroEvent {
45
+ target: XMLHttpRequest;
46
+ currentTarget: XMLHttpRequest;
47
+ loaded: number;
48
+ total: number;
49
+ }
44
50
  // https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
45
51
  declare class XMLHttpRequest extends Events {
46
52
  #private;
@@ -52,21 +58,24 @@ declare class XMLHttpRequest extends Events {
52
58
  // 欺骗一些库让其认为是原生的xhr
53
59
  static toString(): string;
54
60
  toString(): string;
55
- // 事件
61
+ // 事件正常流转: loadstart => progress(可能多次) => load => loadend
62
+ // error 流转: loadstart => error => loadend
63
+ // abort 流转: loadstart => abort => loadend
64
+ // web在线测试: https://developer.mozilla.org/zh-CN/play
56
65
  /** 当 request 被停止时触发,例如当程序调用 XMLHttpRequest.abort() 时 */
57
- onabort: (() => void) | null;
66
+ onabort: ((e: XMLHttpRequestEvent) => void) | null;
58
67
  /** 当 request 遭遇错误时触发 */
59
- onerror: ((err: any) => void) | null;
68
+ onerror: ((e: XMLHttpRequestEvent) => void) | null;
60
69
  /** 接收到响应数据时触发 */
61
- onloadstart: (() => void) | null;
70
+ onloadstart: ((e: XMLHttpRequestEvent) => void) | null;
62
71
  /** 请求成功完成时触发 */
63
- onload: (() => void) | null;
72
+ onload: ((e: XMLHttpRequestEvent) => void) | null;
64
73
  /** 当请求结束时触发,无论请求成功 ( load) 还是失败 (abort 或 error)。 */
65
- onloadend: (() => void) | null;
74
+ onloadend: ((e: XMLHttpRequestEvent) => void) | null;
66
75
  /** 在预设时间内没有接收到响应时触发 */
67
- ontimeout: (() => void) | null;
76
+ ontimeout: ((e: XMLHttpRequestEvent) => void) | null;
68
77
  /** 当 readyState 属性发生变化时,调用的事件处理器 */
69
- onreadystatechange: (() => void) | null;
78
+ onreadystatechange: ((e: XMLHttpRequestEvent) => void) | null;
70
79
  constructor();
71
80
  addEventListener(event: string, callback: (arg: any) => void): void;
72
81
  removeEventListener(event: string, callback: (arg: any) => void): void;
@@ -91,4 +100,4 @@ declare class XMLHttpRequest extends Events {
91
100
  setRequestHeader(header: any, value: any): void;
92
101
  send(data: any): void;
93
102
  }
94
- export { Cookie, document, XMLHttpRequest };
103
+ export { Cookie, document, XMLHttpRequest, XMLHttpRequestEvent };
package/dist/runtime.js CHANGED
@@ -1,4 +1,4 @@
1
- import { parseUrl, Events, window, document } from '@tarojs/runtime';
1
+ import { parseUrl, Events, createEvent, window, document } from '@tarojs/runtime';
2
2
  export { document } from '@tarojs/runtime';
3
3
  import { isString, isFunction, isWebPlatform } from '@tarojs/shared';
4
4
  import { setStorage, getStorageSync, request } from '@tarojs/taro';
@@ -17,6 +17,8 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
17
17
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18
18
  PERFORMANCE OF THIS SOFTWARE.
19
19
  ***************************************************************************** */
20
+ /* global Reflect, Promise */
21
+
20
22
 
21
23
  function __classPrivateFieldGet(receiver, state, kind, f) {
22
24
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
@@ -351,8 +353,43 @@ const STATUS_TEXT_MAP = {
351
353
  504: 'Gateway Timeout',
352
354
  505: 'HTTP Version Not Supported',
353
355
  };
356
+ function createXMLHttpRequestEvent(event, target, loaded) {
357
+ const e = createEvent(event);
358
+ try {
359
+ Object.defineProperties(e, {
360
+ 'currentTarget': {
361
+ enumerable: true,
362
+ value: target
363
+ },
364
+ 'target': {
365
+ enumerable: true,
366
+ value: target
367
+ },
368
+ 'loaded': {
369
+ enumerable: true,
370
+ value: loaded || 0
371
+ },
372
+ // 读 Content-Range 字段,目前来说作用不大,先和 loaded 保持一致
373
+ 'total': {
374
+ enumerable: true,
375
+ value: loaded || 0
376
+ }
377
+ });
378
+ }
379
+ catch (err) {
380
+ // no handler
381
+ }
382
+ return e;
383
+ }
354
384
  // https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
355
385
  class XMLHttpRequest extends Events {
386
+ // 欺骗一些库让其认为是原生的xhr
387
+ static toString() {
388
+ return 'function XMLHttpRequest() { [native code] }';
389
+ }
390
+ toString() {
391
+ return '[object XMLHttpRequest]';
392
+ }
356
393
  constructor() {
357
394
  super();
358
395
  _XMLHttpRequest_instances.add(this);
@@ -369,7 +406,10 @@ class XMLHttpRequest extends Events {
369
406
  _XMLHttpRequest_timeout.set(this, void 0);
370
407
  _XMLHttpRequest_withCredentials.set(this, void 0);
371
408
  _XMLHttpRequest_requestTask.set(this, void 0);
372
- // 事件
409
+ // 事件正常流转: loadstart => progress(可能多次) => load => loadend
410
+ // error 流转: loadstart => error => loadend
411
+ // abort 流转: loadstart => abort => loadend
412
+ // web在线测试: https://developer.mozilla.org/zh-CN/play
373
413
  /** 当 request 被停止时触发,例如当程序调用 XMLHttpRequest.abort() 时 */
374
414
  this.onabort = null;
375
415
  /** 当 request 遭遇错误时触发 */
@@ -401,13 +441,6 @@ class XMLHttpRequest extends Events {
401
441
  __classPrivateFieldSet(this, _XMLHttpRequest_withCredentials, true, "f");
402
442
  __classPrivateFieldSet(this, _XMLHttpRequest_requestTask, null, "f");
403
443
  }
404
- // 欺骗一些库让其认为是原生的xhr
405
- static toString() {
406
- return 'function XMLHttpRequest() { [native code] }';
407
- }
408
- toString() {
409
- return '[object XMLHttpRequest]';
410
- }
411
444
  addEventListener(event, callback) {
412
445
  if (!isString(event))
413
446
  return;
@@ -466,8 +499,9 @@ class XMLHttpRequest extends Events {
466
499
  abort() {
467
500
  if (__classPrivateFieldGet(this, _XMLHttpRequest_requestTask, "f")) {
468
501
  __classPrivateFieldGet(this, _XMLHttpRequest_requestTask, "f").abort();
469
- this.trigger('abort');
470
- isFunction(this.onabort) && this.onabort();
502
+ const abortEvent = createXMLHttpRequestEvent('abort', this, 0);
503
+ this.trigger('abort', abortEvent);
504
+ isFunction(this.onabort) && this.onabort(abortEvent);
471
505
  }
472
506
  }
473
507
  getAllResponseHeaders() {
@@ -512,8 +546,9 @@ _XMLHttpRequest_method = new WeakMap(), _XMLHttpRequest_url = new WeakMap(), _XM
512
546
  const hasChange = readyState !== __classPrivateFieldGet(this, _XMLHttpRequest_readyState, "f");
513
547
  __classPrivateFieldSet(this, _XMLHttpRequest_readyState, readyState, "f");
514
548
  if (hasChange) {
515
- this.trigger('readystatechange');
516
- isFunction(this.onreadystatechange) && this.onreadystatechange();
549
+ const readystatechangeEvent = createXMLHttpRequestEvent('readystatechange', this, 0);
550
+ this.trigger('readystatechange', readystatechangeEvent);
551
+ isFunction(this.onreadystatechange) && this.onreadystatechange(readystatechangeEvent);
517
552
  }
518
553
  }, _XMLHttpRequest_callRequest = function _XMLHttpRequest_callRequest() {
519
554
  if (!window || !window.document) {
@@ -527,8 +562,9 @@ _XMLHttpRequest_method = new WeakMap(), _XMLHttpRequest_url = new WeakMap(), _XM
527
562
  if (__classPrivateFieldGet(this, _XMLHttpRequest_requestTask, "f"))
528
563
  __classPrivateFieldGet(this, _XMLHttpRequest_requestTask, "f").abort();
529
564
  __classPrivateFieldGet(this, _XMLHttpRequest_instances, "m", _XMLHttpRequest_callReadyStateChange).call(this, XMLHttpRequest.DONE);
530
- this.trigger('timeout');
531
- isFunction(this.ontimeout) && this.ontimeout();
565
+ const timeoutEvent = createXMLHttpRequestEvent('timeout', this, 0);
566
+ this.trigger('timeout', timeoutEvent);
567
+ isFunction(this.ontimeout) && this.ontimeout(timeoutEvent);
532
568
  }
533
569
  }, __classPrivateFieldGet(this, _XMLHttpRequest_timeout, "f"));
534
570
  }
@@ -543,7 +579,8 @@ _XMLHttpRequest_method = new WeakMap(), _XMLHttpRequest_url = new WeakMap(), _XM
543
579
  url = url.indexOf('//') === -1 ? window.location.origin + url : url;
544
580
  // 头信息
545
581
  const header = Object.assign({}, __classPrivateFieldGet(this, _XMLHttpRequest_header, "f"));
546
- header.cookie = window.document.cookie;
582
+ // https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies
583
+ header.cookie = window.document.$$cookie;
547
584
  if (!this.withCredentials) {
548
585
  // 不同源,要求 withCredentials 为 true 才携带 cookie
549
586
  const { origin } = parseUrl(url);
@@ -600,23 +637,49 @@ _XMLHttpRequest_method = new WeakMap(), _XMLHttpRequest_url = new WeakMap(), _XM
600
637
  // 处理返回数据
601
638
  if (data) {
602
639
  __classPrivateFieldGet(this, _XMLHttpRequest_instances, "m", _XMLHttpRequest_callReadyStateChange).call(this, XMLHttpRequest.LOADING);
603
- this.trigger('loadstart');
604
- isFunction(this.onloadstart) && this.onloadstart();
640
+ const loadstartEvent = createXMLHttpRequestEvent('loadstart', this, header['Content-Length']);
641
+ this.trigger('loadstart', loadstartEvent);
642
+ isFunction(this.onloadstart) && this.onloadstart(loadstartEvent);
605
643
  __classPrivateFieldSet(this, _XMLHttpRequest_response, data, "f");
606
- this.trigger('load');
607
- isFunction(this.onload) && this.onload();
644
+ const loadEvent = createXMLHttpRequestEvent('load', this, header['Content-Length']);
645
+ this.trigger('load', loadEvent);
646
+ isFunction(this.onload) && this.onload(loadEvent);
608
647
  }
609
648
  }, _XMLHttpRequest_requestFail = function _XMLHttpRequest_requestFail(err) {
649
+ // 微信小程序,无论接口返回200还是其他,响应无论是否有错误,都会进入 success 回调;只有类似超时这种请求错误才会进入 fail 回调
650
+ //
651
+ /**
652
+ * 阿里系小程序,接口返回非200状态码,会进入 fail 回调, 此时 err 对象结构如下(当错误码为 14 或 19 时,会多返回 status、data、headers。可通过这些字段获取服务端相关错误信息):
653
+ {
654
+ data: "{\"code\": 401,\"msg\":\"登录过期,请重新登录\"}"
655
+ error: 19
656
+ errorMessage: "http status error"
657
+ headers: {date: 'Mon, 14 Aug 2023 08:54:58 GMT', content-type: 'application/json;charset=UTF-8', content-length: '52', connection: 'close', access-control-allow-credentials: 'true', …}
658
+ originalData: "{\"code\": 401,\"msg\":\"登录过期,请重新登录\"}"
659
+ status: 401
660
+ }
661
+ */
662
+ // 统一行为,能正常响应的,都算 success.
663
+ if (err.status) {
664
+ __classPrivateFieldGet(this, _XMLHttpRequest_instances, "m", _XMLHttpRequest_requestSuccess).call(this, {
665
+ data: err,
666
+ statusCode: err.status,
667
+ header: err.headers
668
+ });
669
+ return;
670
+ }
610
671
  __classPrivateFieldSet(this, _XMLHttpRequest_status, 0, "f");
611
- __classPrivateFieldSet(this, _XMLHttpRequest_statusText, err.errMsg, "f");
612
- this.trigger('error');
613
- isFunction(this.onerror) && this.onerror(err);
672
+ __classPrivateFieldSet(this, _XMLHttpRequest_statusText, err.errMsg || err.errorMessage, "f");
673
+ const errorEvent = createXMLHttpRequestEvent('error', this, 0);
674
+ this.trigger('error', errorEvent);
675
+ isFunction(this.onerror) && this.onerror(errorEvent);
614
676
  }, _XMLHttpRequest_requestComplete = function _XMLHttpRequest_requestComplete() {
615
677
  __classPrivateFieldSet(this, _XMLHttpRequest_requestTask, null, "f");
616
678
  __classPrivateFieldGet(this, _XMLHttpRequest_instances, "m", _XMLHttpRequest_callReadyStateChange).call(this, XMLHttpRequest.DONE);
617
679
  if (__classPrivateFieldGet(this, _XMLHttpRequest_status, "f")) {
618
- this.trigger('loadend');
619
- isFunction(this.onloadend) && this.onloadend();
680
+ const loadendEvent = createXMLHttpRequestEvent('loadend', this, __classPrivateFieldGet(this, _XMLHttpRequest_header, "f")['Content-Length']);
681
+ this.trigger('loadend', loadendEvent);
682
+ isFunction(this.onloadend) && this.onloadend(loadendEvent);
620
683
  }
621
684
  };
622
685
  XMLHttpRequest.UNSENT = 0;
@@ -646,6 +709,12 @@ if (!isWebPlatform()) {
646
709
  _cookie.setCookie(value, this.URL);
647
710
  },
648
711
  },
712
+ /** 获取完整的 cookie,包括 httpOnly 也能获取到 */
713
+ $$cookie: {
714
+ get() {
715
+ return _cookie.getCookie(this.URL, true);
716
+ },
717
+ }
649
718
  });
650
719
  }
651
720
  window.XMLHttpRequest = XMLHttpRequest;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tarojs/plugin-http",
3
- "version": "3.7.0-alpha.2",
3
+ "version": "3.7.0-alpha.22",
4
4
  "description": "Taro 小程序端支持使用 web 请求 的插件",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -23,12 +23,12 @@
23
23
  },
24
24
  "homepage": "https://github.com/NervJS/taro#readme",
25
25
  "dependencies": {
26
- "@tarojs/runtime": "3.7.0-alpha.2",
27
- "@tarojs/service": "3.7.0-alpha.2",
28
- "@tarojs/shared": "3.7.0-alpha.2"
26
+ "@tarojs/runtime": "3.7.0-alpha.22",
27
+ "@tarojs/service": "3.7.0-alpha.22",
28
+ "@tarojs/shared": "3.7.0-alpha.22"
29
29
  },
30
30
  "devDependencies": {
31
- "@rollup/plugin-json": "^4.1.0",
31
+ "@rollup/plugin-json": "^6.0.0",
32
32
  "@rollup/plugin-node-resolve": "^15.0.1",
33
33
  "jest": "^29.3.1",
34
34
  "jest-cli": "^29.3.1",
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { isArray, isString } from '@tarojs/shared'
1
+ import { isArray, isObject, isString } from '@tarojs/shared'
2
2
  import path from 'path'
3
3
 
4
4
  import { name as packageName } from '../package.json'
@@ -35,6 +35,22 @@ export default (ctx: IPluginContext, options: IOptions) => {
35
35
 
36
36
  return args
37
37
  })
38
+
39
+ if (ctx.initialConfig.compiler === 'webpack4' || (isObject<boolean>(ctx.initialConfig.compiler) && ctx.initialConfig.compiler.type === 'webpack4')) {
40
+ // taro webpack4 中, 未正确识别到 axios package.json 中的 browser 字段, 以致于打包进入了 node 相关的代码(https://github.com/axios/axios/blob/59eb99183546d822bc27e881f5dcd748daa04173/package.json#L128-L132)
41
+ const inAxiosReg = /(\/|\\)(node_modules)(\/|\\)(axios)(\/|\\)/
42
+ chain.merge({
43
+ externals: [
44
+ (context, request, callback) => {
45
+ if (inAxiosReg.test(context) && request.includes('http.js')) {
46
+ // 将 http 适配器从源码里干掉 https://github.com/axios/axios/blob/59eb99183546d822bc27e881f5dcd748daa04173/lib/adapters/adapters.js#L2
47
+ return callback(null, 'var undefined')
48
+ }
49
+ callback()
50
+ }
51
+ ]
52
+ })
53
+ }
38
54
  }
39
55
  })
40
56
 
@@ -1,4 +1,4 @@
1
- import { Events, parseUrl, window } from '@tarojs/runtime'
1
+ import { createEvent, Events, parseUrl, TaroEvent, window } from '@tarojs/runtime'
2
2
  import { isFunction, isString } from '@tarojs/shared'
3
3
  import { request } from '@tarojs/taro'
4
4
 
@@ -51,6 +51,42 @@ const STATUS_TEXT_MAP = {
51
51
  504: 'Gateway Timeout',
52
52
  505: 'HTTP Version Not Supported',
53
53
  }
54
+
55
+ export interface XMLHttpRequestEvent extends TaroEvent {
56
+ target: XMLHttpRequest
57
+ currentTarget: XMLHttpRequest
58
+ loaded: number
59
+ total: number
60
+ }
61
+
62
+ function createXMLHttpRequestEvent (event: string, target:XMLHttpRequest, loaded: number): XMLHttpRequestEvent {
63
+ const e = createEvent(event) as XMLHttpRequestEvent
64
+ try {
65
+ Object.defineProperties(e, {
66
+ 'currentTarget': {
67
+ enumerable: true,
68
+ value: target
69
+ },
70
+ 'target': {
71
+ enumerable: true,
72
+ value: target
73
+ },
74
+ 'loaded': {
75
+ enumerable: true,
76
+ value: loaded || 0
77
+ },
78
+ // 读 Content-Range 字段,目前来说作用不大,先和 loaded 保持一致
79
+ 'total': {
80
+ enumerable: true,
81
+ value: loaded || 0
82
+ }
83
+ })
84
+ } catch (err) {
85
+ // no handler
86
+ }
87
+ return e
88
+ }
89
+
54
90
  // https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
55
91
  export class XMLHttpRequest extends Events {
56
92
  static readonly UNSENT = 0
@@ -82,28 +118,31 @@ export class XMLHttpRequest extends Events {
82
118
  #withCredentials: boolean
83
119
  #requestTask: null | Taro.RequestTask<any>
84
120
 
85
- // 事件
121
+ // 事件正常流转: loadstart => progress(可能多次) => load => loadend
122
+ // error 流转: loadstart => error => loadend
123
+ // abort 流转: loadstart => abort => loadend
124
+ // web在线测试: https://developer.mozilla.org/zh-CN/play
86
125
 
87
126
  /** 当 request 被停止时触发,例如当程序调用 XMLHttpRequest.abort() 时 */
88
- onabort: (() => void) | null = null
127
+ onabort: ((e: XMLHttpRequestEvent) => void) | null = null
89
128
 
90
129
  /** 当 request 遭遇错误时触发 */
91
- onerror: ((err: any) => void) | null = null
130
+ onerror: ((e: XMLHttpRequestEvent) => void) | null = null
92
131
 
93
132
  /** 接收到响应数据时触发 */
94
- onloadstart: (() => void) | null = null
133
+ onloadstart: ((e: XMLHttpRequestEvent) => void) | null = null
95
134
 
96
135
  /** 请求成功完成时触发 */
97
- onload: (() => void) | null = null
136
+ onload: ((e: XMLHttpRequestEvent) => void) | null = null
98
137
 
99
138
  /** 当请求结束时触发,无论请求成功 ( load) 还是失败 (abort 或 error)。 */
100
- onloadend: (() => void) | null = null
139
+ onloadend: ((e: XMLHttpRequestEvent) => void) | null = null
101
140
 
102
141
  /** 在预设时间内没有接收到响应时触发 */
103
- ontimeout: (() => void) | null = null
142
+ ontimeout: ((e: XMLHttpRequestEvent) => void) | null = null
104
143
 
105
144
  /** 当 readyState 属性发生变化时,调用的事件处理器 */
106
- onreadystatechange: (() => void) | null = null
145
+ onreadystatechange: ((e: XMLHttpRequestEvent) => void) | null = null
107
146
 
108
147
  constructor () {
109
148
  super()
@@ -145,8 +184,9 @@ export class XMLHttpRequest extends Events {
145
184
  this.#readyState = readyState
146
185
 
147
186
  if (hasChange) {
148
- this.trigger('readystatechange')
149
- isFunction(this.onreadystatechange) && this.onreadystatechange()
187
+ const readystatechangeEvent = createXMLHttpRequestEvent('readystatechange', this, 0)
188
+ this.trigger('readystatechange', readystatechangeEvent)
189
+ isFunction(this.onreadystatechange) && this.onreadystatechange(readystatechangeEvent)
150
190
  }
151
191
  }
152
192
 
@@ -165,8 +205,9 @@ export class XMLHttpRequest extends Events {
165
205
  // 超时
166
206
  if (this.#requestTask) this.#requestTask.abort()
167
207
  this.#callReadyStateChange(XMLHttpRequest.DONE)
168
- this.trigger('timeout')
169
- isFunction(this.ontimeout) && this.ontimeout()
208
+ const timeoutEvent = createXMLHttpRequestEvent('timeout', this, 0)
209
+ this.trigger('timeout', timeoutEvent)
210
+ isFunction(this.ontimeout) && this.ontimeout(timeoutEvent)
170
211
  }
171
212
  }, this.#timeout)
172
213
  }
@@ -184,7 +225,8 @@ export class XMLHttpRequest extends Events {
184
225
 
185
226
  // 头信息
186
227
  const header = Object.assign({}, this.#header)
187
- header.cookie = window.document.cookie
228
+ // https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies
229
+ header.cookie = window.document.$$cookie
188
230
  if (!this.withCredentials) {
189
231
  // 不同源,要求 withCredentials 为 true 才携带 cookie
190
232
  const { origin } = parseUrl(url)
@@ -255,11 +297,14 @@ export class XMLHttpRequest extends Events {
255
297
  // 处理返回数据
256
298
  if (data) {
257
299
  this.#callReadyStateChange(XMLHttpRequest.LOADING)
258
- this.trigger('loadstart')
259
- isFunction(this.onloadstart) && this.onloadstart()
300
+ const loadstartEvent = createXMLHttpRequestEvent('loadstart', this, header['Content-Length'])
301
+ this.trigger('loadstart', loadstartEvent)
302
+ isFunction(this.onloadstart) && this.onloadstart(loadstartEvent)
260
303
  this.#response = data
261
- this.trigger('load')
262
- isFunction(this.onload) && this.onload()
304
+
305
+ const loadEvent = createXMLHttpRequestEvent('load', this, header['Content-Length'])
306
+ this.trigger('load', loadEvent)
307
+ isFunction(this.onload) && this.onload(loadEvent)
263
308
  }
264
309
  }
265
310
 
@@ -267,10 +312,33 @@ export class XMLHttpRequest extends Events {
267
312
  * 请求失败
268
313
  */
269
314
  #requestFail (err) {
315
+ // 微信小程序,无论接口返回200还是其他,响应无论是否有错误,都会进入 success 回调;只有类似超时这种请求错误才会进入 fail 回调
316
+ //
317
+ /**
318
+ * 阿里系小程序,接口返回非200状态码,会进入 fail 回调, 此时 err 对象结构如下(当错误码为 14 或 19 时,会多返回 status、data、headers。可通过这些字段获取服务端相关错误信息):
319
+ {
320
+ data: "{\"code\": 401,\"msg\":\"登录过期,请重新登录\"}"
321
+ error: 19
322
+ errorMessage: "http status error"
323
+ headers: {date: 'Mon, 14 Aug 2023 08:54:58 GMT', content-type: 'application/json;charset=UTF-8', content-length: '52', connection: 'close', access-control-allow-credentials: 'true', …}
324
+ originalData: "{\"code\": 401,\"msg\":\"登录过期,请重新登录\"}"
325
+ status: 401
326
+ }
327
+ */
328
+ // 统一行为,能正常响应的,都算 success.
329
+ if (err.status) {
330
+ this.#requestSuccess({
331
+ data: err,
332
+ statusCode: err.status,
333
+ header: err.headers
334
+ })
335
+ return
336
+ }
270
337
  this.#status = 0
271
- this.#statusText = err.errMsg
272
- this.trigger('error')
273
- isFunction(this.onerror) && this.onerror(err)
338
+ this.#statusText = err.errMsg || err.errorMessage
339
+ const errorEvent = createXMLHttpRequestEvent('error', this, 0)
340
+ this.trigger('error', errorEvent)
341
+ isFunction(this.onerror) && this.onerror(errorEvent)
274
342
  }
275
343
 
276
344
  /**
@@ -281,8 +349,9 @@ export class XMLHttpRequest extends Events {
281
349
  this.#callReadyStateChange(XMLHttpRequest.DONE)
282
350
 
283
351
  if (this.#status) {
284
- this.trigger('loadend')
285
- isFunction(this.onloadend) && this.onloadend()
352
+ const loadendEvent = createXMLHttpRequestEvent('loadend', this, this.#header['Content-Length'])
353
+ this.trigger('loadend', loadendEvent)
354
+ isFunction(this.onloadend) && this.onloadend(loadendEvent)
286
355
  }
287
356
  }
288
357
 
@@ -346,8 +415,9 @@ export class XMLHttpRequest extends Events {
346
415
  abort () {
347
416
  if (this.#requestTask) {
348
417
  this.#requestTask.abort()
349
- this.trigger('abort')
350
- isFunction(this.onabort) && this.onabort()
418
+ const abortEvent = createXMLHttpRequestEvent('abort', this, 0)
419
+ this.trigger('abort', abortEvent)
420
+ isFunction(this.onabort) && this.onabort(abortEvent)
351
421
  }
352
422
  }
353
423
 
@@ -2,7 +2,7 @@ import { document, window } from '@tarojs/runtime'
2
2
  import { isWebPlatform } from '@tarojs/shared'
3
3
 
4
4
  import { Cookie, createCookieInstance } from './Cookie'
5
- import { XMLHttpRequest } from './XMLHttpRequest'
5
+ import { type XMLHttpRequestEvent, XMLHttpRequest } from './XMLHttpRequest'
6
6
 
7
7
  declare const ENABLE_COOKIE: boolean
8
8
 
@@ -26,10 +26,16 @@ if (!isWebPlatform()) {
26
26
  _cookie.setCookie(value, this.URL)
27
27
  },
28
28
  },
29
+ /** 获取完整的 cookie,包括 httpOnly 也能获取到 */
30
+ $$cookie: {
31
+ get () {
32
+ return _cookie.getCookie(this.URL, true)
33
+ },
34
+ }
29
35
  })
30
36
  }
31
37
 
32
38
  window.XMLHttpRequest = XMLHttpRequest
33
39
  }
34
40
 
35
- export { Cookie, document, XMLHttpRequest }
41
+ export { Cookie, document, XMLHttpRequest, XMLHttpRequestEvent }