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
Fetch polyfill #17468
Fetch polyfill #17468
Conversation
…nto fet-polyfill
src/polyfills/fetch.js
Outdated
import {utf8Encode} from '../utils/bytes'; | ||
|
||
/** @private @enum {number} Allowed fetch responses. */ | ||
const allowedFetchTypes_ = { |
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.
Rename to allowedFetchTypes
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.
done
src/polyfills/fetch.js
Outdated
import {parseJson} from '../json'; | ||
import {utf8Encode} from '../utils/bytes'; | ||
|
||
/** @private @enum {number} Allowed fetch responses. */ |
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.
@private
annotation has no meaning here.
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.
done
src/polyfills/fetch.js
Outdated
* status: number, | ||
* statusText: string, | ||
* responseText: string, | ||
* responseXML: ?Document, |
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 is unneeded now.
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.
done
src/polyfills/fetch.js
Outdated
*/ | ||
class FetchResponse { | ||
/** | ||
* @param {!XMLHttpRequest|!XDomainRequest|!XMLHttpRequestDef} xhr |
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.
XDomainRequest
is dropped.
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.
done
src/polyfills/fetch.js
Outdated
data.statusText = String(init.statusText); | ||
} | ||
|
||
return new FetchResponse(/** @type {XMLHttpRequestDef} */(data)); |
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.
It's kinda weird that new Response() instanceof Response
is false. I think the only difficulty to making Response
be the main class is extracting out the headers from XML?
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.
not really, i can make this a sub class of FetchResponse and just do super(blah)
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.
Not really
Can you explain?
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.
class Response extends FetchResponse{
constructor(body, init={}) {
// all the current logic of functionResponse
// instead of return new FetchResponse(/** @type {XMLHttpRequestDef} */(data));
super(/** @type {XMLHttpRequestDef} */(data));
}
}
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 understand the subclassing. I meant what else is the blocker for just using Response
besides header parsing?
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.
Ah ok, the fetchPolyfill
is using FetchReponse as passing xhr in the constructor.
Just using Response
class would just mean a re-write of that part and some additional code there
src/polyfills/fetch.js
Outdated
*/ | ||
export function install(win) { | ||
if (!win.fetch) { | ||
win.prototype.fetch = /** @type {function(string, RequestInit):!Promise} */ (fetchPolyfill); |
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 should be on win
, not win.prototype
.
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.
done
src/polyfills/fetch.js
Outdated
export function install(win) { | ||
if (!win.fetch) { | ||
win.prototype.fetch = /** @type {function(string, RequestInit):!Promise} */ (fetchPolyfill); | ||
win.Response = Response; |
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.
Use Object.defineProperty
* serialized response returned by the viewer. | ||
* @typedef {{ | ||
* status: number, | ||
* statusText: string, |
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.
Doesn't look like this is used.
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.
added to the FetchResponse
src/polyfills/fetch.js
Outdated
* @param {!XMLHttpRequest|!XDomainRequest|!XMLHttpRequestDef} xhr | ||
*/ | ||
constructor(xhr) { | ||
/** @private @const {!XMLHttpRequest|!XDomainRequest|!XMLHttpRequestDef} */ |
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.
XDomainRequest
again.
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.
removed
src/polyfills/fetch.js
Outdated
*/ | ||
class FetchResponseHeaders { | ||
/** | ||
* @param {!XMLHttpRequest|!XDomainRequest|!XMLHttpRequestDef} xhr |
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.
XDomainRequest
again.
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.
woops, removed
src/polyfills/fetch.js
Outdated
* @return {string} | ||
*/ | ||
getResponseHeader(name) { | ||
return lowercasedHeaders[String(name).toLowerCase()] || null; |
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.
hasOwnProperty
, since the value could be an empty string.
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.
done
src/polyfills/fetch.js
Outdated
data.statusText = String(init.statusText); | ||
} | ||
|
||
return new FetchResponse(/** @type {XMLHttpRequestDef} */(data)); |
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.
Not really
Can you explain?
src/polyfills/fetch.js
Outdated
export function install(win) { | ||
if (!win.fetch) { | ||
win.fetch = /** @type {function(string, RequestInit):!Promise} */ (fetchPolyfill); | ||
win.Response = Response; |
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.
Use Object.defineProperty
.
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.
is there a specific thing we want to configure with Object.defineProperty
?
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.
Object.getOwnPropertyDescriptor(window, 'Response')
{value: ƒ, writable: true, enumerable: false, configurable: true}
Object.getOwnPropertyDescriptor(window, 'fetch')
{value: ƒ, writable: true, enumerable: true, configurable: true}
Enumerability, in particular, has been a source of countless polyfill bugs.
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.
done
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 am curious, can u list one such example?
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.
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.
Gotcha! I have read that before, but now I got the complete understanding. Thanks
src/polyfills/fetch.js
Outdated
/** @const {number} */ | ||
this.status = this.xhr_.status; | ||
|
||
this.statusText = this.xhr_.statusText; |
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.
Needs annotations. But why add it?
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.
It'll align better with the standard definition, without much effort.
src/polyfills/fetch.js
Outdated
* @return {string} | ||
*/ | ||
getResponseHeader(name) { | ||
return hasOwn(lowercasedHeaders, name) ? |
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.
name
needs to be lowercased here, too.
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.
done
/** | ||
* Returns instance of Response. | ||
* @param {?ResponseBodyInit=} body | ||
* @param {!ResponseInit=} init |
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.
Where are ResponseInit
and ResponseBodyInit
defined?
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.
They are native to closure compiler.
src/polyfills/fetch.js
Outdated
}, | ||
}, init); | ||
|
||
init.status = init.status || 200; |
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.
Is this necessary? It also overrides a status of 0
.
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.
fixed it for only undefined
. because closure's types say it can be a number or undefined
src/polyfills/fetch.js
Outdated
String(init.headers[key]); | ||
} | ||
} | ||
if (init.status) { |
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.
We already did this above?
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.
removed
src/polyfills/fetch.js
Outdated
Object.defineProperty(win, 'fetch', { | ||
value: fetch, | ||
writable: true, | ||
enumerable: 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.
fetch
is enumerable. Also configurable.
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.
done
Object.defineProperty(win, 'Response', { | ||
value: Response, | ||
writable: true, | ||
enumerable: 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.
configurable: true
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.
done
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.
Thanks the exhaustive review... 👍
src/polyfills/fetch.js
Outdated
/** @const {number} */ | ||
this.status = this.xhr_.status; | ||
|
||
this.statusText = this.xhr_.statusText; |
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.
It'll align better with the standard definition, without much effort.
/** | ||
* Returns instance of Response. | ||
* @param {?ResponseBodyInit=} body | ||
* @param {!ResponseInit=} init |
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.
They are native to closure compiler.
src/polyfills/fetch.js
Outdated
* @return {string} | ||
*/ | ||
getResponseHeader(name) { | ||
return hasOwn(lowercasedHeaders, name) ? |
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.
done
src/polyfills/fetch.js
Outdated
}, | ||
}, init); | ||
|
||
init.status = init.status || 200; |
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.
fixed it for only undefined
. because closure's types say it can be a number or undefined
src/polyfills/fetch.js
Outdated
String(init.headers[key]); | ||
} | ||
} | ||
if (init.status) { |
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.
removed
src/polyfills/fetch.js
Outdated
Object.defineProperty(win, 'fetch', { | ||
value: fetch, | ||
writable: true, | ||
enumerable: 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.
done
Object.defineProperty(win, 'Response', { | ||
value: Response, | ||
writable: true, | ||
enumerable: 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.
done
4ed1c4b
to
e1456e3
Compare
* reverting skip * adding fetch polyfill * WIP polyfill tests * WIP fetch-polyfill tests * passing tests * adding more test * ading more tests * ading more tests * Update dep-check-config.js * Update polyfills.js * resolving comments * removing extra test * response as a class * resolving comments * fixing type related issues * renaming file to avoid test conflict * adding copyright
Writing a fetch polyfill to be used by AMP runtime.
Response
creationg