2015-03-24 21:40:11 +00:00
|
|
|
/**
|
2015-06-05 22:23:30 +00:00
|
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
2015-03-24 21:40:11 +00:00
|
|
|
*
|
2016-05-25 11:17:35 +00:00
|
|
|
* @providesModule XMLHttpRequest
|
2015-06-05 22:23:30 +00:00
|
|
|
* @flow
|
2015-03-24 21:40:11 +00:00
|
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
|
2016-11-02 19:18:17 +00:00
|
|
|
const EventTarget = require('event-target-shim');
|
2016-05-25 11:17:35 +00:00
|
|
|
const RCTNetworking = require('RCTNetworking');
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
const base64 = require('base64-js');
|
2016-04-11 12:53:41 +00:00
|
|
|
const invariant = require('fbjs/lib/invariant');
|
|
|
|
const warning = require('fbjs/lib/warning');
|
|
|
|
|
|
|
|
type ResponseType = '' | 'arraybuffer' | 'blob' | 'document' | 'json' | 'text';
|
|
|
|
type Response = ?Object | string;
|
2015-11-17 14:28:44 +00:00
|
|
|
|
2016-11-02 19:18:17 +00:00
|
|
|
type XHRInterceptor = {
|
2016-11-08 20:33:16 +00:00
|
|
|
requestSent(
|
2016-11-02 19:18:17 +00:00
|
|
|
id: number,
|
|
|
|
url: string,
|
|
|
|
method: string,
|
2016-11-08 20:33:16 +00:00
|
|
|
headers: Object
|
|
|
|
): void,
|
|
|
|
responseReceived(
|
2016-11-02 19:18:17 +00:00
|
|
|
id: number,
|
|
|
|
url: string,
|
|
|
|
status: number,
|
2016-11-08 20:33:16 +00:00
|
|
|
headers: Object
|
|
|
|
): void,
|
|
|
|
dataReceived(
|
2016-11-02 19:18:17 +00:00
|
|
|
id: number,
|
2016-11-08 20:33:16 +00:00
|
|
|
data: string
|
|
|
|
): void,
|
|
|
|
loadingFinished(
|
2016-11-02 19:18:17 +00:00
|
|
|
id: number,
|
2016-11-08 20:33:16 +00:00
|
|
|
encodedDataLength: number
|
|
|
|
): void,
|
|
|
|
loadingFailed(
|
2016-11-02 19:18:17 +00:00
|
|
|
id: number,
|
2016-11-08 20:33:16 +00:00
|
|
|
error: string
|
|
|
|
): void,
|
2016-11-02 19:18:17 +00:00
|
|
|
};
|
|
|
|
|
2016-02-17 07:58:49 +00:00
|
|
|
const UNSENT = 0;
|
|
|
|
const OPENED = 1;
|
|
|
|
const HEADERS_RECEIVED = 2;
|
|
|
|
const LOADING = 3;
|
|
|
|
const DONE = 4;
|
|
|
|
|
2016-04-11 12:53:41 +00:00
|
|
|
const SUPPORTED_RESPONSE_TYPES = {
|
|
|
|
arraybuffer: typeof global.ArrayBuffer === 'function',
|
|
|
|
blob: typeof global.Blob === 'function',
|
|
|
|
document: false,
|
|
|
|
json: true,
|
|
|
|
text: true,
|
|
|
|
'': true,
|
|
|
|
};
|
|
|
|
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
const REQUEST_EVENTS = [
|
|
|
|
'abort',
|
|
|
|
'error',
|
|
|
|
'load',
|
|
|
|
'loadstart',
|
|
|
|
'progress',
|
|
|
|
'timeout',
|
|
|
|
'loadend',
|
|
|
|
];
|
|
|
|
|
|
|
|
const XHR_EVENTS = REQUEST_EVENTS.concat('readystatechange');
|
|
|
|
|
|
|
|
class XMLHttpRequestEventTarget extends EventTarget(...REQUEST_EVENTS) {
|
|
|
|
onload: ?Function;
|
|
|
|
onloadstart: ?Function;
|
|
|
|
onprogress: ?Function;
|
|
|
|
ontimeout: ?Function;
|
|
|
|
onerror: ?Function;
|
|
|
|
onloadend: ?Function;
|
|
|
|
}
|
|
|
|
|
2015-03-24 21:40:11 +00:00
|
|
|
/**
|
|
|
|
* Shared base for platform-specific XMLHttpRequest implementations.
|
|
|
|
*/
|
2016-05-25 11:17:35 +00:00
|
|
|
class XMLHttpRequest extends EventTarget(...XHR_EVENTS) {
|
2015-03-24 21:40:11 +00:00
|
|
|
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
static UNSENT: number = UNSENT;
|
|
|
|
static OPENED: number = OPENED;
|
|
|
|
static HEADERS_RECEIVED: number = HEADERS_RECEIVED;
|
|
|
|
static LOADING: number = LOADING;
|
|
|
|
static DONE: number = DONE;
|
2016-02-17 07:58:49 +00:00
|
|
|
|
2016-11-02 19:18:17 +00:00
|
|
|
static _interceptor: ?XHRInterceptor = null;
|
|
|
|
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
UNSENT: number = UNSENT;
|
|
|
|
OPENED: number = OPENED;
|
|
|
|
HEADERS_RECEIVED: number = HEADERS_RECEIVED;
|
|
|
|
LOADING: number = LOADING;
|
|
|
|
DONE: number = DONE;
|
2015-03-24 21:40:11 +00:00
|
|
|
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
// EventTarget automatically initializes these to `null`.
|
2015-03-24 21:40:11 +00:00
|
|
|
onload: ?Function;
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
onloadstart: ?Function;
|
|
|
|
onprogress: ?Function;
|
2016-04-15 12:16:53 +00:00
|
|
|
ontimeout: ?Function;
|
|
|
|
onerror: ?Function;
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
onloadend: ?Function;
|
|
|
|
onreadystatechange: ?Function;
|
2015-03-24 21:40:11 +00:00
|
|
|
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
readyState: number = UNSENT;
|
|
|
|
responseHeaders: ?Object;
|
|
|
|
status: number = 0;
|
|
|
|
timeout: number = 0;
|
|
|
|
responseURL: ?string;
|
|
|
|
|
|
|
|
upload: XMLHttpRequestEventTarget = new XMLHttpRequestEventTarget();
|
2015-11-17 14:28:44 +00:00
|
|
|
|
|
|
|
_requestId: ?number;
|
2017-01-31 21:00:12 +00:00
|
|
|
_subscriptions: Array<*>;
|
2015-11-17 14:28:44 +00:00
|
|
|
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
_aborted: boolean = false;
|
2016-04-11 12:53:41 +00:00
|
|
|
_cachedResponse: Response;
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
_hasError: boolean = false;
|
2016-04-11 12:53:41 +00:00
|
|
|
_headers: Object;
|
2015-06-05 22:23:30 +00:00
|
|
|
_lowerCaseResponseHeaders: Object;
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
_method: ?string = null;
|
2016-04-11 12:53:41 +00:00
|
|
|
_response: string | ?Object;
|
|
|
|
_responseType: ResponseType;
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
_response: string = '';
|
2016-04-11 12:53:41 +00:00
|
|
|
_sent: boolean;
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
_url: ?string = null;
|
|
|
|
_timedOut: boolean = false;
|
2016-07-12 00:53:35 +00:00
|
|
|
_trackingName: string = 'unknown';
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
_incrementalEvents: boolean = false;
|
2015-03-24 21:40:11 +00:00
|
|
|
|
2016-11-02 19:18:17 +00:00
|
|
|
static setInterceptor(interceptor: ?XHRInterceptor) {
|
|
|
|
XMLHttpRequest._interceptor = interceptor;
|
|
|
|
}
|
|
|
|
|
2015-03-24 21:40:11 +00:00
|
|
|
constructor() {
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
super();
|
2015-06-05 22:23:30 +00:00
|
|
|
this._reset();
|
|
|
|
}
|
|
|
|
|
2016-04-11 12:53:41 +00:00
|
|
|
_reset(): void {
|
2015-03-24 21:40:11 +00:00
|
|
|
this.readyState = this.UNSENT;
|
|
|
|
this.responseHeaders = undefined;
|
2015-05-22 23:21:58 +00:00
|
|
|
this.status = 0;
|
2016-01-07 18:25:56 +00:00
|
|
|
delete this.responseURL;
|
2015-03-24 21:40:11 +00:00
|
|
|
|
2015-11-17 14:28:44 +00:00
|
|
|
this._requestId = null;
|
|
|
|
|
2016-04-11 12:53:41 +00:00
|
|
|
this._cachedResponse = undefined;
|
|
|
|
this._hasError = false;
|
2015-03-24 21:40:11 +00:00
|
|
|
this._headers = {};
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
this._response = '';
|
2016-04-11 12:53:41 +00:00
|
|
|
this._responseType = '';
|
2015-03-24 21:40:11 +00:00
|
|
|
this._sent = false;
|
2015-06-05 22:23:30 +00:00
|
|
|
this._lowerCaseResponseHeaders = {};
|
2015-11-17 14:28:44 +00:00
|
|
|
|
|
|
|
this._clearSubscriptions();
|
2016-04-15 12:16:53 +00:00
|
|
|
this._timedOut = false;
|
2015-11-17 14:28:44 +00:00
|
|
|
}
|
|
|
|
|
2016-04-11 12:53:41 +00:00
|
|
|
get responseType(): ResponseType {
|
|
|
|
return this._responseType;
|
|
|
|
}
|
|
|
|
|
|
|
|
set responseType(responseType: ResponseType): void {
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
if (this._sent) {
|
2016-04-11 12:53:41 +00:00
|
|
|
throw new Error(
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
'Failed to set the \'responseType\' property on \'XMLHttpRequest\': The ' +
|
|
|
|
'response type cannot be set after the request has been sent.'
|
2016-04-11 12:53:41 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
if (!SUPPORTED_RESPONSE_TYPES.hasOwnProperty(responseType)) {
|
|
|
|
warning(
|
2016-06-03 01:07:36 +00:00
|
|
|
false,
|
|
|
|
`The provided value '${responseType}' is not a valid 'responseType'.`
|
|
|
|
);
|
2016-04-11 12:53:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// redboxes early, e.g. for 'arraybuffer' on ios 7
|
|
|
|
invariant(
|
|
|
|
SUPPORTED_RESPONSE_TYPES[responseType] || responseType === 'document',
|
|
|
|
`The provided value '${responseType}' is unsupported in this environment.`
|
|
|
|
);
|
|
|
|
this._responseType = responseType;
|
|
|
|
}
|
|
|
|
|
2016-06-03 01:07:36 +00:00
|
|
|
get responseText(): string {
|
|
|
|
if (this._responseType !== '' && this._responseType !== 'text') {
|
|
|
|
throw new Error(
|
2016-07-14 11:51:22 +00:00
|
|
|
"The 'responseText' property is only available if 'responseType' " +
|
2016-06-03 01:07:36 +00:00
|
|
|
`is set to '' or 'text', but it is '${this._responseType}'.`
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (this.readyState < LOADING) {
|
|
|
|
return '';
|
|
|
|
}
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
return this._response;
|
2016-06-03 01:07:36 +00:00
|
|
|
}
|
|
|
|
|
2016-04-11 12:53:41 +00:00
|
|
|
get response(): Response {
|
|
|
|
const {responseType} = this;
|
|
|
|
if (responseType === '' || responseType === 'text') {
|
|
|
|
return this.readyState < LOADING || this._hasError
|
|
|
|
? ''
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
: this._response;
|
2016-04-11 12:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.readyState !== DONE) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._cachedResponse !== undefined) {
|
|
|
|
return this._cachedResponse;
|
|
|
|
}
|
|
|
|
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
switch (responseType) {
|
2016-04-11 12:53:41 +00:00
|
|
|
case 'document':
|
|
|
|
this._cachedResponse = null;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'arraybuffer':
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
this._cachedResponse = base64.toByteArray(this._response).buffer;
|
2016-04-11 12:53:41 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'blob':
|
|
|
|
this._cachedResponse = new global.Blob(
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
[base64.toByteArray(this._response).buffer],
|
2016-04-11 12:53:41 +00:00
|
|
|
{type: this.getResponseHeader('content-type') || ''}
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'json':
|
|
|
|
try {
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
this._cachedResponse = JSON.parse(this._response);
|
2016-04-11 12:53:41 +00:00
|
|
|
} catch (_) {
|
|
|
|
this._cachedResponse = null;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
this._cachedResponse = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this._cachedResponse;
|
|
|
|
}
|
|
|
|
|
2016-05-25 11:17:35 +00:00
|
|
|
// exposed for testing
|
|
|
|
__didCreateRequest(requestId: number): void {
|
2015-11-17 14:28:44 +00:00
|
|
|
this._requestId = requestId;
|
2016-11-02 19:18:17 +00:00
|
|
|
|
|
|
|
XMLHttpRequest._interceptor && XMLHttpRequest._interceptor.requestSent(
|
|
|
|
requestId,
|
|
|
|
this._url || '',
|
|
|
|
this._method || 'GET',
|
|
|
|
this._headers);
|
2015-11-17 14:28:44 +00:00
|
|
|
}
|
|
|
|
|
2016-05-09 17:35:19 +00:00
|
|
|
// exposed for testing
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
__didUploadProgress(
|
|
|
|
requestId: number,
|
|
|
|
progress: number,
|
|
|
|
total: number
|
|
|
|
): void {
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
if (requestId === this._requestId) {
|
|
|
|
this.upload.dispatchEvent({
|
|
|
|
type: 'progress',
|
2015-11-17 14:28:44 +00:00
|
|
|
lengthComputable: true,
|
|
|
|
loaded: progress,
|
|
|
|
total,
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
});
|
2015-11-17 14:28:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-03 01:07:36 +00:00
|
|
|
__didReceiveResponse(
|
|
|
|
requestId: number,
|
|
|
|
status: number,
|
|
|
|
responseHeaders: ?Object,
|
|
|
|
responseURL: ?string
|
|
|
|
): void {
|
2015-11-17 14:28:44 +00:00
|
|
|
if (requestId === this._requestId) {
|
|
|
|
this.status = status;
|
|
|
|
this.setResponseHeaders(responseHeaders);
|
|
|
|
this.setReadyState(this.HEADERS_RECEIVED);
|
2016-01-07 18:25:56 +00:00
|
|
|
if (responseURL || responseURL === '') {
|
|
|
|
this.responseURL = responseURL;
|
|
|
|
} else {
|
|
|
|
delete this.responseURL;
|
|
|
|
}
|
2016-11-02 19:18:17 +00:00
|
|
|
|
|
|
|
XMLHttpRequest._interceptor && XMLHttpRequest._interceptor.responseReceived(
|
|
|
|
requestId,
|
|
|
|
responseURL || this._url || '',
|
|
|
|
status,
|
|
|
|
responseHeaders || {});
|
2015-11-17 14:28:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
__didReceiveData(requestId: number, response: string): void {
|
|
|
|
if (requestId !== this._requestId) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this._response = response;
|
|
|
|
this._cachedResponse = undefined; // force lazy recomputation
|
|
|
|
this.setReadyState(this.LOADING);
|
2016-11-02 19:18:17 +00:00
|
|
|
|
|
|
|
XMLHttpRequest._interceptor && XMLHttpRequest._interceptor.dataReceived(
|
|
|
|
requestId,
|
|
|
|
response);
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
__didReceiveIncrementalData(
|
|
|
|
requestId: number,
|
|
|
|
responseText: string,
|
|
|
|
progress: number,
|
|
|
|
total: number
|
|
|
|
) {
|
|
|
|
if (requestId !== this._requestId) {
|
|
|
|
return;
|
2015-11-17 14:28:44 +00:00
|
|
|
}
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
if (!this._response) {
|
|
|
|
this._response = responseText;
|
|
|
|
} else {
|
|
|
|
this._response += responseText;
|
|
|
|
}
|
2016-11-02 19:18:17 +00:00
|
|
|
|
|
|
|
XMLHttpRequest._interceptor && XMLHttpRequest._interceptor.dataReceived(
|
|
|
|
requestId,
|
|
|
|
responseText);
|
|
|
|
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
this.setReadyState(this.LOADING);
|
|
|
|
this.__didReceiveDataProgress(requestId, progress, total);
|
|
|
|
}
|
|
|
|
|
|
|
|
__didReceiveDataProgress(
|
|
|
|
requestId: number,
|
|
|
|
loaded: number,
|
|
|
|
total: number
|
|
|
|
): void {
|
|
|
|
if (requestId !== this._requestId) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.dispatchEvent({
|
|
|
|
type: 'progress',
|
|
|
|
lengthComputable: total >= 0,
|
|
|
|
loaded,
|
|
|
|
total,
|
|
|
|
});
|
2015-11-17 14:28:44 +00:00
|
|
|
}
|
|
|
|
|
2016-05-09 17:35:19 +00:00
|
|
|
// exposed for testing
|
2016-06-03 01:07:36 +00:00
|
|
|
__didCompleteResponse(
|
|
|
|
requestId: number,
|
|
|
|
error: string,
|
|
|
|
timeOutError: boolean
|
|
|
|
): void {
|
2015-11-17 14:28:44 +00:00
|
|
|
if (requestId === this._requestId) {
|
|
|
|
if (error) {
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
if (this._responseType === '' || this._responseType === 'text') {
|
|
|
|
this._response = error;
|
|
|
|
}
|
2016-04-11 12:53:41 +00:00
|
|
|
this._hasError = true;
|
2016-04-15 12:16:53 +00:00
|
|
|
if (timeOutError) {
|
|
|
|
this._timedOut = true;
|
|
|
|
}
|
2015-11-17 14:28:44 +00:00
|
|
|
}
|
|
|
|
this._clearSubscriptions();
|
|
|
|
this._requestId = null;
|
|
|
|
this.setReadyState(this.DONE);
|
2016-11-02 19:18:17 +00:00
|
|
|
|
|
|
|
if (error) {
|
|
|
|
XMLHttpRequest._interceptor && XMLHttpRequest._interceptor.loadingFailed(
|
|
|
|
requestId,
|
|
|
|
error);
|
|
|
|
} else {
|
|
|
|
XMLHttpRequest._interceptor && XMLHttpRequest._interceptor.loadingFinished(
|
|
|
|
requestId,
|
|
|
|
this._response.length);
|
|
|
|
}
|
2015-11-17 14:28:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_clearSubscriptions(): void {
|
|
|
|
(this._subscriptions || []).forEach(sub => {
|
|
|
|
sub.remove();
|
|
|
|
});
|
|
|
|
this._subscriptions = [];
|
2015-03-24 21:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
getAllResponseHeaders(): ?string {
|
2015-06-05 22:23:30 +00:00
|
|
|
if (!this.responseHeaders) {
|
|
|
|
// according to the spec, return null if no response has been received
|
|
|
|
return null;
|
2015-04-21 23:43:07 +00:00
|
|
|
}
|
2015-06-05 22:23:30 +00:00
|
|
|
var headers = this.responseHeaders || {};
|
|
|
|
return Object.keys(headers).map((headerName) => {
|
|
|
|
return headerName + ': ' + headers[headerName];
|
2016-09-23 23:23:16 +00:00
|
|
|
}).join('\r\n');
|
2015-03-24 21:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
getResponseHeader(header: string): ?string {
|
2015-06-05 22:23:30 +00:00
|
|
|
var value = this._lowerCaseResponseHeaders[header.toLowerCase()];
|
|
|
|
return value !== undefined ? value : null;
|
2015-03-24 21:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
setRequestHeader(header: string, value: any): void {
|
2015-06-05 22:23:30 +00:00
|
|
|
if (this.readyState !== this.OPENED) {
|
|
|
|
throw new Error('Request has not been opened');
|
|
|
|
}
|
2016-10-26 05:18:20 +00:00
|
|
|
this._headers[header.toLowerCase()] = String(value);
|
2015-03-24 21:40:11 +00:00
|
|
|
}
|
|
|
|
|
2016-07-12 00:53:35 +00:00
|
|
|
/**
|
|
|
|
* Custom extension for tracking origins of request.
|
|
|
|
*/
|
|
|
|
setTrackingName(trackingName: string): XMLHttpRequest {
|
|
|
|
this._trackingName = trackingName;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2015-03-24 21:40:11 +00:00
|
|
|
open(method: string, url: string, async: ?boolean): void {
|
2015-06-05 22:23:30 +00:00
|
|
|
/* Other optional arguments are not supported yet */
|
2015-03-24 21:40:11 +00:00
|
|
|
if (this.readyState !== this.UNSENT) {
|
|
|
|
throw new Error('Cannot open, already sending');
|
|
|
|
}
|
|
|
|
if (async !== undefined && !async) {
|
|
|
|
// async is default
|
|
|
|
throw new Error('Synchronous http requests are not supported');
|
|
|
|
}
|
2016-01-07 12:00:15 +00:00
|
|
|
if (!url) {
|
|
|
|
throw new Error('Cannot load an empty url');
|
|
|
|
}
|
2016-04-13 13:47:29 +00:00
|
|
|
this._method = method.toUpperCase();
|
2015-03-24 21:40:11 +00:00
|
|
|
this._url = url;
|
|
|
|
this._aborted = false;
|
2015-06-05 22:23:30 +00:00
|
|
|
this.setReadyState(this.OPENED);
|
2015-03-24 21:40:11 +00:00
|
|
|
}
|
|
|
|
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
send(data: any): void {
|
|
|
|
if (this.readyState !== this.OPENED) {
|
|
|
|
throw new Error('Request has not been opened');
|
|
|
|
}
|
|
|
|
if (this._sent) {
|
|
|
|
throw new Error('Request has already been sent');
|
|
|
|
}
|
|
|
|
this._sent = true;
|
|
|
|
const incrementalEvents = this._incrementalEvents ||
|
|
|
|
!!this.onreadystatechange ||
|
|
|
|
!!this.onprogress;
|
|
|
|
|
2016-06-01 13:18:17 +00:00
|
|
|
this._subscriptions.push(RCTNetworking.addListener(
|
|
|
|
'didSendNetworkData',
|
|
|
|
(args) => this.__didUploadProgress(...args)
|
|
|
|
));
|
|
|
|
this._subscriptions.push(RCTNetworking.addListener(
|
|
|
|
'didReceiveNetworkResponse',
|
2016-06-03 01:07:36 +00:00
|
|
|
(args) => this.__didReceiveResponse(...args)
|
2016-06-01 13:18:17 +00:00
|
|
|
));
|
|
|
|
this._subscriptions.push(RCTNetworking.addListener(
|
|
|
|
'didReceiveNetworkData',
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
(args) => this.__didReceiveData(...args)
|
|
|
|
));
|
|
|
|
this._subscriptions.push(RCTNetworking.addListener(
|
|
|
|
'didReceiveNetworkIncrementalData',
|
|
|
|
(args) => this.__didReceiveIncrementalData(...args)
|
|
|
|
));
|
|
|
|
this._subscriptions.push(RCTNetworking.addListener(
|
|
|
|
'didReceiveNetworkDataProgress',
|
|
|
|
(args) => this.__didReceiveDataProgress(...args)
|
2016-06-01 13:18:17 +00:00
|
|
|
));
|
|
|
|
this._subscriptions.push(RCTNetworking.addListener(
|
|
|
|
'didCompleteNetworkResponse',
|
|
|
|
(args) => this.__didCompleteResponse(...args)
|
|
|
|
));
|
2015-03-24 21:40:11 +00:00
|
|
|
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
let nativeResponseType = 'text';
|
|
|
|
if (this._responseType === 'arraybuffer' || this._responseType === 'blob') {
|
|
|
|
nativeResponseType = 'base64';
|
2015-03-24 21:40:11 +00:00
|
|
|
}
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
|
|
|
|
invariant(this._method, 'Request method needs to be defined.');
|
|
|
|
invariant(this._url, 'Request URL needs to be defined.');
|
|
|
|
RCTNetworking.sendRequest(
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
this._method,
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
this._trackingName,
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
this._url,
|
|
|
|
this._headers,
|
|
|
|
data,
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
nativeResponseType,
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
incrementalEvents,
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
this.timeout,
|
|
|
|
this.__didCreateRequest.bind(this),
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
);
|
2015-03-24 21:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
abort(): void {
|
2015-06-05 22:23:30 +00:00
|
|
|
this._aborted = true;
|
2015-11-17 14:28:44 +00:00
|
|
|
if (this._requestId) {
|
|
|
|
RCTNetworking.abortRequest(this._requestId);
|
|
|
|
}
|
2015-03-24 21:40:11 +00:00
|
|
|
// only call onreadystatechange if there is something to abort,
|
|
|
|
// below logic is per spec
|
|
|
|
if (!(this.readyState === this.UNSENT ||
|
|
|
|
(this.readyState === this.OPENED && !this._sent) ||
|
|
|
|
this.readyState === this.DONE)) {
|
2015-06-05 22:23:30 +00:00
|
|
|
this._reset();
|
|
|
|
this.setReadyState(this.DONE);
|
2015-03-24 21:40:11 +00:00
|
|
|
}
|
2015-06-05 22:23:30 +00:00
|
|
|
// Reset again after, in case modified in handler
|
|
|
|
this._reset();
|
2015-03-24 21:40:11 +00:00
|
|
|
}
|
|
|
|
|
2015-06-05 22:23:30 +00:00
|
|
|
setResponseHeaders(responseHeaders: ?Object): void {
|
|
|
|
this.responseHeaders = responseHeaders || null;
|
|
|
|
var headers = responseHeaders || {};
|
|
|
|
this._lowerCaseResponseHeaders =
|
|
|
|
Object.keys(headers).reduce((lcaseHeaders, headerName) => {
|
|
|
|
lcaseHeaders[headerName.toLowerCase()] = headers[headerName];
|
2015-07-07 21:57:05 +00:00
|
|
|
return lcaseHeaders;
|
2015-06-05 22:23:30 +00:00
|
|
|
}, {});
|
2015-03-24 21:40:11 +00:00
|
|
|
}
|
|
|
|
|
2015-06-05 22:23:30 +00:00
|
|
|
setReadyState(newState: number): void {
|
2015-03-24 21:40:11 +00:00
|
|
|
this.readyState = newState;
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
this.dispatchEvent({type: 'readystatechange'});
|
2016-09-23 00:07:56 +00:00
|
|
|
if (newState === this.DONE) {
|
|
|
|
if (this._aborted) {
|
|
|
|
this.dispatchEvent({type: 'abort'});
|
|
|
|
} else if (this._hasError) {
|
2016-04-15 12:16:53 +00:00
|
|
|
if (this._timedOut) {
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
this.dispatchEvent({type: 'timeout'});
|
2016-04-15 12:16:53 +00:00
|
|
|
} else {
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
this.dispatchEvent({type: 'error'});
|
2016-04-15 12:16:53 +00:00
|
|
|
}
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
} else {
|
|
|
|
this.dispatchEvent({type: 'load'});
|
2016-04-15 12:16:53 +00:00
|
|
|
}
|
2016-09-23 00:07:56 +00:00
|
|
|
this.dispatchEvent({type: 'loadend'});
|
2015-06-05 22:23:30 +00:00
|
|
|
}
|
2015-03-24 21:40:11 +00:00
|
|
|
}
|
|
|
|
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
/* global EventListener */
|
|
|
|
addEventListener(type: string, listener: EventListener): void {
|
|
|
|
// If we dont' have a 'readystatechange' event handler, we don't
|
|
|
|
// have to send repeated LOADING events with incremental updates
|
|
|
|
// to responseText, which will avoid a bunch of native -> JS
|
|
|
|
// bridge traffic.
|
Add responseType as a concept to RCTNetworking, send binary data as base64
Summary:
In preparation for Blob support (wherein binary XHR and WebSocket responses can be retained as native data blobs on the native side and JS receives a web-like opaque Blob object), this change makes RCTNetworking aware of the responseType that JS requests. A `xhr.responseType` of `''` or `'text'` translates to a native response type of `'text'`. A `xhr.responseType` of `arraybuffer` translates to a native response type of `base64`, as we currently lack an API to transmit TypedArrays directly to JS. This is analogous to how the WebSocket module already works, and it's a lot more versatile and much less brittle than converting a JS *string* back to a TypedArray, which is what's currently going on.
Now that we don't always send text down to JS, JS consumers might still want to get progress updates about a binary download. This is what the `'progress'` event is designed for, so this change also implements that. This change also follows the XHR spec with regards to `xhr.response` and `xhr.responseText`:
- if the response type is `'text'`, `xhr.responseText` can be peeked at by the JS consumer. It will be updated periodically as the download progresses, so long as there's either an `onreadystatechange` or `onprogress` handler on the XHR.
- if the response type is not `'text'`, `xhr.responseText` can't be accessed and `xhr.response` remains `null` until the response is fully received. `'progress'` events containing response details (total bytes, downloaded so far) are dispatched if there's an `onprogress` handler.
Once Blobs are landed, `xhr.responseType` of `'blob'` will correspond to the same native response type, which will cause RCTNetworking to only send a blob ID down to JS, which can then create a `Blob` object from that for consumers.
Closes https://github.com/facebook/react-native/pull/8324
Reviewed By: javache
Differential Revision: D3508822
Pulled By: davidaurelio
fbshipit-source-id: 441b2d4d40265b6036559c3ccb9fa962999fa5df
2016-07-13 11:53:54 +00:00
|
|
|
if (type === 'readystatechange' || type === 'progress') {
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
this._incrementalEvents = true;
|
2015-03-24 21:40:11 +00:00
|
|
|
}
|
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets
Summary:
So far, XHR only supports a few `onfoo` event handlers, not the entier `EventTarget` interface (`addEventListener`, `removeEventListener`). It also doesn't support the `upload` object on Android -- for no good reason. Even if we don't send any events there yet, there's no reason we have to break consuming code that wants to register an event handler there. This PR rectifies all that.
Fortunately, adding proper `EventTarget` support is very easy thanks to `event-target-shim`. We already use it in our WebSocket implementation. It transparently handles the `addEventListener('foo', ...)` as well as `onfoo` APIs, so when you dispatch an event on the event target, the right handlers will be invoked. The event object is wrapped so that `event.target` is set properly. Basically, it's a super easy way to make us conform to the spec.
Also added a bit of polish here and there, using ES2015 class property goodness to consolidate a lot of Flow property definitions with the corresponding property initializers.
**T
Closes https://github.com/facebook/react-native/pull/7017
Reviewed By: fkgozali
Differential Revision: D3202021
Pulled By: martinbigio
fb-gh-sync-id: 2b007682074356c75c774fab337672918b6c4355
fbshipit-source-id: 2b007682074356c75c774fab337672918b6c4355
2016-04-28 22:58:25 +00:00
|
|
|
super.addEventListener(type, listener);
|
2015-03-24 21:40:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-25 11:17:35 +00:00
|
|
|
module.exports = XMLHttpRequest;
|