From 04a99051ac166c167a6958f7edfe64ae1f79ce55 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Thu, 10 Aug 2017 03:03:36 -0400 Subject: [PATCH] Validate that JS and Native code versions match for RN releases --- Libraries/Core/InitializeCore.js | 12 ++++++++++++ Libraries/Core/ReactNativeVersion.js | 14 ++++++++++++++ React/Base/RCTPlatform.m | 2 ++ React/Base/RCTVersion.h | 12 ++++++++++++ React/React.xcodeproj/project.pbxproj | 6 ++++++ .../com/facebook/react/ReactNativeVersion.java | 16 ++++++++++++++++ .../modules/systeminfo/AndroidInfoModule.java | 2 ++ scripts/bump-oss-version.js | 13 +++++++++++++ scripts/versiontemplates/RCTVersion.h | 12 ++++++++++++ scripts/versiontemplates/ReactNativeVersion.java | 16 ++++++++++++++++ scripts/versiontemplates/ReactNativeVersion.js | 14 ++++++++++++++ 11 files changed, 119 insertions(+) create mode 100644 Libraries/Core/ReactNativeVersion.js create mode 100644 React/Base/RCTVersion.h create mode 100644 ReactAndroid/src/main/java/com/facebook/react/ReactNativeVersion.java create mode 100644 scripts/versiontemplates/RCTVersion.h create mode 100644 scripts/versiontemplates/ReactNativeVersion.java create mode 100644 scripts/versiontemplates/ReactNativeVersion.js diff --git a/Libraries/Core/InitializeCore.js b/Libraries/Core/InitializeCore.js index fd239f119deb14..b2c06fa4843614 100644 --- a/Libraries/Core/InitializeCore.js +++ b/Libraries/Core/InitializeCore.js @@ -116,6 +116,18 @@ if (!global.__fbDisableExceptionsManager) { ErrorUtils.setGlobalHandler(handleError); } +const NativeModules = require('NativeModules'); +const ReactNativeVersion = require('./ReactNativeVersion'); +if (ReactNativeVersion.version !== NativeModules.PlatformConstants.reactNativeVersion) { + throw new Error( + `React Native version mismatch.\n\nJavaScript version: ${ReactNativeVersion.version}\n` + + `Native version: ${NativeModules.PlatformConstants.reactNativeVersion}\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')) { diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js new file mode 100644 index 00000000000000..a34f8ea39136c3 --- /dev/null +++ b/Libraries/Core/ReactNativeVersion.js @@ -0,0 +1,14 @@ +/** + * @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 + */ + +exports.version = 'master'; diff --git a/React/Base/RCTPlatform.m b/React/Base/RCTPlatform.m index 4593341066b1f3..b9ece18b85bb81 100644 --- a/React/Base/RCTPlatform.m +++ b/React/Base/RCTPlatform.m @@ -12,6 +12,7 @@ #import #import "RCTUtils.h" +#import "RCTVersion.h" static NSString *interfaceIdiom(UIUserInterfaceIdiom idiom) { switch(idiom) { @@ -46,6 +47,7 @@ + (BOOL)requiresMainQueueSetup @"systemName": [device systemName], @"interfaceIdiom": interfaceIdiom([device userInterfaceIdiom]), @"isTesting": @(RCTRunningInTestEnvironment()), + @"reactNativeVersion": REACT_NATIVE_VERSION, }; } diff --git a/React/Base/RCTVersion.h b/React/Base/RCTVersion.h new file mode 100644 index 00000000000000..55f68eceb2780a --- /dev/null +++ b/React/Base/RCTVersion.h @@ -0,0 +1,12 @@ +/** + * @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 @"master" diff --git a/React/React.xcodeproj/project.pbxproj b/React/React.xcodeproj/project.pbxproj index 39fb8039830494..fd68e2390d89df 100644 --- a/React/React.xcodeproj/project.pbxproj +++ b/React/React.xcodeproj/project.pbxproj @@ -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 */; }; @@ -1842,6 +1844,7 @@ 191E3EBD1C29D9AF00C180A6 /* RCTRefreshControlManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRefreshControlManager.m; sourceTree = ""; }; 191E3EBF1C29DC3800C180A6 /* RCTRefreshControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRefreshControl.h; sourceTree = ""; }; 191E3EC01C29DC3800C180A6 /* RCTRefreshControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRefreshControl.m; sourceTree = ""; }; + 199B8A6E1F44DB16005DEF67 /* RCTVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTVersion.h; sourceTree = ""; }; 19DED2281E77E29200F089BB /* systemJSCWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = systemJSCWrapper.cpp; sourceTree = ""; }; 27B958731E57587D0096647A /* JSBigString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBigString.cpp; sourceTree = ""; }; 2D2A28131D9B038B00D4039D /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2652,6 +2655,7 @@ 1345A83B1B265A0E00583190 /* RCTURLRequestHandler.h */, 83CBBA4F1A601E3B00E9B192 /* RCTUtils.h */, 83CBBA501A601E3B00E9B192 /* RCTUtils.m */, + 199B8A6E1F44DB16005DEF67 /* RCTVersion.h */, ); path = Base; sourceTree = ""; @@ -2792,6 +2796,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 */, @@ -3029,6 +3034,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 */, diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/ReactNativeVersion.java new file mode 100644 index 00000000000000..b1fb352cec6eb3 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactNativeVersion.java @@ -0,0 +1,16 @@ +/** + * @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; + +public class ReactNativeVersion { + public static final String VERSION = "master"; +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoModule.java index 07666145e48ece..95478bcc560af3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoModule.java @@ -11,6 +11,7 @@ import android.os.Build; +import com.facebook.react.ReactNativeVersion; import com.facebook.react.bridge.BaseJavaModule; import com.facebook.react.module.annotations.ReactModule; @@ -38,6 +39,7 @@ public String getName() { 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; } } diff --git a/scripts/bump-oss-version.js b/scripts/bump-oss-version.js index c1e3a38d3b1c77..0f8fbf1d639640 100755 --- a/scripts/bump-oss-version.js +++ b/scripts/bump-oss-version.js @@ -50,6 +50,19 @@ if (!version || version.indexOf(versionMajor) !== 0) { exit(1); } +// Generate version files to detect mismatches between JS and native. +cat('scripts/versiontemplates/ReactNativeVersion.java') + .replace('${version}', version) + .to('ReactAndroid/src/main/java/com/facebook/react/ReactNativeVersion.java'); + +cat('scripts/versiontemplates/RCTVersion.h') + .replace('${version}', version) + .to('React/Base/RCTVersion.h'); + +cat('scripts/versiontemplates/ReactNativeVersion.js') + .replace('${version}', version) + .to('Libraries/Core/ReactNativeVersion.js'); + let packageJson = JSON.parse(cat(`package.json`)); packageJson.version = version; JSON.stringify(packageJson, null, 2).to(`package.json`); diff --git a/scripts/versiontemplates/RCTVersion.h b/scripts/versiontemplates/RCTVersion.h new file mode 100644 index 00000000000000..e222ad2f71d199 --- /dev/null +++ b/scripts/versiontemplates/RCTVersion.h @@ -0,0 +1,12 @@ +/** + * @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 @"${version}" diff --git a/scripts/versiontemplates/ReactNativeVersion.java b/scripts/versiontemplates/ReactNativeVersion.java new file mode 100644 index 00000000000000..5a159799eb5601 --- /dev/null +++ b/scripts/versiontemplates/ReactNativeVersion.java @@ -0,0 +1,16 @@ +/** + * @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; + +public class ReactNativeVersion { + public static final String VERSION = "${version}"; +} diff --git a/scripts/versiontemplates/ReactNativeVersion.js b/scripts/versiontemplates/ReactNativeVersion.js new file mode 100644 index 00000000000000..9a5a31cec7a29c --- /dev/null +++ b/scripts/versiontemplates/ReactNativeVersion.js @@ -0,0 +1,14 @@ +/** + * @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 + */ + +exports.version = '${version}';