diff --git a/.circleci/config.yml b/.circleci/config.yml index 27e9ccbecdb154..ca6a805cc8fae1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,11 +46,11 @@ aliases: - &restore-cache-buck keys: - - v2-buck-{{ arch }}-v2017.11.16.01 + - v2-buck-{{ arch }}-v2017.09.04.02 - &save-cache-buck paths: - ~/buck - key: v2-buck-{{ arch }}-v2017.11.16.01 + key: v2-buck-{{ arch }}-v2017.09.04.02 - &restore-cache-watchman keys: @@ -67,7 +67,7 @@ aliases: - &install-buck | if [[ ! -e ~/buck ]]; then - git clone https://github.com/facebook/buck.git ~/buck --branch v2017.11.16.01 --depth=1 + git clone https://github.com/facebook/buck.git ~/buck --branch v2017.09.04.02 --depth=1 fi cd ~/buck && ant buck --version diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index 2f78126ef691a6..81e587bd5be798 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -14,7 +14,7 @@ exports.version = { major: 0, - minor: 0, - patch: 0, + minor: 53, + patch: 1, prerelease: null, }; diff --git a/Libraries/Text/RCTText.xcodeproj/project.pbxproj b/Libraries/Text/RCTText.xcodeproj/project.pbxproj index fd6625ac95e63f..68f55f1ec7f53b 100644 --- a/Libraries/Text/RCTText.xcodeproj/project.pbxproj +++ b/Libraries/Text/RCTText.xcodeproj/project.pbxproj @@ -86,6 +86,7 @@ 59E6049B1FE9CB4A00BD90C5 /* RCTUITextField.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 59E604501FE9CAF100BD90C5 /* RCTUITextField.h */; }; 59E8C5CC1F8833D100204F5E /* RCTFontAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = A85C82991F742AA20036C019 /* RCTFontAttributes.m */; }; A85C829A1F742AA20036C019 /* RCTFontAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = A85C82991F742AA20036C019 /* RCTFontAttributes.m */; }; + AD50D1DF20067E6F00A34797 /* RCTBaseTextInputViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5989E14C20018A2200EA444A /* RCTBaseTextInputViewManager.m */; }; AF3225F91DE5574F00D3E7E7 /* RCTConvert+Text.m in Sources */ = {isa = PBXBuildFile; fileRef = AF3225F81DE5574F00D3E7E7 /* RCTConvert+Text.m */; }; AF3225FA1DE5574F00D3E7E7 /* RCTConvert+Text.m in Sources */ = {isa = PBXBuildFile; fileRef = AF3225F81DE5574F00D3E7E7 /* RCTConvert+Text.m */; }; /* End PBXBuildFile section */ @@ -380,6 +381,7 @@ 59E6045D1FE9CAF100BD90C5 /* RCTMultilineTextInputShadowView.m in Sources */, 59E604591FE9CAF100BD90C5 /* RCTRawTextShadowView.m in Sources */, 59E604551FE9CAF100BD90C5 /* RCTTextView.m in Sources */, + AD50D1DF20067E6F00A34797 /* RCTBaseTextInputViewManager.m in Sources */, 59E604691FE9CAF100BD90C5 /* RCTTextSelection.m in Sources */, 59E6045F1FE9CAF100BD90C5 /* RCTMultilineTextInputView.m in Sources */, 59E604611FE9CAF100BD90C5 /* RCTMultilineTextInputViewManager.m in Sources */, diff --git a/Libraries/Utilities/HMRClient.js b/Libraries/Utilities/HMRClient.js index 53cb874c1dc3f8..4934c4ff4283b8 100644 --- a/Libraries/Utilities/HMRClient.js +++ b/Libraries/Utilities/HMRClient.js @@ -121,7 +121,7 @@ Error: ${e.message}` } case 'error': { HMRLoadingView.hide(); - throw new Error(data.body.type + ' ' + data.body.description); + throw new Error(`${data.body.type}: ${data.body.message}`); } default: { throw new Error(`Unexpected message: ${data}`); diff --git a/React.podspec b/React.podspec index edda6e85fe18b0..b0b946a4708aa2 100644 --- a/React.podspec +++ b/React.podspec @@ -139,13 +139,13 @@ Pod::Spec.new do |s| s.subspec "cxxreact" do |ss| ss.dependency "React/jschelpers" ss.dependency "React/jsinspector" - ss.dependency "boost" + ss.dependency "boost-for-react-native", "1.63.0" ss.dependency "Folly", "2016.09.26.00" ss.compiler_flags = folly_compiler_flags ss.source_files = "ReactCommon/cxxreact/*.{cpp,h}" ss.exclude_files = "ReactCommon/cxxreact/SampleCxxModule.*" ss.private_header_files = "ReactCommon/cxxreact/*.h" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/Folly\"" } + ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/Folly\"" } end s.subspec "ART" do |ss| @@ -204,7 +204,7 @@ Pod::Spec.new do |s| s.subspec "RCTText" do |ss| ss.dependency "React/Core" - ss.source_files = "Libraries/Text/*.{h,m}" + ss.source_files = "Libraries/Text/**/*.{h,m}" end s.subspec "RCTVibration" do |ss| diff --git a/React/Base/RCTVersion.h b/React/Base/RCTVersion.h index c741022e5b8537..6cb08f4d0a867c 100644 --- a/React/Base/RCTVersion.h +++ b/React/Base/RCTVersion.h @@ -11,7 +11,7 @@ #define RCT_REACT_NATIVE_VERSION @{ \ @"major": @(0), \ - @"minor": @(0), \ - @"patch": @(0), \ + @"minor": @(53), \ + @"patch": @(1), \ @"prerelease": [NSNull null], \ } diff --git a/React/Views/RCTRefreshControl.m b/React/Views/RCTRefreshControl.m index bdb0fe65795bc3..3b447de55a5227 100644 --- a/React/Views/RCTRefreshControl.m +++ b/React/Views/RCTRefreshControl.m @@ -44,7 +44,7 @@ - (void)layoutSubviews // If the control is refreshing when mounted we need to call // beginRefreshing in layoutSubview or it doesn't work. if (_currentRefreshingState && _isInitialRender) { - [self beginRefreshing]; + [self beginRefreshingProgrammatically]; } _isInitialRender = false; } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 9b7ac6d1254dc8..e375fcc6fab9b6 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=1000.0.0-master +VERSION_NAME=0.53.1 GROUP=com.facebook.react POM_NAME=ReactNative diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK b/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK index e853d9cb477ac4..4e331f8cc7372d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK @@ -12,7 +12,6 @@ android_library( provided_deps = [ react_native_dep("third-party/android/support/v4:lib-support-v4"), ], - required_for_source_only_abi = True, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/common/BUCK b/ReactAndroid/src/main/java/com/facebook/react/common/BUCK index d6db0ab25fe831..8fdc365010c729 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/common/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/common/BUCK @@ -16,7 +16,6 @@ android_library( provided_deps = [ react_native_dep("third-party/android/support/v4:lib-support-v4"), ], - required_for_source_only_abi = True, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/WebsocketJavaScriptExecutor.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/WebsocketJavaScriptExecutor.java index 858f7e004c790a..49d8bc08bf28df 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/WebsocketJavaScriptExecutor.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/WebsocketJavaScriptExecutor.java @@ -9,14 +9,17 @@ package com.facebook.react.devsupport; +import javax.annotation.Nullable; + +import java.util.HashMap; +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicInteger; + import android.os.Handler; import android.os.Looper; + import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.JavaJSExecutor; -import java.util.HashMap; -import java.util.concurrent.Semaphore; -import java.util.concurrent.atomic.AtomicInteger; -import javax.annotation.Nullable; /** * Executes JS remotely via the react nodejs server as a proxy to a browser on the host machine. @@ -157,7 +160,8 @@ public void close() { } @Override - public void loadApplicationScript(String sourceURL) throws JavaJSExecutor.ProxyExecutorException { + public void loadApplicationScript(String sourceURL) + throws ProxyExecutorException { JSExecutorCallbackFuture callback = new JSExecutorCallbackFuture(); Assertions.assertNotNull(mWebSocketClient).loadApplicationScript( sourceURL, @@ -172,7 +176,7 @@ public void loadApplicationScript(String sourceURL) throws JavaJSExecutor.ProxyE @Override public @Nullable String executeJSCall(String methodName, String jsonArgsArray) - throws JavaJSExecutor.ProxyExecutorException { + throws ProxyExecutorException { JSExecutorCallbackFuture callback = new JSExecutorCallbackFuture(); Assertions.assertNotNull(mWebSocketClient).executeJSCall( methodName, diff --git a/ReactAndroid/src/main/java/com/facebook/react/module/annotations/BUCK b/ReactAndroid/src/main/java/com/facebook/react/module/annotations/BUCK index e664393351539a..02e0158396ddb5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/module/annotations/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/module/annotations/BUCK @@ -3,7 +3,6 @@ include_defs("//ReactAndroid/DEFS") android_library( name = "annotations", srcs = glob(["**/*.java"]), - required_for_source_only_abi = True, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index b6514ec58be729..e42adc4732f8be 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -18,7 +18,7 @@ public class ReactNativeVersion { public static final Map VERSION = MapBuilder.of( "major", 0, - "minor", 0, - "patch", 0, + "minor", 53, + "patch", 1, "prerelease", null); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK index 5f528cb784c29f..98ae5be6058e5b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK @@ -14,7 +14,6 @@ android_library( provided_deps = [ react_native_dep("third-party/android/support/v4:lib-support-v4"), ], - required_for_source_only_abi = True, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/annotations/BUCK b/ReactAndroid/src/main/java/com/facebook/react/uimanager/annotations/BUCK index 0e29b5df43580a..32582caafa05b3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/annotations/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/annotations/BUCK @@ -3,7 +3,6 @@ include_defs("//ReactAndroid/DEFS") android_library( name = "annotations", srcs = glob(["*.java"]), - required_for_source_only_abi = True, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/layoutanimation/OpacityAnimation.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/layoutanimation/OpacityAnimation.java index 033b6a4ae15ff7..a7ad690023c500 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/layoutanimation/OpacityAnimation.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/layoutanimation/OpacityAnimation.java @@ -12,7 +12,7 @@ */ /* package */ class OpacityAnimation extends Animation { - static class OpacityAnimationListener implements Animation.AnimationListener { + static class OpacityAnimationListener implements AnimationListener { private final View mView; private boolean mLayerTypeChanged = false; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK index 116dce94d27412..95a7e964cc610b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK @@ -11,7 +11,6 @@ android_library( react_native_dep("third-party/android/support-annotations:android-support-annotations"), react_native_dep("third-party/android/support/v4:lib-support-v4"), ], - required_for_source_only_abi = True, visibility = ["PUBLIC"], deps = [ react_native_dep("third-party/java/jsr-305:jsr-305"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK index eb762eb77a2209..deadbd49ac1821 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK @@ -3,7 +3,6 @@ include_defs("//ReactAndroid/DEFS") android_library( name = "modal", srcs = glob(["*.java"]), - required_for_source_only_abi = True, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/text/BUCK index 23f63bf2e6c1ef..5f5ecfd0fc87fd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/BUCK @@ -3,7 +3,6 @@ include_defs("//ReactAndroid/DEFS") android_library( name = "text", srcs = glob(["*.java"]), - required_for_source_only_abi = True, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK index 141713bc05f9ee..1cb749f65cee45 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK @@ -6,7 +6,6 @@ android_library( provided_deps = [ react_native_dep("third-party/android/support/v4:lib-support-v4"), ], - required_for_source_only_abi = True, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index e0984f86e09cac..2c7900d0a6d3bf 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -54,13 +54,13 @@ public class ReactViewGroup extends ViewGroup implements /** * This listener will be set for child views when removeClippedSubview property is enabled. When - * children layout is updated, it will call {@link #updateSubviewClipStatus} to notify parent view - * about that fact so that view can be attached/detached if necessary. + * children layout is updated, it will call {@link #updateSubviewClipStatus} to notify parent + * view about that fact so that view can be attached/detached if necessary. * - *

TODO(7728005): Attach/detach views in batch - once per frame in case when multiple children + * TODO(7728005): Attach/detach views in batch - once per frame in case when multiple children * update their layout. */ - private static final class ChildrenLayoutChangeListener implements View.OnLayoutChangeListener { + private static final class ChildrenLayoutChangeListener implements OnLayoutChangeListener { private final ReactViewGroup mParent; @@ -422,7 +422,7 @@ protected void onAttachedToWindow() { } @Override - public void addView(View child, int index, ViewGroup.LayoutParams params) { + public void addView(View child, int index, LayoutParams params) { // This will get called for every overload of addView so there is not need to override every method. mDrawingOrderHelper.handleAddView(child); setChildrenDrawingOrderEnabled(mDrawingOrderHelper.shouldEnableCustomDrawingOrder()); @@ -494,8 +494,7 @@ protected void dispatchSetPressed(boolean pressed) { addViewWithSubviewClippingEnabled(child, index, sDefaultLayoutParam); } - /*package*/ void addViewWithSubviewClippingEnabled( - View child, int index, ViewGroup.LayoutParams params) { + /*package*/ void addViewWithSubviewClippingEnabled(View child, int index, LayoutParams params) { Assertions.assertCondition(mRemoveClippedSubviews); Assertions.assertNotNull(mClippingRect); Assertions.assertNotNull(mAllChildren); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/BUCK index 1763cda5de8c03..9e6a4b65cda013 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/BUCK @@ -6,7 +6,6 @@ android_library( provided_deps = [ react_native_dep("third-party/android/support/v4:lib-support-v4"), ], - required_for_source_only_abi = True, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/ReactViewPager.java b/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/ReactViewPager.java index 9a76bace545907..7ed36557135dd0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/ReactViewPager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/ReactViewPager.java @@ -9,17 +9,19 @@ package com.facebook.react.views.viewpager; +import java.util.ArrayList; +import java.util.List; + import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; + import com.facebook.react.bridge.ReactContext; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.react.uimanager.events.NativeGestureUtil; -import java.util.ArrayList; -import java.util.List; /** * Wrapper view for {@link ViewPager}. It's forwarding calls to {@link ViewGroup#addView} to add @@ -116,7 +118,7 @@ public boolean isViewFromObject(View view, Object object) { } } - private class PageChangeListener implements ViewPager.OnPageChangeListener { + private class PageChangeListener implements OnPageChangeListener { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { diff --git a/ReactAndroid/src/main/jni/first-party/fb/BUCK b/ReactAndroid/src/main/jni/first-party/fb/BUCK index 857551cc02da7f..4ffcf0c9cb2b7a 100644 --- a/ReactAndroid/src/main/jni/first-party/fb/BUCK +++ b/ReactAndroid/src/main/jni/first-party/fb/BUCK @@ -2,7 +2,7 @@ include_defs("//ReactAndroid/DEFS") # This target is only used in open source if IS_OSS_BUILD: - fb_xplat_cxx_library( + cxx_library( name = 'jni', soname = 'libfb.$(ext)', srcs = glob(['*.cpp', 'jni/*.cpp', 'lyra/*.cpp']), diff --git a/ReactAndroid/src/main/jni/first-party/fbgloginit/BUCK b/ReactAndroid/src/main/jni/first-party/fbgloginit/BUCK index 0a8cc76675d343..783e60f16b9dc5 100644 --- a/ReactAndroid/src/main/jni/first-party/fbgloginit/BUCK +++ b/ReactAndroid/src/main/jni/first-party/fbgloginit/BUCK @@ -2,7 +2,7 @@ include_defs("//ReactAndroid/DEFS") include_defs("//ReactCommon/DEFS") -fb_xplat_cxx_library( +cxx_library( name = "fbgloginit", srcs = [ "glog_init.cpp", diff --git a/ReactAndroid/src/main/jni/first-party/jni-hack/BUCK b/ReactAndroid/src/main/jni/first-party/jni-hack/BUCK index 269650e6529b94..467d19c9f4bf9b 100644 --- a/ReactAndroid/src/main/jni/first-party/jni-hack/BUCK +++ b/ReactAndroid/src/main/jni/first-party/jni-hack/BUCK @@ -7,7 +7,7 @@ include_defs("//ReactAndroid/DEFS") # 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. -fb_xplat_cxx_library( +cxx_library( name = "jni-hack", header_namespace = "", exported_headers = [ diff --git a/ReactAndroid/src/main/jni/first-party/yogajni/BUCK b/ReactAndroid/src/main/jni/first-party/yogajni/BUCK index b7fbdb563cfa7a..afbd386b6b1bf8 100644 --- a/ReactAndroid/src/main/jni/first-party/yogajni/BUCK +++ b/ReactAndroid/src/main/jni/first-party/yogajni/BUCK @@ -2,7 +2,7 @@ include_defs("//ReactAndroid/DEFS") # This target is only used in open source if IS_OSS_BUILD: - fb_xplat_cxx_library( + cxx_library( name = 'jni', soname = 'libyoga.$(ext)', srcs = glob(['jni/*.cpp']), diff --git a/ReactAndroid/src/main/jni/packagerconnection/BUCK b/ReactAndroid/src/main/jni/packagerconnection/BUCK index b9df8816806c37..c55fd14279cda8 100644 --- a/ReactAndroid/src/main/jni/packagerconnection/BUCK +++ b/ReactAndroid/src/main/jni/packagerconnection/BUCK @@ -1,6 +1,6 @@ include_defs("//ReactAndroid/DEFS") -fb_xplat_cxx_library( +cxx_library( name = "jni", srcs = glob(["*.cpp"]), headers = glob( diff --git a/ReactAndroid/src/main/jni/react/jni/BUCK b/ReactAndroid/src/main/jni/react/jni/BUCK index a9570b425761fa..32878cae633d41 100644 --- a/ReactAndroid/src/main/jni/react/jni/BUCK +++ b/ReactAndroid/src/main/jni/react/jni/BUCK @@ -20,7 +20,7 @@ EXPORTED_HEADERS = [ "WritableNativeMap.h", ] -fb_xplat_cxx_library( +cxx_library( name = "jni", srcs = glob(["*.cpp"]), headers = glob( diff --git a/ReactAndroid/src/main/jni/react/perftests/BUCK b/ReactAndroid/src/main/jni/react/perftests/BUCK index 55f21e6f9b761c..347a578e4e86fb 100644 --- a/ReactAndroid/src/main/jni/react/perftests/BUCK +++ b/ReactAndroid/src/main/jni/react/perftests/BUCK @@ -1,6 +1,6 @@ include_defs("//ReactAndroid/DEFS") -fb_xplat_cxx_library( +cxx_library( name = "perftests", srcs = ["OnLoad.cpp"], compiler_flags = [ diff --git a/ReactCommon/microprofiler/BUCK b/ReactCommon/microprofiler/BUCK index b1c15c02a6c00b..8922e082af3087 100644 --- a/ReactCommon/microprofiler/BUCK +++ b/ReactCommon/microprofiler/BUCK @@ -1,6 +1,6 @@ include_defs("//ReactCommon/DEFS") -fb_xplat_cxx_library( +cxx_library( name = "microprofiler", srcs = [ "MicroProfiler.cpp", diff --git a/ReactCommon/yoga/BUCK b/ReactCommon/yoga/BUCK index 65bfdf418530a4..6e6f1b2e998a9d 100644 --- a/ReactCommon/yoga/BUCK +++ b/ReactCommon/yoga/BUCK @@ -1,4 +1,4 @@ -fb_xplat_cxx_library( +cxx_library( name = "yoga", srcs = glob(["yoga/*.cpp"]), header_namespace = "", diff --git a/local-cli/core/__tests__/findPlugins.spec.js b/local-cli/core/__tests__/findPlugins.spec.js index 075e2cdbfb4bab..3cc7488a30eade 100644 --- a/local-cli/core/__tests__/findPlugins.spec.js +++ b/local-cli/core/__tests__/findPlugins.spec.js @@ -27,18 +27,27 @@ describe('findPlugins', () => { jest.mock(pjsonPath, () => ({ dependencies: {'rnpm-plugin-test': '*'}, })); - expect(findPlugins([ROOT])).toHaveLength(1); - expect(findPlugins([ROOT])[0]).toBe('rnpm-plugin-test'); + + expect(findPlugins([ROOT])).toHaveProperty('commands'); + expect(findPlugins([ROOT])).toHaveProperty('platforms'); + expect(findPlugins([ROOT]).commands).toHaveLength(1); + expect(findPlugins([ROOT]).commands[0]).toBe('rnpm-plugin-test'); + expect(findPlugins([ROOT]).platforms).toHaveLength(0); }); it('returns an empty array if there are no plugins in this folder', () => { jest.mock(pjsonPath, () => ({})); - expect(findPlugins([ROOT])).toHaveLength(0); + expect(findPlugins([ROOT])).toHaveProperty('commands'); + expect(findPlugins([ROOT])).toHaveProperty('platforms'); + expect(findPlugins([ROOT]).commands).toHaveLength(0); + expect(findPlugins([ROOT]).platforms).toHaveLength(0); }); - it('returns an empty array if there is no package.json in the supplied folder', () => { - expect(Array.isArray(findPlugins(['fake-path']))).toBeTruthy(); - expect(findPlugins(['fake-path'])).toHaveLength(0); + it('returns an object with empty arrays if there is no package.json in the supplied folder', () => { + expect(findPlugins(['fake-path'])).toHaveProperty('commands'); + expect(findPlugins(['fake-path'])).toHaveProperty('platforms'); + expect(findPlugins(['fake-path']).commands).toHaveLength(0); + expect(findPlugins(['fake-path']).platforms).toHaveLength(0); }); it('returns plugins from both dependencies and dev dependencies', () => { @@ -46,7 +55,10 @@ describe('findPlugins', () => { dependencies: {'rnpm-plugin-test': '*'}, devDependencies: {'rnpm-plugin-test-2': '*'}, })); - expect(findPlugins([ROOT])).toHaveLength(2); + expect(findPlugins([ROOT])).toHaveProperty('commands'); + expect(findPlugins([ROOT])).toHaveProperty('platforms'); + expect(findPlugins([ROOT]).commands).toHaveLength(2); + expect(findPlugins([ROOT]).platforms).toHaveLength(0); }); it('returns unique list of plugins', () => { @@ -54,6 +66,6 @@ describe('findPlugins', () => { dependencies: {'rnpm-plugin-test': '*'}, devDependencies: {'rnpm-plugin-test': '*'}, })); - expect(findPlugins([ROOT])).toHaveLength(1); + expect(findPlugins([ROOT]).commands).toHaveLength(1); }); }); diff --git a/local-cli/core/android/index.js b/local-cli/core/android/index.js index cc229d298f4fd9..68d2a073c52e13 100644 --- a/local-cli/core/android/index.js +++ b/local-cli/core/android/index.js @@ -126,3 +126,5 @@ exports.dependencyConfig = function dependencyConfigAndroid(folder, userConfig) return { sourceDir, folder, manifest, packageImportPath, packageInstance }; }; + +exports.linkConfig = require('../../link/android'); diff --git a/local-cli/core/findPlugins.js b/local-cli/core/findPlugins.js index f9dc1bc2639369..8a3c30a4253418 100644 --- a/local-cli/core/findPlugins.js +++ b/local-cli/core/findPlugins.js @@ -37,11 +37,19 @@ const findPluginsInReactNativePackage = (pjson) => { return path.join(pjson.name, pjson.rnpm.plugin); }; +const findPlatformsInPackage = (pjson) => { + if (!pjson.rnpm || !pjson.rnpm.platform) { + return []; + } + + return path.join(pjson.name, pjson.rnpm.platform); +}; + const findPluginInFolder = (folder) => { const pjson = readPackage(folder); if (!pjson) { - return []; + return {commands: [], platforms: []}; } const deps = union( @@ -51,27 +59,33 @@ const findPluginInFolder = (folder) => { return deps.reduce( (acc, pkg) => { + let commands = acc.commands; + let platforms = acc.platforms; if (isRNPMPlugin(pkg)) { - return acc.concat(pkg); + commands = commands.concat(pkg); } if (isReactNativePlugin(pkg)) { const pkgJson = readPackage(path.join(folder, 'node_modules', pkg)); - if (!pkgJson) { - return acc; + if (pkgJson) { + commands = commands.concat(findPluginsInReactNativePackage(pkgJson)); + platforms = platforms.concat(findPlatformsInPackage(pkgJson)); } - return acc.concat(findPluginsInReactNativePackage(pkgJson)); } - return acc; + return {commands: commands, platforms: platforms}; }, - [] + {commands: [], platforms: []} ); }; /** * Find plugins in package.json of the given folder * @param {String} folder Path to the folder to get the package.json from - * @type {Array} Array of plugins or an empty array if no package.json found + * @type {Object} Object of commands and platform plugins */ module.exports = function findPlugins(folders) { - return uniq(flatten(folders.map(findPluginInFolder))); + const plugins = folders.map(findPluginInFolder); + return { + commands: uniq(flatten(plugins.map(p => p.commands))), + platforms: uniq(flatten(plugins.map(p => p.platforms))) + }; }; diff --git a/local-cli/core/index.js b/local-cli/core/index.js index 97a2eeb2b6cf90..0d43e87c24122f 100644 --- a/local-cli/core/index.js +++ b/local-cli/core/index.js @@ -15,7 +15,6 @@ const Config = require('../util/Config'); const findPlugins = require('./findPlugins'); const findAssets = require('./findAssets'); const ios = require('./ios'); -const windows = require('./windows'); const wrapCommands = require('./wrapCommands'); /* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error @@ -33,6 +32,10 @@ import type {ConfigT} from 'metro'; export type RNConfig = { ...ConfigT, + /** + * Returns an object with all platform configurations. + */ + getPlatformConfig(): Object, /** * Returns an array of project commands used by the CLI to load */ @@ -55,10 +58,21 @@ const attachPackage = (command, pkg) => Array.isArray(command) ? command.map(cmd => attachPackage(cmd, pkg)) : { ...command, pkg }; +const appRoot = process.cwd(); +const plugins = findPlugins([appRoot]); +const pluginPlatforms = plugins + .platforms + .reduce((acc, pathToPlatforms) => { + // $FlowFixMe non-literal require + return Object.assign(acc, require(path.join(appRoot, 'node_modules', pathToPlatforms))); + }, + {}); + const defaultRNConfig = { + getProjectCommands(): Array { - const appRoot = process.cwd(); - const plugins = findPlugins([appRoot]) + const commands = plugins + .commands .map(pathToCommands => { const name = pathToCommands.split(path.sep)[0]; @@ -70,35 +84,51 @@ const defaultRNConfig = { ); }); - return flatten(plugins); + return flatten(commands); + }, + + getPlatformConfig(): Object { + return { + ios, + android, + ...pluginPlatforms + }; }, getProjectConfig(): Object { + const platforms = this.getPlatformConfig(); const folder = process.cwd(); const rnpm = getRNPMConfig(folder); - return Object.assign({}, rnpm, { - ios: ios.projectConfig(folder, rnpm.ios || {}), - android: android.projectConfig(folder, rnpm.android || {}), - windows: windows.projectConfig(folder, rnpm.windows || {}), + let config = Object.assign({}, rnpm, { assets: findAssets(folder, rnpm.assets), }); + + Object.keys(platforms).forEach(key => { + config[key] = platforms[key].projectConfig(folder, rnpm[key] || {}); + }); + + return config; }, getDependencyConfig(packageName: string) { + const platforms = this.getPlatformConfig(); const folder = path.join(process.cwd(), 'node_modules', packageName); const rnpm = getRNPMConfig( path.join(process.cwd(), 'node_modules', packageName) ); - return Object.assign({}, rnpm, { - ios: ios.dependencyConfig(folder, rnpm.ios || {}), - android: android.dependencyConfig(folder, rnpm.android || {}), - windows: windows.dependencyConfig(folder, rnpm.windows || {}), + let config = Object.assign({}, rnpm, { assets: findAssets(folder, rnpm.assets), commands: wrapCommands(rnpm.commands), params: rnpm.params || [], }); + + Object.keys(platforms).forEach(key => { + config[key] = platforms[key].dependencyConfig(folder, rnpm[key] || {}); + }); + + return config; }, }; diff --git a/local-cli/core/ios/index.js b/local-cli/core/ios/index.js index 6bca5946352085..0d69ac9f11129f 100644 --- a/local-cli/core/ios/index.js +++ b/local-cli/core/ios/index.js @@ -57,3 +57,5 @@ exports.projectConfig = function projectConfigIOS(folder, userConfig) { }; exports.dependencyConfig = exports.projectConfig; + +exports.linkConfig = require('../../link/ios'); diff --git a/local-cli/core/windows/findNamespace.js b/local-cli/core/windows/findNamespace.js deleted file mode 100644 index 4867368f1228ff..00000000000000 --- a/local-cli/core/windows/findNamespace.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * 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. - */ -'use strict'; - -const fs = require('fs'); -const glob = require('glob'); -const path = require('path'); - -/** - * Gets package's namespace - * by searching for its declaration in all C# files present in the folder - * - * @param {String} folder Folder to find C# files - */ -module.exports = function getNamespace(folder) { - const files = glob.sync('**/*.cs', { cwd: folder }); - - const packages = files - .map(filePath => fs.readFileSync(path.join(folder, filePath), 'utf8')) - .map(file => file.match(/namespace (.*)[\s\S]+IReactPackage/)) - .filter(match => match); - - return packages.length ? packages[0][1] : null; -}; diff --git a/local-cli/core/windows/findPackageClassName.js b/local-cli/core/windows/findPackageClassName.js deleted file mode 100644 index 279610eac7f7d4..00000000000000 --- a/local-cli/core/windows/findPackageClassName.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * 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. - */ -'use strict'; - -const fs = require('fs'); -const glob = require('glob'); -const path = require('path'); - -/** - * Gets package's class name (class that implements IReactPackage) - * by searching for its declaration in all C# files present in the folder - * - * @param {String} folder Folder to find C# files - */ -module.exports = function getPackageClassName(folder) { - const files = glob.sync('**/*.cs', { cwd: folder }); - - const packages = files - .map(filePath => fs.readFileSync(path.join(folder, filePath), 'utf8')) - .map(file => file.match(/class (.*) : IReactPackage/)) - .filter(match => match); - - return packages.length ? packages[0][1] : null; -}; diff --git a/local-cli/core/windows/findProject.js b/local-cli/core/windows/findProject.js deleted file mode 100644 index 3b0121f74dea44..00000000000000 --- a/local-cli/core/windows/findProject.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * 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. - */ -'use strict'; - -const glob = require('glob'); -const path = require('path'); - -/** - * Find an C# project file - * - * @param {String} folder Name of the folder where to seek - * @return {String} - */ -module.exports = function findManifest(folder) { - const csprojPath = glob.sync(path.join('**', '*.csproj'), { - cwd: folder, - ignore: ['node_modules/**', '**/build/**', 'Examples/**', 'examples/**'], - })[0]; - - return csprojPath ? path.join(folder, csprojPath) : null; -}; diff --git a/local-cli/core/windows/findWindowsSolution.js b/local-cli/core/windows/findWindowsSolution.js deleted file mode 100644 index fb6782633b92ae..00000000000000 --- a/local-cli/core/windows/findWindowsSolution.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * 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. - */ -'use strict'; - -const glob = require('glob'); -const path = require('path'); - -/** - * Glob pattern to look for solution file - */ -const GLOB_PATTERN = '**/*.sln'; - -/** - * Regexp matching all test projects - */ -const TEST_PROJECTS = /test|example|sample/i; - -/** - * Base windows folder - */ -const WINDOWS_BASE = 'windows'; - -/** - * These folders will be excluded from search to speed it up - */ -const GLOB_EXCLUDE_PATTERN = ['**/@(node_modules)/**']; - -/** - * Finds windows project by looking for all .sln files - * in given folder. - * - * Returns first match if files are found or null - * - * Note: `./windows/*.sln` are returned regardless of the name - */ -module.exports = function findSolution(folder) { - const projects = glob - .sync(GLOB_PATTERN, { - cwd: folder, - ignore: GLOB_EXCLUDE_PATTERN, - }) - .filter(project => { - return path.dirname(project) === WINDOWS_BASE || !TEST_PROJECTS.test(project); - }) - .sort((projectA, projectB) => { - return path.dirname(projectA) === WINDOWS_BASE ? -1 : 1; - }); - - if (projects.length === 0) { - return null; - } - - return projects[0]; -}; diff --git a/local-cli/core/windows/generateGUID.js b/local-cli/core/windows/generateGUID.js deleted file mode 100644 index 25eb456eb284fd..00000000000000 --- a/local-cli/core/windows/generateGUID.js +++ /dev/null @@ -1,10 +0,0 @@ -const s4 = () => { - return Math.floor((1 + Math.random()) * 0x10000) - .toString(16) - .substring(1); -}; - -module.exports = function generateGUID() { - return s4() + s4() + '-' + s4() + '-' + s4() + '-' + - s4() + '-' + s4() + s4() + s4(); -}; diff --git a/local-cli/core/windows/index.js b/local-cli/core/windows/index.js deleted file mode 100644 index c535c4c3e14d8a..00000000000000 --- a/local-cli/core/windows/index.js +++ /dev/null @@ -1,114 +0,0 @@ -/** - * 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. - */ -'use strict'; - -const findWindowsSolution = require('./findWindowsSolution'); -const findNamespace = require('./findNamespace'); -const findProject = require('./findProject'); -const findPackageClassName = require('./findPackageClassName'); -const path = require('path'); -const generateGUID = require('./generateGUID'); - -const relativeProjectPath = (fullProjPath) => { - const windowsPath = fullProjPath - .substring(fullProjPath.lastIndexOf('node_modules') - 1, fullProjPath.length) - .replace(/\//g, '\\'); - - return '..' + windowsPath; -}; - -const getProjectName = (fullProjPath) => { - return fullProjPath.split('/').slice(-1)[0].replace(/\.csproj/i, ''); -}; - -/** - * Gets windows project config by analyzing given folder and taking some - * defaults specified by user into consideration - */ -exports.projectConfig = function projectConfigWindows(folder, userConfig) { - - const csSolution = userConfig.csSolution || findWindowsSolution(folder); - - if (!csSolution) { - return null; - } - - // expects solutions to be named the same as project folders - const solutionPath = path.join(folder, csSolution); - const windowsAppFolder = csSolution.substring(0, csSolution.lastIndexOf('.sln')); - const src = userConfig.sourceDir || windowsAppFolder; - const sourceDir = path.join(folder, src); - const mainPage = path.join(sourceDir, 'MainPage.cs'); - const projectPath = userConfig.projectPath || findProject(folder); - - return { - sourceDir, - solutionPath, - projectPath, - mainPage, - folder, - userConfig, - }; -}; - -/** - * Same as projectConfigWindows except it returns - * different config that applies to packages only - */ -exports.dependencyConfig = function dependencyConfigWindows(folder, userConfig) { - - const csSolution = userConfig.csSolution || findWindowsSolution(folder); - - if (!csSolution) { - return null; - } - - // expects solutions to be named the same as project folders - const windowsAppFolder = csSolution.substring(0, csSolution.lastIndexOf('.sln')); - const src = userConfig.sourceDir || windowsAppFolder; - - if (!src) { - return null; - } - - const sourceDir = path.join(folder, src); - const packageClassName = findPackageClassName(sourceDir); - const namespace = userConfig.namespace || findNamespace(sourceDir); - const csProj = userConfig.csProj || findProject(folder); - - /** - * This module has no package to export or no namespace - */ - if (!packageClassName || !namespace) { - return null; - } - - const packageUsingPath = userConfig.packageUsingPath || - `using ${namespace};`; - - const packageInstance = userConfig.packageInstance || - `new ${packageClassName}()`; - - const projectGUID = generateGUID(); - const pathGUID = generateGUID(); - const projectName = getProjectName(csProj); - const relativeProjPath = relativeProjectPath(csProj); - - return { - sourceDir, - packageUsingPath, - packageInstance, - projectName, - csProj, - folder, - projectGUID, - pathGUID, - relativeProjPath, - }; -}; diff --git a/local-cli/link/__tests__/link.spec.js b/local-cli/link/__tests__/link.spec.js index 3972a0a681c672..6ebe9959a93137 100644 --- a/local-cli/link/__tests__/link.spec.js +++ b/local-cli/link/__tests__/link.spec.js @@ -39,6 +39,7 @@ describe('link', () => { it('should accept a name of a dependency to link', (done) => { const config = { + getPlatformConfig: () => ({ios: {}, android: {}}), getProjectConfig: () => ({ assets: [] }), getDependencyConfig: sinon.stub().returns({ assets: [], commands: {} }), }; @@ -54,6 +55,7 @@ describe('link', () => { it('should read dependencies from package.json when name not provided', (done) => { const config = { + getPlatformConfig: () => ({ios: {}, android: {}}), getProjectConfig: () => ({ assets: [] }), getDependencyConfig: sinon.stub().returns({ assets: [], commands: {} }), }; @@ -79,7 +81,10 @@ describe('link', () => { it('should register native module when android/ios projects are present', (done) => { const registerNativeModule = sinon.stub(); const dependencyConfig = {android: {}, ios: {}, assets: [], commands: {}}; + const androidLinkConfig = require('../android'); + const iosLinkConfig = require('../ios'); const config = { + getPlatformConfig: () => ({ios: { linkConfig: iosLinkConfig }, android: { linkConfig: androidLinkConfig }}), getProjectConfig: () => ({android: {}, ios: {}, assets: []}), getDependencyConfig: sinon.stub().returns(dependencyConfig), }; @@ -116,6 +121,7 @@ describe('link', () => { const registerNativeModule = sinon.stub(); const dependencyConfig = {ios: {}, android: {}, assets: [], commands: {}}; const config = { + getPlatformConfig: () => ({ios: {}, android: {}}), getProjectConfig: () => ({ ios: {}, android: {}, assets: [] }), getDependencyConfig: sinon.stub().returns(dependencyConfig), }; @@ -148,6 +154,62 @@ describe('link', () => { }); }); + it('should register native modules for plugins', (done) => { + const registerNativeModule = sinon.stub(); + const dependencyConfig = {ios: {}, android: {}, test: {}, assets: [], commands: {}}; + const linkPluginConfig = { isInstalled: () => false, register: registerNativeModule }; + const config = { + getPlatformConfig: () => ({ ios: {}, android: {}, test: { linkConfig: () => linkPluginConfig }}), + getProjectConfig: () => ({ ios: {}, android: {}, test: {}, assets: [] }), + getDependencyConfig: sinon.stub().returns(dependencyConfig), + }; + + jest.setMock( + '../ios/isInstalled.js', + sinon.stub().returns(true) + ); + + jest.setMock( + '../android/isInstalled.js', + sinon.stub().returns(true) + ); + + const link = require('../link').func; + + link(['react-native-blur'], config).then(() => { + expect(registerNativeModule.calledOnce).toBeTruthy(); + done(); + }); + }); + + it('should not register native modules for plugins when already installed', (done) => { + const registerNativeModule = sinon.stub(); + const dependencyConfig = {ios: {}, android: {}, test: {}, assets: [], commands: {}}; + const linkPluginConfig = { isInstalled: () => true, register: registerNativeModule}; + const config = { + getPlatformConfig: () => ({ ios: {}, android: {}, test: { linkConfig: () => linkPluginConfig }}), + getProjectConfig: () => ({ ios: {}, android: {}, test: {}, assets: [] }), + getDependencyConfig: sinon.stub().returns(dependencyConfig), + }; + + jest.setMock( + '../ios/isInstalled.js', + sinon.stub().returns(true) + ); + + jest.setMock( + '../android/isInstalled.js', + sinon.stub().returns(true) + ); + + const link = require('../link').func; + + link(['react-native-blur'], config).then(() => { + expect(registerNativeModule.callCount).toEqual(0); + done(); + }); + }); + it('should run prelink and postlink commands at the appropriate times', (done) => { const registerNativeModule = sinon.stub(); const prelink = sinon.stub().yieldsAsync(); @@ -163,7 +225,9 @@ describe('link', () => { sinon.stub().returns(false) ); + const linkConfig = require('../ios'); const config = { + getPlatformConfig: () => ({ ios: { linkConfig: linkConfig }}), getProjectConfig: () => ({ ios: {}, assets: [] }), getDependencyConfig: sinon.stub().returns({ ios: {}, assets: [], commands: { prelink, postlink }, @@ -181,7 +245,7 @@ describe('link', () => { it('should copy assets from both project and dependencies projects', (done) => { const dependencyAssets = ['Fonts/Font.ttf']; - const dependencyConfig = {assets: dependencyAssets, commands: {}}; + const dependencyConfig = {assets: dependencyAssets, ios: {}, commands: {}}; const projectAssets = ['Fonts/FontC.ttf']; const copyAssets = sinon.stub(); @@ -190,7 +254,9 @@ describe('link', () => { copyAssets ); + const linkConfig = require('../ios'); const config = { + getPlatformConfig: () => ({ ios: { linkConfig: linkConfig } }), getProjectConfig: () => ({ ios: {}, assets: projectAssets }), getDependencyConfig: sinon.stub().returns(dependencyConfig), }; diff --git a/local-cli/link/android/copyAssets.js b/local-cli/link/android/copyAssets.js index 709bf0b95c770b..43689ee94d6ba1 100644 --- a/local-cli/link/android/copyAssets.js +++ b/local-cli/link/android/copyAssets.js @@ -8,10 +8,10 @@ const groupFilesByType = require('../groupFilesByType'); * For now, the only types of files that are handled are: * - Fonts (otf, ttf) - copied to targetPath/fonts under original name */ -module.exports = function copyAssetsAndroid(files, targetPath) { +module.exports = function copyAssetsAndroid(files, project) { const assets = groupFilesByType(files); (assets.font || []).forEach(asset => - fs.copySync(asset, path.join(targetPath, 'fonts', path.basename(asset))) + fs.copySync(asset, path.join(project.assetsPath, 'fonts', path.basename(asset))) ); }; diff --git a/local-cli/link/android/index.js b/local-cli/link/android/index.js new file mode 100644 index 00000000000000..986ec59450b8dd --- /dev/null +++ b/local-cli/link/android/index.js @@ -0,0 +1,9 @@ +module.exports = function() { + return { + isInstalled: require('./isInstalled'), + register: require('./registerNativeModule'), + unregister: require('./unregisterNativeModule'), + copyAssets: require('./copyAssets'), + unlinkAssets: require('./unlinkAssets') + }; +}; diff --git a/local-cli/link/android/unlinkAssets.js b/local-cli/link/android/unlinkAssets.js index 1cc0974d3e4e14..8ec42fc262c632 100644 --- a/local-cli/link/android/unlinkAssets.js +++ b/local-cli/link/android/unlinkAssets.js @@ -8,11 +8,11 @@ const groupFilesByType = require('../groupFilesByType'); * For now, the only types of files that are handled are: * - Fonts (otf, ttf) - copied to targetPath/fonts under original name */ -module.exports = function unlinkAssetsAndroid(files, targetPath) { +module.exports = function unlinkAssetsAndroid(files, project) { const assets = groupFilesByType(files); (assets.font || []).forEach((file) => { - const filePath = path.join(targetPath, 'fonts', path.basename(file)); + const filePath = path.join(project.assetsPath, 'fonts', path.basename(file)); if (fs.existsSync(filePath)) { fs.unlinkSync(filePath); } diff --git a/local-cli/link/ios/common/isInstalled.js b/local-cli/link/ios/common/isInstalled.js new file mode 100644 index 00000000000000..a7a5f2d07d192e --- /dev/null +++ b/local-cli/link/ios/common/isInstalled.js @@ -0,0 +1,6 @@ +const isInstalledIOS = require('../isInstalled'); +const isInstalledPods = require('../../pods/isInstalled'); + +module.exports = function isInstalled(config, name) { + return isInstalledIOS(config, name) || isInstalledPods(config, name); +}; diff --git a/local-cli/link/ios/common/registerNativeModule.js b/local-cli/link/ios/common/registerNativeModule.js new file mode 100644 index 00000000000000..38ce59606982ca --- /dev/null +++ b/local-cli/link/ios/common/registerNativeModule.js @@ -0,0 +1,16 @@ +const registerDependencyIOS = require('../registerNativeModule'); +const registerDependencyPods = require('../../pods/registerNativeModule'); + +module.exports = function registerNativeModule( + name, + dependencyConfig, + params, + projectConfig +) { + if (projectConfig.podfile && dependencyConfig.podspec) { + registerDependencyPods(name, dependencyConfig, projectConfig); + } + else { + registerDependencyIOS(dependencyConfig, projectConfig); + } +}; diff --git a/local-cli/link/ios/common/unregisterNativeModule.js b/local-cli/link/ios/common/unregisterNativeModule.js new file mode 100644 index 00000000000000..b42882623fbe34 --- /dev/null +++ b/local-cli/link/ios/common/unregisterNativeModule.js @@ -0,0 +1,22 @@ +const compact = require('lodash').compact; +const isInstalledIOS = require('../isInstalled'); +const isInstalledPods = require('../../pods/isInstalled'); +const unregisterDependencyIOS = require('../registerNativeModule'); +const unregisterDependencyPods = require('../../pods/registerNativeModule'); + +module.exports = function unregisterNativeModule( + name, + dependencyConfig, + projectConfig, + otherDependencies +) { + const isIosInstalled = isInstalledIOS(projectConfig, dependencyConfig); + const isPodInstalled = isInstalledPods(projectConfig, dependencyConfig); + if (isIosInstalled) { + const iOSDependencies = compact(otherDependencies.map(d => d.config.ios)); + unregisterDependencyIOS(dependencyConfig, projectConfig, iOSDependencies); + } + else if (isPodInstalled) { + unregisterDependencyPods(dependencyConfig, projectConfig); + } +}; diff --git a/local-cli/link/ios/index.js b/local-cli/link/ios/index.js new file mode 100644 index 00000000000000..9653b3be80a1d1 --- /dev/null +++ b/local-cli/link/ios/index.js @@ -0,0 +1,9 @@ +module.exports = function() { + return { + isInstalled: require('./common/isInstalled'), + register: require('./common/registerNativeModule'), + unregister: require('./common/unregisterNativeModule'), + copyAssets: require('./copyAssets'), + unlinkAssets: require('./unlinkAssets') + }; +}; diff --git a/local-cli/link/link.js b/local-cli/link/link.js index 969bf63a86bd73..0727494dfd8c92 100644 --- a/local-cli/link/link.js +++ b/local-cli/link/link.js @@ -26,16 +26,6 @@ const chalk = require('chalk'); * run Flow. */ const isEmpty = require('lodash').isEmpty; const promiseWaterfall = require('./promiseWaterfall'); -const registerDependencyAndroid = require('./android/registerNativeModule'); -const registerDependencyWindows = require('./windows/registerNativeModule'); -const registerDependencyIOS = require('./ios/registerNativeModule'); -const registerDependencyPods = require('./pods/registerNativeModule'); -const isInstalledAndroid = require('./android/isInstalled'); -const isInstalledWindows = require('./windows/isInstalled'); -const isInstalledIOS = require('./ios/isInstalled'); -const isInstalledPods = require('./pods/isInstalled'); -const copyAssetsAndroid = require('./android/copyAssets'); -const copyAssetsIOS = require('./ios/copyAssets'); const getProjectDependencies = require('./getProjectDependencies'); const getDependencyConfig = require('./getDependencyConfig'); const pollParams = require('./pollParams'); @@ -49,95 +39,55 @@ log.heading = 'rnpm-link'; const dedupeAssets = (assets) => uniqBy(assets, asset => path.basename(asset)); - -const linkDependencyAndroid = (androidProject, dependency) => { - if (!androidProject || !dependency.config.android) { - return null; - } - - const isInstalled = isInstalledAndroid(androidProject, dependency.name); - - if (isInstalled) { - log.info(chalk.grey(`Android module ${dependency.name} is already linked`)); - return null; - } - - return pollParams(dependency.config.params).then(params => { - log.info(`Linking ${dependency.name} android dependency`); - - registerDependencyAndroid( - dependency.name, - dependency.config.android, - params, - androidProject - ); - - log.info(`Android module ${dependency.name} has been successfully linked`); - }); -}; - -const linkDependencyWindows = (windowsProject, dependency) => { - - if (!windowsProject || !dependency.config.windows) { - return null; - } - - const isInstalled = isInstalledWindows(windowsProject, dependency.config.windows); - - if (isInstalled) { - log.info(chalk.grey(`Windows module ${dependency.name} is already linked`)); - return null; - } - - return pollParams(dependency.config.params).then(params => { - log.info(`Linking ${dependency.name} windows dependency`); - - registerDependencyWindows( - dependency.name, - dependency.config.windows, - params, - windowsProject - ); - - log.info(`Windows module ${dependency.name} has been successfully linked`); - }); +const linkDependency = (platforms, project, dependency) => { + Object.keys(platforms || {}) + .forEach(platform => { + if (!project[platform] || !dependency.config[platform]) { + return null; + } + + const linkConfig = platforms[platform] && platforms[platform].linkConfig && platforms[platform].linkConfig(); + if (!linkConfig || !linkConfig.isInstalled || !linkConfig.register) { + return null; + } + + const isInstalled = linkConfig.isInstalled(project[platform], dependency.config[platform]); + + if (isInstalled) { + log.info(chalk.grey(`Platform '${platform}' module ${dependency.name} is already linked`)); + return null; + } + + return pollParams(dependency.config.params).then(params => { + log.info(`Linking ${dependency.name} ${platform} dependency`); + + linkConfig.register( + dependency.name, + dependency.config[platform], + params, + project[platform] + ); + + log.info(`Platform '${platform}' module ${dependency.name} has been successfully linked`); + }); + }); }; -const linkDependencyIOS = (iOSProject, dependency) => { - if (!iOSProject || !dependency.config.ios) { - return; - } - - const isInstalled = isInstalledIOS(iOSProject, dependency.config.ios) || isInstalledPods(iOSProject, dependency.config.ios); - if (isInstalled) { - log.info(chalk.grey(`iOS module ${dependency.name} is already linked`)); - return; - } - - log.info(`Linking ${dependency.name} ios dependency`); - if (iOSProject.podfile && dependency.config.ios.podspec) { - registerDependencyPods(dependency, iOSProject); - } - else { - registerDependencyIOS(dependency.config.ios, iOSProject); - } - log.info(`iOS module ${dependency.name} has been successfully linked`); -}; - -const linkAssets = (project, assets) => { +const linkAssets = (platforms, project, assets) => { if (isEmpty(assets)) { return; } - if (project.ios) { - log.info('Linking assets to ios project'); - copyAssetsIOS(assets, project.ios); - } + Object.keys(platforms || {}) + .forEach(platform => { + const linkConfig = platforms[platform] && platforms[platform].linkConfig && platforms[platform].linkConfig(); + if (!linkConfig || !linkConfig.copyAssets) { + return; + } - if (project.android) { - log.info('Linking assets to android project'); - copyAssetsAndroid(assets, project.android.assetsPath); - } + log.info(`Linking assets to ${platform} project`); + linkConfig.copyAssets(assets, project[platform]); + }); log.info('Assets have been successfully linked to your project'); }; @@ -150,9 +100,11 @@ const linkAssets = (project, assets) => { * @param config CLI config, see local-cli/core/index.js */ function link(args: Array, config: RNConfig) { - var project; + let project; + let platforms; try { project = config.getProjectConfig(); + platforms = config.getPlatformConfig(); } catch (err) { log.error( 'ERRPACKAGEJSON', @@ -161,7 +113,8 @@ function link(args: Array, config: RNConfig) { return Promise.reject(err); } - if (!project.android && !project.ios && !project.windows && findReactNativeScripts()) { + const hasProjectConfig = Object.keys(platforms).reduce((acc, key) => acc || key in project, false); + if (!hasProjectConfig && findReactNativeScripts()) { throw new Error( '`react-native link` can not be used in Create React Native App projects. ' + 'If you need to include a library that relies on custom native code, ' + @@ -183,19 +136,17 @@ function link(args: Array, config: RNConfig) { ); const assets = dedupeAssets(dependencies.reduce( - (assets, dependency) => assets.concat(dependency.config.assets), + (acc, dependency) => acc.concat(dependency.config.assets), project.assets )); const tasks = flatten(dependencies.map(dependency => [ () => promisify(dependency.config.commands.prelink || commandStub), - () => linkDependencyAndroid(project.android, dependency), - () => linkDependencyIOS(project.ios, dependency), - () => linkDependencyWindows(project.windows, dependency), + () => linkDependency(platforms, project, dependency), () => promisify(dependency.config.commands.postlink || commandStub), ])); - tasks.push(() => linkAssets(project, assets)); + tasks.push(() => linkAssets(platforms, project, assets)); return promiseWaterfall(tasks).catch(err => { log.error( diff --git a/local-cli/link/pods/registerNativeModule.js b/local-cli/link/pods/registerNativeModule.js index e29c5642a1c684..b8d8eb835c9a05 100644 --- a/local-cli/link/pods/registerNativeModule.js +++ b/local-cli/link/pods/registerNativeModule.js @@ -7,10 +7,10 @@ const findMarkedLinesInPodfile = require('./findMarkedLinesInPodfile'); const addPodEntry = require('./addPodEntry'); const savePodFile = require('./savePodFile'); -module.exports = function registerNativeModulePods(dependency, iOSProject) { +module.exports = function registerNativeModulePods(name, dependencyConfig, iOSProject) { const podLines = readPodfile(iOSProject.podfile); const linesToAddEntry = getLinesToAddEntry(podLines, iOSProject); - addPodEntry(podLines, linesToAddEntry, dependency.config.ios.podspec, dependency.name); + addPodEntry(podLines, linesToAddEntry, dependencyConfig.podspec, name); savePodFile(iOSProject.podfile, podLines); }; diff --git a/local-cli/link/unlink.js b/local-cli/link/unlink.js index f4f001853f35e6..7bd9e1cded6070 100644 --- a/local-cli/link/unlink.js +++ b/local-cli/link/unlink.js @@ -1,18 +1,7 @@ const log = require('npmlog'); const getProjectDependencies = require('./getProjectDependencies'); -const unregisterDependencyAndroid = require('./android/unregisterNativeModule'); -const unregisterDependencyWindows = require('./windows/unregisterNativeModule'); -const unregisterDependencyIOS = require('./ios/unregisterNativeModule'); -const unregisterDependencyPods = require('./pods/unregisterNativeModule'); -const isInstalledAndroid = require('./android/isInstalled'); -const isInstalledWindows = require('./windows/isInstalled'); -const isInstalledIOS = require('./ios/isInstalled'); -const isInstalledPods = require('./pods/isInstalled'); -const unlinkAssetsAndroid = require('./android/unlinkAssets'); -const unlinkAssetsIOS = require('./ios/unlinkAssets'); const getDependencyConfig = require('./getDependencyConfig'); -const compact = require('lodash').compact; const difference = require('lodash').difference; const filter = require('lodash').filter; const flatten = require('lodash').flatten; @@ -23,66 +12,37 @@ const promisify = require('./promisify'); log.heading = 'rnpm-link'; -const unlinkDependencyAndroid = (androidProject, dependency, packageName) => { - if (!androidProject || !dependency.android) { - return; - } - - const isInstalled = isInstalledAndroid(androidProject, packageName); - - if (!isInstalled) { - log.info(`Android module ${packageName} is not installed`); - return; - } - - log.info(`Unlinking ${packageName} android dependency`); - - unregisterDependencyAndroid(packageName, dependency.android, androidProject); - - log.info(`Android module ${packageName} has been successfully unlinked`); -}; - -const unlinkDependencyWindows = (windowsProject, dependency, packageName) => { - if (!windowsProject || !dependency.windows) { - return; - } - - const isInstalled = isInstalledWindows(windowsProject, dependency.windows); - - if (!isInstalled) { - log.info(`Windows module ${packageName} is not installed`); - return; - } - - log.info(`Unlinking ${packageName} windows dependency`); +const unlinkDependency = (platforms, project, dependency, packageName, otherDependencies) => { - unregisterDependencyWindows(packageName, dependency.windows, windowsProject); + Object.keys(platforms || {}) + .forEach(platform => { + if (!project[platform] || !dependency[platform]) { + return; + } - log.info(`Windows module ${packageName} has been successfully unlinked`); -}; + const linkConfig = platforms[platform] && platforms[platform].linkConfig && platforms[platform].linkConfig(); + if (!linkConfig || !linkConfig.isInstalled || !linkConfig.unregister) { + return; + } -const unlinkDependencyIOS = (iOSProject, dependency, packageName, iOSDependencies) => { - if (!iOSProject || !dependency.ios) { - return; - } + const isInstalled = linkConfig.isInstalled(project[platform], dependency[platform]); - const isIosInstalled = isInstalledIOS(iOSProject, dependency.ios); - const isPodInstalled = isInstalledPods(iOSProject, dependency.ios); - if (!isIosInstalled && !isPodInstalled) { - log.info(`iOS module ${packageName} is not installed`); - return; - } + if (!isInstalled) { + log.info(`Platform '${platform}' module ${packageName} is not installed`); + return; + } - log.info(`Unlinking ${packageName} ios dependency`); + log.info(`Unlinking ${packageName} ${platform} dependency`); - if (isIosInstalled) { - unregisterDependencyIOS(dependency.ios, iOSProject, iOSDependencies); - } - else if (isPodInstalled) { - unregisterDependencyPods(dependency.ios, iOSProject); - } + linkConfig.unregister( + packageName, + dependency[platform], + project[platform], + otherDependencies + ); - log.info(`iOS module ${packageName} has been successfully unlinked`); + log.info(`Platform '${platform}' module ${dependency.name} has been successfully unlinked`); + }); }; /** @@ -94,10 +54,12 @@ const unlinkDependencyIOS = (iOSProject, dependency, packageName, iOSDependencie function unlink(args, config) { const packageName = args[0]; - var project; - var dependency; + let platforms; + let project; + let dependency; try { + platforms = config.getPlatformConfig(); project = config.getProjectConfig(); } catch (err) { log.error( @@ -119,13 +81,10 @@ function unlink(args, config) { const allDependencies = getDependencyConfig(config, getProjectDependencies()); const otherDependencies = filter(allDependencies, d => d.name !== packageName); - const iOSDependencies = compact(otherDependencies.map(d => d.config.ios)); const tasks = [ () => promisify(dependency.commands.preunlink || commandStub), - () => unlinkDependencyAndroid(project.android, dependency, packageName), - () => unlinkDependencyIOS(project.ios, dependency, packageName, iOSDependencies), - () => unlinkDependencyWindows(project.windows, dependency, packageName), + () => unlinkDependency(platforms, project, dependency, packageName, otherDependencies), () => promisify(dependency.commands.postunlink || commandStub) ]; @@ -142,15 +101,16 @@ function unlink(args, config) { return Promise.resolve(); } - if (project.ios) { - log.info('Unlinking assets from ios project'); - unlinkAssetsIOS(assets, project.ios); - } - - if (project.android) { - log.info('Unlinking assets from android project'); - unlinkAssetsAndroid(assets, project.android.assetsPath); - } + Object.keys(platforms || {}) + .forEach(platform => { + const linkConfig = platforms[platform] && platforms[platform].linkConfig && platforms[platform].linkConfig(); + if (!linkConfig || !linkConfig.unlinkAssets) { + return; + } + + log.info(`Unlinking assets from ${platform} project`); + linkConfig.unlinkAssets(assets, project[platform]); + }); log.info( `${packageName} assets has been successfully unlinked from your project` diff --git a/local-cli/link/windows/isInstalled.js b/local-cli/link/windows/isInstalled.js deleted file mode 100644 index b96edcb21ba2f6..00000000000000 --- a/local-cli/link/windows/isInstalled.js +++ /dev/null @@ -1,8 +0,0 @@ -const fs = require('fs'); -const makeUsingPatch = require('./patches/makeUsingPatch'); - -module.exports = function isInstalled(config, dependencyConfig) { - return fs - .readFileSync(config.mainPage) - .indexOf(makeUsingPatch(dependencyConfig.packageUsingPath).patch) > -1; -}; diff --git a/local-cli/link/windows/patches/applyParams.js b/local-cli/link/windows/patches/applyParams.js deleted file mode 100644 index 21c1e9545bc49a..00000000000000 --- a/local-cli/link/windows/patches/applyParams.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) 2013-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. - */ - -const toCamelCase = require('lodash').camelCase; - -module.exports = function applyParams(str, params, prefix) { - return str.replace( - /\$\{(\w+)\}/g, - (pattern, param) => { - const name = toCamelCase(prefix) + '_' + param; - - return params[param] - ? `getResources().getString(R.string.${name})` - : null; - } - ); -}; diff --git a/local-cli/link/windows/patches/applyPatch.js b/local-cli/link/windows/patches/applyPatch.js deleted file mode 100644 index 81757076cbee15..00000000000000 --- a/local-cli/link/windows/patches/applyPatch.js +++ /dev/null @@ -1,11 +0,0 @@ -const fs = require('fs'); - -module.exports = function applyPatch(file, patch, flip = false) { - - fs.writeFileSync(file, fs - .readFileSync(file, 'utf8') - .replace(patch.pattern, match => { - return flip ? `${patch.patch}${match}` : `${match}${patch.patch}`; - }) - ); -}; diff --git a/local-cli/link/windows/patches/makePackagePatch.js b/local-cli/link/windows/patches/makePackagePatch.js deleted file mode 100644 index ef60e1e6a0cc66..00000000000000 --- a/local-cli/link/windows/patches/makePackagePatch.js +++ /dev/null @@ -1,10 +0,0 @@ -const applyParams = require('./applyParams'); - -module.exports = function makePackagePatch(packageInstance, params, prefix) { - const processedInstance = applyParams(packageInstance, params, prefix); - - return { - pattern: 'new MainReactPackage()', - patch: ',\n ' + processedInstance, - }; -}; diff --git a/local-cli/link/windows/patches/makeProjectPatch.js b/local-cli/link/windows/patches/makeProjectPatch.js deleted file mode 100644 index 6b3d85855d9547..00000000000000 --- a/local-cli/link/windows/patches/makeProjectPatch.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = function makeProjectPatch(windowsConfig) { - - const projectInsert = ` - {${windowsConfig.pathGUID}} - ${windowsConfig.projectName} - - `; - - return { - pattern: '', - patch: projectInsert, - unpatch: new RegExp(` 'https://github.com/facebook/folly.git', :tag => "v#{spec.version}" } spec.module_name = 'folly' - spec.dependency 'boost' + spec.dependency 'boost-for-react-native' spec.dependency 'DoubleConversion' spec.dependency 'GLog' spec.compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1' @@ -28,7 +28,7 @@ Pod::Spec.new do |spec| spec.libraries = "stdc++" spec.pod_target_xcconfig = { "USE_HEADERMAP" => "NO", "CLANG_CXX_LANGUAGE_STANDARD" => "c++14", - "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)\" \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\"" } + "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)\" \"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/DoubleConversion\"" } # Pinning to the same version as React.podspec. spec.platforms = { :ios => "8.0", :tvos => "9.2" } diff --git a/third-party-podspecs/GLog.podspec b/third-party-podspecs/GLog.podspec index 1cea58c1febb8e..5c8091a47c3111 100644 --- a/third-party-podspecs/GLog.podspec +++ b/third-party-podspecs/GLog.podspec @@ -10,6 +10,7 @@ Pod::Spec.new do |spec| spec.source = { :git => 'https://github.com/google/glog.git', :tag => "v#{spec.version}" } spec.module_name = 'glog' + spec.header_dir = 'glog' spec.source_files = 'src/glog/*.h', 'src/demangle.cc', 'src/logging.cc',