@@ -11,16 +11,15 @@ import FetchError from './fetch-error.js';
11
11
const Stream = require ( 'stream' ) ;
12
12
const { PassThrough } = require ( 'stream' ) ;
13
13
14
- const DISTURBED = Symbol ( 'disturbed' ) ;
15
- const ERROR = Symbol ( 'error' ) ;
16
-
17
14
let convert ;
18
15
try { convert = require ( 'encoding' ) . convert ; } catch ( e ) { }
19
16
17
+ const INTERNALS = Symbol ( 'Body internals' ) ;
18
+
20
19
/**
21
- * Body class
20
+ * Body mixin
22
21
*
23
- * Cannot use ES6 class because Body must be called with .call().
22
+ * Ref: https://fetch.spec.whatwg.org/#body
24
23
*
25
24
* @param Stream body Readable stream
26
25
* @param Object opts Response options
@@ -48,22 +47,28 @@ export default function Body(body, {
48
47
// coerce to string
49
48
body = String ( body ) ;
50
49
}
51
- this . body = body ;
52
- this [ DISTURBED ] = false ;
53
- this [ ERROR ] = null ;
50
+ this [ INTERNALS ] = {
51
+ body,
52
+ disturbed : false ,
53
+ error : null
54
+ } ;
54
55
this . size = size ;
55
56
this . timeout = timeout ;
56
57
57
- if ( this . body instanceof Stream ) {
58
- this . body . on ( 'error' , err => {
59
- this [ ERROR ] = new FetchError ( `Invalid response body while trying to fetch ${ this . url } : ${ err . message } ` , 'system' , err ) ;
58
+ if ( body instanceof Stream ) {
59
+ body . on ( 'error' , err => {
60
+ this [ INTERNALS ] . error = new FetchError ( `Invalid response body while trying to fetch ${ this . url } : ${ err . message } ` , 'system' , err ) ;
60
61
} ) ;
61
62
}
62
63
}
63
64
64
65
Body . prototype = {
66
+ get body ( ) {
67
+ return this [ INTERNALS ] . body ;
68
+ } ,
69
+
65
70
get bodyUsed ( ) {
66
- return this [ DISTURBED ] ;
71
+ return this [ INTERNALS ] . disturbed ;
67
72
} ,
68
73
69
74
/**
@@ -139,6 +144,16 @@ Body.prototype = {
139
144
140
145
} ;
141
146
147
+ // In browsers, all properties are enumerable.
148
+ Object . defineProperties ( Body . prototype , {
149
+ body : { enumerable : true } ,
150
+ bodyUsed : { enumerable : true } ,
151
+ arrayBuffer : { enumerable : true } ,
152
+ blob : { enumerable : true } ,
153
+ json : { enumerable : true } ,
154
+ text : { enumerable : true }
155
+ } ) ;
156
+
142
157
Body . mixIn = function ( proto ) {
143
158
for ( const name of Object . getOwnPropertyNames ( Body . prototype ) ) {
144
159
// istanbul ignore else: future proof
@@ -150,19 +165,21 @@ Body.mixIn = function (proto) {
150
165
} ;
151
166
152
167
/**
153
- * Decode buffers into utf-8 string
168
+ * Consume and convert an entire Body to a Buffer.
169
+ *
170
+ * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body
154
171
*
155
172
* @return Promise
156
173
*/
157
- function consumeBody ( body ) {
158
- if ( this [ DISTURBED ] ) {
159
- return Body . Promise . reject ( new Error ( `body used already for: ${ this . url } ` ) ) ;
174
+ function consumeBody ( ) {
175
+ if ( this [ INTERNALS ] . disturbed ) {
176
+ return Body . Promise . reject ( new TypeError ( `body used already for: ${ this . url } ` ) ) ;
160
177
}
161
178
162
- this [ DISTURBED ] = true ;
179
+ this [ INTERNALS ] . disturbed = true ;
163
180
164
- if ( this [ ERROR ] ) {
165
- return Body . Promise . reject ( this [ ERROR ] ) ;
181
+ if ( this [ INTERNALS ] . error ) {
182
+ return Body . Promise . reject ( this [ INTERNALS ] . error ) ;
166
183
}
167
184
168
185
// body is null
@@ -309,21 +326,21 @@ function convertBody(buffer, headers) {
309
326
* @return String
310
327
*/
311
328
function isURLSearchParams ( obj ) {
312
- // Duck-typing as a necessary condition.
313
- if ( typeof obj !== 'object' ||
314
- typeof obj . append !== 'function' ||
315
- typeof obj . delete !== 'function' ||
316
- typeof obj . get !== 'function' ||
317
- typeof obj . getAll !== 'function' ||
318
- typeof obj . has !== 'function' ||
319
- typeof obj . set !== 'function' ) {
320
- return false ;
321
- }
322
-
323
- // Brand-checking and more duck-typing as optional condition.
324
- return obj . constructor . name === 'URLSearchParams' ||
325
- Object . prototype . toString . call ( obj ) === '[object URLSearchParams]' ||
326
- typeof obj . sort === 'function' ;
329
+ // Duck-typing as a necessary condition.
330
+ if ( typeof obj !== 'object' ||
331
+ typeof obj . append !== 'function' ||
332
+ typeof obj . delete !== 'function' ||
333
+ typeof obj . get !== 'function' ||
334
+ typeof obj . getAll !== 'function' ||
335
+ typeof obj . has !== 'function' ||
336
+ typeof obj . set !== 'function' ) {
337
+ return false ;
338
+ }
339
+
340
+ // Brand-checking and more duck-typing as optional condition.
341
+ return obj . constructor . name === 'URLSearchParams' ||
342
+ Object . prototype . toString . call ( obj ) === '[object URLSearchParams]' ||
343
+ typeof obj . sort === 'function' ;
327
344
}
328
345
329
346
/**
@@ -350,7 +367,7 @@ export function clone(instance) {
350
367
body . pipe ( p1 ) ;
351
368
body . pipe ( p2 ) ;
352
369
// set instance body to teed body and return the other teed body
353
- instance . body = p1 ;
370
+ instance [ INTERNALS ] . body = p1 ;
354
371
body = p2 ;
355
372
}
356
373
@@ -362,7 +379,7 @@ export function clone(instance) {
362
379
* specified in the specification:
363
380
* https://fetch.spec.whatwg.org/#concept-bodyinit-extract
364
381
*
365
- * This function assumes that instance.body is present and non-null .
382
+ * This function assumes that instance.body is present.
366
383
*
367
384
* @param Mixed instance Response or Request instance
368
385
*/
0 commit comments