diff --git a/fetch.js b/fetch.js index 091b3f3e..bab3c089 100644 --- a/fetch.js +++ b/fetch.js @@ -184,12 +184,24 @@ return fileReaderReady(reader) } + function bufferClone(buf) { + if (buf.slice) { + return buf.slice(0) + } else { + var view = new Uint8Array(buf.byteLength) + view.set(new Uint8Array(buf)) + return view.buffer + } + } + function Body() { this.bodyUsed = false this._initBody = function(body) { this._bodyInit = body - if (typeof body === 'string') { + if (!body) { + this._bodyText = '' + } else if (typeof body === 'string') { this._bodyText = body } else if (support.blob && Blob.prototype.isPrototypeOf(body)) { this._bodyBlob = body @@ -197,18 +209,12 @@ this._bodyFormData = body } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { this._bodyText = body.toString() - } else if (!body) { - this._bodyText = '' } else if (support.arrayBuffer && support.blob && isDataView(body)) { + this._bodyArrayBuffer = bufferClone(body.buffer) // IE 10-11 can't handle a DataView body. - this._bodyInit = new Blob([body.buffer]) + this._bodyInit = new Blob([this._bodyArrayBuffer]) } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) { - if (body.slice) { - this._bodyArrayBuffer = new Uint8Array(body.slice(0)) - } else { - this._bodyArrayBuffer = new Uint8Array(body.byteLength) - this._bodyArrayBuffer.set(new Uint8Array(body)) - } + this._bodyArrayBuffer = bufferClone(body) } else { throw new Error('unsupported BodyInit type') } @@ -233,37 +239,39 @@ if (this._bodyBlob) { return Promise.resolve(this._bodyBlob) + } else if (this._bodyArrayBuffer) { + return Promise.resolve(new Blob([this._bodyArrayBuffer])) } else if (this._bodyFormData) { throw new Error('could not read FormData body as blob') } else { return Promise.resolve(new Blob([this._bodyText])) } } + } - this.text = function() { - var rejected = consumed(this) - if (rejected) { - return rejected - } - - if (this._bodyBlob) { - return readBlobAsText(this._bodyBlob) - } else if (this._bodyFormData) { - throw new Error('could not read FormData body as text') - } else { - return Promise.resolve(this._bodyText) - } + this.text = function() { + var rejected = consumed(this) + if (rejected) { + return rejected } - } else { - this.text = function() { - return consumed(this) || Promise.resolve(this._bodyText) + + if (this._bodyBlob) { + return readBlobAsText(this._bodyBlob) + } else if (this._bodyArrayBuffer) { + var view = new Uint8Array(this._bodyArrayBuffer) + var str = String.fromCharCode.apply(null, view) + return Promise.resolve(str) + } else if (this._bodyFormData) { + throw new Error('could not read FormData body as text') + } else { + return Promise.resolve(this._bodyText) } } if (support.arrayBuffer) { this.arrayBuffer = function() { if (this._bodyArrayBuffer) { - return consumed(this) || Promise.resolve(this._bodyArrayBuffer.buffer) + return consumed(this) || Promise.resolve(this._bodyArrayBuffer) } else { return this.blob().then(readBlobAsArrayBuffer) } diff --git a/test/test.js b/test/test.js index 1cbdcfce..4a4e03ad 100644 --- a/test/test.js +++ b/test/test.js @@ -118,16 +118,80 @@ exercise.forEach(function(exerciseMode) { assert.equal(text, 'hello') }) }) + + test('consume as array buffer', function() { + var obj = factory(new Blob(['hello'])) + return obj.arrayBuffer().then(readArrayBufferAsText).then(function(text) { + assert.equal(text, 'hello') + }) + }) }) featureDependent(suite, support.arrayBuffer, 'type ArrayBuffer', function() { test('consume as array buffer', function() { var original = arrayBufferFromText('name=hubot') - return factory(original).arrayBuffer().then(function(buf) { - assert.equal( - readArrayBufferAsText(buf), - readArrayBufferAsText(original) - ) + return factory(original).arrayBuffer().then(readArrayBufferAsText).then(function(text) { + assert.equal(text, 'name=hubot') + }) + }) + + featureDependent(test, support.blob, 'consume as blob', function() { + var original = arrayBufferFromText('name=hubot') + return factory(original).blob().then(readBlobAsText).then(function(text) { + assert.equal(text, 'name=hubot') + }) + }) + + test('consume as text', function() { + var original = arrayBufferFromText('name=hubot') + return factory(original).text().then(function(text) { + assert.equal(text, 'name=hubot') + }) + }) + }) + + featureDependent(suite, support.arrayBuffer, 'type Uint8Array', function() { + test('consume as array buffer', function() { + var original = new Uint8Array(arrayBufferFromText('name=hubot')) + return factory(original).arrayBuffer().then(readArrayBufferAsText).then(function(text) { + assert.equal(text, 'name=hubot') + }) + }) + + featureDependent(test, support.blob, 'consume as blob', function() { + var original = new Uint8Array(arrayBufferFromText('name=hubot')) + return factory(original).blob().then(readBlobAsText).then(function(text) { + assert.equal(text, 'name=hubot') + }) + }) + + test('consume as text', function() { + var original = new Uint8Array(arrayBufferFromText('name=hubot')) + return factory(original).text().then(function(text) { + assert.equal(text, 'name=hubot') + }) + }) + }) + + featureDependent(suite, support.arrayBuffer, 'type DataView', function() { + test('consume as array buffer', function() { + var original = new DataView(arrayBufferFromText('name=hubot')) + return factory(original).arrayBuffer().then(readArrayBufferAsText).then(function(text) { + assert.equal(text, 'name=hubot') + }) + }) + + featureDependent(test, support.blob, 'consume as blob', function() { + var original = new DataView(arrayBufferFromText('name=hubot')) + return factory(original).blob().then(readBlobAsText).then(function(text) { + assert.equal(text, 'name=hubot') + }) + }) + + test('consume as text', function() { + var original = new DataView(arrayBufferFromText('name=hubot')) + return factory(original).text().then(function(text) { + assert.equal(text, 'name=hubot') }) }) }) @@ -144,6 +208,12 @@ exercise.forEach(function(exerciseMode) { assert.equal(text, 'hello') }) }) + + featureDependent(test, support.arrayBuffer, 'consume as array buffer', function() { + return factory('hello').arrayBuffer().then(readArrayBufferAsText).then(function(text) { + assert.equal(text, 'hello') + }) + }) }) }) }