Skip to content

Commit 68ac149

Browse files
authored
New architecture support (#7744)
- [x] Upgrade react-native to 0.72 - [x] Add new architechture & fabric support - [x] Fix auto linking - [x] Test backward compatibility Closes #7753 Closes #7547 Closes #7466 Closes #7742
1 parent 8aa2fc6 commit 68ac149

File tree

43 files changed

+485
-289
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+485
-289
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,4 +243,6 @@ artifacts/
243243
lib/Mock/*.js
244244
lib/Mock/*.d.ts
245245
Mock.js
246-
Mock.d.ts
246+
Mock.d.ts
247+
248+
Gemfile.lock

Gemfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
source 'https://rubygems.org'
2+
3+
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
4+
ruby '>= 2.6.10'
5+
6+
gem 'cocoapods', '>= 1.11.3'

ReactNativeNavigation.podspec

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ require 'json'
22

33
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
44

5+
fabric_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1'
6+
57
Pod::Spec.new do |s|
68
s.name = "ReactNativeNavigation"
79
s.version = package['version']
@@ -17,19 +19,34 @@ Pod::Spec.new do |s|
1719

1820
s.subspec 'Core' do |ss|
1921
s.source = { :git => "https://github.com/wix/react-native-navigation.git", :tag => "#{s.version}" }
20-
s.source_files = "lib/ios/**/*.{h,m,mm}"
22+
s.source_files = 'lib/ios/**/*.{h,m,mm,cpp}'
2123
s.exclude_files = "lib/ios/ReactNativeNavigationTests/**/*.*", "lib/ios/OCMock/**/*.*"
2224
end
23-
24-
# s.subspec 'Fabric' do |ss|
25-
# ss.xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/RCT-Folly\"",
26-
# "OTHER_CFLAGS" => "$(inherited) -DRN_FABRIC_ENABLED -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1" }
27-
# ss.dependency 'React-RCTFabric'
28-
# ss.dependency 'React-Fabric'
29-
# ss.dependency 'RCT-Folly/Fabric'
30-
# end
3125

26+
if fabric_enabled
27+
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
28+
fabric_flags = fabric_enabled ? '-DRCT_NEW_ARCH_ENABLED' : ''
29+
s.pod_target_xcconfig = {
30+
'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/boost" "$(PODS_ROOT)/boost-for-react-native" "$(PODS_ROOT)/RCT-Folly" "$(PODS_ROOT)/Headers/Private/React-Core"',
31+
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
32+
}
33+
s.compiler_flags = folly_compiler_flags + ' ' + '-DRCT_NEW_ARCH_ENABLED'
34+
s.requires_arc = true
35+
36+
s.dependency "React"
37+
s.dependency "React-RCTFabric"
38+
s.dependency "React-cxxreact"
39+
s.dependency "React-Fabric"
40+
s.dependency "React-Codegen"
41+
s.dependency "RCT-Folly"
42+
s.dependency "RCTRequired"
43+
s.dependency "RCTTypeSafety"
44+
s.dependency "ReactCommon/turbomodule/core"
45+
s.dependency "React-runtimeexecutor"
46+
s.dependency "React-rncore"
47+
end
3248
s.dependency 'React-Core'
49+
s.dependency 'React-CoreModules'
3350
s.dependency 'React-RCTImage'
3451
s.dependency 'React-RCTText'
3552
s.dependency 'HMSegmentedControl'

autolink/postlink/__snapshots__/appDelegateLinker.test.js.snap

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,6 @@ exports[`appDelegateLinker should work for RN 0.68 1`] = `
5252
return YES;
5353
}
5454
55-
- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge {
56-
return [ReactNativeNavigation extraModulesForBridge:bridge];
57-
}
58-
5955
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
6056
{
6157
#if DEBUG
@@ -184,10 +180,6 @@ static NSString *const kRNConcurrentRoot = @\\"concurrentRoot\\";
184180
return initProps;
185181
}
186182
187-
- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge {
188-
return [ReactNativeNavigation extraModulesForBridge:bridge];
189-
}
190-
191183
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
192184
{
193185
#if DEBUG
@@ -250,17 +242,8 @@ exports[`appDelegateLinker should work for RN 0.71 1`] = `
250242
251243
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
252244
{
253-
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
254-
[ReactNativeNavigation bootstrapWithBridge:bridge];
255-
// You can add your custom initial props in the dictionary below.
256-
// They will be passed down to the ViewController used by React Native.
257-
self.initialProps = @{};
258-
259-
return YES;
260-
}
261-
262-
- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge {
263-
return [ReactNativeNavigation extraModulesForBridge:bridge];
245+
246+
return [super application:application didFinishLaunchingWithOptions:launchOptions];
264247
}
265248
266249
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge

autolink/postlink/appDelegateLinker.js

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ var { warnn, logn, infon, debugn, errorn } = require('./log');
66
class AppDelegateLinker {
77
constructor() {
88
this.appDelegatePath = path.appDelegate;
9+
this.appDelegateHeaderPath = path.appDelegateHeader;
910
this.removeUnneededImportsSuccess = false;
1011
this.removeApplicationLaunchContentSuccess = false;
1112
}
@@ -22,6 +23,12 @@ class AppDelegateLinker {
2223

2324
var appDelegateContents = fs.readFileSync(this.appDelegatePath, 'utf8');
2425

26+
if (this.appDelegateHeaderPath) {
27+
var appDelegateHeaderContents = fs.readFileSync(this.appDelegateHeaderPath, 'utf8');
28+
appDelegateHeaderContents = this._extendRNNAppDelegate(appDelegateHeaderContents);
29+
fs.writeFileSync(this.appDelegateHeaderPath, appDelegateHeaderContents);
30+
}
31+
2532
try {
2633
appDelegateContents = this._removeUnneededImports(appDelegateContents);
2734
this.removeUnneededImportsSuccess = true;
@@ -33,8 +40,6 @@ class AppDelegateLinker {
3340

3441
appDelegateContents = this._bootstrapNavigation(appDelegateContents);
3542

36-
appDelegateContents = this._extraModulesForBridge(appDelegateContents);
37-
3843
try {
3944
appDelegateContents = this._removeApplicationLaunchContent(appDelegateContents);
4045
this.removeApplicationLaunchContentSuccess = true;
@@ -81,6 +86,18 @@ class AppDelegateLinker {
8186
return content;
8287
}
8388

89+
_extendRNNAppDelegate(content) {
90+
return content
91+
.replace(
92+
/#import*.<RCTAppDelegate.h>/,
93+
'#import "RNNAppDelegate.h"'
94+
)
95+
.replace(
96+
/:*.RCTAppDelegate/,
97+
': RNNAppDelegate'
98+
)
99+
}
100+
84101
_importNavigation(content) {
85102
if (!this._doesImportNavigation(content)) {
86103
debugn(' Importing ReactNativeNavigation.h');
@@ -105,52 +122,18 @@ class AppDelegateLinker {
105122
.replace(
106123
/RCTBridge.*];/,
107124
'RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];\n' +
108-
'[ReactNativeNavigation bootstrapWithBridge:bridge];'
109-
)
110-
.replace(
111-
/return \[super application:application didFinishLaunchingWithOptions:launchOptions\];/,
112-
'return YES;'
125+
'[ReactNativeNavigation bootstrapWithBridge:bridge];'
113126
)
114127
.replace(
115-
/self.moduleName.*;/,
116-
'RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];\n' +
117-
' [ReactNativeNavigation bootstrapWithBridge:bridge];'
128+
/self.moduleName.*;(.|\n)*@{};\n?/,
129+
''
118130
);
119131
}
120132

121133
_doesBootstrapNavigation(content) {
122134
return /ReactNativeNavigation\s+bootstrap/.test(content);
123135
}
124136

125-
_extraModulesForBridge(content) {
126-
if (this._doesImplementsRNNExtraModulesForBridge(content)) {
127-
warnn(' extraModulesForBridge already present.');
128-
return content;
129-
} else if (this._doesImplementsExtraModulesForBridge(content)) {
130-
throw new Error(
131-
'extraModulesForBridge implemented for a different module and needs manual linking. Check the manual installation docs to verify that everything is properly setup:\n https://wix.github.io/react-native-navigation/docs/installing#native-installation'
132-
);
133-
}
134-
135-
debugn(' Implementing extraModulesForBridge');
136-
return content.replace(
137-
/-.*\(NSURL.*\*\)sourceURLForBridge:\(RCTBridge.*\*\)bridge/,
138-
'- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge {\n\
139-
return [ReactNativeNavigation extraModulesForBridge:bridge];\n\
140-
}\n\
141-
\n\
142-
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge'
143-
);
144-
}
145-
146-
_doesImplementsExtraModulesForBridge(content) {
147-
return /-.*\(NSArray.*\*\)extraModulesForBridge:\(RCTBridge.*\*\)bridge/.test(content);
148-
}
149-
150-
_doesImplementsRNNExtraModulesForBridge(content) {
151-
return /ReactNativeNavigation\s+extraModulesForBridge/.test(content);
152-
}
153-
154137
_removeApplicationLaunchContent(content) {
155138
debugn(' Removing Application launch content');
156139

autolink/postlink/path.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ exports.appDelegate = glob.sync(
1414
reactNativeVersion < '0.68.0' ? '**/AppDelegate.m' : '**/AppDelegate.mm',
1515
ignoreFolders
1616
)[0];
17+
exports.appDelegateHeader = glob.sync('**/AppDelegate.h', ignoreFolders)[0];
1718
exports.podFile = glob.sync('**/Podfile', ignoreFolders)[0];
1819
exports.plist = glob.sync('**/info.plist', ignoreFolders)[0];

babel.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ module.exports = function (api) {
33
return {
44
presets: ['module:metro-react-native-babel-preset'],
55
plugins: [
6-
'react-native-reanimated/plugin',
76
'@babel/plugin-proposal-export-namespace-from',
87
'@babel/plugin-proposal-export-default-from',
8+
'react-native-reanimated/plugin',
99
],
1010
};
1111
};

e2e/Keyboard.test.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,19 @@ describe.e2e('Keyboard', () => {
2525
await expect(elementById(testIDs.MAIN_BOTTOM_TABS)).toBeVisible();
2626
});
2727

28-
it('focus keyboard continue to resize content', async () => {
29-
await elementById(TestIDs.TEXT_INPUT2).typeText("Hello");
30-
await elementById(TestIDs.TEXT_INPUT2).tapReturnKey();
31-
await expect(elementById(TestIDs.TEXT_INPUT1)).toBeFocused();
32-
await expect(elementById(TestIDs.TEXT_INPUT1)).toBeVisible();
28+
it(':ios: focus keyboard continue to resize content', async () => {
29+
await elementById(TestIDs.TEXT_INPUT2).typeText("Hello");
30+
await elementById(TestIDs.TEXT_INPUT2).tapReturnKey();
31+
await expect(elementById(TestIDs.TEXT_INPUT1)).toBeFocused();
32+
await expect(elementById(TestIDs.TEXT_INPUT1)).toBeVisible();
3333
});
3434

35-
it('focus keyboard on push', async () => {
35+
it(':ios: focus keyboard on push', async () => {
3636
await elementById(TestIDs.PUSH_FOCUSED_KEYBOARD_SCREEN).tap();
3737
await expect(elementById(TestIDs.TEXT_INPUT1)).toBeFocused();
3838
});
3939

40-
it('focus keyboard on show modal', async () => {
40+
it(':ios: focus keyboard on show modal', async () => {
4141
await elementById(TestIDs.MODAL_FOCUSED_KEYBOARD_SCREEN).tap();
4242
await expect(elementById(TestIDs.TEXT_INPUT1)).toBeFocused();
4343
});

e2e/Utils.js

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import { readFileSync } from 'fs';
2-
function bitmapDiff(imagePath, expectedImagePath) {
3-
const PNG = require('pngjs').PNG;
4-
const pixelmatch = require('pixelmatch');
5-
const img1 = PNG.sync.read(readFileSync(imagePath));
6-
const img2 = PNG.sync.read(readFileSync(expectedImagePath));
7-
const {width, height} = img1;
8-
const diff = new PNG({width, height});
2+
function bitmapDiff(imagePath, expectedImagePath) {
3+
const PNG = require('pngjs').PNG;
4+
const pixelmatch = require('pixelmatch');
5+
const img1 = PNG.sync.read(readFileSync(imagePath));
6+
const img2 = PNG.sync.read(readFileSync(expectedImagePath));
7+
const { width, height } = img1;
8+
const diff = new PNG({ width, height });
99

10-
return pixelmatch(img1.data, img2.data, diff.data, width, height, {threshold: 0.0})
10+
return pixelmatch(img1.data, img2.data, diff.data, width, height, { threshold: 0.0 });
1111
}
1212
const utils = {
1313
elementByLabel: (label) => {
14+
// uncomment for running tests with rn's new arch
15+
// return element(by.label(label)).atIndex(0);
1416
return element(by.text(label));
1517
},
1618
elementById: (id) => {
@@ -29,18 +31,18 @@ const utils = {
2931
}
3032
},
3133
sleep: (ms) => new Promise((res) => setTimeout(res, ms)),
32-
expectImagesToBeEqual:(imagePath, expectedImagePath)=>{
33-
let diff = bitmapDiff(imagePath,expectedImagePath);
34-
if(diff!==0){
35-
throw Error(`${imagePath} should be the same as ${expectedImagePath}, with diff: ${diff}`)
36-
}
37-
} ,
38-
expectImagesToBeNotEqual:(imagePath, expectedImagePath)=>{
39-
let diff = bitmapDiff(imagePath,expectedImagePath);
40-
if(diff===0){
41-
throw Error(`${imagePath} should be the same as ${expectedImagePath}, with diff: ${diff}`)
42-
}
34+
expectImagesToBeEqual: (imagePath, expectedImagePath) => {
35+
let diff = bitmapDiff(imagePath, expectedImagePath);
36+
if (diff !== 0) {
37+
throw Error(`${imagePath} should be the same as ${expectedImagePath}, with diff: ${diff}`);
4338
}
39+
},
40+
expectImagesToBeNotEqual: (imagePath, expectedImagePath) => {
41+
let diff = bitmapDiff(imagePath, expectedImagePath);
42+
if (diff === 0) {
43+
throw Error(`${imagePath} should be the same as ${expectedImagePath}, with diff: ${diff}`);
44+
}
45+
},
4446
};
4547

4648
export default utils;

lib/android/app/src/main/java/com/reactnativenavigation/react/ReactView.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.facebook.react.ReactInstanceManager;
99
import com.facebook.react.ReactRootView;
1010
import com.facebook.react.bridge.ReactContext;
11+
import com.facebook.react.config.ReactFeatureFlags;
1112
import com.facebook.react.uimanager.JSTouchDispatcher;
1213
import com.facebook.react.uimanager.UIManagerModule;
1314
import com.facebook.react.uimanager.events.EventDispatcher;
@@ -34,6 +35,7 @@ public ReactView(final Context context, ReactInstanceManager reactInstanceManage
3435
this.componentId = componentId;
3536
this.componentName = componentName;
3637
jsTouchDispatcher = new JSTouchDispatcher(this);
38+
setIsFabric(ReactFeatureFlags.enableFabricRenderer);
3739
}
3840

3941
@Override

0 commit comments

Comments
 (0)