New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Web streams (ReadableStream) support, blob & arrayBuffer accessors, ES6 #140
Conversation
- Return a Node `Buffer` from the Response.blob() constructor. The `Buffer` signature is pretty much the same as `Blob`, so for now this might be a good compromise (until there is better `Blob` support on Node). - Return an `ArrayBuffer` from `Response.arrayBuffer()`. This is cheap, as Node's `Buffer` is implemented in terms of `ArrayBuffer` already. - Clean up `Body` state a bit: - Move _decode related vars to the closure, so that they are GC'ed as soon as possible. This is especially interesting for the _raw response chunks.
The fetch spec prescribes the use of a ReadableStream (from the streams spec) as response & request bodies. With ReadableStream exposed in recent Chrome, client-side code is starting to take advantage of streaming content transformations. To more faithfully implement the fetch spec & support isomorphic stream processing code, this patch adds support for ReadableStream, using the whatwg reference implementation: - `Response.body` is now a ReadableStream. - The `Body` constructor dynamically converts Node streams to `ReadableStream`, but still accepts FormData. - Requests accept ReadableStream, Node stream, or FormData bodies.
Apart from being cleaner, this will let us leverage ES6 getters & setters for lazy ReadableStream construction & type conversion.
- Remove charset detection, as this differs from the spec & browser implementations. Resolves #1. - Use ES6 getters for Request.body / Response.body access. This lets us avoid constructing a ReadableStream in the large number of cases where the full body is consumed with `.text()`, `.json()` or `.blob()`. - Add a fast path avoiding stream construction for request bodies in index.js.
- Convert to basic ES6. - Convert `fetch` into a regular function. This is in line with the spec & browser implementations, where calling `fetch` as a constructor is explicitly not supported. (Example: Chrome returns "TypeError: fetch is not a constructor".) Additionally, constructors masquerading as functions is no longer supported in ES6.
Thx for the PR, but as great as it might be, I won't be merging it due to multiple breaking change. I will however keep it open for future reference. |
Upstream [is not keen on incorporating breaking changes](node-fetch#140) like the removal of charset detection & the introduction of ReadableStream. In the meantime, we need a spec conforming `fetch` compatible polyfill that can be used in ServiceWorker code. So, for now, the path of least resistance seems to be to rename the project to node-fetch-polyfill & bump the version to 2.0.0 to signal breaking API changes.
I think this would be a good starting point of v 2.0 or at least some of it Could maybe wish for a v2.0 brach that we can push to instead and also that this PR was broken down to a few smaller pull requests instead of one big. or perhaps just keep this as a reference like you said |
@@ -15,37 +15,37 @@ const webStreams = require('node-web-streams'); | |||
*/ | |||
class Body { | |||
constructor(body, opts) { | |||
opts = opts || {}; | |||
opts = opts || {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 ← click
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just did some very preliminary review on Body
.
Was there a reason why you changed the code formatting? It makes finding the difference in code a lot harder, when there are unrelated changes mixed in.
|
||
set body(val) { | ||
this._rawBody = val; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This goes against the WHATWG spec, which specifies that
readonly attribute ReadableStream? body;
The readonly
annotation means that the setter should be left blank.
/** | ||
* Accumulate the body & return a Buffer. | ||
* | ||
* @return Promise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make clear what the type of the encapsulated data in the Promise is as well.
constructor(body, opts) { | ||
opts = opts || {}; | ||
this._rawBody = body; | ||
this.bodyUsed = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the Fetch spec declares bodyUsed
as readonly
you might want to do the getter/setter dance similar to rawBody
and body
.
class Body { | ||
constructor(body, opts) { | ||
opts = opts || {}; | ||
this._rawBody = body; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could make rawBody
a Symbol
Incorporates some changes from #140, by Gabriel Wicke <gwicke@wikimedia.org>.
Incorporates some changes from #140, by Gabriel Wicke <gwicke@wikimedia.org>.
Elements of this commit come from #140 by Gabriel Wicke <gwicke@wikimedia.org>.
Incorporates some changes from #140, by Gabriel Wicke <gwicke@wikimedia.org>.
This PR is pretty old btw. Current work is in the master branch of https://github.com/gwicke/node-fetch-polyfill. |
Incorporates some changes from #140, by Gabriel Wicke <gwicke@wikimedia.org>.
Incorporates some changes from #140, by Gabriel Wicke <gwicke@wikimedia.org>.
body
as WhatWGReadableStream
, in line with the spec & browser implementations.ReadableStream
only when needed.