Skip to content

Commit

Permalink
ArrayBuffer can now be consumed through blob()/text()
Browse files Browse the repository at this point in the history
Before, when a Request or Response was initialized with an ArrayBuffer
or TypedArray, that data was only accessible through `arrayBuffer()`
method, and if it was initialized with DataView, it wasn't accessible at
all.

Now, regardless of the original type of body, the accessors `blob()`,
`arrayBuffer()`, and `text()` always work.
  • Loading branch information
mislav committed Nov 14, 2016
1 parent 9a04a06 commit 9a703ba
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 32 deletions.
62 changes: 35 additions & 27 deletions fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,31 +184,37 @@
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
} else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
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')
}
Expand All @@ -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)
}
Expand Down
80 changes: 75 additions & 5 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')
})
})
})
Expand All @@ -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')
})
})
})
})
}
Expand Down

0 comments on commit 9a703ba

Please sign in to comment.