Merge commit 'ed8e5e51516a81158d64dbbf39be3bff9796cc46' into 0.67-merge-latest

This commit is contained in:
Adam Gleitman 2022-05-05 07:37:32 -07:00
Родитель b74e7f8241 ed8e5e5151
Коммит 562d288f90
197 изменённых файлов: 5018 добавлений и 3755 удалений

2
.bundle/config Normal file
Просмотреть файл

@ -0,0 +1,2 @@
BUNDLE_PATH: "vendor/bundle"
BUNDLE_FORCE_RUBY_PLATFORM: 1

Просмотреть файл

@ -65,6 +65,16 @@ commands:
name: Initial Setup
command: mkdir -p ./reports/{buck,build,junit,outputs}
setup_ruby:
steps:
- restore_cache:
key: 1-gems-{{ checksum "Gemfile.lock" }}
- run: bundle check || bundle install --path vendor/bundle --clean
- save_cache:
key: 1-gems-{{ checksum "Gemfile.lock" }}
paths:
- vendor/bundle
run_yarn:
steps:
- restore_cache:
@ -223,9 +233,14 @@ jobs:
# Note: The yarn gpg key needs to be refreshed to work around https://github.com/yarnpkg/yarn/issues/7866
- run:
name: Install additional GitHub bot dependencies
# TEMP: Added workaround from https://github.com/nodesource/distributions/issues/1266#issuecomment-932583579
command: |
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
apt update && apt install -y shellcheck jq
apt-get install openssl ca-certificates
update-ca-certificates
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
apt update && apt install -y shellcheck jq
- run:
name: Run linters against modified files (analysis-bot)
@ -352,6 +367,7 @@ jobs:
steps:
- checkout
- setup_artifacts
- setup_ruby
- run_yarn
- run: |
@ -405,7 +421,7 @@ jobs:
- run:
name: Setup the CocoaPods environment
command: pod setup
command: bundle exec pod setup
- with_rntester_pods_cache_span:
steps:
@ -584,26 +600,6 @@ jobs:
name: Build the template application
command: cd template/android/ && ./gradlew assembleDebug
# -------------------------
# JOBS: Test Docker
# -------------------------
test_docker_android:
machine: true
steps:
- checkout
- run:
name: Configure Node
command: |
source ~/.bashrc
nvm i node
echo y | npx envinfo@latest
- run:
name: Pulls down the React Native Community Android Docker image
command: npm run docker-setup-android
- run:
name: Builds the Docker image with a compiled instance of the test app
command: npm run docker-build-android
# -------------------------
# JOBS: Windows
# -------------------------
@ -760,12 +756,21 @@ jobs:
- store_artifacts:
path: ~/react-native/build/
destination: build
- when:
condition:
matches: { pattern: '^pull\/.*$', value: << pipeline.git.branch >> }
steps:
- install_github_bot_deps
- run:
name: Post link to PR build artifacts (pull-bot)
command: GITHUB_TOKEN="$PUBLIC_PULLBOT_GITHUB_TOKEN_A""$PUBLIC_PULLBOT_GITHUB_TOKEN_B" scripts/circleci/post-artifacts-link.sh
# -------------------------
# JOBS: Nightly
# -------------------------
nightly_job:
machine: true
machine:
image: ubuntu-2004:202010-01
steps:
- run:
name: Nightly

Просмотреть файл

@ -79,4 +79,4 @@ untyped-import
untyped-type-import
[version]
^0.161.0
^0.162.0

Просмотреть файл

@ -82,4 +82,4 @@ untyped-import
untyped-type-import
[version]
^0.161.0
^0.162.0

Просмотреть файл

@ -79,4 +79,4 @@ untyped-import
untyped-type-import
[version]
^0.161.0
^0.162.0

19
.github/workflows/stale-bot.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,19 @@
name: Mark stale issues and pull requests
on:
schedule:
- cron: "30 1 * * *"
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v4
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 365
stale-issue-message: 'This issue is stale because it has been open 365 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
stale-pr-message: 'This PR is stale because it has been open 365 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
close-issue-message: 'This issue was closed because it has been stalled for 7 days with no activity.'
close-pr-message: 'This PR was closed because it has been stalled for 7 days with no activity.'

19
.github/workflows/test-docker-android.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,19 @@
name: Test Docker Android Image
# This workflow is triggered on commits to main and pull requests.
on:
push:
branches:
- main
pull_request:
types: [ synchronize ]
branches:
- main
jobs:
test-docker-android:
name: Test Docker
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build Docker image with Android test app
run: npm run docker-build-android

4
.gitignore поставляемый
Просмотреть файл

@ -98,6 +98,10 @@ package-lock.json
/React/FBReactNativeSpec/**/*.xcodeproj
/packages/react-native-codegen/**/*.xcodeproj
# Ruby Gems (Bundler)
/vendor
/template/vendor
# CocoaPods
/template/ios/Pods/
/template/ios/Podfile.lock

1
.ruby-version Normal file
Просмотреть файл

@ -0,0 +1 @@
2.7.4

6
Gemfile Normal file
Просмотреть файл

@ -0,0 +1,6 @@
source 'https://rubygems.org'
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby '2.7.4'
gem 'cocoapods', '~> 1.11', '>= 1.11.2'

100
Gemfile.lock Normal file
Просмотреть файл

@ -0,0 +1,100 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.4)
rexml
activesupport (6.1.4.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
atomos (0.1.3)
claide (1.0.3)
cocoapods (1.11.2)
addressable (~> 2.8)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.11.2)
cocoapods-deintegrate (>= 1.0.3, < 2.0)
cocoapods-downloader (>= 1.4.0, < 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.4.0, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored2 (~> 3.1)
escape (~> 0.0.4)
fourflusher (>= 2.3.0, < 3.0)
gh_inspector (~> 1.0)
molinillo (~> 0.8.0)
nap (~> 1.0)
ruby-macho (>= 1.0, < 3.0)
xcodeproj (>= 1.21.0, < 2.0)
cocoapods-core (1.11.2)
activesupport (>= 5.0, < 7)
addressable (~> 2.8)
algoliasearch (~> 1.0)
concurrent-ruby (~> 1.1)
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
netrc (~> 0.11)
public_suffix (~> 4.0)
typhoeus (~> 1.0)
cocoapods-deintegrate (1.0.5)
cocoapods-downloader (1.5.1)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.1)
cocoapods-trunk (1.6.0)
nap (>= 0.8, < 2.0)
netrc (~> 0.11)
cocoapods-try (1.2.0)
colored2 (3.1.2)
concurrent-ruby (1.1.9)
escape (0.0.4)
ethon (0.14.0)
ffi (>= 1.15.0)
ffi (1.15.4)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
httpclient (2.8.3)
i18n (1.8.10)
concurrent-ruby (~> 1.0)
json (2.5.1)
minitest (5.14.4)
molinillo (0.8.0)
nanaimo (0.3.0)
nap (1.1.0)
netrc (0.11.0)
public_suffix (4.0.6)
rexml (3.2.5)
ruby-macho (2.5.1)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
xcodeproj (1.21.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
rexml (~> 3.2.4)
zeitwerk (2.4.2)
PLATFORMS
ruby
DEPENDENCIES
cocoapods (~> 1.11, >= 1.11.2)
RUBY VERSION
ruby 2.7.4p191
BUNDLED WITH
2.2.28

Просмотреть файл

@ -355,7 +355,7 @@ function shouldUseNativeDriver(
'animated module is missing. Falling back to JS-based animation. To ' +
'resolve this, add `RCTAnimation` module to this app, or remove ' +
'`useNativeDriver`. ' +
'Make sure to run `pod install` first. Read more about autolinking: https://github.com/react-native-community/cli/blob/master/docs/autolinking.md',
'Make sure to run `bundle exec pod install` first. Read more about autolinking: https://github.com/react-native-community/cli/blob/master/docs/autolinking.md',
);
_warnedMissingNativeAnimated = true;
}

Просмотреть файл

@ -31,6 +31,7 @@ const AndroidHorizontalScrollViewNativeComponent: HostComponent<Props> = NativeC
scrollPerfTag: true,
sendMomentumEvents: true,
showsHorizontalScrollIndicator: true,
snapToAlignment: true,
snapToEnd: true,
snapToInterval: true,
snapToStart: true,

Просмотреть файл

@ -22,7 +22,7 @@ export type Props = ViewProps;
* supports layout with flexbox, style, some touch handling, and accessibility
* controls.
*
* @see https://reactnative.dev/docs/view.html
* @see https://reactnative.dev/docs/view
*/
const View: React.AbstractComponent<
ViewProps,

Просмотреть файл

@ -91,5 +91,5 @@ export type AccessibilityValue = $ReadOnly<{|
/**
* A textual description of this component's value. (will override minimum, current, and maximum if set)
*/
text?: string,
text?: Stringish,
|}>;

Просмотреть файл

@ -56,8 +56,6 @@ function reportException(
isFatal: boolean,
reportToConsole: boolean, // only true when coming from handleException; the error has not yet been logged
) {
const NativeExceptionsManager = require('./NativeExceptionsManager').default;
if (NativeExceptionsManager) {
const parseErrorStack = require('./Devtools/parseErrorStack');
const stack = parseErrorStack(e?.stack);
const currentExceptionID = ++exceptionID;
@ -75,11 +73,6 @@ function reportException(
message =
e.jsEngine == null ? message : `${message}, js engine: ${e.jsEngine}`;
const isHandledByLogBox =
e.forceRedbox !== true &&
global.RN$Bridgeless !== true &&
!global.RN$Express;
const data = preprocessException({
message,
originalMessage: message === originalMessage ? null : originalMessage,
@ -92,10 +85,6 @@ function reportException(
extraData: {
jsEngine: e.jsEngine,
rawStack: e.stack,
// Hack to hide native redboxes when in the LogBox experiment.
// This is intentionally untyped and stuffed here, because it is temporary.
suppressRedBox: isHandledByLogBox,
},
});
@ -106,44 +95,18 @@ function reportException(
console.error(data.message);
}
if (__DEV__ && isHandledByLogBox) {
if (__DEV__) {
const LogBox = require('../LogBox/LogBox');
LogBox.addException({
...data,
isComponentError: !!e.isComponentError,
});
}
if (isFatal || e.type !== 'warn') {
} else if (isFatal || e.type !== 'warn') {
const NativeExceptionsManager = require('./NativeExceptionsManager')
.default;
if (NativeExceptionsManager) {
NativeExceptionsManager.reportException(data);
if (__DEV__ && !global.RN$Express) {
if (e.preventSymbolication === true) {
return;
}
const symbolicateStackTrace = require('./Devtools/symbolicateStackTrace');
symbolicateStackTrace(stack)
.then(({stack: prettyStack}) => {
if (prettyStack) {
NativeExceptionsManager.updateExceptionMessage(
data.message,
prettyStack,
currentExceptionID,
);
} else {
throw new Error('The stack is null');
}
})
.catch(error => {
console.log('Unable to symbolicate stack trace: ' + error.message);
});
}
}
} else if (reportToConsole) {
// we feed back into console.error, to make sure any methods that are
// monkey patched on top of console.error are called when coming from
// handleException
console.error(e);
}
}

Просмотреть файл

@ -12,7 +12,6 @@ export type ExtendedError = Error & {
jsEngine?: string,
preventSymbolication?: boolean,
componentStack?: string,
forceRedbox?: boolean,
isComponentError?: boolean,
type?: string,
...

Просмотреть файл

@ -12,6 +12,7 @@
const ExceptionsManager = require('../ExceptionsManager');
const NativeExceptionsManager = require('../NativeExceptionsManager').default;
const LogBox = require('../../LogBox/LogBox');
const ReactFiberErrorDialog = require('../ReactFiberErrorDialog').default;
const fs = require('fs');
const path = require('path');
@ -27,9 +28,13 @@ const capturedErrorDefaults = {
describe('ExceptionsManager', () => {
let nativeReportException;
let logBoxAddException;
beforeEach(() => {
jest.resetModules();
jest.mock('../../LogBox/LogBox', () => ({
addException: jest.fn(),
}));
jest.mock('../NativeExceptionsManager', () => {
return {
default: {
@ -49,6 +54,7 @@ describe('ExceptionsManager', () => {
);
jest.spyOn(console, 'error').mockReturnValue(undefined);
nativeReportException = NativeExceptionsManager.reportException;
logBoxAddException = LogBox.addException;
});
afterEach(() => {
@ -66,6 +72,11 @@ describe('ExceptionsManager', () => {
error,
});
if (__DEV__) {
expect(nativeReportException.mock.calls.length).toBe(0);
expect(logBoxAddException.mock.calls.length).toBe(1);
return;
}
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
const formattedMessage =
@ -101,8 +112,15 @@ describe('ExceptionsManager', () => {
error,
});
let exceptionData;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(1);
exceptionData = logBoxAddException.mock.calls[0][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
exceptionData = nativeReportException.mock.calls[0][0];
}
expect(getLineFromFrame(exceptionData.stack[0])).toBe(
"const error = new Error('Some error happened');",
);
@ -119,8 +137,15 @@ describe('ExceptionsManager', () => {
error,
});
let exceptionData;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(1);
exceptionData = logBoxAddException.mock.calls[0][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
exceptionData = nativeReportException.mock.calls[0][0];
}
expect(exceptionData.message).toBe(
'Error: ' +
message +
@ -149,8 +174,15 @@ describe('ExceptionsManager', () => {
error: message,
});
let exceptionData;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(1);
exceptionData = logBoxAddException.mock.calls[0][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
exceptionData = nativeReportException.mock.calls[0][0];
}
const formattedMessage =
message +
'\n\n' +
@ -173,8 +205,15 @@ describe('ExceptionsManager', () => {
error: null,
});
let exceptionData;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(1);
exceptionData = logBoxAddException.mock.calls[0][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
exceptionData = nativeReportException.mock.calls[0][0];
}
const formattedMessage =
'Unspecified error' +
'\n\n' +
@ -200,8 +239,15 @@ describe('ExceptionsManager', () => {
error,
});
let exceptionData;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(1);
exceptionData = logBoxAddException.mock.calls[0][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
exceptionData = nativeReportException.mock.calls[0][0];
}
expect(getLineFromFrame(exceptionData.stack[0])).toBe(
"const error = Object.freeze(new Error('Some error happened'));",
);
@ -216,8 +262,12 @@ describe('ExceptionsManager', () => {
error,
});
if (__DEV__) {
expect(logBoxAddException).toHaveBeenCalled();
} else {
expect(nativeReportException).toHaveBeenCalled();
expect(error.message).toBe(message);
}
});
test('can safely process the same error multiple times', () => {
@ -230,6 +280,7 @@ describe('ExceptionsManager', () => {
];
for (const componentStack of componentStacks) {
nativeReportException.mockClear();
logBoxAddException.mockClear();
const formattedMessage =
'ReferenceError: ' +
message +
@ -242,8 +293,15 @@ describe('ExceptionsManager', () => {
error,
});
let exceptionData;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(1);
exceptionData = logBoxAddException.mock.calls[0][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
exceptionData = nativeReportException.mock.calls[0][0];
}
expect(exceptionData.message).toBe(formattedMessage);
expect(exceptionData.originalMessage).toBe(message);
expect(exceptionData.componentStack).toBe(componentStack);
@ -281,8 +339,15 @@ describe('ExceptionsManager', () => {
console.error(error);
let exceptionData;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(1);
exceptionData = logBoxAddException.mock.calls[0][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
exceptionData = nativeReportException.mock.calls[0][0];
}
const formattedMessage = 'Error: ' + message;
expect(exceptionData.message).toBe(formattedMessage);
expect(exceptionData.originalMessage).toBe(message);
@ -301,8 +366,15 @@ describe('ExceptionsManager', () => {
console.error(message);
let exceptionData;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(1);
exceptionData = logBoxAddException.mock.calls[0][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
exceptionData = nativeReportException.mock.calls[0][0];
}
expect(exceptionData.message).toBe('console.error: Some error happened');
expect(exceptionData.originalMessage).toBe('Some error happened');
expect(exceptionData.name).toBe('console.error');
@ -318,8 +390,15 @@ describe('ExceptionsManager', () => {
console.error(...args);
let exceptionData;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(1);
exceptionData = logBoxAddException.mock.calls[0][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
exceptionData = nativeReportException.mock.calls[0][0];
}
expect(exceptionData.message).toBe(
'console.error: 42 true ["symbol" failed to stringify] {"y":null}',
);
@ -367,7 +446,11 @@ describe('ExceptionsManager', () => {
console.error(...args);
if (__DEV__) {
expect(logBoxAddException).toHaveBeenCalled();
} else {
expect(nativeReportException).toHaveBeenCalled();
}
});
test('does not log "warn"-type errors', () => {
@ -399,8 +482,15 @@ describe('ExceptionsManager', () => {
console.error(error);
let exceptionData;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(1);
exceptionData = logBoxAddException.mock.calls[0][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
exceptionData = nativeReportException.mock.calls[0][0];
}
expect(getLineFromFrame(exceptionData.stack[0])).toBe(
"const error = new Error('Some error happened');",
);
@ -414,8 +504,15 @@ describe('ExceptionsManager', () => {
ExceptionsManager.handleException(error, true);
let exceptionData;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(1);
exceptionData = logBoxAddException.mock.calls[0][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
exceptionData = nativeReportException.mock.calls[0][0];
}
const formattedMessage = 'Error: ' + message;
expect(exceptionData.message).toBe(formattedMessage);
expect(exceptionData.originalMessage).toBe(message);
@ -434,8 +531,15 @@ describe('ExceptionsManager', () => {
ExceptionsManager.handleException(error, false);
let exceptionData;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(1);
exceptionData = logBoxAddException.mock.calls[0][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
exceptionData = nativeReportException.mock.calls[0][0];
}
const formattedMessage = 'Error: ' + message;
expect(exceptionData.message).toBe(formattedMessage);
expect(exceptionData.originalMessage).toBe(message);
@ -453,8 +557,15 @@ describe('ExceptionsManager', () => {
ExceptionsManager.handleException(message, true);
let exceptionData;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(1);
exceptionData = logBoxAddException.mock.calls[0][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
exceptionData = nativeReportException.mock.calls[0][0];
}
expect(exceptionData.message).toBe(message);
expect(exceptionData.originalMessage).toBe(null);
expect(exceptionData.name).toBe(null);
@ -473,8 +584,15 @@ describe('ExceptionsManager', () => {
ExceptionsManager.handleException(error, true);
let exceptionData;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(1);
exceptionData = logBoxAddException.mock.calls[0][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(1);
const exceptionData = nativeReportException.mock.calls[0][0];
exceptionData = nativeReportException.mock.calls[0][0];
}
expect(getLineFromFrame(exceptionData.stack[0])).toBe(
"const error = new Error('Some error happened');",
);
@ -486,7 +604,11 @@ describe('ExceptionsManager', () => {
ExceptionsManager.handleException(error, true);
if (__DEV__) {
expect(logBoxAddException).toHaveBeenCalled();
} else {
expect(nativeReportException).toHaveBeenCalled();
}
});
});
@ -520,19 +642,30 @@ describe('ExceptionsManager', () => {
ExceptionsManager.unstable_setExceptionDecorator(decorator);
ExceptionsManager.handleException(error, true);
expect(nativeReportException.mock.calls.length).toBe(2);
expect(decorator.mock.calls.length).toBe(1);
const withoutDecoratorInstalled = nativeReportException.mock.calls[0][0];
const afterDecorator = nativeReportException.mock.calls[1][0];
const beforeDecorator = decorator.mock.calls[0][0];
let withoutDecoratorInstalled;
let afterDecorator;
if (__DEV__) {
expect(logBoxAddException.mock.calls.length).toBe(2);
withoutDecoratorInstalled = logBoxAddException.mock.calls[0][0];
afterDecorator = logBoxAddException.mock.calls[1][0];
} else {
expect(nativeReportException.mock.calls.length).toBe(2);
withoutDecoratorInstalled = nativeReportException.mock.calls[0][0];
afterDecorator = nativeReportException.mock.calls[1][0];
}
expect(afterDecorator.id).toEqual(beforeDecorator.id);
// id will change between successive exceptions
delete withoutDecoratorInstalled.id;
delete beforeDecorator.id;
delete afterDecorator.id;
delete withoutDecoratorInstalled.isComponentError;
delete afterDecorator.isComponentError;
expect(withoutDecoratorInstalled).toEqual(beforeDecorator);
expect(afterDecorator).toEqual({
@ -553,7 +686,11 @@ describe('ExceptionsManager', () => {
ExceptionsManager.handleException(error, true);
expect(decorator).not.toHaveBeenCalled();
if (__DEV__) {
expect(logBoxAddException).toHaveBeenCalled();
} else {
expect(nativeReportException).toHaveBeenCalled();
}
});
test('prevents decorator recursion from error handler', () => {
@ -569,10 +706,17 @@ describe('ExceptionsManager', () => {
ExceptionsManager.unstable_setExceptionDecorator(decorator);
ExceptionsManager.handleException(error, true);
if (__DEV__) {
expect(logBoxAddException).toHaveBeenCalledTimes(1);
expect(logBoxAddException.mock.calls[0][0].message).toMatch(
/decorated: .*Some error happened/,
);
} else {
expect(nativeReportException).toHaveBeenCalledTimes(1);
expect(nativeReportException.mock.calls[0][0].message).toMatch(
/decorated: .*Some error happened/,
);
}
expect(mockError).toHaveBeenCalledTimes(2);
expect(mockError.mock.calls[0][0]).toMatch(
/Logging an error within the decorator/,
@ -595,6 +739,15 @@ describe('ExceptionsManager', () => {
ExceptionsManager.unstable_setExceptionDecorator(decorator);
console.error(error);
if (__DEV__) {
expect(logBoxAddException).toHaveBeenCalledTimes(2);
expect(logBoxAddException.mock.calls[0][0].message).toMatch(
/Logging an error within the decorator/,
);
expect(logBoxAddException.mock.calls[1][0].message).toMatch(
/decorated: .*Some error happened/,
);
} else {
expect(nativeReportException).toHaveBeenCalledTimes(2);
expect(nativeReportException.mock.calls[0][0].message).toMatch(
/Logging an error within the decorator/,
@ -602,6 +755,7 @@ describe('ExceptionsManager', () => {
expect(nativeReportException.mock.calls[1][0].message).toMatch(
/decorated: .*Some error happened/,
);
}
expect(mockError).toHaveBeenCalledTimes(2);
// console.error calls are chained without exception pre-processing, so decorator doesn't apply
expect(mockError.mock.calls[0][0].toString()).toMatch(
@ -621,11 +775,19 @@ describe('ExceptionsManager', () => {
ExceptionsManager.unstable_setExceptionDecorator(decorator);
ExceptionsManager.handleException(error, true);
if (__DEV__) {
expect(logBoxAddException).toHaveBeenCalledTimes(1);
// Exceptions in decorators are ignored and the decorator is not applied
expect(logBoxAddException.mock.calls[0][0].message).toMatch(
/Error: Some error happened/,
);
} else {
expect(nativeReportException).toHaveBeenCalledTimes(1);
// Exceptions in decorators are ignored and the decorator is not applied
expect(nativeReportException.mock.calls[0][0].message).toMatch(
/Error: Some error happened/,
);
}
expect(mockError).toHaveBeenCalledTimes(1);
expect(mockError.mock.calls[0][0]).toMatch(/Error: Some error happened/);
});
@ -639,11 +801,19 @@ describe('ExceptionsManager', () => {
ExceptionsManager.unstable_setExceptionDecorator(decorator);
console.error(error);
if (__DEV__) {
expect(logBoxAddException).toHaveBeenCalledTimes(1);
// Exceptions in decorators are ignored and the decorator is not applied
expect(logBoxAddException.mock.calls[0][0].message).toMatch(
/Error: Some error happened/,
);
} else {
expect(nativeReportException).toHaveBeenCalledTimes(1);
// Exceptions in decorators are ignored and the decorator is not applied
expect(nativeReportException.mock.calls[0][0].message).toMatch(
/Error: Some error happened/,
);
}
expect(mockError).toHaveBeenCalledTimes(1);
expect(mockError.mock.calls[0][0].toString()).toMatch(
/Error: Some error happened/,

Просмотреть файл

@ -14,10 +14,6 @@
* Sets up global variables for React Native.
* You can use this module directly, or just require InitializeCore.
*/
if (global.GLOBAL === undefined) {
global.GLOBAL = global;
}
if (global.window === undefined) {
// $FlowFixMe[cannot-write]
global.window = global;

Просмотреть файл

@ -100,7 +100,6 @@ export function reportLogBoxError(
): void {
const ExceptionsManager = require('../../Core/ExceptionsManager');
error.forceRedbox = true;
error.message = `${LOGBOX_ERROR_MESSAGE}\n\n${error.message}`;
if (componentStack != null) {
error.componentStack = componentStack;

Просмотреть файл

@ -676,7 +676,6 @@ describe('LogBoxData', () => {
const receivedError = ExceptionsManager.handleException.mock.calls[0][0];
expect(receivedError.componentStack).toBe(' in Component (file.js:1)');
expect(receivedError.forceRedbox).toBe(true);
expect(receivedError.message).toBe(
'An error was thrown when attempting to render log messages via LogBox.\n\nSimulated Error',
);
@ -689,7 +688,6 @@ describe('LogBoxData', () => {
const receivedError = ExceptionsManager.handleException.mock.calls[0][0];
expect(receivedError.componentStack).toBeUndefined();
expect(receivedError.forceRedbox).toBe(true);
expect(receivedError.message).toBe(
'An error was thrown when attempting to render log messages via LogBox.\n\nSimulated Error',
);

Просмотреть файл

@ -27,6 +27,15 @@ describe('<Modal />', () => {
expect(instance).toMatchSnapshot();
});
it('should not render its children when mocked with visible=false', () => {
const instance = render.create(
<Modal visible={false}>
<View testID="child" />
</Modal>,
);
expect(instance.root.findAllByProps({testID: 'child'})).toHaveLength(0);
});
it('should shallow render as <Modal> when mocked', () => {
const output = render.shallow(
<Modal>

Просмотреть файл

@ -13,7 +13,7 @@ exports[`<Modal /> should render as <RCTModalHostView> when not mocked 1`] = `
<RCTModalHostView
animationType="none"
hardwareAccelerated={false}
identifier={1}
identifier={4}
onDismiss={[Function]}
onStartShouldSetResponder={[Function]}
presentationStyle="fullScreen"

Просмотреть файл

@ -44,7 +44,8 @@ export type PermissionType =
| 'android.permission.WRITE_EXTERNAL_STORAGE'
| 'android.permission.BLUETOOTH_CONNECT'
| 'android.permission.BLUETOOTH_SCAN'
| 'android.permission.BLUETOOTH_ADVERTISE';
| 'android.permission.BLUETOOTH_ADVERTISE'
| 'android.permission.ACCESS_MEDIA_LOCATION';
*/
export interface Spec extends TurboModule {

Просмотреть файл

@ -62,6 +62,7 @@ const PERMISSIONS = Object.freeze({
BLUETOOTH_CONNECT: 'android.permission.BLUETOOTH_CONNECT',
BLUETOOTH_SCAN: 'android.permission.BLUETOOTH_SCAN',
BLUETOOTH_ADVERTISE: 'android.permission.BLUETOOTH_ADVERTISE',
ACCESS_MEDIA_LOCATION: 'android.permission.ACCESS_MEDIA_LOCATION',
});
/**
@ -75,6 +76,7 @@ class PermissionsAndroid {
ACCESS_BACKGROUND_LOCATION: string,
ACCESS_COARSE_LOCATION: string,
ACCESS_FINE_LOCATION: string,
ACCESS_MEDIA_LOCATION: string,
ADD_VOICEMAIL: string,
BLUETOOTH_ADVERTISE: string,
BLUETOOTH_CONNECT: string,

Просмотреть файл

@ -189,8 +189,10 @@ const AppRegistry = {
displayMode?: number,
): void {
if (appKey !== 'LogBox') {
const msg =
'Running "' + appKey + '" with ' + JSON.stringify(appParameters);
const logParams = __DEV__
? '" with ' + JSON.stringify(appParameters)
: '';
const msg = 'Running "' + appKey + logParams;
infoLog(msg);
BugReporting.addSource(
'AppRegistry.runApplication' + runCount++,

Просмотреть файл

@ -1 +1 @@
e8feb11b62e869804970258fa629922edbfc836b
afcb9cdc9343ddc134b03dcf4d7fbc0810b6002b

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -297,16 +297,18 @@ static RCTUIColor *defaultPlaceholderColor() // TODO(OSS Candidate ISS#2710739)
_textWasPasted = YES;
}
#if !TARGET_OS_OSX // TODO(macOS GH#774)
// Turn off scroll animation to fix flaky scrolling.
// This is only necessary for iOS <= 13.
// TODO(macOS GH#774) - we may not need to check for !TARGET_OS_OSX if __IPHONE_OS_VERSION_MAX_ALLOWED is defined,
// but it shouldn't hurt to do so for clarity's sake.
#if !TARGET_OS_OSX && defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < 140000
- (void)setContentOffset:(CGPoint)contentOffset animated:(__unused BOOL)animated
{
// Turning off scroll animation.
// This fixes the problem also known as "flaky scrolling".
[super setContentOffset:contentOffset animated:NO];
}
#endif // [TODO(macOS GH#774)
#endif
#if TARGET_OS_OSX
#if TARGET_OS_OSX // [TODO(macOS GH#774)
#pragma mark - Placeholder

Просмотреть файл

@ -47,7 +47,6 @@ Pod::Spec.new do |s|
s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags
s.header_dir = "React"
s.framework = "JavaScriptCore"
s.library = "stdc++"
s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/RCT-Folly\" \"${PODS_ROOT}/Headers/Public/React-hermes\" \"${PODS_ROOT}/Headers/Public/hermes-engine\"", "DEFINES_MODULE" => "YES" }
s.user_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/Headers/Private/React-Core\""}
s.default_subspec = "Default"

Просмотреть файл

@ -0,0 +1,24 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RCTAccessibilityManager.h"
#import <React/RCTDefines.h>
NS_ASSUME_NONNULL_BEGIN
RCT_EXTERN_C_BEGIN
// Only to be used for testing and internal tooling. Do not use this in
// production.
void RCTAccessibilityManagerSetIsVoiceOverEnabled(
RCTAccessibilityManager *accessibiltyManager,
BOOL isVoiceOverEnabled);
RCT_EXTERN_C_END
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -6,6 +6,7 @@
*/
#import "RCTAccessibilityManager.h"
#import "RCTAccessibilityManager+Internal.h"
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTBridge.h>
@ -185,9 +186,14 @@ RCT_EXPORT_MODULE()
- (void)voiceVoiceOverStatusDidChange:(__unused NSNotification *)notification
{
BOOL newIsVoiceOverEnabled = UIAccessibilityIsVoiceOverRunning();
if (_isVoiceOverEnabled != newIsVoiceOverEnabled) {
_isVoiceOverEnabled = newIsVoiceOverEnabled;
BOOL isVoiceOverEnabled = UIAccessibilityIsVoiceOverRunning();
[self _setIsVoiceOverEnabled:isVoiceOverEnabled];
}
- (void)_setIsVoiceOverEnabled:(BOOL)isVoiceOverEnabled
{
if (_isVoiceOverEnabled != isVoiceOverEnabled) {
_isVoiceOverEnabled = isVoiceOverEnabled;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[[_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"screenReaderChanged"
@ -352,6 +358,15 @@ RCT_EXPORT_METHOD(getCurrentVoiceOverState
return std::make_shared<facebook::react::NativeAccessibilityManagerSpecJSI>(params);
}
#pragma mark - Internal
void RCTAccessibilityManagerSetIsVoiceOverEnabled(
RCTAccessibilityManager *accessibilityManager,
BOOL isVoiceOverEnabled)
{
[accessibilityManager _setIsVoiceOverEnabled:isVoiceOverEnabled];
}
@end
@implementation RCTBridge (RCTAccessibilityManager)

Просмотреть файл

@ -128,7 +128,9 @@ RCT_EXPORT_MODULE(Appearance)
RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSString *, getColorScheme)
{
#if !TARGET_OS_OSX // [TODO(macOS GH#774)
if (_currentColorScheme == nil) {
_currentColorScheme = RCTColorSchemePreference(nil);
}
#endif // ]TODO(macOS GH#774)
return _currentColorScheme;
}

Просмотреть файл

@ -35,15 +35,10 @@ RCT_EXPORT_MODULE()
return self;
}
- (void)reportSoft:(NSString *)message
stack:(NSArray<NSDictionary *> *)stack
exceptionId:(double)exceptionId
suppressRedBox:(BOOL)suppressRedBox
- (void)reportSoft:(NSString *)message stack:(NSArray<NSDictionary *> *)stack exceptionId:(double)exceptionId
{
if (!suppressRedBox) {
RCTRedBox *redbox = [_moduleRegistry moduleForName:"RedBox"];
[redbox showErrorMessage:message withStack:stack errorCookie:(int)exceptionId];
}
if (_delegate) {
[_delegate handleSoftJSExceptionWithMessage:message
@ -52,15 +47,10 @@ RCT_EXPORT_MODULE()
}
}
- (void)reportFatal:(NSString *)message
stack:(NSArray<NSDictionary *> *)stack
exceptionId:(double)exceptionId
suppressRedBox:(BOOL)suppressRedBox
- (void)reportFatal:(NSString *)message stack:(NSArray<NSDictionary *> *)stack exceptionId:(double)exceptionId
{
if (!suppressRedBox) {
RCTRedBox *redbox = [_moduleRegistry moduleForName:"RedBox"];
[redbox showErrorMessage:message withStack:stack errorCookie:(int)exceptionId];
}
if (_delegate) {
[_delegate handleFatalJSExceptionWithMessage:message
@ -72,7 +62,7 @@ RCT_EXPORT_MODULE()
if (!RCT_DEBUG && reloadRetries < _maxReloadAttempts) {
reloadRetries++;
RCTTriggerReloadCommandListeners(@"JS Crash Reload");
} else if (!RCT_DEV || !suppressRedBox) {
} else if (!RCT_DEV) {
NSString *description = [@"Unhandled JS Exception: " stringByAppendingString:message];
NSDictionary *errorInfo = @{NSLocalizedDescriptionKey : description, RCTJSStackTraceKey : stack};
RCTFatal([NSError errorWithDomain:RCTErrorDomain code:0 userInfo:errorInfo]);
@ -84,7 +74,7 @@ RCT_EXPORT_METHOD(reportSoftException
: (NSArray<NSDictionary *> *)stack exceptionId
: (double)exceptionId)
{
[self reportSoft:message stack:stack exceptionId:exceptionId suppressRedBox:NO];
[self reportSoft:message stack:stack exceptionId:exceptionId];
}
RCT_EXPORT_METHOD(reportFatalException
@ -92,7 +82,7 @@ RCT_EXPORT_METHOD(reportFatalException
: (NSArray<NSDictionary *> *)stack exceptionId
: (double)exceptionId)
{
[self reportFatal:message stack:stack exceptionId:exceptionId suppressRedBox:NO];
[self reportFatal:message stack:stack exceptionId:exceptionId];
}
RCT_EXPORT_METHOD(updateExceptionMessage
@ -120,7 +110,6 @@ RCT_EXPORT_METHOD(reportException : (JS::NativeExceptionsManager::ExceptionData
{
NSString *message = data.message();
double exceptionId = data.id_();
id<NSObject> extraData = data.extraData();
// Reserialize data.stack() into an array of untyped dictionaries.
// TODO: (moti) T53588496 Replace `(NSArray<NSDictionary *> *)stack` in
@ -141,13 +130,11 @@ RCT_EXPORT_METHOD(reportException : (JS::NativeExceptionsManager::ExceptionData
}
[stackArray addObject:frameDict];
}
NSDictionary *dict = (NSDictionary *)extraData;
BOOL suppressRedBox = [[dict objectForKey:@"suppressRedBox"] boolValue];
if (data.isFatal()) {
[self reportFatal:message stack:stackArray exceptionId:exceptionId suppressRedBox:suppressRedBox];
[self reportFatal:message stack:stackArray exceptionId:exceptionId];
} else {
[self reportSoft:message stack:stackArray exceptionId:exceptionId suppressRedBox:suppressRedBox];
[self reportSoft:message stack:stackArray exceptionId:exceptionId];
}
}

Просмотреть файл

@ -156,9 +156,6 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
auto eventEmitter = [self modalEventEmitter];
if (eventEmitter) {
eventEmitter->onShow(ModalHostViewEventEmitter::OnShow{});
// A hack so that EventEmitter.cpp's eventTarget_ does not become null when modal is dismissed
eventEmitter->setEnabled(true);
}
}];
}

Просмотреть файл

@ -498,6 +498,11 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg
}
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[self _handleFinishedScrolling:scrollView];
}
- (void)_handleFinishedScrolling:(UIScrollView *)scrollView
{
[self _forceDispatchNextScrollEvent];
[self scrollViewDidScroll:scrollView];
@ -710,6 +715,12 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg
}
[_scrollView setContentOffset:offset animated:animated];
if (!animated) {
// When not animated, the expected workflow in ``scrollViewDidEndScrollingAnimation`` after scrolling is not going
// to get triggered. We will need to manually execute here.
[self _handleFinishedScrolling:_scrollView];
}
}
- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated

Просмотреть файл

@ -36,7 +36,6 @@ Pod::Spec.new do |s|
s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags
s.header_dir = "React"
s.framework = "JavaScriptCore"
s.library = "stdc++"
s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/Headers/Private/React-Core\"" }
s.xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/glog\" \"$(PODS_ROOT)/RCT-Folly\"",
"OTHER_CFLAGS" => "$(inherited) -DRN_FABRIC_ENABLED" + " " + folly_flags }

Просмотреть файл

@ -31,7 +31,8 @@ rn_xplat_cxx_library(
],
headers = ["HermesSamplingProfiler.h"],
header_namespace = "",
compiler_flags = ["-fexceptions"],
compiler_flags_enable_exceptions = True, # TODO: is this necessary?
compiler_flags_enable_rtti = True, # TODO: is this necessary?
labels = ["supermodule:xplat/default/public.react_native.infra"],
platforms = ANDROID,
soname = "libjsijniprofiler.$(ext)",

Просмотреть файл

@ -91,6 +91,7 @@ public class ReactContext extends ContextWrapper {
/** Initialize message queue threads using a ReactQueueConfiguration. */
public synchronized void initializeMessageQueueThreads(ReactQueueConfiguration queueConfig) {
FLog.w(TAG, "initializeMessageQueueThreads() is called.");
if (mUiMessageQueueThread != null
|| mNativeModulesMessageQueueThread != null
|| mJSMessageQueueThread != null) {

Просмотреть файл

@ -11,12 +11,6 @@ rn_xplat_cxx_library(
],
prefix = "react/common/mapbuffer",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
fbandroid_allow_jni_merging = True,
labels = ["supermodule:xplat/default/public.react_native.infra"],
platforms = ANDROID,

Просмотреть файл

@ -103,4 +103,6 @@ public class ReactFeatureFlags {
public static boolean enableScrollViewSnapToAlignmentProp = true;
public static boolean useDispatchUniqueForCoalescableEvents = false;
public static boolean useUpdatedTouchPreprocessing = false;
}

Просмотреть файл

@ -16,7 +16,6 @@ import com.facebook.react.bridge.NativeMap;
import com.facebook.react.bridge.ReadableNativeMap;
import com.facebook.react.bridge.RuntimeExecutor;
import com.facebook.react.bridge.RuntimeScheduler;
import com.facebook.react.bridge.queue.MessageQueueThread;
import com.facebook.react.fabric.events.EventBeatManager;
import com.facebook.react.fabric.events.EventEmitterWrapper;
import com.facebook.react.uimanager.PixelUtil;
@ -42,7 +41,6 @@ public class Binding {
RuntimeScheduler runtimeScheduler,
Object uiManager,
EventBeatManager eventBeatManager,
MessageQueueThread jsMessageQueueThread,
ComponentFactory componentsRegistry,
Object reactNativeConfig);
@ -89,7 +87,6 @@ public class Binding {
@Nullable RuntimeScheduler runtimeScheduler,
@NonNull FabricUIManager fabricUIManager,
@NonNull EventBeatManager eventBeatManager,
@NonNull MessageQueueThread jsMessageQueueThread,
@NonNull ComponentFactory componentFactory,
@NonNull ReactNativeConfig reactNativeConfig) {
fabricUIManager.setBinding(this);
@ -98,7 +95,6 @@ public class Binding {
runtimeScheduler,
fabricUIManager,
eventBeatManager,
jsMessageQueueThread,
componentFactory,
reactNativeConfig);

Просмотреть файл

@ -11,7 +11,6 @@ import androidx.annotation.NonNull;
import com.facebook.react.bridge.JSIModuleProvider;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.UIManager;
import com.facebook.react.bridge.queue.MessageQueueThread;
import com.facebook.react.common.mapbuffer.ReadableMapBufferSoLoader;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.fabric.events.EventBeatManager;
@ -41,24 +40,20 @@ public class FabricJSIModuleProvider implements JSIModuleProvider<UIManager> {
Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "FabricJSIModuleProvider.get");
final EventBeatManager eventBeatManager = new EventBeatManager(mReactApplicationContext);
final FabricUIManager uiManager = createUIManager(eventBeatManager);
Systrace.beginSection(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "FabricJSIModuleProvider.registerBinding");
final Binding binding = new Binding();
if (ReactFeatureFlags.enableEagerInitializeMapBufferSoFile) {
ReadableMapBufferSoLoader.staticInit();
}
MessageQueueThread jsMessageQueueThread =
mReactApplicationContext
.getCatalystInstance()
.getReactQueueConfiguration()
.getJSQueueThread();
binding.register(
mReactApplicationContext.getCatalystInstance().getRuntimeExecutor(),
mReactApplicationContext.getCatalystInstance().getRuntimeScheduler(),
uiManager,
eventBeatManager,
jsMessageQueueThread,
mComponentFactory,
mConfig);

Просмотреть файл

@ -54,7 +54,6 @@ import com.facebook.react.common.build.ReactBuildConfig;
import com.facebook.react.common.mapbuffer.ReadableMapBuffer;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.fabric.events.EventBeatManager;
import com.facebook.react.fabric.events.EventCategoryDef;
import com.facebook.react.fabric.events.EventEmitterWrapper;
import com.facebook.react.fabric.events.FabricEventEmitter;
import com.facebook.react.fabric.mounting.MountItemDispatcher;
@ -78,6 +77,7 @@ import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIManagerHelper;
import com.facebook.react.uimanager.ViewManagerPropertyUpdater;
import com.facebook.react.uimanager.ViewManagerRegistry;
import com.facebook.react.uimanager.events.EventCategoryDef;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.uimanager.events.EventDispatcherImpl;
import com.facebook.react.uimanager.events.LockFreeEventDispatcherImpl;
@ -628,6 +628,15 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
public int getSurfaceId() {
return View.NO_ID;
}
@Override
public String toString() {
String propsString =
IS_DEVELOPMENT_ENVIRONMENT
? (props != null ? props.toHashMap().toString() : "<null>")
: "<hidden>";
return String.format("SYNC UPDATE PROPS [%d]: %s", reactTag, propsString);
}
};
// If the reactTag exists, we assume that it might at the end of the next
@ -1016,6 +1025,11 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
public int getSurfaceId() {
return surfaceId;
}
@Override
public String toString() {
return String.format("SET_JS_RESPONDER [%d] [surface:%d]", reactTag, surfaceId);
}
});
}
@ -1035,6 +1049,11 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
public int getSurfaceId() {
return View.NO_ID;
}
@Override
public String toString() {
return "CLEAR_JS_RESPONDER";
}
});
}

Просмотреть файл

@ -16,6 +16,7 @@ import com.facebook.react.bridge.NativeMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.fabric.FabricSoLoader;
import com.facebook.react.uimanager.events.EventCategoryDef;
/**
* This class holds reference to the C++ EventEmitter object. Instances of this class are created on

Просмотреть файл

@ -22,6 +22,7 @@ import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.fabric.FabricUIManager;
import com.facebook.react.uimanager.events.EventCategoryDef;
import com.facebook.react.uimanager.events.RCTModernEventEmitter;
import com.facebook.react.uimanager.events.TouchEventType;
import com.facebook.systrace.Systrace;
@ -46,7 +47,7 @@ public class FabricEventEmitter implements RCTModernEventEmitter {
@Override
public void receiveEvent(
int surfaceId, int reactTag, String eventName, @Nullable WritableMap params) {
receiveEvent(surfaceId, reactTag, eventName, false, 0, params);
receiveEvent(surfaceId, reactTag, eventName, false, 0, params, EventCategoryDef.UNSPECIFIED);
}
@Override
@ -56,37 +57,46 @@ public class FabricEventEmitter implements RCTModernEventEmitter {
String eventName,
boolean canCoalesceEvent,
int customCoalesceKey,
@Nullable WritableMap params) {
@Nullable WritableMap params,
@EventCategoryDef int category) {
Systrace.beginSection(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
"FabricEventEmitter.receiveEvent('" + eventName + "')");
mUIManager.receiveEvent(
surfaceId, reactTag, eventName, canCoalesceEvent, customCoalesceKey, params);
surfaceId, reactTag, eventName, canCoalesceEvent, customCoalesceKey, params, category);
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
}
/**
* Processes touches in a JS compatible way and send it to Fabric core
*
* @param eventName the event name (see {@link TouchEventType})
* @param touches all the touch data extracted from MotionEvent
* @param changedIndices the indices of the pointers that changed (MOVE/CANCEL includes all
* touches, START/END only the one that was added/removed)
*/
@Override
public void receiveTouches(
@NonNull String eventTopLevelType,
@NonNull String eventName,
@NonNull WritableArray touches,
@NonNull WritableArray changedIndices) {
Systrace.beginSection(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
"FabricEventEmitter.receiveTouches('" + eventTopLevelType + "')");
"FabricEventEmitter.receiveTouches('" + eventName + "')");
boolean isPointerEndEvent =
TouchEventType.END.getJsName().equalsIgnoreCase(eventTopLevelType)
|| TouchEventType.CANCEL.getJsName().equalsIgnoreCase(eventTopLevelType);
boolean isFinalEvent =
TouchEventType.END.getJsName().equalsIgnoreCase(eventName)
|| TouchEventType.CANCEL.getJsName().equalsIgnoreCase(eventName);
Pair<WritableArray, WritableArray> result =
isPointerEndEvent
isFinalEvent
? removeTouchesAtIndices(touches, changedIndices)
: touchSubsequence(touches, changedIndices);
WritableArray changedTouches = result.first;
touches = result.second;
int eventCategory = getTouchCategory(eventTopLevelType);
int eventCategory = getTouchCategory(eventName);
for (int jj = 0; jj < changedTouches.size(); jj++) {
WritableMap touch = getWritableMap(changedTouches.getMap(jj));
// Touch objects can fulfill the role of `DOM` `Event` objects if we set
@ -104,8 +114,7 @@ public class FabricEventEmitter implements RCTModernEventEmitter {
rootNodeID = targetReactTag;
}
mUIManager.receiveEvent(
targetSurfaceId, rootNodeID, eventTopLevelType, false, 0, touch, eventCategory);
receiveEvent(targetSurfaceId, rootNodeID, eventName, false, 0, touch, eventCategory);
}
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);

Просмотреть файл

@ -11,12 +11,8 @@ rn_xplat_cxx_library(
],
prefix = "react/fabric",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
compiler_flags_enable_exceptions = True,
compiler_flags_enable_rtti = True, # dynamic_cast used within Binding.cpp
fbandroid_allow_jni_merging = True,
labels = ["supermodule:xplat/default/public.react_native.infra"],
platforms = ANDROID,

Просмотреть файл

@ -243,8 +243,9 @@ Binding::getInspectorDataForInstance(
}
EventEmitterWrapper *cEventEmitter = cthis(eventEmitterWrapper);
InspectorData data =
scheduler->getInspectorDataForInstance(cEventEmitter->eventEmitter);
InspectorData data = scheduler->getInspectorDataForInstance(
enableEventEmitterRawPointer_ ? *cEventEmitter->eventEmitterPointer
: *cEventEmitter->eventEmitter);
folly::dynamic result = folly::dynamic::object;
result["fileName"] = data.fileName;
@ -497,7 +498,6 @@ void Binding::installFabricUIManager(
jni::alias_ref<JRuntimeScheduler::javaobject> runtimeSchedulerHolder,
jni::alias_ref<jobject> javaUIManager,
EventBeatManager *eventBeatManager,
jni::alias_ref<JavaMessageQueueThread::javaobject> jsMessageQueueThread,
ComponentFactory *componentsRegistry,
jni::alias_ref<jobject> reactNativeConfig) {
SystraceSection s("FabricUIManagerBinding::installFabricUIManager");
@ -511,6 +511,9 @@ void Binding::installFabricUIManager(
disableRevisionCheckForPreallocation_ =
config->getBool("react_fabric:disable_revision_check_for_preallocation");
enableEventEmitterRawPointer_ =
config->getBool("react_fabric:enable_event_emitter_wrapper_raw_pointer");
if (enableFabricLogs_) {
LOG(WARNING) << "Binding::installFabricUIManager() was called (address: "
<< this << ").";
@ -528,8 +531,6 @@ void Binding::installFabricUIManager(
ContextContainer::Shared contextContainer =
std::make_shared<ContextContainer>();
auto sharedJSMessageQueueThread =
std::make_shared<JMessageQueueThread>(jsMessageQueueThread);
auto runtimeExecutor = runtimeExecutorHolder->cthis()->get();
if (runtimeSchedulerHolder) {
@ -645,16 +646,19 @@ inline local_ref<ReadableArray::javaobject> castReadableArray(
// TODO: this method will be removed when binding for components are code-gen
local_ref<JString> getPlatformComponentName(const ShadowView &shadowView) {
local_ref<JString> componentName;
auto newViewProps =
std::dynamic_pointer_cast<const ScrollViewProps>(shadowView.props);
static std::string scrollViewComponentName = std::string("ScrollView");
if (newViewProps &&
newViewProps->getProbablyMoreHorizontalThanVertical_DEPRECATED()) {
local_ref<JString> componentName;
if (scrollViewComponentName.compare(shadowView.componentName) == 0) {
auto newViewProps =
std::static_pointer_cast<const ScrollViewProps>(shadowView.props);
if (newViewProps->getProbablyMoreHorizontalThanVertical_DEPRECATED()) {
componentName = make_jstring("AndroidHorizontalScrollView");
} else {
componentName = make_jstring(shadowView.componentName);
return componentName;
}
}
componentName = make_jstring(shadowView.componentName);
return componentName;
}
@ -920,8 +924,11 @@ void Binding::schedulerDidFinishTransaction(
mountItem.newChildShadowView.eventEmitter;
auto javaEventEmitter = EventEmitterWrapper::newObjectJavaArgs();
EventEmitterWrapper *cEventEmitter = cthis(javaEventEmitter);
if (enableEventEmitterRawPointer_) {
cEventEmitter->eventEmitterPointer = eventEmitter.get();
} else {
cEventEmitter->eventEmitter = eventEmitter;
}
temp[0] = mountItem.newChildShadowView.tag;
temp[1] = isLayoutable;
env->SetIntArrayRegion(intBufferArray, intBufferPosition, 2, temp);
@ -1071,7 +1078,11 @@ void Binding::schedulerDidFinishTransaction(
// Do not hold a reference to javaEventEmitter from the C++ side.
auto javaEventEmitter = EventEmitterWrapper::newObjectJavaArgs();
EventEmitterWrapper *cEventEmitter = cthis(javaEventEmitter);
if (enableEventEmitterRawPointer_) {
cEventEmitter->eventEmitterPointer = eventEmitter.get();
} else {
cEventEmitter->eventEmitter = eventEmitter;
}
(*objBufferArray)[objBufferPosition++] = javaEventEmitter.get();
}
@ -1198,9 +1209,13 @@ void Binding::preallocateShadowView(
if (eventEmitter != nullptr) {
javaEventEmitter = EventEmitterWrapper::newObjectJavaArgs();
EventEmitterWrapper *cEventEmitter = cthis(javaEventEmitter);
if (enableEventEmitterRawPointer_) {
cEventEmitter->eventEmitterPointer = eventEmitter.get();
} else {
cEventEmitter->eventEmitter = eventEmitter;
}
}
}
local_ref<ReadableMap::javaobject> props = castReadableMap(
ReadableNativeMap::newObjectCxxArgs(shadowView.props->rawProps));

Просмотреть файл

@ -8,7 +8,6 @@
#pragma once
#include <fbjni/fbjni.h>
#include <react/jni/JMessageQueueThread.h>
#include <react/jni/JRuntimeExecutor.h>
#include <react/jni/JRuntimeScheduler.h>
#include <react/jni/ReadableNativeMap.h>
@ -109,7 +108,6 @@ class Binding : public jni::HybridClass<Binding>,
jni::alias_ref<JRuntimeScheduler::javaobject> runtimeSchedulerHolder,
jni::alias_ref<jobject> javaUIManager,
EventBeatManager *eventBeatManager,
jni::alias_ref<JavaMessageQueueThread::javaobject> jsMessageQueueThread,
ComponentFactory *componentsRegistry,
jni::alias_ref<jobject> reactNativeConfig);
@ -202,6 +200,7 @@ class Binding : public jni::HybridClass<Binding>,
bool enableFabricLogs_{false};
bool enableEarlyEventEmitterUpdate_{false};
bool disableRevisionCheckForPreallocation_{false};
bool enableEventEmitterRawPointer_{false};
};
} // namespace react

Просмотреть файл

@ -22,6 +22,15 @@ void EventEmitterWrapper::invokeEvent(
std::string eventName,
NativeMap *payload,
int category) {
if (eventEmitterPointer) {
eventEmitterPointer->dispatchEvent(
std::move(eventName),
payload->consume(),
EventPriority::AsynchronousBatched,
static_cast<RawEvent::Category>(category));
return;
}
// It is marginal, but possible for this to be constructed without a valid
// EventEmitter. In those cases, make sure we noop/blackhole events instead of
// crashing.
@ -38,6 +47,11 @@ void EventEmitterWrapper::invokeUniqueEvent(
std::string eventName,
NativeMap *payload,
int customCoalesceKey) {
if (eventEmitterPointer) {
eventEmitterPointer->dispatchUniqueEvent(
std::move(eventName), payload->consume());
return;
}
// TODO: customCoalesceKey currently unused
// It is marginal, but possible for this to be constructed without a valid
// EventEmitter. In those cases, make sure we noop/blackhole events instead of

Просмотреть файл

@ -24,6 +24,7 @@ class EventEmitterWrapper : public jni::HybridClass<EventEmitterWrapper> {
static void registerNatives();
SharedEventEmitter eventEmitter;
EventEmitter const *eventEmitterPointer;
void invokeEvent(std::string eventName, NativeMap *params, int category);
void invokeUniqueEvent(

Просмотреть файл

@ -226,8 +226,12 @@ public class IntBufferBatchMountItem implements MountItem {
: "<hidden>";
s.append(String.format("UPDATE PROPS [%d]: %s\n", mIntBuffer[i++], propsString));
} else if (type == INSTRUCTION_UPDATE_STATE) {
j += 1;
s.append(String.format("UPDATE STATE [%d]\n", mIntBuffer[i++]));
StateWrapper state = castToState(mObjBuffer[j++]);
String stateString =
IS_DEVELOPMENT_ENVIRONMENT
? (state != null ? state.getStateData().toString() : "<null>")
: "<hidden>";
s.append(String.format("UPDATE STATE [%d]: %s\n", mIntBuffer[i++], stateString));
} else if (type == INSTRUCTION_UPDATE_LAYOUT) {
s.append(
String.format(

Просмотреть файл

@ -20,7 +20,8 @@ rn_xplat_cxx_library(
srcs = glob(["*.cpp"]),
headers = glob(["*.h"]),
header_namespace = "",
compiler_flags = ["-fexceptions"],
compiler_flags_enable_exceptions = True, # TODO: is this necessary?
compiler_flags_enable_rtti = True, # TODO: is this necessary?
fbandroid_allow_jni_merging = True,
platforms = ANDROID,
soname = "libjscexecutor.$(ext)",

Просмотреть файл

@ -5,12 +5,6 @@ rn_xplat_cxx_library(
srcs = glob(["*.cpp"]),
headers = glob(["*.h"]),
header_namespace = "",
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
labels = ["supermodule:xplat/default/public.react_native.infra"],
platforms = ANDROID,
soname = "libreactnativeblob.$(ext)",

Просмотреть файл

@ -65,19 +65,8 @@ public class ExceptionsManagerModule extends NativeExceptionsManagerSpec {
public void reportException(ReadableMap data) {
String message = data.hasKey("message") ? data.getString("message") : "";
ReadableArray stack = data.hasKey("stack") ? data.getArray("stack") : Arguments.createArray();
int id = data.hasKey("id") ? data.getInt("id") : -1;
boolean isFatal = data.hasKey("isFatal") ? data.getBoolean("isFatal") : false;
if (mDevSupportManager.getDevSupportEnabled()) {
boolean suppressRedBox = false;
if (data.getMap("extraData") != null && data.getMap("extraData").hasKey("suppressRedBox")) {
suppressRedBox = data.getMap("extraData").getBoolean("suppressRedBox");
}
if (!suppressRedBox) {
mDevSupportManager.showNewJSError(message, stack, id);
}
} else {
String extraDataAsJson = ExceptionDataHelper.getExtraDataAsJson(data);
if (isFatal) {
throw new JavascriptException(JSStackTrace.format(message, stack))
@ -89,7 +78,6 @@ public class ExceptionsManagerModule extends NativeExceptionsManagerSpec {
}
}
}
}
@Override
public void updateExceptionMessage(

Просмотреть файл

@ -59,7 +59,7 @@ import javax.lang.model.util.Types;
/**
* This annotation processor crawls subclasses of ReactShadowNode and ViewManager and finds their
* exported properties with the @ReactProp or @ReactGroupProp annotation. It generates a class per
* shadow node/view manager that is named {@code <classname>$$PropSetter}. This class contains
* shadow node/view manager that is named {@code <classname>$$PropsSetter}. This class contains
* methods to retrieve the name and type of all methods and a way to set these properties without
* reflection.
*/

Просмотреть файл

@ -9,12 +9,6 @@ rn_xplat_cxx_library(
exported_headers = {
"reactperflogger/JNativeModulePerfLogger.h": "reactperflogger/JNativeModulePerfLogger.h",
},
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
fbandroid_allow_jni_merging = True,
fbandroid_labels = [
"supermodule:xplat/default/public.react_native.infra",

Просмотреть файл

@ -11,12 +11,6 @@ rn_xplat_cxx_library(
"ReactCommon/TurboModuleManager.h": "ReactCommon/TurboModuleManager.h",
"ReactCommon/TurboModuleManagerDelegate.h": "ReactCommon/TurboModuleManagerDelegate.h",
},
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
labels = ["supermodule:xplat/default/public.react_native.infra"],
platforms = ANDROID,
preprocessor_flags = [
@ -49,12 +43,6 @@ rn_xplat_cxx_library(
exported_headers = {
"ReactCommon/CallInvokerHolder.h": "ReactCommon/CallInvokerHolder.h",
},
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
fbandroid_deps = [
FBJNI_TARGET,
],

Просмотреть файл

@ -182,7 +182,6 @@ public class TouchTargetHelper {
eventCoords[0] = childPoint.x;
eventCoords[1] = childPoint.y;
View targetView = findTouchTargetViewWithPointerEvents(eventCoords, child, pathAccumulator);
if (targetView != null) {
// We don't allow touches on views that are outside the bounds of an `overflow: hidden`
// View
@ -196,6 +195,9 @@ public class TouchTargetHelper {
}
if (inOverflowBounds) {
return targetView;
} else if (pathAccumulator != null) {
// Not a hit, reset the path found so far
pathAccumulator.clear();
}
}
eventCoords[0] = restoreX;

Просмотреть файл

@ -182,6 +182,11 @@ public abstract class Event<T extends Event> {
return null;
}
@EventCategoryDef
protected int getEventCategory() {
return EventCategoryDef.UNSPECIFIED;
}
/**
* Dispatch this event to JS using a V2 EventEmitter. If surfaceId is not -1 and `getEventData` is
* non-null, this will use the RCTModernEventEmitter API. Otherwise, it falls back to the
@ -192,7 +197,7 @@ public abstract class Event<T extends Event> {
if (getSurfaceId() != -1) {
WritableMap eventData = getEventData();
if (eventData != null) {
rctEventEmitter.receiveEvent(getSurfaceId(), getViewTag(), getEventName(), getEventData());
rctEventEmitter.receiveEvent(getSurfaceId(), getViewTag(), getEventName(), eventData);
return;
}
}
@ -215,7 +220,8 @@ public abstract class Event<T extends Event> {
getEventName(),
canCoalesce(),
getCoalescingKey(),
eventData);
eventData,
getEventCategory());
return;
}
}

Просмотреть файл

@ -5,13 +5,13 @@
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.fabric.events;
package com.facebook.react.uimanager.events;
import static com.facebook.react.fabric.events.EventCategoryDef.CONTINUOUS;
import static com.facebook.react.fabric.events.EventCategoryDef.CONTINUOUS_END;
import static com.facebook.react.fabric.events.EventCategoryDef.CONTINUOUS_START;
import static com.facebook.react.fabric.events.EventCategoryDef.DISCRETE;
import static com.facebook.react.fabric.events.EventCategoryDef.UNSPECIFIED;
import static com.facebook.react.uimanager.events.EventCategoryDef.CONTINUOUS;
import static com.facebook.react.uimanager.events.EventCategoryDef.CONTINUOUS_END;
import static com.facebook.react.uimanager.events.EventCategoryDef.CONTINUOUS_START;
import static com.facebook.react.uimanager.events.EventCategoryDef.DISCRETE;
import static com.facebook.react.uimanager.events.EventCategoryDef.UNSPECIFIED;
import androidx.annotation.IntDef;

Просмотреть файл

@ -28,5 +28,6 @@ public interface RCTModernEventEmitter extends RCTEventEmitter {
String eventName,
boolean canCoalesceEvent,
int customCoalesceKey,
@Nullable WritableMap event);
@Nullable WritableMap event,
@EventCategoryDef int category);
}

Просмотреть файл

@ -64,7 +64,7 @@ public class ReactEventEmitter implements RCTModernEventEmitter {
int surfaceId, int targetTag, String eventName, @Nullable WritableMap event) {
// The two additional params here, `canCoalesceEvent` and `customCoalesceKey`, have no
// meaning outside of Fabric.
receiveEvent(surfaceId, targetTag, eventName, false, 0, event);
receiveEvent(surfaceId, targetTag, eventName, false, 0, event, EventCategoryDef.UNSPECIFIED);
}
@Override
@ -120,11 +120,18 @@ public class ReactEventEmitter implements RCTModernEventEmitter {
String eventName,
boolean canCoalesceEvent,
int customCoalesceKey,
@Nullable WritableMap event) {
@Nullable WritableMap event,
@EventCategoryDef int category) {
@UIManagerType int uiManagerType = ViewUtil.getUIManagerType(targetReactTag);
if (uiManagerType == UIManagerType.FABRIC && mFabricEventEmitter != null) {
mFabricEventEmitter.receiveEvent(
surfaceId, targetReactTag, eventName, canCoalesceEvent, customCoalesceKey, event);
surfaceId,
targetReactTag,
eventName,
canCoalesceEvent,
customCoalesceKey,
event,
category);
} else if (uiManagerType == UIManagerType.DEFAULT && getEventEmitter(targetReactTag) != null) {
mRCTEventEmitter.receiveEvent(targetReactTag, eventName, event);
} else {

Просмотреть файл

@ -13,6 +13,7 @@ import androidx.core.util.Pools;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.ReactSoftExceptionLogger;
import com.facebook.react.bridge.SoftAssertions;
import com.facebook.react.config.ReactFeatureFlags;
/**
* An event representing the start, end or movement of a touch. Corresponds to a single {@link
@ -188,18 +189,48 @@ public class TouchEvent extends Event<TouchEvent> {
"Cannot dispatch a TouchEvent that has no MotionEvent; the TouchEvent has been recycled"));
return;
}
TouchesHelper.sendTouchEvent(
rctEventEmitter,
Assertions.assertNotNull(mTouchEventType),
getSurfaceId(),
getViewTag(),
this);
TouchesHelper.sendTouchEvent(rctEventEmitter, this);
}
@Override
public void dispatchModern(RCTModernEventEmitter rctEventEmitter) {
if (ReactFeatureFlags.useUpdatedTouchPreprocessing) {
TouchesHelper.sendTouchEventModern(rctEventEmitter, this, /* useDispatchV2 */ false);
} else {
dispatch(rctEventEmitter);
}
}
@Override
public void dispatchModernV2(RCTModernEventEmitter rctEventEmitter) {
if (ReactFeatureFlags.useUpdatedTouchPreprocessing) {
TouchesHelper.sendTouchEventModern(rctEventEmitter, this, /* useDispatchV2 */ true);
} else {
dispatch(rctEventEmitter);
}
}
@Override
protected int getEventCategory() {
TouchEventType type = mTouchEventType;
if (type == null) {
return EventCategoryDef.UNSPECIFIED;
}
switch (type) {
case START:
return EventCategoryDef.CONTINUOUS_START;
case END:
case CANCEL:
return EventCategoryDef.CONTINUOUS_END;
case MOVE:
return EventCategoryDef.CONTINUOUS;
}
// Something something smart compiler...
return super.getEventCategory();
}
public MotionEvent getMotionEvent() {
Assertions.assertNotNull(mMotionEvent);
@ -210,6 +241,10 @@ public class TouchEvent extends Event<TouchEvent> {
return mMotionEvent != null;
}
public TouchEventType getTouchEventType() {
return Assertions.assertNotNull(mTouchEventType);
}
public float getViewX() {
return mViewX;
}

Просмотреть файл

@ -9,13 +9,13 @@ package com.facebook.react.uimanager.events;
import android.view.MotionEvent;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactSoftExceptionLogger;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.PixelUtil;
/** Class responsible for generating catalyst touch events based on android {@link MotionEvent}. */
public class TouchesHelper {
public static final String TARGET_SURFACE_KEY = "targetSurface";
public static final String TARGET_KEY = "target";
public static final String CHANGED_TOUCHES_KEY = "changedTouches";
@ -28,15 +28,16 @@ public class TouchesHelper {
private static final String LOCATION_X_KEY = "locationX";
private static final String LOCATION_Y_KEY = "locationY";
private static final String TAG = "TouchesHelper";
/**
* Creates catalyst pointers array in format that is expected by RCTEventEmitter JS module from
* given {@param event} instance. This method use {@param reactTarget} parameter to set as a
* target view id associated with current gesture.
*/
private static WritableArray createsPointersArray(
int surfaceId, int reactTarget, TouchEvent event) {
WritableArray touches = Arguments.createArray();
private static WritableMap[] createPointersArray(TouchEvent event) {
MotionEvent motionEvent = event.getMotionEvent();
WritableMap[] touches = new WritableMap[motionEvent.getPointerCount()];
// Calculate the coordinates for the target view.
// The MotionEvent contains the X,Y of the touch in the coordinate space of the root view
@ -60,11 +61,12 @@ public class TouchesHelper {
float locationY = motionEvent.getY(index) - targetViewCoordinateY;
touch.putDouble(LOCATION_X_KEY, PixelUtil.toDIPFromPixel(locationX));
touch.putDouble(LOCATION_Y_KEY, PixelUtil.toDIPFromPixel(locationY));
touch.putInt(TARGET_SURFACE_KEY, surfaceId);
touch.putInt(TARGET_KEY, reactTarget);
touch.putInt(TARGET_SURFACE_KEY, event.getSurfaceId());
touch.putInt(TARGET_KEY, event.getViewTag());
touch.putDouble(TIMESTAMP_KEY, event.getTimestampMs());
touch.putDouble(POINTER_IDENTIFIER_KEY, motionEvent.getPointerId(index));
touches.pushMap(touch);
touches[index] = touch;
}
return touches;
@ -75,17 +77,12 @@ public class TouchesHelper {
* context}. Touch event can encode multiple concurrent touches (pointers).
*
* @param rctEventEmitter Event emitter used to execute JS module call
* @param type type of the touch event (see {@link TouchEventType})
* @param reactTarget target view react id associated with this gesture
* @param touchEvent native touch event to read pointers count and coordinates from
*/
public static void sendTouchEvent(
RCTEventEmitter rctEventEmitter,
TouchEventType type,
int surfaceId,
int reactTarget,
TouchEvent touchEvent) {
WritableArray pointers = createsPointersArray(surfaceId, reactTarget, touchEvent);
public static void sendTouchEvent(RCTEventEmitter rctEventEmitter, TouchEvent touchEvent) {
TouchEventType type = touchEvent.getTouchEventType();
WritableArray pointers = getWritableArray(createPointersArray(touchEvent));
MotionEvent motionEvent = touchEvent.getMotionEvent();
// For START and END events send only index of the pointer that is associated with that event
@ -103,4 +100,98 @@ public class TouchesHelper {
rctEventEmitter.receiveTouches(TouchEventType.getJSEventName(type), pointers, changedIndices);
}
/**
* Generate touch event data to match JS expectations. Combines logic in {@link #sendTouchEvent}
* and FabricEventEmitter to create the same data structure in a more efficient manner.
*
* <p>Touches have to be dispatched as separate events for each changed pointer to make JS process
* them correctly. To avoid allocations, we preprocess touch events in Java world and then convert
* them to native before dispatch.
*
* @param eventEmitter emitter to dispatch event to
* @param event the touch event to extract data from
* @param useDispatchV2 whether to dispatch additional data used by {@link Event#dispatchModernV2}
*/
public static void sendTouchEventModern(
RCTModernEventEmitter eventEmitter, TouchEvent event, boolean useDispatchV2) {
TouchEventType type = event.getTouchEventType();
MotionEvent motionEvent = event.getMotionEvent();
if (motionEvent == null) {
ReactSoftExceptionLogger.logSoftException(
TAG,
new IllegalStateException(
"Cannot dispatch a TouchEvent that has no MotionEvent; the TouchEvent has been recycled"));
return;
}
WritableMap[] touches = createPointersArray(event);
WritableMap[] changedTouches = null;
switch (type) {
case START:
int newPointerIndex = motionEvent.getActionIndex();
changedTouches = new WritableMap[] {touches[newPointerIndex].copy()};
break;
case END:
int finishedPointerIndex = motionEvent.getActionIndex();
/*
* Clear finished pointer index for compatibility with W3C touch "end" events, where the
* active touches don't include the set that has just been "ended".
*/
WritableMap finishedPointer = touches[finishedPointerIndex];
touches[finishedPointerIndex] = null;
changedTouches = new WritableMap[] {finishedPointer};
break;
case MOVE:
changedTouches = new WritableMap[touches.length];
for (int i = 0; i < touches.length; i++) {
changedTouches[i] = touches[i].copy();
}
break;
case CANCEL:
changedTouches = touches;
touches = new WritableMap[0];
break;
}
WritableArray touchesArray = getWritableArray(touches);
WritableArray changedTouchesArray = getWritableArray(/* copyObjects */ true, changedTouches);
for (WritableMap eventData : changedTouches) {
eventData.putArray(CHANGED_TOUCHES_KEY, changedTouchesArray);
eventData.putArray(TOUCHES_KEY, touchesArray);
if (useDispatchV2) {
eventEmitter.receiveEvent(
event.getSurfaceId(),
event.getViewTag(),
event.getEventName(),
event.canCoalesce(),
0,
eventData,
event.getEventCategory());
} else {
eventEmitter.receiveEvent(
event.getSurfaceId(), event.getViewTag(), event.getEventName(), eventData);
}
}
}
private static WritableArray getWritableArray(WritableMap... objects) {
return getWritableArray(false, objects);
}
private static WritableArray getWritableArray(boolean copyObjects, WritableMap... objects) {
WritableArray result = Arguments.createArray();
for (WritableMap object : objects) {
if (object != null) {
result.pushMap(copyObjects ? object.copy() : object);
}
}
return result;
}
}

Просмотреть файл

@ -11,12 +11,6 @@ rn_xplat_cxx_library(
],
prefix = "react/uimanager/jni",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
fbandroid_allow_jni_merging = True,
labels = ["supermodule:xplat/default/public.react_native.infra"],
platforms = ANDROID,

Просмотреть файл

@ -1231,8 +1231,12 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
}
super.scrollTo(x, y);
updateStateOnScroll(x, y);
setPendingContentOffsets(x, y);
// The final scroll position might be different from (x, y). For example, we may need to scroll
// to the last item in the list, but that item cannot be move to the start position of the view.
final int actualX = getScrollX();
final int actualY = getScrollY();
updateStateOnScroll(actualX, actualY);
setPendingContentOffsets(actualX, actualY);
}
/**

Просмотреть файл

@ -1006,8 +1006,12 @@ public class ReactScrollView extends ScrollView
@Override
public void scrollTo(int x, int y) {
super.scrollTo(x, y);
updateStateOnScroll(x, y);
setPendingContentOffsets(x, y);
// The final scroll position might be different from (x, y). For example, we may need to scroll
// to the last item in the list, but that item cannot be move to the start position of the view.
final int actualX = getScrollX();
final int actualY = getScrollY();
updateStateOnScroll(actualX, actualY);
setPendingContentOffsets(actualX, actualY);
}
/**

Просмотреть файл

@ -766,13 +766,13 @@ public class ReactViewGroup extends ViewGroup
child.getElevation() > 0 && ReactFeatureFlags.insertZReorderBarriersOnViewGroupChildren;
if (drawWithZ) {
CanvasUtil.enableZ(canvas, false);
CanvasUtil.enableZ(canvas, true);
}
boolean result = super.drawChild(canvas, child, drawingTime);
if (drawWithZ) {
CanvasUtil.enableZ(canvas, true);
CanvasUtil.enableZ(canvas, false);
}
return result;
}
@ -786,6 +786,7 @@ public class ReactViewGroup extends ViewGroup
}
break;
case ViewProps.HIDDEN:
case ViewProps.SCROLL:
float left = 0f;
float top = 0f;
float right = getWidth();

Просмотреть файл

@ -35,14 +35,11 @@ rn_xplat_cxx_library(
header_namespace = "react/jni",
exported_headers = EXPORTED_HEADERS,
compiler_flags = [
"-Wall",
"-Werror",
"-fexceptions",
"-std=c++1y",
"-frtti",
"-Wno-pessimizing-move",
"-Wno-inconsistent-missing-override",
],
compiler_flags_enable_exceptions = True,
compiler_flags_enable_rtti = True, # dynamic_cast used within ReadableNative*
fbandroid_allow_jni_merging = True,
labels = ["supermodule:xplat/default/public.react_native.infra"],
platforms = ANDROID,

Просмотреть файл

@ -3,10 +3,6 @@ load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "react_native_xplat_target
rn_xplat_cxx_library(
name = "perftests",
srcs = ["OnLoad.cpp"],
compiler_flags = [
"-fexceptions",
"-std=c++1y",
],
platforms = ANDROID,
soname = "libnativereactperftests.$(ext)",
visibility = [

Просмотреть файл

@ -32,7 +32,6 @@ Pod::Spec.new do |s|
s.platforms = { :ios => "11.0" }
s.source = source
s.source_files = "dummyFile.cpp"
s.library = "stdc++"
s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES",
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17" }

Просмотреть файл

@ -29,12 +29,6 @@ rn_xplat_cxx_library(
],
prefix = "better",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
fbobjc_compiler_flags = APPLE_COMPILER_FLAGS,
fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(),
force_static = True,

Просмотреть файл

@ -10,12 +10,6 @@ rn_xplat_cxx_library(
],
prefix = "ReactCommon",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
labels = ["supermodule:xplat/default/public.react_native.infra"],
platforms = (ANDROID, APPLE, CXX),
preferred_linkage = "static",

Просмотреть файл

@ -1,11 +1,6 @@
load("@fbsource//tools/build_defs:glob_defs.bzl", "subdir_glob")
load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "get_android_inspector_flags", "get_apple_compiler_flags", "get_apple_inspector_flags", "get_preprocessor_flags_for_build_mode", "react_native_xplat_target", "rn_xplat_cxx_library")
CXX_LIBRARY_COMPILER_FLAGS = [
"-std=c++17",
"-Wall",
]
rn_xplat_cxx_library(
name = "module",
header_namespace = "",
@ -17,7 +12,6 @@ rn_xplat_cxx_library(
],
prefix = "cxxreact",
),
compiler_flags = CXX_LIBRARY_COMPILER_FLAGS,
fbobjc_compiler_flags = get_apple_compiler_flags(),
force_static = True,
labels = ["supermodule:xplat/default/public.react_native.infra"],
@ -39,10 +33,6 @@ rn_xplat_cxx_library(
[("", "JSBigString.h")],
prefix = "cxxreact",
),
compiler_flags = CXX_LIBRARY_COMPILER_FLAGS + [
"-fexceptions",
"-frtti",
],
fbobjc_compiler_flags = get_apple_compiler_flags(),
force_static = True,
labels = ["supermodule:xplat/default/public.react_native.infra"],
@ -61,9 +51,8 @@ rn_xplat_cxx_library(
srcs = ["SampleCxxModule.cpp"],
header_namespace = "",
exported_headers = ["SampleCxxModule.h"],
compiler_flags = CXX_LIBRARY_COMPILER_FLAGS + [
compiler_flags = [
"-fno-omit-frame-pointer",
"-fexceptions",
],
fbobjc_compiler_flags = get_apple_compiler_flags(),
labels = ["supermodule:xplat/default/public.react_native.infra"],
@ -120,10 +109,6 @@ rn_xplat_cxx_library(
)
for header in CXXREACT_PUBLIC_HEADERS
]),
compiler_flags = CXX_LIBRARY_COMPILER_FLAGS + [
"-fexceptions",
"-frtti",
],
fbandroid_preprocessor_flags = get_android_inspector_flags(),
fbobjc_compiler_flags = get_apple_compiler_flags(),
fbobjc_force_static = True,

Просмотреть файл

@ -14,11 +14,6 @@ rn_xplat_cxx_library(
],
compiler_flags = [
"-O3",
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
"-Werror",
"-Wextra",
"-Wcast-qual",
"-Wdelete-non-virtual-dtor",
@ -45,10 +40,6 @@ rn_xplat_cxx_library(
exported_headers = [
"jsi/JSIDynamic.h",
],
compiler_flags = [
"-fexceptions",
"-frtti",
],
fbobjc_force_static = True,
labels = ["supermodule:xplat/default/public.react_native.infra"],
visibility = [

Просмотреть файл

@ -26,11 +26,6 @@ rn_xplat_cxx_library(
],
prefix = "jsinspector",
),
compiler_flags = [
"-Wall",
"-fexceptions",
"-std=c++1y",
],
fbandroid_preferred_linkage = "shared",
labels = ["supermodule:xplat/default/public.react_native.infra"],
platforms = (ANDROID, APPLE, CXX, FBCODE, WINDOWS),

Просмотреть файл

@ -26,11 +26,6 @@ rn_xplat_cxx_library(
],
prefix = "logger",
),
compiler_flags = [
"-Wall",
"-fexceptions",
"-std=c++17",
],
fbandroid_preferred_linkage = "shared",
labels = ["supermodule:xplat/default/public.react_native.infra"],
platforms = (ANDROID, APPLE, CXX, FBCODE, WINDOWS),

Просмотреть файл

@ -18,12 +18,6 @@ rn_xplat_cxx_library(
],
prefix = "react/config",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
fbobjc_compiler_flags = APPLE_COMPILER_FLAGS,
fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(),
force_static = True,

Просмотреть файл

@ -29,12 +29,6 @@ rn_xplat_cxx_library(
],
prefix = "react/debug",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
exported_platform_linker_flags = [
(
"^android.*",

Просмотреть файл

@ -13,10 +13,6 @@ rn_xplat_cxx_library(
prefix = "ReactCommon",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
"-Wno-global-constructors",
],
fbandroid_deps = [
@ -35,7 +31,6 @@ rn_xplat_cxx_library(
],
),
fbobjc_compiler_flags = [
"-Wall",
"-fobjc-arc-exceptions",
],
fbobjc_inherited_buck_flags = get_static_library_ios_flags(),

Просмотреть файл

@ -12,12 +12,6 @@ rn_xplat_cxx_library(
],
prefix = "ReactCommon",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
fbandroid_deps = [
react_native_target("jni/react/jni:jni"),
FBJNI_TARGET,
@ -34,7 +28,6 @@ rn_xplat_cxx_library(
],
),
fbobjc_compiler_flags = [
"-Wall",
"-fobjc-arc-exceptions",
],
fbobjc_inherited_buck_flags = get_static_library_ios_flags(),

Просмотреть файл

@ -32,10 +32,6 @@ rn_xplat_cxx_library(
prefix = "react/renderer/animations",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
"-lm",
],
fbobjc_compiler_flags = APPLE_COMPILER_FLAGS,

Просмотреть файл

@ -31,12 +31,6 @@ rn_xplat_cxx_library(
],
prefix = "react/renderer/attributedstring",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
fbandroid_deps = [
react_native_xplat_target("react/renderer/mapbuffer:mapbuffer"),
],

Просмотреть файл

@ -30,12 +30,6 @@ rn_xplat_cxx_library(
],
prefix = "react/renderer/componentregistry",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
fbobjc_compiler_flags = APPLE_COMPILER_FLAGS,
fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(),
force_static = True,

Просмотреть файл

@ -29,12 +29,6 @@ rn_xplat_cxx_library(
],
prefix = "react/renderer/componentregistry/native",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
fbobjc_compiler_flags = APPLE_COMPILER_FLAGS,
fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(),
force_static = True,

Просмотреть файл

@ -29,12 +29,6 @@ rn_xplat_cxx_library(
],
prefix = "react/renderer/components/image",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
fbandroid_deps = [
react_native_xplat_target("react/renderer/mapbuffer:mapbuffer"),
],

Просмотреть файл

@ -7,7 +7,6 @@
#pragma once
#include <react/debug/react_native_assert.h>
#include <react/renderer/components/image/ImageShadowNode.h>
#include <react/renderer/core/ConcreteComponentDescriptor.h>
#include <react/renderer/imagemanager/ImageManager.h>
@ -29,7 +28,6 @@ class ImageComponentDescriptor final
void adopt(ShadowNode::Unshared const &shadowNode) const override {
ConcreteComponentDescriptor::adopt(shadowNode);
react_native_assert(std::dynamic_pointer_cast<ImageShadowNode>(shadowNode));
auto imageShadowNode =
std::static_pointer_cast<ImageShadowNode>(shadowNode);

Просмотреть файл

@ -24,12 +24,6 @@ rn_xplat_cxx_library(
],
prefix = "react/renderer/components/inputaccessory",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
fbobjc_compiler_flags = APPLE_COMPILER_FLAGS,
fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(),
force_static = True,

Просмотреть файл

@ -23,13 +23,9 @@ class InputAccessoryComponentDescriptor final
using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
void adopt(ShadowNode::Unshared const &shadowNode) const override {
react_native_assert(
std::dynamic_pointer_cast<InputAccessoryShadowNode>(shadowNode));
auto concreteShadowNode =
std::static_pointer_cast<InputAccessoryShadowNode>(shadowNode);
react_native_assert(std::dynamic_pointer_cast<YogaLayoutableShadowNode>(
concreteShadowNode));
auto layoutableShadowNode =
std::static_pointer_cast<YogaLayoutableShadowNode>(concreteShadowNode);

Просмотреть файл

@ -27,12 +27,6 @@ rn_xplat_cxx_library(
],
prefix = "react/renderer/components/legacyviewmanagerinterop",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
fbobjc_compiler_flags = APPLE_COMPILER_FLAGS,
fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(),
force_static = True,

Просмотреть файл

@ -31,12 +31,6 @@ rn_xplat_cxx_library(
],
prefix = "react/renderer/components/modal",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
fbandroid_deps = [
react_native_xplat_target("react/renderer/mapbuffer:mapbuffer"),
],

Просмотреть файл

@ -8,7 +8,6 @@
#pragma once
#include <glog/logging.h>
#include <react/debug/react_native_assert.h>
#include <react/renderer/components/modal/ModalHostViewShadowNode.h>
#include <react/renderer/core/ConcreteComponentDescriptor.h>
@ -25,13 +24,9 @@ class ModalHostViewComponentDescriptor final
using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
void adopt(ShadowNode::Unshared const &shadowNode) const override {
react_native_assert(
std::dynamic_pointer_cast<ModalHostViewShadowNode>(shadowNode));
auto modalShadowNode =
std::static_pointer_cast<ModalHostViewShadowNode>(shadowNode);
react_native_assert(
std::dynamic_pointer_cast<YogaLayoutableShadowNode>(modalShadowNode));
auto layoutableShadowNode =
std::static_pointer_cast<YogaLayoutableShadowNode>(modalShadowNode);

Просмотреть файл

@ -32,12 +32,6 @@ rn_xplat_cxx_library(
],
prefix = "react/renderer/components/progressbar",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++17",
"-Wall",
],
cxx_tests = [":tests"],
fbandroid_deps = [
react_native_target("jni/react/jni:jni"),

Просмотреть файл

@ -7,7 +7,6 @@
#pragma once
#include <react/debug/react_native_assert.h>
#include <react/renderer/core/ConcreteComponentDescriptor.h>
#include "AndroidProgressBarMeasurementsManager.h"
#include "AndroidProgressBarShadowNode.h"
@ -31,8 +30,6 @@ class AndroidProgressBarComponentDescriptor final
void adopt(ShadowNode::Unshared const &shadowNode) const override {
ConcreteComponentDescriptor::adopt(shadowNode);
react_native_assert(
std::dynamic_pointer_cast<AndroidProgressBarShadowNode>(shadowNode));
auto androidProgressBarShadowNode =
std::static_pointer_cast<AndroidProgressBarShadowNode>(shadowNode);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше