react-native 0.73.8 → 0.73.9

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.
@@ -12,6 +12,6 @@
12
12
  exports.version = {
13
13
  major: 0,
14
14
  minor: 73,
15
- patch: 8,
15
+ patch: 9,
16
16
  prerelease: null,
17
17
  };
@@ -23,7 +23,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
23
23
  __rnVersion = @{
24
24
  RCTVersionMajor: @(0),
25
25
  RCTVersionMinor: @(73),
26
- RCTVersionPatch: @(8),
26
+ RCTVersionPatch: @(9),
27
27
  RCTVersionPrerelease: [NSNull null],
28
28
  };
29
29
  });
@@ -89,6 +89,9 @@ RCT_EXPORT_MODULE()
89
89
 
90
90
  - (void)invalidate
91
91
  {
92
+ if (_invalidated) {
93
+ return;
94
+ }
92
95
  _invalidated = YES;
93
96
  [self _cleanupObservers];
94
97
  }
@@ -109,10 +112,7 @@ RCT_EXPORT_MODULE()
109
112
 
110
113
  [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTWindowFrameDidChangeNotification object:nil];
111
114
 
112
- [[NSNotificationCenter defaultCenter] addObserver:self
113
- selector:@selector(invalidate)
114
- name:RCTBridgeWillInvalidateModulesNotification
115
- object:nil];
115
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTBridgeWillInvalidateModulesNotification object:nil];
116
116
  }
117
117
 
118
118
  static BOOL RCTIsIPhoneNotched()
@@ -1,4 +1,4 @@
1
- VERSION_NAME=0.73.8
1
+ VERSION_NAME=0.73.9
2
2
  react.internal.publishingGroup=com.facebook.react
3
3
 
4
4
  android.useAndroidX=true
@@ -17,6 +17,6 @@ public class ReactNativeVersion {
17
17
  public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of(
18
18
  "major", 0,
19
19
  "minor", 73,
20
- "patch", 8,
20
+ "patch", 9,
21
21
  "prerelease", null);
22
22
  }
@@ -17,7 +17,7 @@ namespace facebook::react {
17
17
  constexpr struct {
18
18
  int32_t Major = 0;
19
19
  int32_t Minor = 73;
20
- int32_t Patch = 8;
20
+ int32_t Patch = 9;
21
21
  std::string_view Prerelease = "";
22
22
  } ReactNativeVersion;
23
23
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native",
3
- "version": "0.73.8",
3
+ "version": "0.73.9",
4
4
  "description": "A framework for building native apps using React",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -93,11 +93,11 @@
93
93
  },
94
94
  "dependencies": {
95
95
  "@jest/create-cache-key-function": "^29.6.3",
96
- "@react-native-community/cli": "12.3.6",
97
- "@react-native-community/cli-platform-android": "12.3.6",
98
- "@react-native-community/cli-platform-ios": "12.3.6",
96
+ "@react-native-community/cli": "12.3.7",
97
+ "@react-native-community/cli-platform-android": "12.3.7",
98
+ "@react-native-community/cli-platform-ios": "12.3.7",
99
99
  "@react-native/assets-registry": "0.73.1",
100
- "@react-native/community-cli-plugin": "0.73.17",
100
+ "@react-native/community-cli-plugin": "0.73.18",
101
101
  "@react-native/codegen": "0.73.3",
102
102
  "@react-native/gradle-plugin": "0.73.4",
103
103
  "@react-native/js-polyfills": "0.73.1",
@@ -0,0 +1,170 @@
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
+ module PrivacyManifestUtils
7
+ def self.add_aggregated_privacy_manifest(installer)
8
+ user_project = get_user_project_from(installer)
9
+ targets = get_application_targets(user_project)
10
+ file_path = get_privacyinfo_file_path(user_project, targets)
11
+
12
+ privacy_info = read_privacyinfo_file(file_path) || {
13
+ "NSPrivacyCollectedDataTypes" => [],
14
+ "NSPrivacyTracking" => false
15
+ }
16
+
17
+ # Get all required reason APIs defined in current pods
18
+ required_reason_apis = get_used_required_reason_apis(installer)
19
+
20
+ # Add the Required Reason APIs from React Native core
21
+ get_core_accessed_apis.each do |accessed_api|
22
+ api_type = accessed_api["NSPrivacyAccessedAPIType"]
23
+ reasons = accessed_api["NSPrivacyAccessedAPITypeReasons"]
24
+ required_reason_apis[api_type] ||= []
25
+ required_reason_apis[api_type] += reasons
26
+ end
27
+
28
+ # Merge the Required Reason APIs from pods with the ones from the existing PrivacyInfo file
29
+ (privacy_info["NSPrivacyAccessedAPITypes"] || []).each do |accessed_api|
30
+ api_type = accessed_api["NSPrivacyAccessedAPIType"]
31
+ reasons = accessed_api["NSPrivacyAccessedAPITypeReasons"]
32
+ # Add reasons from existing PrivacyInfo file to the ones from pods
33
+ required_reason_apis[api_type] ||= []
34
+ required_reason_apis[api_type] += reasons
35
+ end
36
+
37
+ # Update the existing PrivacyInfo file with the new aggregated data
38
+ privacy_info["NSPrivacyAccessedAPITypes"] = required_reason_apis.map { |api_type, reasons|
39
+ {
40
+ "NSPrivacyAccessedAPIType" => api_type,
41
+ "NSPrivacyAccessedAPITypeReasons" => reasons.uniq
42
+ }
43
+ }
44
+
45
+ Xcodeproj::Plist.write_to_path(privacy_info, file_path)
46
+
47
+ targets.each do |target|
48
+ ensure_reference(file_path, user_project, target)
49
+ end
50
+ end
51
+
52
+ def self.get_application_targets(user_project)
53
+ return user_project.targets.filter { |t| t.symbol_type == :application }
54
+ end
55
+
56
+ def self.read_privacyinfo_file(file_path)
57
+ # Maybe add missing default NSPrivacyTracking, NSPrivacyTrackingDomains, NSPrivacyCollectedDataTypes, but this works without those keys
58
+ source_data = nil
59
+ # Try to read an existing PrivacyInfo.xcprivacy file
60
+ begin
61
+ source_data = Xcodeproj::Plist.read_from_path(file_path)
62
+ Pod::UI.puts "[Privacy Manifest Aggregation] Appending aggregated reasons to existing PrivacyInfo.xcprivacy file."
63
+ rescue => e
64
+ Pod::UI.puts "[Privacy Manifest Aggregation] No existing PrivacyInfo.xcprivacy file found, creating a new one."
65
+ end
66
+ return source_data
67
+ end
68
+
69
+ def self.ensure_reference(file_path, user_project, target)
70
+ reference_exists = target.resources_build_phase.files_references.any? { |file_ref| file_ref.path&.end_with? "PrivacyInfo.xcprivacy" }
71
+ unless reference_exists
72
+ # We try to find the main group, but if it doesn't exist, we default to adding the file to the project root – both work
73
+ file_root = user_project.root_object.main_group.children.find { |group| group.class == Xcodeproj::Project::Object::PBXGroup && (group.name == target.name || group.path == target.name) } || user_project
74
+ file_ref = file_root.new_file(file_path)
75
+ build_file = target.resources_build_phase.add_file_reference(file_ref, true)
76
+ end
77
+ end
78
+
79
+ def self.get_privacyinfo_file_path(user_project, targets)
80
+ file_refs = targets.flat_map { |target| target.resources_build_phase.files_references }
81
+ existing_file = file_refs.find { |file_ref| file_ref.path&.end_with? "PrivacyInfo.xcprivacy" }
82
+ if existing_file
83
+ return existing_file.real_path
84
+ end
85
+ # We try to find a file we know exists in the project to get the path to the main group directory
86
+ info_plist_path = user_project.files.find { |file_ref| file_ref.name == "Info.plist" }
87
+ if info_plist_path.nil?
88
+ # return path that is sibling to .xcodeproj
89
+ path = user_project.path
90
+ return File.join(File.dirname(path), "PrivacyInfo.xcprivacy")
91
+ end
92
+ return File.join(File.dirname(info_plist_path.real_path),"PrivacyInfo.xcprivacy")
93
+ end
94
+
95
+ def self.get_used_required_reason_apis(installer)
96
+ # A dictionary with keys of type string (NSPrivacyAccessedAPIType) and values of type string[] (NSPrivacyAccessedAPITypeReasons[])
97
+ used_apis = {}
98
+ Pod::UI.puts "[Privacy Manifest Aggregation] Reading .xcprivacy files to aggregate all used Required Reason APIs."
99
+ installer.pod_targets.each do |pod_target|
100
+ # puts pod_target
101
+ pod_target.file_accessors.each do |file_accessor|
102
+ file_accessor.resource_bundles.each do |bundle_name, bundle_files|
103
+ bundle_files.each do |file_path|
104
+ # This needs to be named like that due to apple requirements
105
+ if File.basename(file_path) == 'PrivacyInfo.xcprivacy'
106
+ content = Xcodeproj::Plist.read_from_path(file_path)
107
+ accessed_api_types = content["NSPrivacyAccessedAPITypes"]
108
+ accessed_api_types&.each do |accessed_api|
109
+ api_type = accessed_api["NSPrivacyAccessedAPIType"]
110
+ reasons = accessed_api["NSPrivacyAccessedAPITypeReasons"]
111
+ next unless api_type
112
+ used_apis[api_type] ||= []
113
+ used_apis[api_type] += reasons
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ return used_apis
121
+ end
122
+
123
+ def self.get_privacy_manifest_paths_from(user_project)
124
+ privacy_manifests = user_project
125
+ .files
126
+ .select { |p|
127
+ p.path&.end_with?('PrivacyInfo.xcprivacy')
128
+ }
129
+ return privacy_manifests
130
+ end
131
+
132
+ def self.get_core_accessed_apis()
133
+ file_timestamp_accessed_api = {
134
+ "NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategoryFileTimestamp",
135
+ "NSPrivacyAccessedAPITypeReasons" => ["C617.1"],
136
+ }
137
+ user_defaults_accessed_api = {
138
+ "NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategoryUserDefaults",
139
+ "NSPrivacyAccessedAPITypeReasons" => ["CA92.1"],
140
+ }
141
+ boot_time_accessed_api = {
142
+ "NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategorySystemBootTime",
143
+ "NSPrivacyAccessedAPITypeReasons" => ["35F9.1"],
144
+ }
145
+ return [file_timestamp_accessed_api, user_defaults_accessed_api, boot_time_accessed_api]
146
+ end
147
+
148
+
149
+ def self.get_user_project_from(installer)
150
+ user_project = installer.aggregate_targets
151
+ .map{ |t| t.user_project }
152
+ .first
153
+ return user_project
154
+ end
155
+
156
+ def self.add_privacy_manifest_if_needed(installer)
157
+ user_project = get_user_project_from(installer)
158
+ privacy_manifest = self.get_privacy_manifest_paths_from(user_project).first
159
+ if privacy_manifest.nil?
160
+ privacy_manifest = {
161
+ "NSPrivacyCollectedDataTypes" => [],
162
+ "NSPrivacyTracking" => false,
163
+ "NSPrivacyAccessedAPITypes" => get_core_accessed_apis
164
+ }
165
+ path = File.join(user_project.path.parent, "PrivacyInfo.xcprivacy")
166
+ Xcodeproj::Plist.write_to_path(privacy_manifest, path)
167
+ Pod::UI.puts "Your app does not have a privacy manifest! A template has been generated containing Required Reasons API usage in the core React Native library. Please add the PrivacyInfo.xcprivacy file to your project and complete data use, tracking and any additional required reasons your app is using according to Apple's guidance: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files. Then, you will need to manually add this file to your project in Xcode.".red
168
+ end
169
+ end
170
+ end
@@ -561,44 +561,6 @@ class ReactNativePodsUtils
561
561
  ReactNativePodsUtils.update_header_paths_if_depends_on(target_installation_result, "React-ImageManager", header_search_paths)
562
562
  end
563
563
 
564
- def self.get_privacy_manifest_paths_from(user_project)
565
- privacy_manifests = user_project
566
- .files
567
- .select { |p|
568
- p.path&.end_with?('PrivacyInfo.xcprivacy')
569
- }
570
- return privacy_manifests
571
- end
572
-
573
- def self.add_privacy_manifest_if_needed(installer)
574
- user_project = installer.aggregate_targets
575
- .map{ |t| t.user_project }
576
- .first
577
- privacy_manifest = self.get_privacy_manifest_paths_from(user_project).first
578
- if privacy_manifest.nil?
579
- file_timestamp_reason = {
580
- "NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategoryFileTimestamp",
581
- "NSPrivacyAccessedAPITypeReasons" => ["C617.1"],
582
- }
583
- user_defaults_reason = {
584
- "NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategoryUserDefaults",
585
- "NSPrivacyAccessedAPITypeReasons" => ["CA92.1"],
586
- }
587
- boot_time_reason = {
588
- "NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategorySystemBootTime",
589
- "NSPrivacyAccessedAPITypeReasons" => ["35F9.1"],
590
- }
591
- privacy_manifest = {
592
- "NSPrivacyCollectedDataTypes" => [],
593
- "NSPrivacyTracking" => false,
594
- "NSPrivacyAccessedAPITypes" => [file_timestamp_reason, user_defaults_reason, boot_time_reason]
595
- }
596
- path = File.join(user_project.path.parent, "PrivacyInfo.xcprivacy")
597
- Xcodeproj::Plist.write_to_path(privacy_manifest, path)
598
- Pod::UI.puts "Your app does not have a privacy manifest! A template has been generated containing Required Reasons API usage in the core React Native library. Please add the PrivacyInfo.xcprivacy file to your project and complete data use, tracking and any additional required reasons your app is using according to Apple's guidance: https://developer.apple.com/.../privacy_manifest_files. Then, you will need to manually add this file to your project in Xcode.".red
599
- end
600
- end
601
-
602
564
  def self.react_native_pods
603
565
  return [
604
566
  "DoubleConversion",
@@ -17,6 +17,7 @@ require_relative './cocoapods/new_architecture.rb'
17
17
  require_relative './cocoapods/local_podspec_patch.rb'
18
18
  require_relative './cocoapods/runtime.rb'
19
19
  require_relative './cocoapods/helpers.rb'
20
+ require_relative './cocoapods/privacy_manifest_utils.rb'
20
21
 
21
22
  $CODEGEN_OUTPUT_DIR = 'build/generated/ios'
22
23
  $CODEGEN_COMPONENT_DIR = 'react/renderer/components'
@@ -79,7 +80,8 @@ def use_react_native! (
79
80
  flipper_configuration: FlipperConfiguration.disabled,
80
81
  app_path: '..',
81
82
  config_file_dir: '',
82
- ios_folder: 'ios'
83
+ ios_folder: 'ios',
84
+ privacy_file_aggregation_enabled: true
83
85
  )
84
86
 
85
87
  # Set the app_path as env variable so the podspecs can access it.
@@ -101,6 +103,7 @@ def use_react_native! (
101
103
  fabric_enabled = fabric_enabled || NewArchitectureHelper.new_arch_enabled
102
104
  ENV['RCT_FABRIC_ENABLED'] = fabric_enabled ? "1" : "0"
103
105
  ENV['USE_HERMES'] = hermes_enabled ? "1" : "0"
106
+ ENV['RCT_AGGREGATE_PRIVACY_FILES'] = privacy_file_aggregation_enabled ? "1" : "0"
104
107
 
105
108
  prefix = path
106
109
 
@@ -295,6 +298,7 @@ def react_native_post_install(
295
298
 
296
299
  fabric_enabled = ENV['RCT_FABRIC_ENABLED'] == '1'
297
300
  hermes_enabled = ENV['USE_HERMES'] == '1'
301
+ privacy_file_aggregation_enabled = ENV['RCT_AGGREGATE_PRIVACY_FILES'] == '1'
298
302
 
299
303
  if hermes_enabled
300
304
  ReactNativePodsUtils.set_gcc_preprocessor_definition_for_React_hermes(installer)
@@ -309,7 +313,12 @@ def react_native_post_install(
309
313
  ReactNativePodsUtils.apply_xcode_15_patch(installer)
310
314
  ReactNativePodsUtils.updateOSDeploymentTarget(installer)
311
315
  ReactNativePodsUtils.fix_flipper_for_xcode_15_3(installer)
312
- ReactNativePodsUtils.add_privacy_manifest_if_needed(installer)
316
+
317
+ if privacy_file_aggregation_enabled
318
+ PrivacyManifestUtils.add_aggregated_privacy_manifest(installer)
319
+ else
320
+ PrivacyManifestUtils.add_privacy_manifest_if_needed(installer)
321
+ end
313
322
 
314
323
  NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer)
315
324
  NewArchitectureHelper.modify_flags_for_new_architecture(installer, NewArchitectureHelper.new_arch_enabled)
Binary file
Binary file
Binary file
@@ -11,7 +11,7 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "react": "18.2.0",
14
- "react-native": "0.73.8"
14
+ "react-native": "0.73.9"
15
15
  },
16
16
  "devDependencies": {
17
17
  "@babel/core": "^7.20.0",