react-native 0.72.3 → 0.72.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +1 -0
  2. package/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js +1 -0
  3. package/Libraries/Components/ScrollView/ScrollViewViewConfig.js +1 -0
  4. package/Libraries/Components/TextInput/TextInput.d.ts +15 -0
  5. package/Libraries/Components/TextInput/TextInput.js +8 -3
  6. package/Libraries/Core/ReactNativeVersion.js +1 -1
  7. package/Libraries/ReactNative/AppContainer.js +32 -9
  8. package/Libraries/StyleSheet/StyleSheetTypes.d.ts +1 -0
  9. package/React/Base/RCTBundleURLProvider.h +33 -2
  10. package/React/Base/RCTBundleURLProvider.mm +78 -15
  11. package/React/Base/RCTVersion.m +1 -1
  12. package/React/CoreModules/RCTTiming.mm +5 -0
  13. package/ReactAndroid/gradle.properties +1 -1
  14. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +19 -1
  15. package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +37 -10
  16. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
  17. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java +6 -1
  18. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java +4 -0
  19. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +6 -1
  20. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java +19 -0
  21. package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +65 -0
  22. package/ReactAndroid/src/main/jni/CMakeLists.txt +5 -0
  23. package/ReactCommon/React-Fabric.podspec +1 -1
  24. package/ReactCommon/ReactCommon.podspec +1 -1
  25. package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
  26. package/ReactCommon/jsc/JSCRuntime.cpp +10 -0
  27. package/ReactCommon/react/debug/React-debug.podspec +1 -1
  28. package/ReactCommon/react/nativemodule/core/platform/ios/React-NativeModulesApple.podspec +1 -1
  29. package/ReactCommon/react/nativemodule/samples/ReactCommon-Samples.podspec +1 -1
  30. package/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp +15 -1
  31. package/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h +1 -0
  32. package/ReactCommon/react/renderer/core/RawPropsKeyMap.cpp +2 -0
  33. package/ReactCommon/react/renderer/core/RawPropsParser.cpp +1 -0
  34. package/ReactCommon/react/renderer/core/RawPropsPrimitives.h +4 -4
  35. package/ReactCommon/react/renderer/graphics/React-graphics.podspec +1 -1
  36. package/ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec +1 -1
  37. package/ReactCommon/react/renderer/mounting/ShadowTree.cpp +9 -5
  38. package/ReactCommon/react/renderer/runtimescheduler/React-runtimescheduler.podspec +1 -1
  39. package/ReactCommon/react/utils/React-utils.podspec +1 -1
  40. package/package.json +8 -8
  41. package/scripts/cocoapods/__tests__/test_utils/XcodebuildMock.rb +26 -0
  42. package/scripts/cocoapods/__tests__/utils-test.rb +115 -18
  43. package/scripts/cocoapods/helpers.rb +16 -0
  44. package/scripts/cocoapods/jsengine.rb +1 -1
  45. package/scripts/cocoapods/utils.rb +97 -8
  46. package/scripts/react_native_pods.rb +6 -2
  47. package/sdks/.hermesversion +1 -1
  48. package/sdks/hermes-engine/utils/build-apple-framework.sh +8 -1
  49. package/sdks/hermes-engine/utils/build-hermes-xcode.sh +8 -0
  50. package/sdks/hermesc/osx-bin/hermesc +0 -0
  51. package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
  52. package/template/package.json +3 -3
@@ -213,6 +213,7 @@ public class ReactScrollViewManager extends ViewGroupManager<ReactScrollView>
213
213
  @Override
214
214
  public void scrollTo(
215
215
  ReactScrollView scrollView, ReactScrollViewCommandHelper.ScrollToCommandData data) {
216
+ scrollView.abortAnimation();
216
217
  if (data.mAnimated) {
217
218
  scrollView.reactSmoothScrollTo(data.mDestX, data.mDestY);
218
219
  } else {
@@ -379,4 +380,22 @@ public class ReactScrollViewManager extends ViewGroupManager<ReactScrollView>
379
380
  public void setScrollEventThrottle(ReactScrollView view, int scrollEventThrottle) {
380
381
  view.setScrollEventThrottle(scrollEventThrottle);
381
382
  }
383
+
384
+ @ReactProp(name = "isInvertedVirtualizedList")
385
+ public void setIsInvertedVirtualizedList(ReactScrollView view, boolean applyFix) {
386
+ // Usually when inverting the scroll view we are using scaleY: -1 on the list
387
+ // and on the parent container. HOWEVER, starting from android API 33 there is
388
+ // a bug that can cause an ANR due to that. Thus we are using different transform
389
+ // commands to circumvent the ANR. This however causes the vertical scrollbar to
390
+ // be on the wrong side. Thus we are moving it to the other side, when the list
391
+ // is inverted.
392
+ // See also:
393
+ // - https://github.com/facebook/react-native/issues/35350
394
+ // - https://issuetracker.google.com/issues/287304310
395
+ if (applyFix) {
396
+ view.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_LEFT);
397
+ } else {
398
+ view.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_DEFAULT);
399
+ }
400
+ }
382
401
  }
@@ -10,6 +10,8 @@ package com.facebook.react.views.textinput;
10
10
  import static com.facebook.react.uimanager.UIManagerHelper.getReactContext;
11
11
  import static com.facebook.react.views.text.TextAttributeProps.UNSET;
12
12
 
13
+ import android.content.ClipData;
14
+ import android.content.ClipboardManager;
13
15
  import android.content.Context;
14
16
  import android.graphics.Color;
15
17
  import android.graphics.Paint;
@@ -28,8 +30,11 @@ import android.text.TextWatcher;
28
30
  import android.text.method.KeyListener;
29
31
  import android.text.method.QwertyKeyListener;
30
32
  import android.util.TypedValue;
33
+ import android.view.ActionMode;
31
34
  import android.view.Gravity;
32
35
  import android.view.KeyEvent;
36
+ import android.view.Menu;
37
+ import android.view.MenuItem;
33
38
  import android.view.MotionEvent;
34
39
  import android.view.View;
35
40
  import android.view.accessibility.AccessibilityNodeInfo;
@@ -180,6 +185,35 @@ public class ReactEditText extends AppCompatEditText
180
185
  }
181
186
  };
182
187
  ViewCompat.setAccessibilityDelegate(this, editTextAccessibilityDelegate);
188
+ ActionMode.Callback customActionModeCallback =
189
+ new ActionMode.Callback() {
190
+ /*
191
+ * Editor onCreateActionMode adds the cut, copy, paste, share, autofill,
192
+ * and paste as plain text items to the context menu.
193
+ */
194
+ @Override
195
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
196
+ menu.removeItem(android.R.id.pasteAsPlainText);
197
+ return true;
198
+ }
199
+
200
+ @Override
201
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
202
+ return true;
203
+ }
204
+
205
+ @Override
206
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
207
+ return false;
208
+ }
209
+
210
+ @Override
211
+ public void onDestroyActionMode(ActionMode mode) {}
212
+ };
213
+ setCustomSelectionActionModeCallback(customActionModeCallback);
214
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
215
+ setCustomInsertionActionModeCallback(customActionModeCallback);
216
+ }
183
217
  }
184
218
 
185
219
  @Override
@@ -268,6 +302,37 @@ public class ReactEditText extends AppCompatEditText
268
302
  return inputConnection;
269
303
  }
270
304
 
305
+ /*
306
+ * Called when a context menu option for the text view is selected.
307
+ * React Native replaces copy (as rich text) with copy as plain text.
308
+ */
309
+ @Override
310
+ public boolean onTextContextMenuItem(int id) {
311
+ if (id == android.R.id.paste) {
312
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
313
+ id = android.R.id.pasteAsPlainText;
314
+ } else {
315
+ ClipboardManager clipboard =
316
+ (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
317
+ ClipData previousClipData = clipboard.getPrimaryClip();
318
+ if (previousClipData != null) {
319
+ for (int i = 0; i < previousClipData.getItemCount(); i++) {
320
+ final CharSequence text = previousClipData.getItemAt(i).coerceToText(getContext());
321
+ final CharSequence paste = (text instanceof Spanned) ? text.toString() : text;
322
+ if (paste != null) {
323
+ ClipData clipData = ClipData.newPlainText(null, text);
324
+ clipboard.setPrimaryClip(clipData);
325
+ }
326
+ }
327
+ boolean actionPerformed = super.onTextContextMenuItem(id);
328
+ clipboard.setPrimaryClip(previousClipData);
329
+ return actionPerformed;
330
+ }
331
+ }
332
+ }
333
+ return super.onTextContextMenuItem(id);
334
+ }
335
+
271
336
  @Override
272
337
  public void clearFocus() {
273
338
  setFocusableInTouchMode(false);
@@ -8,6 +8,11 @@ set(CMAKE_VERBOSE_MAKEFILE on)
8
8
 
9
9
  project(ReactAndroid)
10
10
 
11
+ # Convert input paths to CMake format (with forward slashes)
12
+ file(TO_CMAKE_PATH "${REACT_ANDROID_DIR}" REACT_ANDROID_DIR)
13
+ file(TO_CMAKE_PATH "${REACT_BUILD_DIR}" REACT_BUILD_DIR)
14
+ file(TO_CMAKE_PATH "${REACT_COMMON_DIR}" REACT_COMMON_DIR)
15
+
11
16
  # If you have ccache installed, we're going to honor it.
12
17
  find_program(CCACHE_FOUND ccache)
13
18
  if(CCACHE_FOUND)
@@ -36,7 +36,7 @@ Pod::Spec.new do |s|
36
36
  "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" }
37
37
 
38
38
  if ENV['USE_FRAMEWORKS']
39
- s.header_mappings_dir = File.absolute_path('./')
39
+ s.header_mappings_dir = './'
40
40
  s.module_name = 'React_Fabric'
41
41
  end
42
42
 
@@ -37,7 +37,7 @@ Pod::Spec.new do |s|
37
37
  "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
38
38
  "GCC_WARN_PEDANTIC" => "YES" }
39
39
  if ENV['USE_FRAMEWORKS']
40
- s.header_mappings_dir = File.absolute_path("./")
40
+ s.header_mappings_dir = './'
41
41
  end
42
42
 
43
43
  # TODO (T48588859): Restructure this target to align with dir structure: "react/nativemodule/..."
@@ -17,7 +17,7 @@ namespace facebook::react {
17
17
  constexpr struct {
18
18
  int32_t Major = 0;
19
19
  int32_t Minor = 72;
20
- int32_t Patch = 3;
20
+ int32_t Patch = 5;
21
21
  std::string_view Prerelease = "";
22
22
  } ReactNativeVersion;
23
23
 
@@ -302,6 +302,9 @@ class JSCRuntime : public jsi::Runtime {
302
302
  #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0
303
303
  #define _JSC_NO_ARRAY_BUFFERS
304
304
  #endif
305
+ #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 160400
306
+ #define _JSC_HAS_INSPECTABLE
307
+ #endif
305
308
  #endif
306
309
  #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
307
310
  #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_11
@@ -398,6 +401,13 @@ JSCRuntime::JSCRuntime(JSGlobalContextRef ctx)
398
401
  stringCounter_(0)
399
402
  #endif
400
403
  {
404
+ #ifndef NDEBUG
405
+ #ifdef _JSC_HAS_INSPECTABLE
406
+ if (__builtin_available(macOS 13.3, iOS 16.4, tvOS 16.4, *)) {
407
+ JSGlobalContextSetInspectable(ctx_, true);
408
+ }
409
+ #endif
410
+ #endif
401
411
  }
402
412
 
403
413
  JSCRuntime::~JSCRuntime() {
@@ -31,6 +31,6 @@ Pod::Spec.new do |s|
31
31
 
32
32
  if ENV['USE_FRAMEWORKS']
33
33
  s.module_name = "React_debug"
34
- s.header_mappings_dir = File.absolute_path("../..")
34
+ s.header_mappings_dir = "../.."
35
35
  end
36
36
  end
@@ -37,7 +37,7 @@ Pod::Spec.new do |s|
37
37
  "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
38
38
  "GCC_WARN_PEDANTIC" => "YES" }
39
39
  if ENV['USE_FRAMEWORKS']
40
- s.header_mappings_dir = File.absolute_path('./')
40
+ s.header_mappings_dir = './'
41
41
  end
42
42
 
43
43
  s.source_files = "ReactCommon/**/*.{mm,cpp,h}"
@@ -37,7 +37,7 @@ Pod::Spec.new do |s|
37
37
  "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
38
38
  "GCC_WARN_PEDANTIC" => "YES" }
39
39
  if ENV['USE_FRAMEWORKS']
40
- s.header_mappings_dir = File.absolute_path('./')
40
+ s.header_mappings_dir = './'
41
41
  end
42
42
 
43
43
 
@@ -319,6 +319,15 @@ ScrollViewProps::ScrollViewProps(
319
319
  rawProps,
320
320
  "scrollToOverflowEnabled",
321
321
  sourceProps.scrollToOverflowEnabled,
322
+ {})),
323
+ isInvertedVirtualizedList(
324
+ CoreFeatures::enablePropIteratorSetter
325
+ ? sourceProps.isInvertedVirtualizedList
326
+ : convertRawProp(
327
+ context,
328
+ rawProps,
329
+ "isInvertedVirtualizedList",
330
+ sourceProps.isInvertedVirtualizedList,
322
331
  {})) {}
323
332
 
324
333
  void ScrollViewProps::setProp(
@@ -368,6 +377,7 @@ void ScrollViewProps::setProp(
368
377
  RAW_SET_PROP_SWITCH_CASE_BASIC(snapToEnd);
369
378
  RAW_SET_PROP_SWITCH_CASE_BASIC(contentInsetAdjustmentBehavior);
370
379
  RAW_SET_PROP_SWITCH_CASE_BASIC(scrollToOverflowEnabled);
380
+ RAW_SET_PROP_SWITCH_CASE_BASIC(isInvertedVirtualizedList);
371
381
  }
372
382
  }
373
383
 
@@ -492,7 +502,11 @@ SharedDebugStringConvertibleList ScrollViewProps::getDebugProps() const {
492
502
  debugStringConvertibleItem(
493
503
  "snapToStart", snapToStart, defaultScrollViewProps.snapToStart),
494
504
  debugStringConvertibleItem(
495
- "snapToEnd", snapToEnd, defaultScrollViewProps.snapToEnd)};
505
+ "snapToEnd", snapToEnd, defaultScrollViewProps.snapToEnd),
506
+ debugStringConvertibleItem(
507
+ "isInvertedVirtualizedList",
508
+ snapToEnd,
509
+ defaultScrollViewProps.isInvertedVirtualizedList)};
496
510
  }
497
511
  #endif
498
512
 
@@ -69,6 +69,7 @@ class ScrollViewProps final : public ViewProps {
69
69
  ContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior{
70
70
  ContentInsetAdjustmentBehavior::Never};
71
71
  bool scrollToOverflowEnabled{false};
72
+ bool isInvertedVirtualizedList{false};
72
73
 
73
74
  #pragma mark - DebugStringConvertible
74
75
 
@@ -38,6 +38,8 @@ void RawPropsKeyMap::insert(
38
38
  item.value = value;
39
39
  key.render(item.name, &item.length);
40
40
  items_.push_back(item);
41
+ react_native_assert(
42
+ items_.size() < std::numeric_limits<RawPropsPropNameLength>::max());
41
43
  }
42
44
 
43
45
  void RawPropsKeyMap::reindex() noexcept {
@@ -42,6 +42,7 @@ RawValue const *RawPropsParser::at(
42
42
  // This is not thread-safe part; this happens only during initialization of
43
43
  // a `ComponentDescriptor` where it is actually safe.
44
44
  keys_.push_back(key);
45
+ react_native_assert(size < std::numeric_limits<RawPropsValueIndex>::max());
45
46
  nameToIndex_.insert(key, static_cast<RawPropsValueIndex>(size));
46
47
  return nullptr;
47
48
  }
@@ -16,11 +16,11 @@ namespace react {
16
16
  /*
17
17
  * Type used to represent an index of some stored values in small arrays.
18
18
  */
19
- using RawPropsValueIndex = uint8_t;
19
+ using RawPropsValueIndex = uint16_t;
20
20
  static_assert(
21
- sizeof(RawPropsValueIndex) == 1,
22
- "RawPropsValueIndex must be one byte size.");
23
- using RawPropsPropNameLength = uint8_t;
21
+ sizeof(RawPropsValueIndex) == 2,
22
+ "RawPropsValueIndex must be two byte size.");
23
+ using RawPropsPropNameLength = uint16_t;
24
24
  using RawPropsPropNameHash = uint32_t;
25
25
 
26
26
  /*
@@ -45,7 +45,7 @@ Pod::Spec.new do |s|
45
45
 
46
46
  if ENV['USE_FRAMEWORKS']
47
47
  s.module_name = "React_graphics"
48
- s.header_mappings_dir = File.absolute_path("../../..")
48
+ s.header_mappings_dir = "../../.."
49
49
  header_search_paths = header_search_paths + ["\"$(PODS_TARGET_SRCROOT)/platform/ios\""]
50
50
  end
51
51
 
@@ -42,7 +42,7 @@ Pod::Spec.new do |s|
42
42
 
43
43
  if ENV['USE_FRAMEWORKS']
44
44
  s.module_name = "React_ImageManager"
45
- s.header_mappings_dir = File.absolute_path("./")
45
+ s.header_mappings_dir = "./"
46
46
  header_search_paths = header_search_paths + [
47
47
  "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\"",
48
48
  "\"$(PODS_ROOT)/DoubleConversion\"",
@@ -355,6 +355,11 @@ CommitStatus ShadowTree::tryCommit(
355
355
  newRootShadowNode = delegate_.shadowTreeWillCommit(
356
356
  *this, oldRootShadowNode, newRootShadowNode);
357
357
 
358
+ if (!newRootShadowNode ||
359
+ (commitOptions.shouldYield && commitOptions.shouldYield())) {
360
+ return CommitStatus::Cancelled;
361
+ }
362
+
358
363
  // Layout nodes.
359
364
  std::vector<LayoutableShadowNode const *> affectedLayoutableNodes{};
360
365
  affectedLayoutableNodes.reserve(1024);
@@ -372,17 +377,16 @@ CommitStatus ShadowTree::tryCommit(
372
377
  // Updating `currentRevision_` in unique manner if it hasn't changed.
373
378
  std::unique_lock lock(commitMutex_);
374
379
 
380
+ if (commitOptions.shouldYield && commitOptions.shouldYield()) {
381
+ return CommitStatus::Cancelled;
382
+ }
383
+
375
384
  if (currentRevision_.number != oldRevision.number) {
376
385
  return CommitStatus::Failed;
377
386
  }
378
387
 
379
388
  auto newRevisionNumber = oldRevision.number + 1;
380
389
 
381
- if (!newRootShadowNode ||
382
- (commitOptions.shouldYield && commitOptions.shouldYield())) {
383
- return CommitStatus::Cancelled;
384
- }
385
-
386
390
  {
387
391
  std::lock_guard<std::mutex> dispatchLock(EventEmitter::DispatchMutex());
388
392
 
@@ -47,7 +47,7 @@ Pod::Spec.new do |s|
47
47
 
48
48
  if ENV['USE_FRAMEWORKS']
49
49
  s.module_name = "React_runtimescheduler"
50
- s.header_mappings_dir = File.absolute_path("../../..")
50
+ s.header_mappings_dir = "../../.."
51
51
  end
52
52
 
53
53
  s.dependency "React-jsi"
@@ -48,7 +48,7 @@ Pod::Spec.new do |s|
48
48
 
49
49
  if ENV['USE_FRAMEWORKS']
50
50
  s.module_name = "React_utils"
51
- s.header_mappings_dir = File.absolute_path("../..")
51
+ s.header_mappings_dir = "../.."
52
52
  end
53
53
 
54
54
  s.dependency "RCT-Folly", folly_version
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native",
3
- "version": "0.72.3",
3
+ "version": "0.72.5",
4
4
  "bin": "./cli.js",
5
5
  "description": "A framework for building native apps using React",
6
6
  "license": "MIT",
@@ -79,15 +79,15 @@
79
79
  },
80
80
  "dependencies": {
81
81
  "@jest/create-cache-key-function": "^29.2.1",
82
- "@react-native-community/cli": "11.3.5",
83
- "@react-native-community/cli-platform-android": "11.3.5",
84
- "@react-native-community/cli-platform-ios": "11.3.5",
82
+ "@react-native-community/cli": "11.3.7",
83
+ "@react-native-community/cli-platform-android": "11.3.7",
84
+ "@react-native-community/cli-platform-ios": "11.3.7",
85
85
  "@react-native/assets-registry": "^0.72.0",
86
- "@react-native/codegen": "^0.72.6",
86
+ "@react-native/codegen": "^0.72.7",
87
87
  "@react-native/gradle-plugin": "^0.72.11",
88
88
  "@react-native/js-polyfills": "^0.72.1",
89
89
  "@react-native/normalize-colors": "^0.72.0",
90
- "@react-native/virtualized-lists": "^0.72.6",
90
+ "@react-native/virtualized-lists": "^0.72.8",
91
91
  "abort-controller": "^3.0.0",
92
92
  "anser": "^1.4.9",
93
93
  "base64-js": "^1.1.2",
@@ -98,8 +98,8 @@
98
98
  "jest-environment-node": "^29.2.1",
99
99
  "jsc-android": "^250231.0.0",
100
100
  "memoize-one": "^5.0.0",
101
- "metro-runtime": "0.76.7",
102
- "metro-source-map": "0.76.7",
101
+ "metro-runtime": "0.76.8",
102
+ "metro-source-map": "0.76.8",
103
103
  "mkdirp": "^0.5.1",
104
104
  "nullthrows": "^1.1.1",
105
105
  "pretty-format": "^26.5.2",
@@ -0,0 +1,26 @@
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ class XcodebuildMock < Xcodebuild
7
+ @@version = ""
8
+ @@version_invocation_count = 0
9
+
10
+ def self.set_version=(v)
11
+ @@version = v
12
+ end
13
+
14
+ def self.version
15
+ @@version_invocation_count += 1
16
+ @@version
17
+ end
18
+
19
+ def self.version_invocation_count
20
+ @@version_invocation_count
21
+ end
22
+
23
+ def self.reset()
24
+ @@version_invocation_count = 0
25
+ end
26
+ end
@@ -14,6 +14,7 @@ require_relative "./test_utils/FileMock.rb"
14
14
  require_relative "./test_utils/systemUtils.rb"
15
15
  require_relative "./test_utils/PathnameMock.rb"
16
16
  require_relative "./test_utils/TargetDefinitionMock.rb"
17
+ require_relative "./test_utils/XcodebuildMock.rb"
17
18
 
18
19
  class UtilsTests < Test::Unit::TestCase
19
20
  def setup
@@ -28,6 +29,7 @@ class UtilsTests < Test::Unit::TestCase
28
29
  Pod::Config.reset()
29
30
  SysctlChecker.reset()
30
31
  Environment.reset()
32
+ XcodebuildMock.reset()
31
33
  ENV['RCT_NEW_ARCH_ENABLED'] = '0'
32
34
  ENV['USE_HERMES'] = '1'
33
35
  ENV['USE_FRAMEWORKS'] = nil
@@ -437,9 +439,9 @@ class UtilsTests < Test::Unit::TestCase
437
439
  # ================================= #
438
440
  # Test - Apply Xcode 15 Patch #
439
441
  # ================================= #
440
-
441
- def test_applyXcode15Patch_correctlyAppliesNecessaryPatch
442
+ def test_applyXcode15Patch_whenXcodebuild14_correctlyAppliesNecessaryPatch
442
443
  # Arrange
444
+ XcodebuildMock.set_version = "Xcode 14.3"
443
445
  first_target = prepare_target("FirstTarget")
444
446
  second_target = prepare_target("SecondTarget")
445
447
  third_target = TargetMock.new("ThirdTarget", [
@@ -468,24 +470,117 @@ class UtilsTests < Test::Unit::TestCase
468
470
  ])
469
471
 
470
472
  # Act
471
- ReactNativePodsUtils.apply_xcode_15_patch(installer)
473
+ user_project_mock.build_configurations.each do |config|
474
+ assert_nil(config.build_settings["OTHER_LDFLAGS"])
475
+ end
476
+
477
+ ReactNativePodsUtils.apply_xcode_15_patch(installer, :xcodebuild_manager => XcodebuildMock)
472
478
 
473
479
  # Assert
474
- first_target.build_configurations.each do |config|
475
- assert_equal(config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"].strip,
476
- '$(inherited) "_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION"'
477
- )
480
+ user_project_mock.build_configurations.each do |config|
481
+ assert_equal("$(inherited) _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION", config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"])
482
+ assert_equal("$(inherited) ", config.build_settings["OTHER_LDFLAGS"])
478
483
  end
479
- second_target.build_configurations.each do |config|
480
- assert_equal(config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"].strip,
481
- '$(inherited) "_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION"'
482
- )
484
+
485
+ # User project and Pods project
486
+ assert_equal(2, XcodebuildMock.version_invocation_count)
487
+ end
488
+
489
+ def test_applyXcode15Patch_whenXcodebuild15_correctlyAppliesNecessaryPatch
490
+ # Arrange
491
+ XcodebuildMock.set_version = "Xcode 15.0"
492
+ first_target = prepare_target("FirstTarget")
493
+ second_target = prepare_target("SecondTarget")
494
+ third_target = TargetMock.new("ThirdTarget", [
495
+ BuildConfigurationMock.new("Debug", {
496
+ "GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" '
497
+ }),
498
+ BuildConfigurationMock.new("Release", {
499
+ "GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" '
500
+ }),
501
+ ], nil)
502
+
503
+ user_project_mock = UserProjectMock.new("/a/path", [
504
+ prepare_config("Debug"),
505
+ prepare_config("Release"),
506
+ ],
507
+ :native_targets => [
508
+ first_target,
509
+ second_target
510
+ ]
511
+ )
512
+ pods_projects_mock = PodsProjectMock.new([], {"hermes-engine" => {}}, :native_targets => [
513
+ third_target
514
+ ])
515
+ installer = InstallerMock.new(pods_projects_mock, [
516
+ AggregatedProjectMock.new(user_project_mock)
517
+ ])
518
+
519
+ # Act
520
+ user_project_mock.build_configurations.each do |config|
521
+ assert_nil(config.build_settings["OTHER_LDFLAGS"])
483
522
  end
484
- third_target.build_configurations.each do |config|
485
- assert_equal(config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"].strip,
486
- '$(inherited) "SomeFlag=1" "_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION"'
487
- )
523
+
524
+ ReactNativePodsUtils.apply_xcode_15_patch(installer, :xcodebuild_manager => XcodebuildMock)
525
+
526
+ # Assert
527
+ user_project_mock.build_configurations.each do |config|
528
+ assert_equal("$(inherited) _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION", config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"])
529
+ assert_equal("$(inherited) -Wl -ld_classic ", config.build_settings["OTHER_LDFLAGS"])
488
530
  end
531
+
532
+ # User project and Pods project
533
+ assert_equal(2, XcodebuildMock.version_invocation_count)
534
+ end
535
+
536
+ def test_applyXcode15Patch_whenXcodebuild14ButProjectHasSettings_correctlyRemovesNecessaryPatch
537
+ # Arrange
538
+ XcodebuildMock.set_version = "Xcode 14.3"
539
+ first_target = prepare_target("FirstTarget")
540
+ second_target = prepare_target("SecondTarget")
541
+ third_target = TargetMock.new("ThirdTarget", [
542
+ BuildConfigurationMock.new("Debug", {
543
+ "GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" '
544
+ }),
545
+ BuildConfigurationMock.new("Release", {
546
+ "GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" '
547
+ }),
548
+ ], nil)
549
+
550
+ debug_config = prepare_config("Debug", {"OTHER_LDFLAGS" => "$(inherited) -Wl -ld_classic "})
551
+ release_config = prepare_config("Release", {"OTHER_LDFLAGS" => "$(inherited) -Wl -ld_classic "})
552
+
553
+ user_project_mock = UserProjectMock.new("/a/path", [
554
+ debug_config,
555
+ release_config,
556
+ ],
557
+ :native_targets => [
558
+ first_target,
559
+ second_target
560
+ ]
561
+ )
562
+ pods_projects_mock = PodsProjectMock.new([debug_config.clone, release_config.clone], {"hermes-engine" => {}}, :native_targets => [
563
+ third_target
564
+ ])
565
+ installer = InstallerMock.new(pods_projects_mock, [
566
+ AggregatedProjectMock.new(user_project_mock)
567
+ ])
568
+
569
+ # Act
570
+ user_project_mock.build_configurations.each do |config|
571
+ assert_equal("$(inherited) -Wl -ld_classic ", config.build_settings["OTHER_LDFLAGS"])
572
+ end
573
+
574
+ ReactNativePodsUtils.apply_xcode_15_patch(installer, :xcodebuild_manager => XcodebuildMock)
575
+
576
+ # Assert
577
+ user_project_mock.build_configurations.each do |config|
578
+ assert_equal("$(inherited) _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION", config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"])
579
+ assert_equal("$(inherited) ", config.build_settings["OTHER_LDFLAGS"])
580
+ end
581
+
582
+ # User project and Pods project
583
+ assert_equal(2, XcodebuildMock.version_invocation_count)
489
584
  end
490
585
 
491
586
  # ==================================== #
@@ -744,12 +839,14 @@ def prepare_empty_user_project_mock
744
839
  ])
745
840
  end
746
841
 
747
- def prepare_config(config_name)
748
- return BuildConfigurationMock.new(config_name, {"LIBRARY_SEARCH_PATHS" => [
842
+ def prepare_config(config_name, extra_config = {})
843
+ config = {"LIBRARY_SEARCH_PATHS" => [
749
844
  "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)",
750
845
  "\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"",
751
846
  "another/path",
752
- ]})
847
+ ]}.merge(extra_config)
848
+
849
+ return BuildConfigurationMock.new(config_name, config)
753
850
  end
754
851
 
755
852
  def prepare_target(name, product_type = nil, dependencies = [])
@@ -11,6 +11,14 @@ class SysctlChecker
11
11
  end
12
12
  end
13
13
 
14
+ # Helper class that is used to easily send commands to Xcodebuild
15
+ # And that can be subclassed for testing purposes.
16
+ class Xcodebuild
17
+ def self.version
18
+ `xcodebuild -version`
19
+ end
20
+ end
21
+
14
22
  # Helper object to wrap system properties like RUBY_PLATFORM
15
23
  # This makes it easier to mock the behaviour in tests
16
24
  class Environment
@@ -26,3 +34,11 @@ class Finder
26
34
  return `find #{path} -type f \\( #{js_files} -or #{ts_files} \\)`.split("\n").sort()
27
35
  end
28
36
  end
37
+
38
+ module Helpers
39
+ class Constants
40
+ def self.min_ios_version_supported
41
+ return '12.4'
42
+ end
43
+ end
44
+ end
@@ -32,7 +32,7 @@ def setup_hermes!(react_native_path: "../node_modules/react-native", fabric_enab
32
32
  pod 'React-jsi', :path => "#{react_native_path}/ReactCommon/jsi"
33
33
  # This `:tag => hermestag` below is only to tell CocoaPods to update hermes-engine when React Native version changes.
34
34
  # We have custom logic to compute the source for hermes-engine. See sdks/hermes-engine/*
35
- hermestag_file = File.join(react_native_path, "sdks", ".hermesversion")
35
+ hermestag_file = File.join(react_native_dir, "sdks", ".hermesversion")
36
36
  hermestag = File.exist?(hermestag_file) ? File.read(hermestag_file).strip : ''
37
37
 
38
38
  pod 'hermes-engine', :podspec => "#{react_native_path}/sdks/hermes-engine/hermes-engine.podspec", :tag => hermestag