2121 * THE SOFTWARE.
2222 */
2323
24+ import { Blob } from 'buffer' ;
2425import * as http from 'http' ;
2526import * as https from 'https' ;
27+ import DOMException from './domexception' ;
28+ import File from './file' ;
2629import FormData from './formdata' ;
2730import ProgressEvent from './progressevent' ;
28- import DOMException from './webidl/domexception' ;
2931import XMLHttpRequestEventTarget from './xmlhttprequesteventtarget' ;
3032import XMLHttpRequestUpload from './xmlhttprequestupload' ;
3133
@@ -77,12 +79,11 @@ const FORBIDDEN_RESPONSE_HEADERS = ['set-cookie', 'set-cookie2'];
7779 */
7880const HTTP_HEADER_FIELD_NAME_REGEXP = / [ ! # $ % & ' * + - . ^ _ ` | ~ a - z 0 - 9 ] + / ;
7981
80- export type BodyInit =
81- | ArrayBuffer
82- | Buffer
82+ export type XMLHttpRequestBodyInit =
83+ | Blob
84+ | BufferSource
8385 | FormData
8486 | URLSearchParams
85- | Uint8Array
8687 | string ;
8788
8889export type XMLHttpRequestResponseType =
@@ -478,24 +479,64 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget {
478479 /**
479480 * @see {@link https://xhr.spec.whatwg.org/#the-send()-method XMLHttpRequest Standard - 4.5.6. The send() method }
480481 */
481- send ( body : BodyInit | null = null ) : void {
482+ send ( body : XMLHttpRequestBodyInit | null = null ) : void {
482483 if ( this . readyState !== XMLHttpRequest . OPENED || ! this . #client) {
483484 // TODO: Add human readable message.
484485 throw new DOMException ( '' , 'InvalidStateError' ) ;
485486 }
486487
487- if ( body ) {
488- const bodyInit =
489- body instanceof ArrayBuffer || body instanceof Uint8Array
490- ? Buffer . from ( body )
491- : body ;
488+ this . dispatchEvent ( new ProgressEvent ( 'loadstart' ) ) ;
489+
490+ if ( body && ! [ 'GET' , 'HEAD' ] . includes ( this . #client. method ) ) {
491+ let chunk = new Blob ( [ ] ) ;
492492
493- if ( typeof bodyInit === 'string' || bodyInit instanceof Buffer ) {
494- const length = Buffer . isBuffer ( bodyInit )
495- ? bodyInit . length
496- : Buffer . byteLength ( bodyInit ) ;
493+ if (
494+ body instanceof ArrayBuffer ||
495+ ArrayBuffer . isView ( body ) ||
496+ body instanceof Blob
497+ ) {
498+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
499+ // @ts -ignore
500+ chunk = new Blob ( [ body ] ) ;
501+ } else if ( body instanceof URLSearchParams ) {
502+ chunk = new Blob ( [ body . toString ( ) ] , {
503+ type : 'application/x-www-form-urlencoded; charset=UTF-8'
504+ } ) ;
505+ } else if ( body instanceof FormData ) {
506+ const boundary = '------xxxxx' ;
507+
508+ let chunk = new Blob ( [ ] , {
509+ type : `multipart/form-data; boundary=${ boundary } `
510+ } ) ;
511+ for ( const [ name , value ] of body ) {
512+ if ( value instanceof File ) {
513+ chunk = new Blob (
514+ [
515+ chunk ,
516+ `Content-Disposition: form-data; name="${ name } "; filename="${ value . name } "\r\n` ,
517+ '\r\n' ,
518+ value ,
519+ `\r\n`
520+ ] ,
521+ { type : chunk . type }
522+ ) ;
523+ } else {
524+ chunk = new Blob (
525+ [
526+ chunk ,
527+ `${ boundary } \r\n` ,
528+ `Content-Disposition: form-data; name="${ name } "\r\n` ,
529+ '\r\n' ,
530+ `${ value } \r\n`
531+ ] ,
532+ { type : chunk . type }
533+ ) ;
534+ }
535+ }
497536
498- this . #client. setHeader ( 'Content-Length' , length ) ;
537+ chunk = new Blob ( [ chunk , `${ boundary } \r\n` ] , { type : chunk . type } ) ;
538+ } else {
539+ chunk = new Blob ( [ body ] , { type : 'text/plain' } ) ;
499540 }
500541
501542 this . #client. addListener ( 'socket' , ( socket ) => {
@@ -511,10 +552,26 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget {
511552 } ) ;
512553 } ) ;
513554
514- this . #client. write ( body ) ;
555+ if ( chunk . type ) {
556+ this . setRequestHeader ( 'Content-Type' , chunk . type ) ;
557+ }
558+
559+ this . setRequestHeader ( 'Content-Length' , chunk . size . toString ( ) ) ;
560+
561+ chunk
562+ . arrayBuffer ( )
563+ . then ( ( buffer ) => {
564+ if ( ! this . #client) {
565+ throw new TypeError ( 'The client is initialized unintentionally.' ) ;
566+ }
567+
568+ this . #client. write ( new Uint8Array ( buffer ) ) ;
569+ } )
570+ . catch ( ( error ) => {
571+ throw error ;
572+ } ) ;
515573 }
516574
517- this . dispatchEvent ( new ProgressEvent ( 'loadstart' ) ) ;
518575 this . #client. end ( ) ;
519576 }
520577
0 commit comments