@react-native-oh/react-native-harmony 0.72.10 → 0.72.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/Components/Button/Button.harmony.js +1 -1
- package/Libraries/Components/ScrollView/ScrollView.harmony.js +9 -20
- package/Libraries/Components/TextInput/TextInput.harmony.js +1 -1
- package/index.js +14 -4
- package/metro.config.js +154 -74
- package/package.json +4 -3
- package/{rnoh-4.0.0.200.har → rnoh-4.0.0.201-09-vmall.har} +0 -0
- package/types/index.d.ts +7 -7
- package/Libraries/Network/XMLHttpRequest.harmony.js +0 -677
|
@@ -38,7 +38,7 @@ import Dimensions from "react-native/Libraries/Utilities/Dimensions";
|
|
|
38
38
|
import dismissKeyboard from "react-native/Libraries/Utilities/dismissKeyboard";
|
|
39
39
|
import Platform from "../../Utilities/Platform";
|
|
40
40
|
import Keyboard from "react-native/Libraries/Components/Keyboard/Keyboard";
|
|
41
|
-
import TextInputState from "
|
|
41
|
+
import TextInputState from "../TextInput/TextInputState.harmony";
|
|
42
42
|
import View from "react-native/Libraries/Components/View/View";
|
|
43
43
|
import AndroidHorizontalScrollContentViewNativeComponent from "react-native/Libraries/Components/ScrollView/AndroidHorizontalScrollContentViewNativeComponent";
|
|
44
44
|
import AndroidHorizontalScrollViewNativeComponent from "react-native/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent";
|
|
@@ -914,15 +914,12 @@ class ScrollView extends React.Component<Props, State> {
|
|
|
914
914
|
if (this._scrollView.nativeInstance == null) {
|
|
915
915
|
return;
|
|
916
916
|
}
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
animated !== false
|
|
924
|
-
);
|
|
925
|
-
}, 100)
|
|
917
|
+
Commands.scrollTo(
|
|
918
|
+
this._scrollView.nativeInstance,
|
|
919
|
+
x || 0,
|
|
920
|
+
y || 0,
|
|
921
|
+
animated !== false
|
|
922
|
+
);
|
|
926
923
|
};
|
|
927
924
|
|
|
928
925
|
/**
|
|
@@ -1812,18 +1809,10 @@ class ScrollView extends React.Component<Props, State> {
|
|
|
1812
1809
|
// default to true
|
|
1813
1810
|
snapToEnd: this.props.snapToEnd !== false,
|
|
1814
1811
|
// pagingEnabled is overridden by snapToInterval / snapToOffsets
|
|
1815
|
-
pagingEnabled:
|
|
1816
|
-
// on iOS, pagingEnabled must be set to false to have snapToInterval / snapToOffsets work
|
|
1817
|
-
ios:
|
|
1812
|
+
pagingEnabled:
|
|
1818
1813
|
this.props.pagingEnabled === true &&
|
|
1819
1814
|
this.props.snapToInterval == null &&
|
|
1820
|
-
this.props.snapToOffsets == null,
|
|
1821
|
-
// on Android, pagingEnabled must be set to true to have snapToInterval / snapToOffsets work
|
|
1822
|
-
android:
|
|
1823
|
-
this.props.pagingEnabled === true ||
|
|
1824
|
-
this.props.snapToInterval != null ||
|
|
1825
|
-
this.props.snapToOffsets != null,
|
|
1826
|
-
}),
|
|
1815
|
+
this.props.snapToOffsets == null,
|
|
1827
1816
|
};
|
|
1828
1817
|
|
|
1829
1818
|
const { decelerationRate } = this.props;
|
|
@@ -30,7 +30,7 @@ import Text from 'react-native/Libraries/Text/Text';
|
|
|
30
30
|
import TextAncestor from 'react-native/Libraries/Text/TextAncestor';
|
|
31
31
|
import Platform from '../../Utilities/Platform';
|
|
32
32
|
import useMergeRefs from 'react-native/Libraries/Utilities/useMergeRefs';
|
|
33
|
-
import TextInputState from '
|
|
33
|
+
import TextInputState from './TextInputState.harmony';
|
|
34
34
|
import invariant from 'invariant';
|
|
35
35
|
import nullthrows from 'nullthrows';
|
|
36
36
|
import * as React from 'react';
|
package/index.js
CHANGED
|
@@ -65,7 +65,7 @@ module.exports = {
|
|
|
65
65
|
get Keyboard() {
|
|
66
66
|
return require('react-native/Libraries/Components/Keyboard/Keyboard');
|
|
67
67
|
},
|
|
68
|
-
get KeyboardAvoidingView(){
|
|
68
|
+
get KeyboardAvoidingView() {
|
|
69
69
|
return require('react-native/Libraries/Components/Keyboard/KeyboardAvoidingView')
|
|
70
70
|
.default;
|
|
71
71
|
},
|
|
@@ -89,6 +89,13 @@ module.exports = {
|
|
|
89
89
|
get RefreshControl() {
|
|
90
90
|
return require('./Libraries/Components/RefreshControl/RefreshControl');
|
|
91
91
|
},
|
|
92
|
+
get requireNativeComponent() {
|
|
93
|
+
return require('react-native/Libraries/ReactNative/requireNativeComponent')
|
|
94
|
+
.default;
|
|
95
|
+
},
|
|
96
|
+
get RootTagContext() {
|
|
97
|
+
return require('react-native/Libraries/ReactNative/RootTag').RootTagContext;
|
|
98
|
+
},
|
|
92
99
|
get SafeAreaView() {
|
|
93
100
|
return require('./Libraries/Components/SafeAreaView/SafeAreaView').default;
|
|
94
101
|
},
|
|
@@ -114,16 +121,16 @@ module.exports = {
|
|
|
114
121
|
return require('react-native/Libraries/Components/Touchable/Touchable');
|
|
115
122
|
},
|
|
116
123
|
get TouchableHighlight() {
|
|
117
|
-
return require(
|
|
124
|
+
return require('./Libraries/Components/Touchable/TouchableHighlight');
|
|
118
125
|
},
|
|
119
126
|
get TouchableNativeFeedback() {
|
|
120
|
-
return require(
|
|
127
|
+
return require('./Libraries/Components/Touchable/TouchableNativeFeedback');
|
|
121
128
|
},
|
|
122
129
|
get TouchableOpacity() {
|
|
123
130
|
return require('react-native/Libraries/Components/Touchable/TouchableOpacity');
|
|
124
131
|
},
|
|
125
132
|
get TouchableWithoutFeedback() {
|
|
126
|
-
return require(
|
|
133
|
+
return require('./Libraries/Components/Touchable/TouchableWithoutFeedback');
|
|
127
134
|
},
|
|
128
135
|
get TurboModuleRegistry() {
|
|
129
136
|
return require('react-native/Libraries/TurboModule/TurboModuleRegistry');
|
|
@@ -174,5 +181,8 @@ module.exports = {
|
|
|
174
181
|
return require('react-native/Libraries/Renderer/shims/ReactNative')
|
|
175
182
|
.dispatchCommand;
|
|
176
183
|
},
|
|
184
|
+
get EventEmitter() {
|
|
185
|
+
return require('react-native/Libraries/vendor/emitter/EventEmitter')
|
|
186
|
+
}
|
|
177
187
|
// END: react-native-harmony specific exports
|
|
178
188
|
};
|
package/metro.config.js
CHANGED
|
@@ -1,79 +1,109 @@
|
|
|
1
1
|
//@ts-check
|
|
2
2
|
const pathUtils = require('path');
|
|
3
3
|
const fs = require('fs');
|
|
4
|
+
const colors = require('colors/safe');
|
|
5
|
+
|
|
6
|
+
let shouldPrintInfoAboutRNRedirection = true;
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
|
-
* @
|
|
9
|
+
* @param msg {string}
|
|
7
10
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
11
|
+
function info(msg) {
|
|
12
|
+
const infoPrefix = '[' + colors.bold(colors.cyan(`INFO`)) + ']';
|
|
13
|
+
console.log(infoPrefix, msg);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param options {{reactNativeHarmonyPackageName: string} | undefined}
|
|
18
|
+
* @returns {import("metro-config").InputConfigT}
|
|
19
|
+
*/
|
|
20
|
+
function createHarmonyMetroConfig(options) {
|
|
21
|
+
const reactNativeHarmonyName =
|
|
22
|
+
options?.reactNativeHarmonyPackageName ?? 'react-native-harmony';
|
|
23
|
+
return {
|
|
24
|
+
transformer: {
|
|
25
|
+
assetRegistryPath: 'react-native/Libraries/Image/AssetRegistry',
|
|
26
|
+
getTransformOptions: async () => ({
|
|
27
|
+
transform: {
|
|
28
|
+
experimentalImportSupport: false,
|
|
29
|
+
inlineRequires: true,
|
|
30
|
+
},
|
|
31
|
+
}),
|
|
32
|
+
},
|
|
33
|
+
resolver: {
|
|
34
|
+
/** By default, Metro pickups files from native, "harmony" directory what causes conflicts. */
|
|
35
|
+
blockList: [/\\harmony\/.*/],
|
|
36
|
+
resolveRequest: (ctx, moduleName, platform) => {
|
|
37
|
+
if (platform === 'harmony') {
|
|
38
|
+
if (shouldPrintInfoAboutRNRedirection) {
|
|
39
|
+
info(
|
|
40
|
+
`Redirected imports from ${colors.bold(
|
|
41
|
+
colors.gray('react-native'),
|
|
42
|
+
)} to ${colors.bold(reactNativeHarmonyName)}`,
|
|
35
43
|
);
|
|
36
|
-
|
|
37
|
-
return ctx.resolveRequest(
|
|
38
|
-
ctx,
|
|
39
|
-
`react-native-harmony${pathUtils.sep}${modulePathRelativeToReactNative}`,
|
|
40
|
-
'harmony'
|
|
41
|
-
);
|
|
42
|
-
} catch (err) {}
|
|
44
|
+
shouldPrintInfoAboutRNRedirection = false;
|
|
43
45
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const alias = getPackageName(moduleName);
|
|
56
|
-
if (alias) {
|
|
57
|
-
const harmonyPackageName = harmonyPackageNameByAlias[alias];
|
|
58
|
-
if (
|
|
59
|
-
harmonyPackageName &&
|
|
60
|
-
!isRequestFromHarmonyPackage(
|
|
61
|
-
ctx.originModulePath,
|
|
62
|
-
harmonyPackageName
|
|
63
|
-
)
|
|
64
|
-
) {
|
|
65
|
-
return ctx.resolveRequest(
|
|
66
|
-
ctx,
|
|
67
|
-
moduleName.replace(alias, harmonyPackageName),
|
|
68
|
-
platform
|
|
46
|
+
if (moduleName === 'react-native') {
|
|
47
|
+
return ctx.resolveRequest(ctx, reactNativeHarmonyName, platform);
|
|
48
|
+
} else if (moduleName.startsWith('react-native/')) {
|
|
49
|
+
return ctx.resolveRequest(ctx, moduleName, 'ios');
|
|
50
|
+
} else if (
|
|
51
|
+
isInternalReactNativeRelativeImport(ctx.originModulePath)
|
|
52
|
+
) {
|
|
53
|
+
if (moduleName.startsWith('.')) {
|
|
54
|
+
const moduleAbsPath = pathUtils.resolve(
|
|
55
|
+
pathUtils.dirname(ctx.originModulePath),
|
|
56
|
+
moduleName,
|
|
69
57
|
);
|
|
58
|
+
const [_, modulePathRelativeToReactNative] = moduleAbsPath.split(
|
|
59
|
+
`${pathUtils.sep}node_modules${pathUtils.sep}react-native${pathUtils.sep}`,
|
|
60
|
+
);
|
|
61
|
+
try {
|
|
62
|
+
return ctx.resolveRequest(
|
|
63
|
+
ctx,
|
|
64
|
+
`${reactNativeHarmonyName}${pathUtils.sep}${modulePathRelativeToReactNative}`,
|
|
65
|
+
'harmony',
|
|
66
|
+
);
|
|
67
|
+
} catch (err) {}
|
|
68
|
+
}
|
|
69
|
+
return ctx.resolveRequest(ctx, moduleName, 'ios');
|
|
70
|
+
} else {
|
|
71
|
+
/**
|
|
72
|
+
* Replace `react-native-foo` with `react-native-harmony-foo` if a package has harmony directory and proper package.json configuration e.g.
|
|
73
|
+
*
|
|
74
|
+
* react-native-harmony-foo/package.json:
|
|
75
|
+
* "harmony": {
|
|
76
|
+
* "alias": "react-native-foo"
|
|
77
|
+
* }
|
|
78
|
+
*/
|
|
79
|
+
const harmonyPackageNameByAlias = getHarmonyPackageNameByAlias('.');
|
|
80
|
+
const alias = getPackageName(moduleName);
|
|
81
|
+
if (alias) {
|
|
82
|
+
const harmonyPackageName = harmonyPackageNameByAlias[alias];
|
|
83
|
+
if (
|
|
84
|
+
harmonyPackageName &&
|
|
85
|
+
!isRequestFromHarmonyPackage(
|
|
86
|
+
ctx.originModulePath,
|
|
87
|
+
harmonyPackageName,
|
|
88
|
+
)
|
|
89
|
+
) {
|
|
90
|
+
return ctx.resolveRequest(
|
|
91
|
+
ctx,
|
|
92
|
+
moduleName.replace(alias, harmonyPackageName),
|
|
93
|
+
platform,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
70
96
|
}
|
|
71
97
|
}
|
|
72
98
|
}
|
|
73
|
-
|
|
74
|
-
|
|
99
|
+
return ctx.resolveRequest(ctx, moduleName, platform);
|
|
100
|
+
},
|
|
75
101
|
},
|
|
76
|
-
}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = {
|
|
106
|
+
createHarmonyMetroConfig,
|
|
77
107
|
};
|
|
78
108
|
|
|
79
109
|
/**
|
|
@@ -104,7 +134,7 @@ function getPackageName(moduleName) {
|
|
|
104
134
|
*/
|
|
105
135
|
function isInternalReactNativeRelativeImport(originModulePath) {
|
|
106
136
|
return originModulePath.includes(
|
|
107
|
-
`${pathUtils.sep}node_modules${pathUtils.sep}react-native${pathUtils.sep}
|
|
137
|
+
`${pathUtils.sep}node_modules${pathUtils.sep}react-native${pathUtils.sep}`,
|
|
108
138
|
);
|
|
109
139
|
}
|
|
110
140
|
|
|
@@ -114,8 +144,10 @@ function isInternalReactNativeRelativeImport(originModulePath) {
|
|
|
114
144
|
* @returns {boolean}
|
|
115
145
|
*/
|
|
116
146
|
function isRequestFromHarmonyPackage(originModulePath, harmonyPackageName) {
|
|
147
|
+
const slashes = new RegExp('/', 'g');
|
|
148
|
+
const packagePath = harmonyPackageName.replace(slashes, pathUtils.sep);
|
|
117
149
|
return originModulePath.includes(
|
|
118
|
-
`${pathUtils.sep}node_modules${pathUtils.sep}${
|
|
150
|
+
`${pathUtils.sep}node_modules${pathUtils.sep}${packagePath}${pathUtils.sep}`,
|
|
119
151
|
);
|
|
120
152
|
}
|
|
121
153
|
|
|
@@ -136,13 +168,20 @@ function getHarmonyPackageNameByAlias(projectRootPath) {
|
|
|
136
168
|
return cachedHarmonyPackageAliasByName;
|
|
137
169
|
}
|
|
138
170
|
cachedHarmonyPackageAliasByName = findHarmonyNodeModulePaths(
|
|
139
|
-
projectRootPath
|
|
171
|
+
findHarmonyNodeModuleSearchPaths(projectRootPath),
|
|
140
172
|
).reduce((acc, harmonyNodeModulePath) => {
|
|
141
173
|
const harmonyNodeModulePathSegments = harmonyNodeModulePath.split(
|
|
142
|
-
pathUtils.sep
|
|
174
|
+
pathUtils.sep,
|
|
143
175
|
);
|
|
144
|
-
|
|
176
|
+
let harmonyNodeModuleName =
|
|
145
177
|
harmonyNodeModulePathSegments[harmonyNodeModulePathSegments.length - 1];
|
|
178
|
+
if (harmonyNodeModulePathSegments.length > 1) {
|
|
179
|
+
const harmonyNodeModuleParentDirName =
|
|
180
|
+
harmonyNodeModulePathSegments[harmonyNodeModulePathSegments.length - 2];
|
|
181
|
+
if (harmonyNodeModuleParentDirName.startsWith('@')) {
|
|
182
|
+
harmonyNodeModuleName = `${harmonyNodeModuleParentDirName}/${harmonyNodeModuleName}`;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
146
185
|
const packageJSONPath = `${harmonyNodeModulePath}${pathUtils.sep}package.json`;
|
|
147
186
|
const packageJSON = readHarmonyModulePackageJSON(packageJSONPath);
|
|
148
187
|
const alias = packageJSON.harmony?.alias;
|
|
@@ -151,8 +190,32 @@ function getHarmonyPackageNameByAlias(projectRootPath) {
|
|
|
151
190
|
}
|
|
152
191
|
return acc;
|
|
153
192
|
}, initialAcc);
|
|
154
|
-
|
|
155
|
-
|
|
193
|
+
const harmonyPackagesCount = Object.keys(
|
|
194
|
+
cachedHarmonyPackageAliasByName,
|
|
195
|
+
).length;
|
|
196
|
+
if (harmonyPackagesCount > 0) {
|
|
197
|
+
const prettyHarmonyPackagesCount = colors.bold(
|
|
198
|
+
harmonyPackagesCount > 0
|
|
199
|
+
? colors.green(harmonyPackagesCount.toString())
|
|
200
|
+
: harmonyPackagesCount.toString(),
|
|
201
|
+
);
|
|
202
|
+
info(
|
|
203
|
+
`Redirected imports to ${prettyHarmonyPackagesCount} harmony-specific third-party package(s):`,
|
|
204
|
+
);
|
|
205
|
+
if (harmonyPackagesCount > 0) {
|
|
206
|
+
Object.entries(cachedHarmonyPackageAliasByName).forEach(
|
|
207
|
+
([original, alias]) => {
|
|
208
|
+
info(
|
|
209
|
+
`• ${colors.bold(colors.gray(original))} → ${colors.bold(alias)}`,
|
|
210
|
+
);
|
|
211
|
+
},
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
} else {
|
|
215
|
+
info('No harmony-specific third-party packages have been detected');
|
|
216
|
+
}
|
|
217
|
+
console.log('');
|
|
218
|
+
|
|
156
219
|
return cachedHarmonyPackageAliasByName;
|
|
157
220
|
}
|
|
158
221
|
|
|
@@ -160,12 +223,29 @@ function getHarmonyPackageNameByAlias(projectRootPath) {
|
|
|
160
223
|
* @param projectRootPath {string}
|
|
161
224
|
* @returns {string[]}
|
|
162
225
|
*/
|
|
163
|
-
function
|
|
226
|
+
function findHarmonyNodeModuleSearchPaths(projectRootPath) {
|
|
164
227
|
const nodeModulesPath = `${projectRootPath}${pathUtils.sep}node_modules`;
|
|
165
|
-
|
|
228
|
+
const searchPaths = fs
|
|
166
229
|
.readdirSync(nodeModulesPath)
|
|
167
|
-
.
|
|
168
|
-
.
|
|
230
|
+
.filter(dirName => dirName.startsWith('@'))
|
|
231
|
+
.map(dirName => `${nodeModulesPath}${pathUtils.sep}${dirName}`);
|
|
232
|
+
searchPaths.push(nodeModulesPath);
|
|
233
|
+
return searchPaths;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @param searchPaths {string[]}
|
|
238
|
+
* @returns {string[]}
|
|
239
|
+
*/
|
|
240
|
+
function findHarmonyNodeModulePaths(searchPaths) {
|
|
241
|
+
return searchPaths
|
|
242
|
+
.map(searchPath => {
|
|
243
|
+
return fs
|
|
244
|
+
.readdirSync(searchPath)
|
|
245
|
+
.map(dirName => `${searchPath}${pathUtils.sep}${dirName}`)
|
|
246
|
+
.filter(hasNodeModulePathHarmonyCode);
|
|
247
|
+
})
|
|
248
|
+
.flat();
|
|
169
249
|
}
|
|
170
250
|
|
|
171
251
|
/**
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-native-oh/react-native-harmony",
|
|
3
|
-
"version": "0.72.
|
|
4
|
-
|
|
3
|
+
"version": "0.72.11",
|
|
4
|
+
"description": "",
|
|
5
|
+
"publishConfig": {
|
|
5
6
|
"registry": "https://registry.npmjs.org/",
|
|
6
7
|
"access": "public"
|
|
7
8
|
},
|
|
8
|
-
"description": "",
|
|
9
9
|
"scripts": {
|
|
10
10
|
"install:dev-cli": "cd ../react-native-harmony-cli && npm pack && cd ../react-native-harmony && npm i ../react-native-harmony-cli/rnoh-react-native-harmony-cli-0.0.15.tgz && cd ../react-native-harmony",
|
|
11
11
|
"pack:harmony": "react-native pack-harmony --oh-module-path ../tester/harmony/rnoh --harmony-dir-path ./harmony --package-json-path ./package.json",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@react-native-oh/react-native-harmony-cli": "^0.0.15",
|
|
41
|
+
"colors": "^1.4.0",
|
|
41
42
|
"fs-extra": "^11.1.1",
|
|
42
43
|
"metro": "^0.76.3",
|
|
43
44
|
"metro-config": "^0.76.3"
|
|
Binary file
|
package/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// export * from 'react-native/Libraries/ActionSheetIOS/ActionSheetIOS';
|
|
2
|
-
export * from
|
|
2
|
+
export * from 'react-native/Libraries/Alert/Alert';
|
|
3
3
|
export * from 'react-native/Libraries/Animated/Animated';
|
|
4
4
|
export * from 'react-native/Libraries/Animated/Easing';
|
|
5
5
|
export * from 'react-native/Libraries/Animated/useAnimatedValue';
|
|
@@ -31,7 +31,7 @@ export * from 'react-native/Libraries/Components/Touchable/TouchableNativeFeedba
|
|
|
31
31
|
export * from 'react-native/Libraries/Components/Touchable/TouchableOpacity';
|
|
32
32
|
export * from 'react-native/Libraries/Components/Touchable/TouchableWithoutFeedback';
|
|
33
33
|
export * from 'react-native/Libraries/Components/View/View';
|
|
34
|
-
|
|
34
|
+
export * from 'react-native/Libraries/Components/View/ViewAccessibility';
|
|
35
35
|
export * from 'react-native/Libraries/Components/View/ViewPropTypes';
|
|
36
36
|
export * from 'react-native/Libraries/Components/Button';
|
|
37
37
|
export * from 'react-native/Libraries/EventEmitter/NativeEventEmitter';
|
|
@@ -47,7 +47,7 @@ export * from 'react-native/Libraries/LayoutAnimation/LayoutAnimation';
|
|
|
47
47
|
export * from 'react-native/Libraries/Linking/Linking';
|
|
48
48
|
export * from 'react-native/Libraries/Lists/FlatList';
|
|
49
49
|
export * from 'react-native/Libraries/Lists/SectionList';
|
|
50
|
-
export * from 'react-native/
|
|
50
|
+
export * from '@react-native/virtualized-lists';
|
|
51
51
|
// export * from 'react-native/Libraries/LogBox/LogBox';
|
|
52
52
|
export * from 'react-native/Libraries/Modal/Modal';
|
|
53
53
|
// export * as Systrace from 'react-native/Libraries/Performance/Systrace';
|
|
@@ -56,9 +56,9 @@ export * from 'react-native/Libraries/Modal/Modal';
|
|
|
56
56
|
export * from 'react-native/Libraries/ReactNative/AppRegistry';
|
|
57
57
|
export * from 'react-native/Libraries/ReactNative/I18nManager';
|
|
58
58
|
export * from 'react-native/Libraries/ReactNative/RendererProxy';
|
|
59
|
-
|
|
59
|
+
export * from 'react-native/Libraries/ReactNative/RootTag';
|
|
60
60
|
export * from 'react-native/Libraries/ReactNative/UIManager';
|
|
61
|
-
|
|
61
|
+
export * from 'react-native/Libraries/ReactNative/requireNativeComponent';
|
|
62
62
|
// export * from 'react-native/Libraries/Settings/Settings';
|
|
63
63
|
// export * from 'react-native/Libraries/Share/Share';
|
|
64
64
|
// export * from 'react-native/Libraries/StyleSheet/PlatformColorValueTypesIOS';
|
|
@@ -69,7 +69,7 @@ export * from 'react-native/Libraries/StyleSheet/processColor';
|
|
|
69
69
|
export * from 'react-native/Libraries/Text/Text';
|
|
70
70
|
// export * from 'react-native/Libraries/TurboModule/RCTExport';
|
|
71
71
|
export * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry';
|
|
72
|
-
|
|
72
|
+
export * from 'react-native/Libraries/Types/CoreEventTypes';
|
|
73
73
|
export * from 'react-native/Libraries/Utilities/Appearance';
|
|
74
74
|
export * from 'react-native/Libraries/Utilities/BackHandler';
|
|
75
75
|
// export * from 'react-native/Libraries/Utilities/DevSettings';
|
|
@@ -79,7 +79,7 @@ export * from '../Libraries/Utilities/Platform';
|
|
|
79
79
|
export * from 'react-native/Libraries/Vibration/Vibration';
|
|
80
80
|
// export * from 'react-native/Libraries/YellowBox/YellowBoxDeprecated';
|
|
81
81
|
// export * from 'react-native/Libraries/vendor/core/ErrorUtils';
|
|
82
|
-
|
|
82
|
+
export * from 'react-native/Libraries/vendor/emitter/EventEmitter';
|
|
83
83
|
|
|
84
84
|
export * from 'react-native/types/public/DeprecatedPropertiesAlias';
|
|
85
85
|
export * from 'react-native/types/public/Insets';
|
|
@@ -1,677 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RNOH: patch
|
|
3
|
-
* - imports
|
|
4
|
-
* - forces responseType to be 'text'
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
9
|
-
*
|
|
10
|
-
* This source code is licensed under the MIT license found in the
|
|
11
|
-
* LICENSE file in the root directory of this source tree.
|
|
12
|
-
*
|
|
13
|
-
* @format
|
|
14
|
-
* @flow
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
'use strict';
|
|
18
|
-
|
|
19
|
-
import type {IPerformanceLogger} from 'react-native/Libraries/Utilities/createPerformanceLogger';
|
|
20
|
-
|
|
21
|
-
import {type EventSubscription} from 'react-native/Libraries/vendor/emitter/EventEmitter';
|
|
22
|
-
import EventTarget from 'event-target-shim';
|
|
23
|
-
|
|
24
|
-
const BlobManager = require('react-native/Libraries/Blob/BlobManager');
|
|
25
|
-
const GlobalPerformanceLogger = require('react-native/Libraries/Utilities/GlobalPerformanceLogger');
|
|
26
|
-
const RCTNetworking = require('react-native/Libraries/Network/RCTNetworking').default;
|
|
27
|
-
const base64 = require('base64-js');
|
|
28
|
-
const invariant = require('invariant');
|
|
29
|
-
|
|
30
|
-
const DEBUG_NETWORK_SEND_DELAY: false = false; // Set to a number of milliseconds when debugging
|
|
31
|
-
|
|
32
|
-
export type NativeResponseType = 'base64' | 'blob' | 'text';
|
|
33
|
-
export type ResponseType =
|
|
34
|
-
| ''
|
|
35
|
-
| 'arraybuffer'
|
|
36
|
-
| 'blob'
|
|
37
|
-
| 'document'
|
|
38
|
-
| 'json'
|
|
39
|
-
| 'text';
|
|
40
|
-
export type Response = ?Object | string;
|
|
41
|
-
|
|
42
|
-
type XHRInterceptor = interface {
|
|
43
|
-
requestSent(id: number, url: string, method: string, headers: Object): void,
|
|
44
|
-
responseReceived(
|
|
45
|
-
id: number,
|
|
46
|
-
url: string,
|
|
47
|
-
status: number,
|
|
48
|
-
headers: Object,
|
|
49
|
-
): void,
|
|
50
|
-
dataReceived(id: number, data: string): void,
|
|
51
|
-
loadingFinished(id: number, encodedDataLength: number): void,
|
|
52
|
-
loadingFailed(id: number, error: string): void,
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
// The native blob module is optional so inject it here if available.
|
|
56
|
-
if (BlobManager.isAvailable) {
|
|
57
|
-
BlobManager.addNetworkingHandler();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const UNSENT = 0;
|
|
61
|
-
const OPENED = 1;
|
|
62
|
-
const HEADERS_RECEIVED = 2;
|
|
63
|
-
const LOADING = 3;
|
|
64
|
-
const DONE = 4;
|
|
65
|
-
|
|
66
|
-
const SUPPORTED_RESPONSE_TYPES = {
|
|
67
|
-
arraybuffer: false, // RNOH: patch - typeof global.ArrayBuffer === 'function',
|
|
68
|
-
blob: false, // RNOH: patch - typeof global.Blob === 'function',
|
|
69
|
-
document: false,
|
|
70
|
-
json: true,
|
|
71
|
-
text: true,
|
|
72
|
-
'': true,
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const REQUEST_EVENTS = [
|
|
76
|
-
'abort',
|
|
77
|
-
'error',
|
|
78
|
-
'load',
|
|
79
|
-
'loadstart',
|
|
80
|
-
'progress',
|
|
81
|
-
'timeout',
|
|
82
|
-
'loadend',
|
|
83
|
-
];
|
|
84
|
-
|
|
85
|
-
const XHR_EVENTS = REQUEST_EVENTS.concat('readystatechange');
|
|
86
|
-
|
|
87
|
-
class XMLHttpRequestEventTarget extends (EventTarget(...REQUEST_EVENTS): any) {
|
|
88
|
-
onload: ?Function;
|
|
89
|
-
onloadstart: ?Function;
|
|
90
|
-
onprogress: ?Function;
|
|
91
|
-
ontimeout: ?Function;
|
|
92
|
-
onerror: ?Function;
|
|
93
|
-
onabort: ?Function;
|
|
94
|
-
onloadend: ?Function;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Shared base for platform-specific XMLHttpRequest implementations.
|
|
99
|
-
*/
|
|
100
|
-
class XMLHttpRequest extends (EventTarget(...XHR_EVENTS): any) {
|
|
101
|
-
static UNSENT: number = UNSENT;
|
|
102
|
-
static OPENED: number = OPENED;
|
|
103
|
-
static HEADERS_RECEIVED: number = HEADERS_RECEIVED;
|
|
104
|
-
static LOADING: number = LOADING;
|
|
105
|
-
static DONE: number = DONE;
|
|
106
|
-
|
|
107
|
-
static _interceptor: ?XHRInterceptor = null;
|
|
108
|
-
|
|
109
|
-
UNSENT: number = UNSENT;
|
|
110
|
-
OPENED: number = OPENED;
|
|
111
|
-
HEADERS_RECEIVED: number = HEADERS_RECEIVED;
|
|
112
|
-
LOADING: number = LOADING;
|
|
113
|
-
DONE: number = DONE;
|
|
114
|
-
|
|
115
|
-
// EventTarget automatically initializes these to `null`.
|
|
116
|
-
onload: ?Function;
|
|
117
|
-
onloadstart: ?Function;
|
|
118
|
-
onprogress: ?Function;
|
|
119
|
-
ontimeout: ?Function;
|
|
120
|
-
onerror: ?Function;
|
|
121
|
-
onabort: ?Function;
|
|
122
|
-
onloadend: ?Function;
|
|
123
|
-
onreadystatechange: ?Function;
|
|
124
|
-
|
|
125
|
-
readyState: number = UNSENT;
|
|
126
|
-
responseHeaders: ?Object;
|
|
127
|
-
status: number = 0;
|
|
128
|
-
timeout: number = 0;
|
|
129
|
-
responseURL: ?string;
|
|
130
|
-
withCredentials: boolean = true;
|
|
131
|
-
|
|
132
|
-
upload: XMLHttpRequestEventTarget = new XMLHttpRequestEventTarget();
|
|
133
|
-
|
|
134
|
-
_requestId: ?number;
|
|
135
|
-
_subscriptions: Array<EventSubscription>;
|
|
136
|
-
|
|
137
|
-
_aborted: boolean = false;
|
|
138
|
-
_cachedResponse: Response;
|
|
139
|
-
_hasError: boolean = false;
|
|
140
|
-
_headers: Object;
|
|
141
|
-
_lowerCaseResponseHeaders: Object;
|
|
142
|
-
_method: ?string = null;
|
|
143
|
-
_perfKey: ?string = null;
|
|
144
|
-
_responseType: ResponseType;
|
|
145
|
-
_response: string = '';
|
|
146
|
-
_sent: boolean;
|
|
147
|
-
_url: ?string = null;
|
|
148
|
-
_timedOut: boolean = false;
|
|
149
|
-
_trackingName: string = 'unknown';
|
|
150
|
-
_incrementalEvents: boolean = false;
|
|
151
|
-
_performanceLogger: IPerformanceLogger = GlobalPerformanceLogger;
|
|
152
|
-
|
|
153
|
-
static setInterceptor(interceptor: ?XHRInterceptor) {
|
|
154
|
-
XMLHttpRequest._interceptor = interceptor;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
constructor() {
|
|
158
|
-
super();
|
|
159
|
-
this._reset();
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
_reset(): void {
|
|
163
|
-
this.readyState = this.UNSENT;
|
|
164
|
-
this.responseHeaders = undefined;
|
|
165
|
-
this.status = 0;
|
|
166
|
-
delete this.responseURL;
|
|
167
|
-
|
|
168
|
-
this._requestId = null;
|
|
169
|
-
|
|
170
|
-
this._cachedResponse = undefined;
|
|
171
|
-
this._hasError = false;
|
|
172
|
-
this._headers = {};
|
|
173
|
-
this._response = '';
|
|
174
|
-
this._responseType = '';
|
|
175
|
-
this._sent = false;
|
|
176
|
-
this._lowerCaseResponseHeaders = {};
|
|
177
|
-
|
|
178
|
-
this._clearSubscriptions();
|
|
179
|
-
this._timedOut = false;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
get responseType(): ResponseType {
|
|
183
|
-
return this._responseType;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
set responseType(responseType: ResponseType): void {
|
|
187
|
-
if (this._sent) {
|
|
188
|
-
throw new Error(
|
|
189
|
-
"Failed to set the 'responseType' property on 'XMLHttpRequest': The " +
|
|
190
|
-
'response type cannot be set after the request has been sent.',
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// RNOH: patch
|
|
195
|
-
this._responseType = "text"
|
|
196
|
-
return
|
|
197
|
-
if (!SUPPORTED_RESPONSE_TYPES.hasOwnProperty(responseType)) {
|
|
198
|
-
console.warn(
|
|
199
|
-
`The provided value '${responseType}' is not a valid 'responseType'.`,
|
|
200
|
-
);
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// redboxes early, e.g. for 'arraybuffer' on ios 7
|
|
205
|
-
invariant(
|
|
206
|
-
SUPPORTED_RESPONSE_TYPES[responseType] || responseType === 'document',
|
|
207
|
-
`The provided value '${responseType}' is unsupported in this environment.`,
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
if (responseType === 'blob') {
|
|
211
|
-
invariant(
|
|
212
|
-
BlobManager.isAvailable,
|
|
213
|
-
'Native module BlobModule is required for blob support',
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
this._responseType = responseType;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
get responseText(): string {
|
|
220
|
-
if (this._responseType !== '' && this._responseType !== 'text') {
|
|
221
|
-
throw new Error(
|
|
222
|
-
"The 'responseText' property is only available if 'responseType' " +
|
|
223
|
-
`is set to '' or 'text', but it is '${this._responseType}'.`,
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
if (this.readyState < LOADING) {
|
|
227
|
-
return '';
|
|
228
|
-
}
|
|
229
|
-
return this._response;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
get response(): Response {
|
|
233
|
-
const {responseType} = this;
|
|
234
|
-
if (responseType === '' || responseType === 'text') {
|
|
235
|
-
return this.readyState < LOADING || this._hasError ? '' : this._response;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (this.readyState !== DONE) {
|
|
239
|
-
return null;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (this._cachedResponse !== undefined) {
|
|
243
|
-
return this._cachedResponse;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
switch (responseType) {
|
|
247
|
-
case 'document':
|
|
248
|
-
this._cachedResponse = null;
|
|
249
|
-
break;
|
|
250
|
-
|
|
251
|
-
case 'arraybuffer':
|
|
252
|
-
this._cachedResponse = base64.toByteArray(this._response).buffer;
|
|
253
|
-
break;
|
|
254
|
-
|
|
255
|
-
case 'blob':
|
|
256
|
-
if (typeof this._response === 'object' && this._response) {
|
|
257
|
-
this._cachedResponse = BlobManager.createFromOptions(this._response);
|
|
258
|
-
} else if (this._response === '') {
|
|
259
|
-
this._cachedResponse = BlobManager.createFromParts([]);
|
|
260
|
-
} else {
|
|
261
|
-
throw new Error(`Invalid response for blob: ${this._response}`);
|
|
262
|
-
}
|
|
263
|
-
break;
|
|
264
|
-
|
|
265
|
-
case 'json':
|
|
266
|
-
try {
|
|
267
|
-
this._cachedResponse = JSON.parse(this._response);
|
|
268
|
-
} catch (_) {
|
|
269
|
-
this._cachedResponse = null;
|
|
270
|
-
}
|
|
271
|
-
break;
|
|
272
|
-
|
|
273
|
-
default:
|
|
274
|
-
this._cachedResponse = null;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
return this._cachedResponse;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// exposed for testing
|
|
281
|
-
__didCreateRequest(requestId: number): void {
|
|
282
|
-
this._requestId = requestId;
|
|
283
|
-
|
|
284
|
-
XMLHttpRequest._interceptor &&
|
|
285
|
-
XMLHttpRequest._interceptor.requestSent(
|
|
286
|
-
requestId,
|
|
287
|
-
this._url || '',
|
|
288
|
-
this._method || 'GET',
|
|
289
|
-
this._headers,
|
|
290
|
-
);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// exposed for testing
|
|
294
|
-
__didUploadProgress(
|
|
295
|
-
requestId: number,
|
|
296
|
-
progress: number,
|
|
297
|
-
total: number,
|
|
298
|
-
): void {
|
|
299
|
-
if (requestId === this._requestId) {
|
|
300
|
-
this.upload.dispatchEvent({
|
|
301
|
-
type: 'progress',
|
|
302
|
-
lengthComputable: true,
|
|
303
|
-
loaded: progress,
|
|
304
|
-
total,
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
__didReceiveResponse(
|
|
310
|
-
requestId: number,
|
|
311
|
-
status: number,
|
|
312
|
-
responseHeaders: ?Object,
|
|
313
|
-
responseURL: ?string,
|
|
314
|
-
): void {
|
|
315
|
-
if (requestId === this._requestId) {
|
|
316
|
-
this._perfKey != null &&
|
|
317
|
-
this._performanceLogger.stopTimespan(this._perfKey);
|
|
318
|
-
this.status = status;
|
|
319
|
-
this.setResponseHeaders(responseHeaders);
|
|
320
|
-
this.setReadyState(this.HEADERS_RECEIVED);
|
|
321
|
-
if (responseURL || responseURL === '') {
|
|
322
|
-
this.responseURL = responseURL;
|
|
323
|
-
} else {
|
|
324
|
-
delete this.responseURL;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
XMLHttpRequest._interceptor &&
|
|
328
|
-
XMLHttpRequest._interceptor.responseReceived(
|
|
329
|
-
requestId,
|
|
330
|
-
responseURL || this._url || '',
|
|
331
|
-
status,
|
|
332
|
-
responseHeaders || {},
|
|
333
|
-
);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
__didReceiveData(requestId: number, response: string): void {
|
|
338
|
-
if (requestId !== this._requestId) {
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
this._response = response;
|
|
342
|
-
this._cachedResponse = undefined; // force lazy recomputation
|
|
343
|
-
this.setReadyState(this.LOADING);
|
|
344
|
-
|
|
345
|
-
XMLHttpRequest._interceptor &&
|
|
346
|
-
XMLHttpRequest._interceptor.dataReceived(requestId, response);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
__didReceiveIncrementalData(
|
|
350
|
-
requestId: number,
|
|
351
|
-
responseText: string,
|
|
352
|
-
progress: number,
|
|
353
|
-
total: number,
|
|
354
|
-
) {
|
|
355
|
-
if (requestId !== this._requestId) {
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
if (!this._response) {
|
|
359
|
-
this._response = responseText;
|
|
360
|
-
} else {
|
|
361
|
-
this._response += responseText;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
XMLHttpRequest._interceptor &&
|
|
365
|
-
XMLHttpRequest._interceptor.dataReceived(requestId, responseText);
|
|
366
|
-
|
|
367
|
-
this.setReadyState(this.LOADING);
|
|
368
|
-
this.__didReceiveDataProgress(requestId, progress, total);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
__didReceiveDataProgress(
|
|
372
|
-
requestId: number,
|
|
373
|
-
loaded: number,
|
|
374
|
-
total: number,
|
|
375
|
-
): void {
|
|
376
|
-
if (requestId !== this._requestId) {
|
|
377
|
-
return;
|
|
378
|
-
}
|
|
379
|
-
this.dispatchEvent({
|
|
380
|
-
type: 'progress',
|
|
381
|
-
lengthComputable: total >= 0,
|
|
382
|
-
loaded,
|
|
383
|
-
total,
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// exposed for testing
|
|
388
|
-
__didCompleteResponse(
|
|
389
|
-
requestId: number,
|
|
390
|
-
error: string,
|
|
391
|
-
timeOutError: boolean,
|
|
392
|
-
): void {
|
|
393
|
-
if (requestId === this._requestId) {
|
|
394
|
-
if (error) {
|
|
395
|
-
if (this._responseType === '' || this._responseType === 'text') {
|
|
396
|
-
this._response = error;
|
|
397
|
-
}
|
|
398
|
-
this._hasError = true;
|
|
399
|
-
if (timeOutError) {
|
|
400
|
-
this._timedOut = true;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
this._clearSubscriptions();
|
|
404
|
-
this._requestId = null;
|
|
405
|
-
this.setReadyState(this.DONE);
|
|
406
|
-
|
|
407
|
-
if (error) {
|
|
408
|
-
XMLHttpRequest._interceptor &&
|
|
409
|
-
XMLHttpRequest._interceptor.loadingFailed(requestId, error);
|
|
410
|
-
} else {
|
|
411
|
-
XMLHttpRequest._interceptor &&
|
|
412
|
-
XMLHttpRequest._interceptor.loadingFinished(
|
|
413
|
-
requestId,
|
|
414
|
-
this._response.length,
|
|
415
|
-
);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
_clearSubscriptions(): void {
|
|
421
|
-
(this._subscriptions || []).forEach(sub => {
|
|
422
|
-
if (sub) {
|
|
423
|
-
sub.remove();
|
|
424
|
-
}
|
|
425
|
-
});
|
|
426
|
-
this._subscriptions = [];
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
getAllResponseHeaders(): ?string {
|
|
430
|
-
if (!this.responseHeaders) {
|
|
431
|
-
// according to the spec, return null if no response has been received
|
|
432
|
-
return null;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
// Assign to non-nullable local variable.
|
|
436
|
-
const responseHeaders = this.responseHeaders;
|
|
437
|
-
|
|
438
|
-
const unsortedHeaders: Map<
|
|
439
|
-
string,
|
|
440
|
-
{lowerHeaderName: string, upperHeaderName: string, headerValue: string},
|
|
441
|
-
> = new Map();
|
|
442
|
-
for (const rawHeaderName of Object.keys(responseHeaders)) {
|
|
443
|
-
const headerValue = responseHeaders[rawHeaderName];
|
|
444
|
-
const lowerHeaderName = rawHeaderName.toLowerCase();
|
|
445
|
-
const header = unsortedHeaders.get(lowerHeaderName);
|
|
446
|
-
if (header) {
|
|
447
|
-
header.headerValue += ', ' + headerValue;
|
|
448
|
-
unsortedHeaders.set(lowerHeaderName, header);
|
|
449
|
-
} else {
|
|
450
|
-
unsortedHeaders.set(lowerHeaderName, {
|
|
451
|
-
lowerHeaderName,
|
|
452
|
-
upperHeaderName: rawHeaderName.toUpperCase(),
|
|
453
|
-
headerValue,
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// Sort in ascending order, with a being less than b if a's name is legacy-uppercased-byte less than b's name.
|
|
459
|
-
const sortedHeaders = [...unsortedHeaders.values()].sort((a, b) => {
|
|
460
|
-
if (a.upperHeaderName < b.upperHeaderName) {
|
|
461
|
-
return -1;
|
|
462
|
-
}
|
|
463
|
-
if (a.upperHeaderName > b.upperHeaderName) {
|
|
464
|
-
return 1;
|
|
465
|
-
}
|
|
466
|
-
return 0;
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
// Combine into single text response.
|
|
470
|
-
return (
|
|
471
|
-
sortedHeaders
|
|
472
|
-
.map(header => {
|
|
473
|
-
return header.lowerHeaderName + ': ' + header.headerValue;
|
|
474
|
-
})
|
|
475
|
-
.join('\r\n') + '\r\n'
|
|
476
|
-
);
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
getResponseHeader(header: string): ?string {
|
|
480
|
-
const value = this._lowerCaseResponseHeaders[header.toLowerCase()];
|
|
481
|
-
return value !== undefined ? value : null;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
setRequestHeader(header: string, value: any): void {
|
|
485
|
-
if (this.readyState !== this.OPENED) {
|
|
486
|
-
throw new Error('Request has not been opened');
|
|
487
|
-
}
|
|
488
|
-
this._headers[header.toLowerCase()] = String(value);
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
/**
|
|
492
|
-
* Custom extension for tracking origins of request.
|
|
493
|
-
*/
|
|
494
|
-
setTrackingName(trackingName: string): XMLHttpRequest {
|
|
495
|
-
this._trackingName = trackingName;
|
|
496
|
-
return this;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
/**
|
|
500
|
-
* Custom extension for setting a custom performance logger
|
|
501
|
-
*/
|
|
502
|
-
setPerformanceLogger(performanceLogger: IPerformanceLogger): XMLHttpRequest {
|
|
503
|
-
this._performanceLogger = performanceLogger;
|
|
504
|
-
return this;
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
open(method: string, url: string, async: ?boolean): void {
|
|
508
|
-
/* Other optional arguments are not supported yet */
|
|
509
|
-
if (this.readyState !== this.UNSENT) {
|
|
510
|
-
throw new Error('Cannot open, already sending');
|
|
511
|
-
}
|
|
512
|
-
if (async !== undefined && !async) {
|
|
513
|
-
// async is default
|
|
514
|
-
throw new Error('Synchronous http requests are not supported');
|
|
515
|
-
}
|
|
516
|
-
if (!url) {
|
|
517
|
-
throw new Error('Cannot load an empty url');
|
|
518
|
-
}
|
|
519
|
-
this._method = method.toUpperCase();
|
|
520
|
-
this._url = url;
|
|
521
|
-
this._aborted = false;
|
|
522
|
-
this.setReadyState(this.OPENED);
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
send(data: any): void {
|
|
526
|
-
if (this.readyState !== this.OPENED) {
|
|
527
|
-
throw new Error('Request has not been opened');
|
|
528
|
-
}
|
|
529
|
-
if (this._sent) {
|
|
530
|
-
throw new Error('Request has already been sent');
|
|
531
|
-
}
|
|
532
|
-
this._sent = true;
|
|
533
|
-
const incrementalEvents =
|
|
534
|
-
this._incrementalEvents || !!this.onreadystatechange || !!this.onprogress;
|
|
535
|
-
|
|
536
|
-
this._subscriptions.push(
|
|
537
|
-
RCTNetworking.addListener('didSendNetworkData', args =>
|
|
538
|
-
this.__didUploadProgress(...args),
|
|
539
|
-
),
|
|
540
|
-
);
|
|
541
|
-
this._subscriptions.push(
|
|
542
|
-
RCTNetworking.addListener('didReceiveNetworkResponse', args =>
|
|
543
|
-
this.__didReceiveResponse(...args),
|
|
544
|
-
),
|
|
545
|
-
);
|
|
546
|
-
this._subscriptions.push(
|
|
547
|
-
RCTNetworking.addListener('didReceiveNetworkData', args =>
|
|
548
|
-
this.__didReceiveData(...args),
|
|
549
|
-
),
|
|
550
|
-
);
|
|
551
|
-
this._subscriptions.push(
|
|
552
|
-
RCTNetworking.addListener('didReceiveNetworkIncrementalData', args =>
|
|
553
|
-
this.__didReceiveIncrementalData(...args),
|
|
554
|
-
),
|
|
555
|
-
);
|
|
556
|
-
this._subscriptions.push(
|
|
557
|
-
RCTNetworking.addListener('didReceiveNetworkDataProgress', args =>
|
|
558
|
-
this.__didReceiveDataProgress(...args),
|
|
559
|
-
),
|
|
560
|
-
);
|
|
561
|
-
this._subscriptions.push(
|
|
562
|
-
RCTNetworking.addListener('didCompleteNetworkResponse', args =>
|
|
563
|
-
this.__didCompleteResponse(...args),
|
|
564
|
-
),
|
|
565
|
-
);
|
|
566
|
-
|
|
567
|
-
let nativeResponseType: NativeResponseType = 'text';
|
|
568
|
-
if (this._responseType === 'arraybuffer') {
|
|
569
|
-
nativeResponseType = 'base64';
|
|
570
|
-
}
|
|
571
|
-
if (this._responseType === 'blob') {
|
|
572
|
-
nativeResponseType = 'blob';
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
const doSend = () => {
|
|
576
|
-
const friendlyName =
|
|
577
|
-
this._trackingName !== 'unknown' ? this._trackingName : this._url;
|
|
578
|
-
this._perfKey = 'network_XMLHttpRequest_' + String(friendlyName);
|
|
579
|
-
this._performanceLogger.startTimespan(this._perfKey);
|
|
580
|
-
invariant(
|
|
581
|
-
this._method,
|
|
582
|
-
'XMLHttpRequest method needs to be defined (%s).',
|
|
583
|
-
friendlyName,
|
|
584
|
-
);
|
|
585
|
-
invariant(
|
|
586
|
-
this._url,
|
|
587
|
-
'XMLHttpRequest URL needs to be defined (%s).',
|
|
588
|
-
friendlyName,
|
|
589
|
-
);
|
|
590
|
-
RCTNetworking.sendRequest(
|
|
591
|
-
this._method,
|
|
592
|
-
this._trackingName,
|
|
593
|
-
this._url,
|
|
594
|
-
this._headers,
|
|
595
|
-
data,
|
|
596
|
-
/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found
|
|
597
|
-
* when making Flow check .android.js files. */
|
|
598
|
-
nativeResponseType,
|
|
599
|
-
incrementalEvents,
|
|
600
|
-
this.timeout,
|
|
601
|
-
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
|
|
602
|
-
this.__didCreateRequest.bind(this),
|
|
603
|
-
this.withCredentials,
|
|
604
|
-
);
|
|
605
|
-
};
|
|
606
|
-
if (DEBUG_NETWORK_SEND_DELAY) {
|
|
607
|
-
setTimeout(doSend, DEBUG_NETWORK_SEND_DELAY);
|
|
608
|
-
} else {
|
|
609
|
-
doSend();
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
abort(): void {
|
|
614
|
-
this._aborted = true;
|
|
615
|
-
if (this._requestId) {
|
|
616
|
-
RCTNetworking.abortRequest(this._requestId);
|
|
617
|
-
}
|
|
618
|
-
// only call onreadystatechange if there is something to abort,
|
|
619
|
-
// below logic is per spec
|
|
620
|
-
if (
|
|
621
|
-
!(
|
|
622
|
-
this.readyState === this.UNSENT ||
|
|
623
|
-
(this.readyState === this.OPENED && !this._sent) ||
|
|
624
|
-
this.readyState === this.DONE
|
|
625
|
-
)
|
|
626
|
-
) {
|
|
627
|
-
this._reset();
|
|
628
|
-
this.setReadyState(this.DONE);
|
|
629
|
-
}
|
|
630
|
-
// Reset again after, in case modified in handler
|
|
631
|
-
this._reset();
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
setResponseHeaders(responseHeaders: ?Object): void {
|
|
635
|
-
this.responseHeaders = responseHeaders || null;
|
|
636
|
-
const headers = responseHeaders || {};
|
|
637
|
-
this._lowerCaseResponseHeaders = Object.keys(headers).reduce<{
|
|
638
|
-
[string]: any,
|
|
639
|
-
}>((lcaseHeaders, headerName) => {
|
|
640
|
-
lcaseHeaders[headerName.toLowerCase()] = headers[headerName];
|
|
641
|
-
return lcaseHeaders;
|
|
642
|
-
}, {});
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
setReadyState(newState: number): void {
|
|
646
|
-
this.readyState = newState;
|
|
647
|
-
this.dispatchEvent({type: 'readystatechange'});
|
|
648
|
-
if (newState === this.DONE) {
|
|
649
|
-
if (this._aborted) {
|
|
650
|
-
this.dispatchEvent({type: 'abort'});
|
|
651
|
-
} else if (this._hasError) {
|
|
652
|
-
if (this._timedOut) {
|
|
653
|
-
this.dispatchEvent({type: 'timeout'});
|
|
654
|
-
} else {
|
|
655
|
-
this.dispatchEvent({type: 'error'});
|
|
656
|
-
}
|
|
657
|
-
} else {
|
|
658
|
-
this.dispatchEvent({type: 'load'});
|
|
659
|
-
}
|
|
660
|
-
this.dispatchEvent({type: 'loadend'});
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
/* global EventListener */
|
|
665
|
-
addEventListener(type: string, listener: EventListener): void {
|
|
666
|
-
// If we dont' have a 'readystatechange' event handler, we don't
|
|
667
|
-
// have to send repeated LOADING events with incremental updates
|
|
668
|
-
// to responseText, which will avoid a bunch of native -> JS
|
|
669
|
-
// bridge traffic.
|
|
670
|
-
if (type === 'readystatechange' || type === 'progress') {
|
|
671
|
-
this._incrementalEvents = true;
|
|
672
|
-
}
|
|
673
|
-
super.addEventListener(type, listener);
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
module.exports = XMLHttpRequest;
|