Validate that JS and Native code versions match for RN releases
Summary: Basic implementation of the proposal in #15271 Note that this should not affect facebook internally since they are not using OSS releases. Points to consider: - How strict should the version match be, right now I just match exact versions. - Wasn't able to use haste for ReactNativeVersion because I was getting duplicate module provider caused by the template file in scripts/versiontemplates. I tried adding the scripts folder to modulePathIgnorePatterns in package.json but that didn't help. - Redscreen vs. warning, I think warning is useless because if the app crashes you won't have time to see the warning. - Should the check and native modules be __DEV__ only? **Test plan** Tested that it works when version match and that it redscreens when versions don't before getting other errors on Android and iOS. Closes https://github.com/facebook/react-native/pull/15518 Differential Revision: D5813551 Pulled By: hramos fbshipit-source-id: 901757e25724b0f22bf39de172b56309d0dd5a95
This commit is contained in:
parent
9b3cc30357
commit
1af645b2fd
|
@ -116,6 +116,23 @@ if (!global.__fbDisableExceptionsManager) {
|
|||
ErrorUtils.setGlobalHandler(handleError);
|
||||
}
|
||||
|
||||
const formatVersion = version =>
|
||||
`${version.major}.${version.minor}.${version.patch}` +
|
||||
(version.prerelease !== null ? `-${version.prerelease}` : '');
|
||||
|
||||
const ReactNativeVersion = require('ReactNativeVersion');
|
||||
const nativeVersion = require('NativeModules').PlatformConstants.reactNativeVersion;
|
||||
if (ReactNativeVersion.version.major !== nativeVersion.major ||
|
||||
ReactNativeVersion.version.minor !== nativeVersion.minor) {
|
||||
throw new Error(
|
||||
`React Native version mismatch.\n\nJavaScript version: ${formatVersion(ReactNativeVersion.version)}\n` +
|
||||
`Native version: ${formatVersion(nativeVersion)}\n\n` +
|
||||
'Make sure that you have rebuilt the native code. If the problem persists ' +
|
||||
'try clearing the watchman and packager caches with `watchman watch-del-all ' +
|
||||
'&& react-native start --reset-cache`.'
|
||||
);
|
||||
}
|
||||
|
||||
// Set up collections
|
||||
const _shouldPolyfillCollection = require('_shouldPolyfillES6Collection');
|
||||
if (_shouldPolyfillCollection('Map')) {
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* @generated by scripts/bump-oss-version.js
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @flow
|
||||
* @providesModule ReactNativeVersion
|
||||
*/
|
||||
|
||||
exports.version = {
|
||||
major: 0,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
prerelease: null,
|
||||
};
|
|
@ -12,6 +12,7 @@
|
|||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTUtils.h"
|
||||
#import "RCTVersion.h"
|
||||
|
||||
static NSString *interfaceIdiom(UIUserInterfaceIdiom idiom) {
|
||||
switch(idiom) {
|
||||
|
@ -46,6 +47,7 @@ RCT_EXPORT_MODULE(PlatformConstants)
|
|||
@"systemName": [device systemName],
|
||||
@"interfaceIdiom": interfaceIdiom([device userInterfaceIdiom]),
|
||||
@"isTesting": @(RCTRunningInTestEnvironment()),
|
||||
@"reactNativeVersion": REACT_NATIVE_VERSION,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* @generated by scripts/bump-oss-version.js
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define REACT_NATIVE_VERSION @{ \
|
||||
@"major": @(0), \
|
||||
@"minor": @(0), \
|
||||
@"patch": @(0), \
|
||||
@"prerelease": [NSNull null], \
|
||||
}
|
|
@ -203,6 +203,8 @@
|
|||
14F7A0F01BDA714B003C6C10 /* RCTFPSGraph.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F7A0EF1BDA714B003C6C10 /* RCTFPSGraph.m */; };
|
||||
191E3EBE1C29D9AF00C180A6 /* RCTRefreshControlManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 191E3EBD1C29D9AF00C180A6 /* RCTRefreshControlManager.m */; };
|
||||
191E3EC11C29DC3800C180A6 /* RCTRefreshControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 191E3EC01C29DC3800C180A6 /* RCTRefreshControl.m */; };
|
||||
199B8A6F1F44DB16005DEF67 /* RCTVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = 199B8A6E1F44DB16005DEF67 /* RCTVersion.h */; };
|
||||
199B8A761F44DEDA005DEF67 /* RCTVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = 199B8A6E1F44DB16005DEF67 /* RCTVersion.h */; };
|
||||
19F61BFA1E8495CD00571D81 /* bignum-dtoa.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 139D7E3A1E25C5A300323FB7 /* bignum-dtoa.h */; };
|
||||
19F61BFB1E8495CD00571D81 /* bignum.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 139D7E3C1E25C5A300323FB7 /* bignum.h */; };
|
||||
19F61BFC1E8495CD00571D81 /* cached-powers.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 139D7E3E1E25C5A300323FB7 /* cached-powers.h */; };
|
||||
|
@ -1921,6 +1923,7 @@
|
|||
191E3EBD1C29D9AF00C180A6 /* RCTRefreshControlManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRefreshControlManager.m; sourceTree = "<group>"; };
|
||||
191E3EBF1C29DC3800C180A6 /* RCTRefreshControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRefreshControl.h; sourceTree = "<group>"; };
|
||||
191E3EC01C29DC3800C180A6 /* RCTRefreshControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRefreshControl.m; sourceTree = "<group>"; };
|
||||
199B8A6E1F44DB16005DEF67 /* RCTVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTVersion.h; sourceTree = "<group>"; };
|
||||
19DED2281E77E29200F089BB /* systemJSCWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = systemJSCWrapper.cpp; sourceTree = "<group>"; };
|
||||
27B958731E57587D0096647A /* JSBigString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBigString.cpp; sourceTree = "<group>"; };
|
||||
2D2A28131D9B038B00D4039D /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -2750,6 +2753,7 @@
|
|||
1345A83B1B265A0E00583190 /* RCTURLRequestHandler.h */,
|
||||
83CBBA4F1A601E3B00E9B192 /* RCTUtils.h */,
|
||||
83CBBA501A601E3B00E9B192 /* RCTUtils.m */,
|
||||
199B8A6E1F44DB16005DEF67 /* RCTVersion.h */,
|
||||
);
|
||||
path = Base;
|
||||
sourceTree = "<group>";
|
||||
|
@ -2903,6 +2907,7 @@
|
|||
3D302F411DF828F800D6DDAE /* RCTModuleMethod.h in Headers */,
|
||||
3D302F421DF828F800D6DDAE /* RCTMultipartDataTask.h in Headers */,
|
||||
3D302F431DF828F800D6DDAE /* RCTMultipartStreamReader.h in Headers */,
|
||||
199B8A761F44DEDA005DEF67 /* RCTVersion.h in Headers */,
|
||||
3D302F441DF828F800D6DDAE /* RCTNullability.h in Headers */,
|
||||
3D302F451DF828F800D6DDAE /* RCTParserUtils.h in Headers */,
|
||||
3D302F461DF828F800D6DDAE /* RCTPerformanceLogger.h in Headers */,
|
||||
|
@ -3145,6 +3150,7 @@
|
|||
3D80DA191DF820620028D040 /* RCTImageLoader.h in Headers */,
|
||||
C654505E1F3BD9280090799B /* RCTManagedPointer.h in Headers */,
|
||||
13134C941E296B2A00B9F3CB /* RCTObjcExecutor.h in Headers */,
|
||||
199B8A6F1F44DB16005DEF67 /* RCTVersion.h in Headers */,
|
||||
3D80DA1A1DF820620028D040 /* RCTImageStoreManager.h in Headers */,
|
||||
130443A11E3FEAA900D93A67 /* RCTFollyConvert.h in Headers */,
|
||||
59FBEFB41E46D91C0095D885 /* RCTScrollContentViewManager.h in Headers */,
|
||||
|
|
|
@ -38,6 +38,7 @@ public class AndroidInfoModule extends BaseJavaModule {
|
|||
constants.put("Version", Build.VERSION.SDK_INT);
|
||||
constants.put("ServerHost", AndroidInfoHelpers.getServerHost());
|
||||
constants.put("isTesting", "true".equals(System.getProperty(IS_TESTING)));
|
||||
constants.put("reactNativeVersion", ReactNativeVersion.VERSION);
|
||||
return constants;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ android_library(
|
|||
name = "systeminfo",
|
||||
srcs = [
|
||||
"AndroidInfoModule.java",
|
||||
"ReactNativeVersion.java",
|
||||
],
|
||||
exported_deps = [
|
||||
":systeminfo-moduleless",
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* @generated by scripts/bump-oss-version.js
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.facebook.react.modules.systeminfo;
|
||||
|
||||
import com.facebook.react.common.MapBuilder;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ReactNativeVersion {
|
||||
public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of(
|
||||
"major", 0,
|
||||
"minor", 0,
|
||||
"patch", 0,
|
||||
"prerelease", null);
|
||||
}
|
|
@ -34,7 +34,7 @@ jest
|
|||
jest.setMock('ErrorUtils', require('ErrorUtils'));
|
||||
|
||||
jest
|
||||
.mock('InitializeCore')
|
||||
.mock('InitializeCore', () => {})
|
||||
.mock('Image', () => mockComponent('Image'))
|
||||
.mock('Text', () => mockComponent('Text'))
|
||||
.mock('TextInput', () => mockComponent('TextInput'))
|
||||
|
|
|
@ -46,10 +46,39 @@ let versionMajor = branch.slice(0, branch.indexOf(`-stable`));
|
|||
// e.g. 0.33.1 or 0.33.0-rc4
|
||||
let version = argv._[0];
|
||||
if (!version || version.indexOf(versionMajor) !== 0) {
|
||||
echo(`You must pass a tag like ${versionMajor}.[X]-rc[Y] to bump a version`);
|
||||
echo(`You must pass a tag like 0.${versionMajor}.[X]-rc[Y] to bump a version`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Generate version files to detect mismatches between JS and native.
|
||||
let match = version.match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
|
||||
if (!match) {
|
||||
echo(`You must pass a correctly formatted version; couldn't parse ${version}`);
|
||||
exit(1);
|
||||
}
|
||||
let [, major, minor, patch, prerelease] = match;
|
||||
|
||||
cat('scripts/versiontemplates/ReactNativeVersion.java.template')
|
||||
.replace('${major}', major)
|
||||
.replace('${minor}', minor)
|
||||
.replace('${patch}', patch)
|
||||
.replace('${prerelease}', prerelease !== undefined ? `"${prerelease}"` : 'null')
|
||||
.to('ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java');
|
||||
|
||||
cat('scripts/versiontemplates/RCTVersion.h.template')
|
||||
.replace('${major}', `@(${major})`)
|
||||
.replace('${minor}', `@(${minor})`)
|
||||
.replace('${patch}', `@(${patch})`)
|
||||
.replace('${prerelease}', prerelease !== undefined ? `@"${prerelease}"` : '[NSNull null]')
|
||||
.to('React/Base/RCTVersion.h');
|
||||
|
||||
cat('scripts/versiontemplates/ReactNativeVersion.js.template')
|
||||
.replace('${major}', major)
|
||||
.replace('${minor}', minor)
|
||||
.replace('${patch}', patch)
|
||||
.replace('${prerelease}', prerelease !== undefined ? `'${prerelease}'` : 'null')
|
||||
.to('Libraries/Core/ReactNativeVersion.js');
|
||||
|
||||
let packageJson = JSON.parse(cat(`package.json`));
|
||||
packageJson.version = version;
|
||||
JSON.stringify(packageJson, null, 2).to(`package.json`);
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* @generated by scripts/bump-oss-version.js
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define REACT_NATIVE_VERSION @{ \
|
||||
@"major": ${major}, \
|
||||
@"minor": ${minor}, \
|
||||
@"patch": ${patch}, \
|
||||
@"prerelease": ${prerelease}, \
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* @generated by scripts/bump-oss-version.js
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.facebook.react.modules.systeminfo;
|
||||
|
||||
import com.facebook.react.common.MapBuilder;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ReactNativeVersion {
|
||||
public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of(
|
||||
"major", ${major},
|
||||
"minor", ${minor},
|
||||
"patch", ${patch},
|
||||
"prerelease", ${prerelease});
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* @generated by scripts/bump-oss-version.js
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @flow
|
||||
* @providesModule ReactNativeVersion
|
||||
*/
|
||||
|
||||
exports.version = {
|
||||
major: ${major},
|
||||
minor: ${minor},
|
||||
patch: ${patch},
|
||||
prerelease: ${prerelease},
|
||||
};
|
Loading…
Reference in New Issue