Commit Graph

22 Commits

Author SHA1 Message Date
Paige Sun 37e5fa3a6c Refactor: Migrate Logbox surface initialization to Fabric when available, in Bridge and Bridgeless modes
Summary:
Changelog: [iOS][Internal] Refactor: Migrate Logbox surface initialization to Fabric when available, in Bridge and Bridgeless modes

# Why
This diff main purpose is to add `RCTErrorNewArchitectureValidation(RCTNotAllowedInAppWideFabric)` in `RCTSurface`, to ensure Paper surfaces are never created in FBiOS.

# The Situation
Before this diff, in Bridged Fabric, `[RCTLogbox show]` initializes a Paper `RCTSurface`, [using `[RCTLogBoxView initWithWindow]`](https://github.com/facebook/react-native/blob/main/React/CoreModules/RCTLogBoxView.mm#L46))
In this diff,  in Bridged and Bridgeless Fabric, `[RCTLogbox show]` initializes a Fabric `RCTFabricSurface`.

Before this diff, in Bridgeless Fabric,  RCTLogBox posts a "CreateLogBoxSurface" notification to RCTInstance.
In this diff, the notification hack is replaced by the same `RCTFabricSurface` initialization above.
Behavior is the same.

Reviewed By: RSNara

Differential Revision: D35177311

fbshipit-source-id: 6de418af8a01f914c9a806bb8d74915015f9087a
2022-03-29 18:40:19 -07:00
Vincent Riemer d31d83f410 Update iOS LogBox to render its UIWindow with the key window's UIWindowScene
Summary:
If an RN app is embedded in a Mac Catalyst app that uses the UIWindowScene API to manage multiple windows, LogBox would fail to render because it didn't know which UIWindowScene to render to. This diff fixes that situation by ensuring that the LogBox window gets rendered in the key window's scene.

Changelog:
[iOS][Fixed] - Update iOS LogBox to render its UIWindow with the key window's UIWindowScene

Reviewed By: appden

Differential Revision: D35027831

fbshipit-source-id: e0df5865f95323b03d08d6b1fb3ec912aa9a9167
2022-03-25 13:28:50 -07:00
Vincent Riemer 84f8c9ad55 Ensure LogBoxView is sized based on the "window" size instead of the "screen" size
Summary:
In iOS, the native LogBox that gets rendered for JS errors/warnings is statically sized once and bases that size off of the entire screen's size. This causes issues when being run in a Mac Catalyst app since 1) the sizing is not static since we can resize the window and 2) the size of the LogBox's root should fill the *window* and not the screen. This diff fixes both of these issues.

Changelog:
[iOS][Fixed] - Ensure LogBoxView is sized relative to the key window instead of the full screen

Reviewed By: appden

Differential Revision: D34697076

fbshipit-source-id: 9665fd51bc86ed29837672cec882bac97904b0c8
2022-03-09 15:43:37 -08:00
Andres Suarez 8bd3edec88 Update copyright headers from Facebook to Meta
Reviewed By: aaronabramov

Differential Revision: D33367752

fbshipit-source-id: 4ce94d184485e5ee0a62cf67ad2d3ba16e285c8f
2021-12-30 15:11:21 -08:00
CodemodService FBSourceClangFormatLinterBot 64711b0d98 Daily arc lint --take CLANGFORMAT
Reviewed By: zertosh

Differential Revision: D31891742

fbshipit-source-id: f6f6ad019e972de5acc8d04f0e8c8d9c9a2e3324
2021-10-25 04:08:21 -07:00
Andrew Rahn 72ea0e111f Hide the logbox window explicitly. New behavior in iOS SDK appears to… (#32435)
Summary:
Fixes  https://github.com/facebook/react-native/issues/32434: RCTLogBox window is orphaned, covering entire screen.

After this change, the logbox window once again is removed from the screen.

## Changelog

Some third-party SDKs may hold references to created UIWindow, UIViewController, or UIView objects. Doing so means that the current code's `hide` method that releases the reference to the UIWindow in LogBox will not cause the window to be dealloc'd, and thus instead it will remain on the screen. This change explicitly hides the LogBox window when the reference is released, so that even if some other SDK holds onto the window it will still be taken off the screen.

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://github.com/facebook/react-native/wiki/Changelog
-->

[iOS] [Fixed] - 32434

Pull Request resolved: https://github.com/facebook/react-native/pull/32435

Test Plan:
1.     Use console.warn to generate a yellow warning message in log box.  Also install a third-party SDK that holds onto a reference to UIWindow -- for example the Facebook SDK, the Data Dog SDK, or any number of other SDKs that use `swizzling` to intercept calls like `viewDidAppear:`.
2.     click the log
3.     tap "dismiss"
4.     try to tap anywhere
5. Use Xcode view debugger to inspect the UI state

## Expected

The app still responds to the touch.
In Xcode, there is not an extra UIWindow covering the screen

Reviewed By: philIip

Differential Revision: D31794242

Pulled By: sshic

fbshipit-source-id: 28aa247b3ed3fd60b8e7c2ed7d0606cbf5c42408
2021-10-24 13:52:40 -07:00
Paige Sun 1271e7afc3 iOS: Don't display LogBox in Dev if Bridge was invalided
Summary: Bridge can get invalidated during tear down. If a JS error is thrown then, don't display a LogBox so we don't hit the invalid bridge assert in RCTSurface.

Reviewed By: fkgozali

Differential Revision: D30464848

fbshipit-source-id: 87a8daa95fd06342d194a4805ecfa97279820f2e
2021-08-20 18:45:11 -07:00
Lulu Wu bdbb040382 Fix Logbox Fullscreen View
Summary:
Logbox inside bridgeless surfaces was crashing and not able to open, this diff should fix it.

Changelog: [Internal]

Reviewed By: PeteTheHeat

Differential Revision: D23043773

fbshipit-source-id: 6e584f97e53e626b9bfedd6dc997ba6ba8c08b8f
2020-08-18 12:29:45 -07:00
Peter Argany 774ebd9c12 Cleanup logbox imports
Summary:
Was looking at removing logbox from CoreModules, realized it had a bunch of extra deps.

Changelog: [Internal]

Reviewed By: rickhanlonii

Differential Revision: D21535374

fbshipit-source-id: 2427cc66fa34635b49ac4b4fafaf0b6481f5687d
2020-05-12 22:40:29 -07:00
Ramanpreet Nara 03bd7d799e Part 2: Update ObjC++ codegen classes to use ObjCTurboModule::InitParams
Summary:
## Summary
Please check out D21035209.

## Changes
- Codemod all ObjC NativeModule `getTurboModuleWithJsInvoker:nativeInvoker:perfLogger` methods to `getTurboModule:(const ObjCTurboModule::Args)`

## Script
```
var withSpaces = (...args) => args.join('\s*')

var regexString = withSpaces(
  '-',
  '\(',
  'std::shared_ptr',
  '<',
  '(?<turboModuleClass>(facebook::react::|react::|::|)TurboModule)',
  '>',
  '\)',
  'getTurboModuleWithJsInvoker',
  ':',
  '\(',
  'std::shared_ptr',
  '<',
  '(?<fbNamespace>(facebook::react::|react::|::|))CallInvoker',
  '>',
  '\)',
  '(?<jsInvokerInstance>[A-Za-z0-9]+)',
  'nativeInvoker',
  ':',
  '\(',
  'std::shared_ptr',
  '<',
  '(facebook::react::|react::|::|)CallInvoker',
  '>',
  '\)',
  '(?<nativeInvokerInstance>[A-Za-z0-9]+)',
  'perfLogger',
  ':',
  '\(',
  'id',
  '<',
  'RCTTurboModulePerformanceLogger',
  '>',
  '\)',
  '(?<perfLoggerInstance>[A-Za-z0-9]+)',
  '{',
  'return',
  'std::make_shared',
  '<',
  '(?<specName>(facebook::react::|react::|::|)Native[%A-Za-z0-9]+SpecJSI)',
  '>',
  '\(',
  'self',
  ',',
  '\k<jsInvokerInstance>',
  ',',
  '\k<nativeInvokerInstance>',
  ',',
  '\k<perfLoggerInstance>',
  '\)',
  ';',
  '}',
)

var replaceString = `- (std::shared_ptr<$<turboModuleClass>>) getTurboModule:(const $<fbNamespace>ObjCTurboModule::InitParams &)params
{
  return std::make_shared<$<specName>>(params);
}`

const exec = require('../lib/exec');
const abspath = require('../lib/abspath');
const relpath = require('../lib/relpath');
const readFile = (filename) => require('fs').readFileSync(filename, 'utf8');
const writeFile = (filename, content) => require('fs').writeFileSync(filename, content);

function main() {
  const tmFiles = exec('cd ~/fbsource && xbgs -n 10000 -l getTurboModuleWithJsInvoker:').split('\n').filter(Boolean);

  tmFiles
    .filter((filename) => !filename.includes('microsoft-fork-of-react-native'))
    .map(abspath)
    .forEach((filename) => {
      const source = readFile(filename);
      const newSource = source.replace(new RegExp(regexString, 'g'), replaceString);

      if (source == newSource) {
        console.log(relpath(filename));
      }

      writeFile(filename, newSource);
    });
}

if (!module.parent) {
  main();
}
```

## Re-generating diff
```
> hg revert -r .^ --all
> node index.js # run script
```

Changelog: [iOS][Changed] - Make all ObjC NativeModules create TurboModules using ObjCTurboModule::Args

Reviewed By: PeteTheHeat

Differential Revision: D21036265

fbshipit-source-id: 404bcc548d1775ef23d793527606d02fe384a0a2
2020-04-16 17:29:55 -07:00
Ramanpreet Nara 69698b25fc Codemod all getTurboModuleWithJsInvoker methods to accept a native CallInvoker
Summary:
To make iOS TurboModules integrate with the bridge's onBatchComplete event, they need to use a native CallInvoker. This call invoker is created by the `NativeToJsBridge`, and ObjCTurboModule will use this native CallInvoker to dispatch TurboModule method calls. This diff makes sure that ObjCTurboModules are created with that native CallInvoker.

## Script
```
var withSpaces = (...args) => args.join('\s*')

var regexString = withSpaces(
  '-',
  '\(',
  'std::shared_ptr',
  '<',
  '(?<turboModuleClass>(facebook::react::|react::|::|)TurboModule)',
  '>',
  '\)',
  'getTurboModuleWithJsInvoker',
  ':',
  '\(',
  'std::shared_ptr',
  '<',
  '(?<callInvokerClass>(facebook::react::|react::|::|)CallInvoker)',
  '>',
  '\)',
  '(?<jsInvokerInstance>[A-Za-z0-9]+)',
  'perfLogger',
  ':',
  '\(',
  'id',
  '<',
  'RCTTurboModulePerformanceLogger',
  '>',
  '\)',
  '(?<perfLoggerInstance>[A-Za-z0-9]+)',
  '{',
  'return',
  'std::make_shared',
  '<',
  '(?<specName>(facebook::react::|react::|::|)Native[%A-Za-z0-9]+SpecJSI)',
  '>',
  '\(',
  'self',
  ',',
  '\k<jsInvokerInstance>',
  ',',
  '\k<perfLoggerInstance>',
  '\)',
  ';',
  '}',
)

var replaceString = `- (std::shared_ptr<$<turboModuleClass>>)
    getTurboModuleWithJsInvoker:(std::shared_ptr<$<callInvokerClass>>)$<jsInvokerInstance>
                  nativeInvoker:(std::shared_ptr<$<callInvokerClass>>)nativeInvoker
                     perfLogger:(id<RCTTurboModulePerformanceLogger>)$<perfLoggerInstance>
{
  return std::make_shared<$<specName>>(self, $<jsInvokerInstance>, nativeInvoker, $<perfLoggerInstance>);
}`

const exec = require('../lib/exec');
const abspath = require('../lib/abspath');
const relpath = require('../lib/relpath');
const readFile = (filename) => require('fs').readFileSync(filename, 'utf8');
const writeFile = (filename, content) => require('fs').writeFileSync(filename, content);

function main() {
  const tmFiles = exec('cd ~/fbsource && xbgs -n 10000 -l getTurboModuleWithJsInvoker:').split('\n').filter(Boolean);

  tmFiles
    .filter((filename) => !filename.includes('microsoft-fork-of-react-native'))
    .map(abspath)
    .forEach((filename) => {
      const source = readFile(filename);
      const newSource = source.replace(new RegExp(regexString, 'g'), replaceString);

      if (source == newSource) {
        console.log(relpath(filename));
      }

      writeFile(filename, newSource);
    });
}

if (!module.parent) {
  main();
}
```

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D20809202

fbshipit-source-id: 5d39b3cacdaa5681b70ce1803351d0432dd74550
2020-04-03 02:27:10 -07:00
generatedunixname89002005287564 ec2cfe98d2 Daily arc lint --take CLANGFORMAT
Reviewed By: zertosh

Differential Revision: D20666684

fbshipit-source-id: 32255ac7509e0257693969a7b4b044569af30df7
2020-03-26 05:22:59 -07:00
Peter Argany 72ac2125bc Fix retaining self in block in LogBox impl
Summary:
Logbox has a retain cycle (see linked task for my deeper investigation).

This diff doesn't fix the retain cycle, but it's just good practice to not retain self strongly in blocks.

Changelog: [iOS][Internal] Fix retaining self in block in LogBox implementation

Reviewed By: shergin

Differential Revision: D20630693

fbshipit-source-id: cf399495e9bcd1917932fcc0e9c9d2d2a32bf6f0
2020-03-25 12:25:49 -07:00
Ramanpreet Nara 652fa1b8d4 Add a perfLogger argument to getTurboModuleWithJSInvoker:
Summary:
## Purpose
We must modify the `getTurboModuleWithJsInvoker:` method of all our NativeModules to also accept a `id<RCTTurboModulePerformanceLogger>` object. This performance logger object should then be forwarded to the `Native*SpecJSI` constructor.

## Script
Run the following script via Node:
```
var withSpaces = (...args) => args.join('\s*')

var regexString = withSpaces(
  '-',
  '\(',
  'std::shared_ptr',
  '<',
  '(?<turboModuleClass>(facebook::react::|react::|::|)TurboModule)',
  '>',
  '\)',
  'getTurboModuleWithJsInvoker',
  ':',
  '\(',
  'std::shared_ptr',
  '<',
  '(?<callInvokerClass>(facebook::react::|react::|::|)CallInvoker)',
  '>',
  '\)',
  'jsInvoker',
  '{',
  'return',
  'std::make_shared',
  '<',
  '(?<specName>(facebook::react::|react::|::|)Native[A-Za-z0-9]+SpecJSI)',
  '>',
  '\(',
  '(?<arg1>[A-Za-z0-9]+)',
  ',',
  '(?<arg2>[A-Za-z0-9]+)',
  '\)',
  ';',
  '}',
)

var replaceString = `- (std::shared_ptr<$<turboModuleClass>>)
    getTurboModuleWithJsInvoker:(std::shared_ptr<$<callInvokerClass>>)jsInvoker
                     perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
{
  return std::make_shared<$<specName>>($<arg1>, $<arg2>, perfLogger);
}`

const exec = (cmd) => require('child_process').execSync(cmd, { encoding: 'utf8' });
const abspath = (filename) => `${process.env.HOME}/${filename}`;
const relpath = (filename) => filename.replace(process.env.HOME + '/', '');
const readFile = (filename) => require('fs').readFileSync(filename, 'utf8');
const writeFile = (filename, content) => require('fs').writeFileSync(filename, content);

function main() {
  const tmFiles = exec('cd ~/fbsource && xbgs -n 10000 -l getTurboModuleWithJsInvoker:').split('\n').filter(Boolean);

  tmFiles
    .filter((filename) => !filename.includes('microsoft-fork-of-react-native'))
    .map(abspath)
    .forEach((filename) => {
      const source = readFile(filename);
      const newSource = source.replace(new RegExp(regexString, 'g'), replaceString);

      if (source == newSource) {
        console.log(relpath(filename));
      }

      writeFile(filename, newSource);
    });
}

if (!module.parent) {
  main();
}
```

Also, run: `pushd ~/fbsource && js1 build oss-native-modules-specs -p ios && js1 build oss-native-modules-specs -p android && popd;`

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D20478718

fbshipit-source-id: 89ee27ed8a0338a66a9b2dbb716168a4c4582c44
2020-03-18 11:01:15 -07:00
Valentin Shergin d0871d0a9a Clang format for all React Native files
Summary:
Buckle up, this enables clang-format prettifier for all files in React Native opensource repo.

Changelog: [Internal] Clang-format codemod.

Reviewed By: mdvacca

Differential Revision: D20331210

fbshipit-source-id: 8da0f94700be0c35bfd399e0c48f1706de04f5b1
2020-03-08 23:01:17 -07:00
Rick Hanlon cb749f1c52 LogBox - Revert back to RedBox window strategy
Summary: This diff reverts the iOS LogBox module back to the UIWindow strategy used by Redbox.

Reviewed By: sammy-SC

Differential Revision: D19941390

fbshipit-source-id: 4aea09137ea9e8bfc166a733272647a79102bf35
2020-02-18 06:19:44 -08:00
Rick Hanlon 6ba2aeefa8 LogBox - Deallocate _rootViewController to release surface reference and break cycle
Summary:
This def breaks a reference cycle in logbox causing a memory leak in development.

Changelog: [iOS] [Fix] LogBox - Fix dependency cycle

Reviewed By: PeteTheHeat

Differential Revision: D19768068

fbshipit-source-id: 518b9c66499aa092465a9213f955965bffeebd88
2020-02-11 06:58:15 -08:00
Rick Hanlon 88813761ec LogBox - Double sync rendering timeout
Summary:
On slower devices , 0.5s is not fast enough and we frequently render a black screen. Let's bump the sync rendering timeout to 1s.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D19282619

fbshipit-source-id: 0d9ae60f4869b0de7c4523c2cb33fbbf320c6438
2020-01-05 05:22:01 -08:00
Kevin Gozali 6ceef13a9c iOS Logbox: always return a turbomodule instance
Summary:
We have assertion to ensure that `getTurboModuleWithJsInvoker:` returns non-nullptr, so conditionally returning `nullptr` is not going to work.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D19103125

fbshipit-source-id: 663850c01e4db40cca96d254950ea5a7bf6b96b7
2019-12-16 15:04:27 -08:00
Rick Hanlon 586d55d54f LogBox - lazily initialize on iOS, use sync APIs
Summary:
Update LogBox on iOS to lazily initialize, using a synchronous RCTSurface, behind RCTSharedApplication checks.

This results in faster of LogBox, without keeping around a long lived window in the background, and only used when LogBox is used.

On Android, we still start the react app in the background but we create a dialog when it's shown and then destroy it when it's hidden. Once we have the sync APIs on android we can update it to use the same strategy.

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D18925538

fbshipit-source-id: 1a72c39aa0fc26c8ba657d36c7fa7bc0ae777eb9
2019-12-13 03:09:00 -08:00
Kevin Gozali 3b9c721996 LogBox iOS: don't initialize logbox window if redbox flag is disabled
Summary:
If redbox flag is disabled, don't initialize LogBox window even if the native module exists. This makes the module noop.

Changelog: [Internal]

Reviewed By: shergin

Differential Revision: D18927309

fbshipit-source-id: 3dc6c08ed537925594cabf77d1142568d47132e9
2019-12-10 21:49:33 -08:00
Rick Hanlon 6b22a4e802 Add NativeLogBox module on iOS
Summary:
This diff adds a NativeLogBox module implementation on iOS to manage rendering LogBox the way we render RedBox, except rendering a React Native component instead of a native view.

The strategy here is:
- initialize: will create a hidden window (the way redbox does) and render the LogBox to it
- show: will show the window
- hide: will hide the window

Most of this is copied from the way RedBox works, the difference here is that we eagerly initialize the window with the `initialize` function so that it's warm by the time LogBox needs to render.

Changelog: [Internal]

Reviewed By: RSNara

Differential Revision: D18750008

fbshipit-source-id: 013e55ded55c8572bb08e0219ff4cd0060ebe0da
2019-12-10 02:31:37 -08:00