not-react-native-macos 0.87.1-rc.1 → 0.87.1-rc.2

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 (62) hide show
  1. package/Libraries/Alert/RCTAlertManager.macos.js +21 -0
  2. package/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.macos.js +23 -0
  3. package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.macos.js +23 -0
  4. package/Libraries/Components/ToastAndroid/ToastAndroid.macos.js +23 -0
  5. package/Libraries/Image/Image.macos.js +23 -0
  6. package/Libraries/NativeComponent/BaseViewConfig.macos.js +23 -0
  7. package/Libraries/Network/RCTNetworking.macos.js +23 -0
  8. package/Libraries/Settings/Settings.macos.js +33 -0
  9. package/Libraries/StyleSheet/PlatformColorValueTypes.macos.js +21 -0
  10. package/Libraries/Utilities/BackHandler.macos.js +23 -0
  11. package/Libraries/Utilities/Platform.macos.js +23 -0
  12. package/React/Base/RCTRootView.h +1 -1
  13. package/React/Base/RCTTextView.h +31 -0
  14. package/React/Base/RCTUIKit.h +121 -0
  15. package/React/Base/RCTUIKit.m +29 -0
  16. package/React/Base/Surface/RCTSurfaceView.h +1 -1
  17. package/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingView.h +1 -1
  18. package/React/CoreModules/RCTDevLoadingView.mm +1 -1
  19. package/React/CoreModules/RCTFPSGraph.h +1 -1
  20. package/React/CoreModules/RCTPerfMonitor.mm +1 -1
  21. package/React/CoreModules/RCTRedBox2Controller.mm +4 -4
  22. package/React/CoreModules/RCTRedBoxController.mm +2 -2
  23. package/React/CoreModules/React-CoreModules.podspec +0 -6
  24. package/React/DevSupport/RCTPausedInDebuggerOverlayController.mm +2 -2
  25. package/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryContentView.h +1 -1
  26. package/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryContentView.mm +1 -1
  27. package/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm +1 -1
  28. package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +1 -1
  29. package/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm +1 -1
  30. package/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +1 -1
  31. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +1 -1
  32. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +2 -2
  33. package/React/Fabric/Mounting/RCTComponentViewDescriptor.h +1 -1
  34. package/React/Fabric/Mounting/RCTComponentViewRegistry.h +1 -1
  35. package/React/Modules/RCTRedBoxExtraDataViewController.m +1 -1
  36. package/React/Views/RCTDebuggingOverlay.m +2 -2
  37. package/React/Views/RCTView.h +1 -1
  38. package/React/Views/RCTWrapperViewController.m +1 -1
  39. package/React-Core.podspec +0 -2
  40. package/macos/UIKitCompat/RCTPlatformViewCompat.h +9 -4
  41. package/macos/UIKitCompat/React-UIKitCompat.podspec +10 -2
  42. package/macos/UIKitCompat/UIKit/UIApplicationDelegate.h +13 -0
  43. package/macos/UIKitCompat/UIKit/UIControls.m +1 -1
  44. package/macos/UIKitCompat/UIKit/UIEvent.h +12 -0
  45. package/macos/UIKitCompat/UIKit/UIEvent.m +4 -1
  46. package/macos/UIKitCompat/UIKit/UIPlatformGaps.h +1 -1
  47. package/macos/UIKitCompat/UIKit/UIPlatformGaps.m +15 -1
  48. package/macos/UIKitCompat/UIKit/UITouch.h +24 -0
  49. package/macos/UIKitCompat/UIKit/UIView.h +18 -5
  50. package/macos/UIKitCompat/UIKit/UIView.m +24 -6
  51. package/macos/UIKitCompat/UIKit/UIViewController.h +24 -0
  52. package/macos/UIKitCompat/UIKit/UIWindow.h +24 -0
  53. package/macos/UIKitCompat/macos-excludes.txt +12 -33
  54. package/macos/metro-config.js +47 -25
  55. package/package.json +1 -1
  56. package/scripts/cocoapods/autolinking.rb +11 -2
  57. package/scripts/cocoapods/codegen.rb +3 -1
  58. package/scripts/cocoapods/codegen_utils.rb +7 -2
  59. package/scripts/codegen/generate-artifacts-executor/generateRCTThirdPartyComponents.js +3 -1
  60. package/scripts/codegen/generate-artifacts-executor/index.js +52 -4
  61. package/scripts/codegen/templates/RCTThirdPartyComponentsProviderMM.template +22 -1
  62. package/src/private/devsupport/rndevtools/ReactDevToolsSettingsManager.macos.js +17 -0
@@ -36,36 +36,49 @@
36
36
 
37
37
  'use strict';
38
38
 
39
- const MACOS_SUFFIX = /\.macos\.[^.]+$/;
40
-
41
39
  /**
42
- * Resolve one specifier as `.macos.*` -> iOS resolution.
40
+ * Resolve one specifier for the `macos` platform.
41
+ *
42
+ * Metro's own `macos` resolution already does the right thing almost always:
43
+ * `Foo.macos.js`, then `Foo.native.js`, then the shared `Foo.js`. A package that
44
+ * ships `Foo.ios`, `Foo.android` *and* `Foo.js` means the shared file for every
45
+ * other platform, macOS included -- expo-router's `toolbar/native.tsx` is
46
+ * exactly that, and taking its `.ios` sibling instead drags in iOS-only native
47
+ * modules that are not linked here.
48
+ *
49
+ * Falling back to iOS is still needed twice:
43
50
  *
44
- * Only a file that genuinely carries the `.macos.` suffix counts as an
45
- * override. Anything else is the shared file, which iOS resolution reaches too
46
- * -- and which may itself be the re-export that needs a suffixed sibling.
51
+ * - Nothing resolves at all, because the module exists only as `Foo.ios.js`
52
+ * and `Foo.android.js`. ReactDevToolsSettingsManager is one of about twenty.
53
+ * - The shared file *is* the importer. `Platform.js` re-exports `./Platform`
54
+ * and expects a platform-suffixed sibling to answer; with no
55
+ * `Platform.macos.js` it resolves to itself, and `Platform.OS` comes out
56
+ * undefined by way of a require cycle.
57
+ *
58
+ * So: take Metro's answer unless it is unusable, and only then ask for iOS.
47
59
  */
48
- function resolveMacOS(context, moduleName, platform) {
60
+ function resolveMacOS(context, moduleName, platform, next) {
61
+ const resolve = next ?? ((ctx, name, plat) => ctx.resolveRequest(ctx, name, plat));
62
+
49
63
  if (platform !== 'macos') {
50
- return context.resolveRequest(context, moduleName, platform);
64
+ return resolve(context, moduleName, platform);
51
65
  }
52
66
 
53
67
  const attempt = candidate => {
54
68
  try {
55
- return context.resolveRequest(context, moduleName, candidate);
69
+ return resolve(context, moduleName, candidate);
56
70
  } catch (error) {
57
71
  return error;
58
72
  }
59
73
  };
60
74
 
61
75
  const macos = attempt('macos');
62
- if (
63
- macos != null &&
64
- !(macos instanceof Error) &&
65
- typeof macos.filePath === 'string' &&
66
- MACOS_SUFFIX.test(macos.filePath)
67
- ) {
68
- return macos;
76
+ if (!(macos instanceof Error)) {
77
+ const resolvedToImporter =
78
+ typeof macos.filePath === 'string' && macos.filePath === context.originModulePath;
79
+ if (!resolvedToImporter) {
80
+ return macos;
81
+ }
69
82
  }
70
83
 
71
84
  const ios = attempt('ios');
@@ -73,24 +86,33 @@ function resolveMacOS(context, moduleName, platform) {
73
86
  return ios;
74
87
  }
75
88
 
76
- // Report the macOS failure, not the iOS one: it names the platform asked for.
77
- if (macos instanceof Error) {
78
- throw macos;
79
- }
80
- return macos;
89
+ // Report the macOS failure: it names the platform that was asked for.
90
+ throw macos instanceof Error ? macos : ios;
81
91
  }
82
92
 
83
93
  /**
84
94
  * A Metro config fragment that teaches the resolver about macOS.
85
95
  *
86
- * Merge it over `getDefaultConfig()`. It sets nothing else, so an app keeps
87
- * full control of transformer, serializer and watch folders.
96
+ * Pass the config you are extending. If it already has a `resolveRequest` --
97
+ * `@expo/metro-config` installs a substantial one -- this *wraps* it rather
98
+ * than replacing it, because `context.resolveRequest` inside a custom resolver
99
+ * is Metro's default resolver, not whatever was configured before. Assigning
100
+ * over it silently drops the other resolver's behaviour.
101
+ *
102
+ * Sets nothing else, so an app keeps full control of transformer, serializer
103
+ * and watch folders.
104
+ *
105
+ * const config = getDefaultConfig(__dirname);
106
+ * module.exports = mergeConfig(config, getMacOSConfig(config));
88
107
  */
89
- function getMacOSConfig() {
108
+ function getMacOSConfig(baseConfig) {
109
+ const upstream = baseConfig?.resolver?.resolveRequest;
110
+
90
111
  return {
91
112
  resolver: {
92
113
  platforms: ['macos', 'ios', 'android', 'native'],
93
- resolveRequest: resolveMacOS,
114
+ resolveRequest: (context, moduleName, platform) =>
115
+ resolveMacOS(context, moduleName, platform, upstream),
94
116
  },
95
117
  };
96
118
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "not-react-native-macos",
3
- "version": "0.87.1-rc.1",
3
+ "version": "0.87.1-rc.2",
4
4
  "description": "A framework for building native apps using React",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,7 +38,16 @@ def list_native_modules!(config_command)
38
38
  config = JSON.parse(json)
39
39
 
40
40
  packages = config["dependencies"]
41
- ios_project_root = Pathname.new(config["project"]["ios"]["sourceDir"])
41
+
42
+ # [macOS] The autolinking JSON is keyed by platform, and a macOS build asks the
43
+ # CLI for `--platform macos`, so the only key present is "macos" -- indexing
44
+ # "ios" unconditionally crashes with `undefined method '[]' for nil`. Take the
45
+ # key from the target's own platform, and fall back to "ios" so nothing changes
46
+ # for an iOS build. macOS]
47
+ autolinking_platform = current_target_definition&.platform&.name == :osx ? "macos" : "ios"
48
+
49
+ project_config = config["project"][autolinking_platform] || config["project"]["ios"]
50
+ ios_project_root = Pathname.new(project_config["sourceDir"])
42
51
  react_native_path = Pathname.new(config["reactNativePath"])
43
52
  codegen_output_path = ios_project_root.join("build/generated/autolinking/autolinking.json")
44
53
 
@@ -49,7 +58,7 @@ def list_native_modules!(config_command)
49
58
  found_pods = []
50
59
 
51
60
  packages.each do |package_name, package|
52
- next unless package_config = package["platforms"]["ios"]
61
+ next unless package_config = package["platforms"][autolinking_platform] # [macOS] was hardcoded "ios"
53
62
 
54
63
  name = package["name"]
55
64
  podspec_path = package_config["podspecPath"]
@@ -34,7 +34,9 @@ def run_codegen!(
34
34
  :config_file_dir => config_file_dir,
35
35
  :codegen_output_dir => codegen_output_dir,
36
36
  :config_key => config_key,
37
- :folly_version => folly_version
37
+ :folly_version => folly_version,
38
+ # [macOS] see CodegenUtils#use_react_native_codegen_discovery!
39
+ :target_platform => (current_target_definition&.platform&.name == :osx ? "macos" : "ios")
38
40
  )
39
41
  end
40
42
 
@@ -35,7 +35,12 @@ class CodegenUtils
35
35
  folly_version: Helpers::Constants.folly_config[:version],
36
36
  codegen_utils: CodegenUtils.new(),
37
37
  file_manager: File,
38
- logger: CodegenUtils::UI
38
+ logger: CodegenUtils::UI,
39
+ # [macOS] The generated providers are platform-specific: they map names to
40
+ # classes that only exist if the owning library was built for this
41
+ # platform. Upstream hardcodes "ios" because every library supports iOS.
42
+ # macOS]
43
+ target_platform: "ios"
39
44
  )
40
45
  return if codegen_disabled
41
46
 
@@ -58,7 +63,7 @@ class CodegenUtils
58
63
  "#{relative_installation_root}/#{react_native_path}/scripts/generate-codegen-artifacts.js",
59
64
  "-p", "#{app_path}",
60
65
  "-o", Pod::Config.instance.installation_root,
61
- "-t", "ios",
66
+ "-t", target_platform, # [macOS] was hardcoded "ios"
62
67
  ])
63
68
  Pod::UI.puts out;
64
69
 
@@ -139,7 +139,9 @@ function generateRCTThirdPartyComponents(
139
139
  .flatMap(library => {
140
140
  const components = componentsInLibraries[library];
141
141
  return components.map(({componentName, className}) => {
142
- return `\t\t@"${componentName}": NSClassFromString(@"${className}"), // ${library}`;
142
+ // [macOS] The class name, not NSClassFromString: the provider resolves
143
+ // it at runtime and skips what is not in the binary. See the template.
144
+ return `\t\t@"${componentName}": @"${className}", // ${library}`;
143
145
  });
144
146
  })
145
147
  .join('\n');
@@ -28,7 +28,10 @@ const {
28
28
  generateRCTThirdPartyComponents,
29
29
  } = require('./generateRCTThirdPartyComponents');
30
30
  const {generateReactCodegenPodspec} = require('./generateReactCodegenPodspec');
31
- const {generateSchemaInfos} = require('./generateSchemaInfos');
31
+ const {
32
+ extractSupportedApplePlatforms, // [macOS] filters the Apple providers by platform
33
+ generateSchemaInfos,
34
+ } = require('./generateSchemaInfos');
32
35
  const {
33
36
  generateUnstableModulesRequiringMainQueueSetupProvider,
34
37
  } = require('./generateUnstableModulesRequiringMainQueueSetupProvider');
@@ -39,6 +42,7 @@ const {
39
42
  findCodegenEnabledLibraries,
40
43
  findDisabledLibrariesByPlatform,
41
44
  findReactNativeRootPath,
45
+ isReactNativeCoreLibrary, // [macOS] core libraries skip the platform filter
42
46
  pkgJsonIncludesGeneratedCode,
43
47
  readPkgJsonInDirectory,
44
48
  readReactNativeConfig,
@@ -72,6 +76,18 @@ function execute(
72
76
  codegenLog(`Analyzing ${path.join(projectRoot, 'package.json')}`);
73
77
 
74
78
  const supportedPlatforms = ['android', 'ios'];
79
+
80
+ // [macOS] macOS consumes the iOS codegen output -- same specs, same output
81
+ // directory, same native code. The only thing that differs is which
82
+ // libraries may appear in the generated Apple providers, because a library
83
+ // that does not support macOS is never compiled and its class would be nil.
84
+ // So normalise the target here and keep the real platform for that filter.
85
+ const applePlatform = targetPlatform === 'macos' ? 'macos' : null;
86
+ if (applePlatform != null) {
87
+ targetPlatform = 'ios';
88
+ }
89
+ // macOS]
90
+
75
91
  if (
76
92
  targetPlatform !== 'all' &&
77
93
  !supportedPlatforms.includes(targetPlatform)
@@ -152,15 +168,47 @@ function execute(
152
168
  }
153
169
 
154
170
  if (source === 'app' && platform !== 'android') {
171
+ // [macOS] Only libraries that support the platform being built.
172
+ //
173
+ // The generated providers map component and module names to classes via
174
+ // NSClassFromString, and put the result straight into a dictionary
175
+ // literal. A library whose podspec does not support this platform is
176
+ // never compiled, so its class is nil, and the dictionary throws
177
+ // "attempt to insert nil object from objects[0]" as the app starts.
178
+ //
179
+ // Every library supports iOS, so upstream never had to filter. An
180
+ // out-of-tree platform does: on macOS an app pulls in plenty of
181
+ // iOS-only modules through its dependency tree. macOS]
182
+ const applePlatformLibraries = libraries.filter(library => {
183
+ if (isReactNativeCoreLibrary(library.config.name)) {
184
+ return true;
185
+ }
186
+ let supported;
187
+ try {
188
+ supported = extractSupportedApplePlatforms(
189
+ library.config.name,
190
+ library.libraryPath,
191
+ );
192
+ } catch {
193
+ supported = null;
194
+ }
195
+ // No podspec, or one that says nothing, means no opinion. Keep the
196
+ // library, which is what upstream did for every platform.
197
+ return supported == null || supported[applePlatform ?? platform] !== false;
198
+ });
199
+
155
200
  // These components are only required by apps, not by libraries and are Apple specific.
156
- generateRCTThirdPartyComponents(libraries, reactCodegenOutputPath);
201
+ generateRCTThirdPartyComponents(
202
+ applePlatformLibraries,
203
+ reactCodegenOutputPath,
204
+ );
157
205
  generateRCTModuleProviders(
158
206
  projectRoot,
159
207
  pkgJson,
160
- libraries,
208
+ applePlatformLibraries,
161
209
  reactCodegenOutputPath,
162
210
  );
163
- generateCustomURLHandlers(libraries, reactCodegenOutputPath);
211
+ generateCustomURLHandlers(applePlatformLibraries, reactCodegenOutputPath);
164
212
  generateUnstableModulesRequiringMainQueueSetupProvider(
165
213
  libraries,
166
214
  reactCodegenOutputPath,
@@ -19,9 +19,30 @@
19
19
  static dispatch_once_t nativeComponentsToken;
20
20
 
21
21
  dispatch_once(&nativeComponentsToken, ^{
22
- thirdPartyComponents = @{
22
+ // [macOS] Built key by key, skipping classes that are not in the binary.
23
+ //
24
+ // The entries below are class *names*, resolved one at a time. A literal of
25
+ // NSClassFromString results throws "attempt to insert nil object" the moment
26
+ // one misses. On iOS none ever do. On an out-of-tree platform they do: the
27
+ // dependency tree holds libraries that are not built for it, and codegen
28
+ // cannot always tell -- a podspec may advertise a platform that autolinking
29
+ // then skips.
30
+ //
31
+ // A component that is not linked cannot be rendered either way. Leaving it
32
+ // out of the map lets the rest of the app start. macOS]
33
+ NSDictionary<NSString *, NSString *> *candidates = @{
23
34
  {thirdPartyComponentsMapping}
24
35
  };
36
+
37
+ NSMutableDictionary<NSString *, Class<RCTComponentViewProtocol>> *resolved =
38
+ [NSMutableDictionary dictionaryWithCapacity:candidates.count];
39
+ for (NSString *name in candidates) {
40
+ Class componentClass = NSClassFromString(candidates[name]);
41
+ if (componentClass != nil) {
42
+ resolved[name] = componentClass;
43
+ }
44
+ }
45
+ thirdPartyComponents = [resolved copy];
25
46
  });
26
47
 
27
48
  return thirdPartyComponents;
@@ -0,0 +1,17 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict-local
8
+ * @format
9
+ */
10
+
11
+ // [macOS] macOS resolves as `.macos` -> `.native` -> shared, so without this
12
+ // file `ReactDevToolsSettingsManager` re-exports itself: the shared file is a
13
+ // stub that expects a platform-suffixed sibling to answer. Point it at the iOS
14
+ // implementation, which is what this fork uses on macOS wherever upstream has
15
+ // no platform-neutral one. macOS]
16
+
17
+ export * from './ReactDevToolsSettingsManager.ios';