Merge commit '8595f3f22c31e245b7b6b34ec8de011534803a74' into 0.67-merge-latest

This commit is contained in:
Adam Gleitman 2022-05-03 14:23:05 -07:00
Родитель 8ed6a5538b 8595f3f22c
Коммит bc18692ac1
117 изменённых файлов: 3561 добавлений и 1726 удалений

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

@ -558,6 +558,32 @@ jobs:
- store_test_results: - store_test_results:
path: ./reports/junit path: ./reports/junit
# -------------------------
# JOBS: Test Android Template
# -------------------------
test_android_template:
executor: reactnativeandroid
steps:
- checkout
- run_yarn
- run:
name: Setup the Android Template
command: |
cd template
sed -i 's/1000\.0\.0/file\:\.\./g' package.json
npm install
# react-native-community/cli is needed as the Android template is referencing a .gradle file inside it.
npm i @react-native-community/cli
- run:
name: Bundle the latest version of ReactAndroid
command: ./gradlew :ReactAndroid:publishReleasePublicationToNpmRepository
- run:
name: Build the template application
command: cd template/android/ && ./gradlew assembleDebug
# ------------------------- # -------------------------
# JOBS: Test Docker # JOBS: Test Docker
# ------------------------- # -------------------------
@ -715,6 +741,19 @@ jobs:
git config --global user.name "npm Deployment Script" git config --global user.name "npm Deployment Script"
echo "machine github.com login react-native-bot password $GITHUB_TOKEN" > ~/.netrc echo "machine github.com login react-native-bot password $GITHUB_TOKEN" > ~/.netrc
- run: node ./scripts/publish-npm.js << parameters.publish_npm_args >> - run: node ./scripts/publish-npm.js << parameters.publish_npm_args >>
- when:
condition:
equal: [ --dry-run, << parameters.publish_npm_args >> ]
steps:
- run:
name: Build release package as a job artifact
command: |
mkdir -p build
FILENAME=$(npm pack)
mv $FILENAME build/
- store_artifacts:
path: ~/react-native/build/
destination: build
# ------------------------- # -------------------------
# JOBS: Nightly # JOBS: Nightly
@ -746,6 +785,11 @@ workflows:
branches: branches:
# TODO(macOS GH#774): disable this test which is redundant to Azure Devops test and it requires a CCI plan with resource-class:large. # TODO(macOS GH#774): disable this test which is redundant to Azure Devops test and it requires a CCI plan with resource-class:large.
ignore: /.*/ ignore: /.*/
- test_android_template:
filters:
branches:
# TODO(macOS GH#774): disable this test which is redundant to Azure Devops test and it requires a CCI plan with resource-class:large.
ignore: /.*/
- test_ios: - test_ios:
name: test_ios_unit_jsc name: test_ios_unit_jsc
run_unit_tests: true run_unit_tests: true
@ -811,6 +855,16 @@ workflows:
# Only act on version tags. # Only act on version tags.
tags: tags:
only: /v[0-9]+(\.[0-9]+)*(\-rc(\.[0-9]+)?)?/ only: /v[0-9]+(\.[0-9]+)*(\-rc(\.[0-9]+)?)?/
- publish_npm_package:
# Build a release package on every untagged commit, but do not publish to npm.
name: build_commit_package
publish_npm_args: --dry-run
filters:
branches:
only:
- main
tags:
ignore: /v[0-9]+(\.[0-9]+)*(\-rc(\.[0-9]+)?)?/
analysis: analysis:
jobs: jobs:

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

@ -79,4 +79,4 @@ untyped-import
untyped-type-import untyped-type-import
[version] [version]
^0.159.0 ^0.160.2

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

@ -82,4 +82,4 @@ untyped-import
untyped-type-import untyped-type-import
[version] [version]
^0.159.0 ^0.160.2

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

@ -1,6 +1,7 @@
load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native")
load("//tools/build_defs/apple:config_utils_defs.bzl", "STATIC_LIBRARY_APPLETVOS_CONFIG", "fbobjc_configs")
load("//tools/build_defs/apple:fb_apple_test.bzl", "fb_apple_test") load("//tools/build_defs/apple:fb_apple_test.bzl", "fb_apple_test")
load("//tools/build_defs/apple:flag_defs.bzl", "get_objc_arc_preprocessor_flags", "get_preprocessor_flags_for_build_mode", "get_static_library_ios_flags") load("//tools/build_defs/apple:flag_defs.bzl", "get_base_appletvos_flags", "get_objc_arc_preprocessor_flags", "get_preprocessor_flags_for_build_mode", "get_static_library_ios_flags")
load("//tools/build_defs/apple/plugins:plugin_defs.bzl", "plugin") load("//tools/build_defs/apple/plugins:plugin_defs.bzl", "plugin")
load("//tools/build_defs/oss:metro_defs.bzl", "rn_library") load("//tools/build_defs/oss:metro_defs.bzl", "rn_library")
load( load(
@ -183,6 +184,8 @@ rn_xplat_cxx_library2(
prefix = "React", prefix = "React",
), ),
apple_sdks = (IOS, APPLETVOS), apple_sdks = (IOS, APPLETVOS),
appletvos_configs = fbobjc_configs(STATIC_LIBRARY_APPLETVOS_CONFIG),
appletvos_inherited_buck_flags = get_base_appletvos_flags(),
contacts = ["oncall+react_native@xmail.facebook.com"], contacts = ["oncall+react_native@xmail.facebook.com"],
fbobjc_enable_exceptions = True, fbobjc_enable_exceptions = True,
frameworks = [ frameworks = [

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

@ -47,6 +47,7 @@ const ActionSheetIOS = {
+cancelButtonIndex?: ?number, +cancelButtonIndex?: ?number,
+anchor?: ?number, +anchor?: ?number,
+tintColor?: ColorValue | ProcessedColorValue, +tintColor?: ColorValue | ProcessedColorValue,
+cancelButtonTintColor?: ColorValue | ProcessedColorValue,
+userInterfaceStyle?: string, +userInterfaceStyle?: string,
+disabledButtonIndices?: Array<number>, +disabledButtonIndices?: Array<number>,
|}, |},
@ -59,7 +60,12 @@ const ActionSheetIOS = {
invariant(typeof callback === 'function', 'Must provide a valid callback'); invariant(typeof callback === 'function', 'Must provide a valid callback');
invariant(RCTActionSheetManager, "ActionSheetManager doesn't exist"); invariant(RCTActionSheetManager, "ActionSheetManager doesn't exist");
const {tintColor, destructiveButtonIndex, ...remainingOptions} = options; const {
tintColor,
cancelButtonTintColor,
destructiveButtonIndex,
...remainingOptions
} = options;
let destructiveButtonIndices = null; let destructiveButtonIndices = null;
if (Array.isArray(destructiveButtonIndex)) { if (Array.isArray(destructiveButtonIndex)) {
@ -69,14 +75,21 @@ const ActionSheetIOS = {
} }
const processedTintColor = processColor(tintColor); const processedTintColor = processColor(tintColor);
const processedCancelButtonTintColor = processColor(cancelButtonTintColor);
invariant( invariant(
processedTintColor == null || typeof processedTintColor === 'number', processedTintColor == null || typeof processedTintColor === 'number',
'Unexpected color given for ActionSheetIOS.showActionSheetWithOptions tintColor', 'Unexpected color given for ActionSheetIOS.showActionSheetWithOptions tintColor',
); );
invariant(
processedCancelButtonTintColor == null ||
typeof processedCancelButtonTintColor === 'number',
'Unexpected color given for ActionSheetIOS.showActionSheetWithOptions cancelButtonTintColor',
);
RCTActionSheetManager.showActionSheetWithOptions( RCTActionSheetManager.showActionSheetWithOptions(
{ {
...remainingOptions, ...remainingOptions,
tintColor: processedTintColor, tintColor: processedTintColor,
cancelButtonTintColor: processedCancelButtonTintColor,
destructiveButtonIndices, destructiveButtonIndices,
}, },
callback, callback,

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

@ -22,6 +22,7 @@ export interface Spec extends TurboModule {
+cancelButtonIndex?: ?number, +cancelButtonIndex?: ?number,
+anchor?: ?number, +anchor?: ?number,
+tintColor?: ?number, +tintColor?: ?number,
+cancelButtonTintColor?: ?number,
+userInterfaceStyle?: ?string, +userInterfaceStyle?: ?string,
+disabledButtonIndices?: Array<number>, +disabledButtonIndices?: Array<number>,
|}, |},
@ -34,6 +35,7 @@ export interface Spec extends TurboModule {
+subject?: ?string, +subject?: ?string,
+anchor?: ?number, +anchor?: ?number,
+tintColor?: ?number, +tintColor?: ?number,
+cancelButtonTintColor?: ?number,
+excludedActivityTypes?: ?Array<string>, +excludedActivityTypes?: ?Array<string>,
+userInterfaceStyle?: ?string, +userInterfaceStyle?: ?string,
|}, |},

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

@ -10,10 +10,12 @@
'use strict'; 'use strict';
const Image = require('./Image'); import Image from './Image';
const React = require('react'); import * as React from 'react';
const StyleSheet = require('../StyleSheet/StyleSheet'); import StyleSheet from '../StyleSheet/StyleSheet';
const View = require('../Components/View/View'); import flattenStyle from '../StyleSheet/flattenStyle';
import View from '../Components/View/View';
import type {ImageBackgroundProps} from './ImageProps';
/** /**
* Very simple drop-in replacement for <Image> which supports nesting views. * Very simple drop-in replacement for <Image> which supports nesting views.
@ -39,7 +41,7 @@ const View = require('../Components/View/View');
* AppRegistry.registerComponent('DisplayAnImageBackground', () => DisplayAnImageBackground); * AppRegistry.registerComponent('DisplayAnImageBackground', () => DisplayAnImageBackground);
* ``` * ```
*/ */
class ImageBackground extends React.Component<$FlowFixMeProps> { class ImageBackground extends React.Component<ImageBackgroundProps> {
setNativeProps(props: Object) { setNativeProps(props: Object) {
// Work-around flow // Work-around flow
const viewRef = this._viewRef; const viewRef = this._viewRef;
@ -56,7 +58,7 @@ class ImageBackground extends React.Component<$FlowFixMeProps> {
render(): React.Node { render(): React.Node {
const {children, style, imageStyle, imageRef, ...props} = this.props; const {children, style, imageStyle, imageRef, ...props} = this.props;
const flattenedStyle = flattenStyle(style);
return ( return (
<View <View
accessibilityIgnoresInvertColors={true} accessibilityIgnoresInvertColors={true}
@ -74,8 +76,8 @@ class ImageBackground extends React.Component<$FlowFixMeProps> {
// So, we have to proxy/reapply these styles explicitly for actual <Image> component. // So, we have to proxy/reapply these styles explicitly for actual <Image> component.
// This workaround should be removed after implementing proper support of // This workaround should be removed after implementing proper support of
// intrinsic content size of the <Image>. // intrinsic content size of the <Image>.
width: style?.width, width: flattenedStyle?.width,
height: style?.height, height: flattenedStyle?.height,
}, },
imageStyle, imageStyle,
]} ]}

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

@ -15,6 +15,8 @@ import type {EdgeInsetsProp} from '../StyleSheet/EdgeInsetsPropType';
import type {ImageSource} from './ImageSource'; import type {ImageSource} from './ImageSource';
import type {ViewStyleProp, ImageStyleProp} from '../StyleSheet/StyleSheet'; import type {ViewStyleProp, ImageStyleProp} from '../StyleSheet/StyleSheet';
import type {ViewProps} from '../Components/View/ViewPropTypes'; import type {ViewProps} from '../Components/View/ViewPropTypes';
import type {Node, Ref} from 'react';
import typeof Image from './Image';
export type ImageLoadEvent = SyntheticEvent< export type ImageLoadEvent = SyntheticEvent<
$ReadOnly<{| $ReadOnly<{|
@ -176,3 +178,29 @@ export type ImageProps = {|
*/ */
tooltip?: ?string, tooltip?: ?string,
|}; |};
export type ImageBackgroundProps = $ReadOnly<{|
...ImageProps,
children?: Node,
/**
* Style applied to the outer View component
*
* See https://reactnative.dev/docs/imagebackground#style
*/
style?: ?ViewStyleProp,
/**
* Style applied to the inner Image component
*
* See https://reactnative.dev/docs/imagebackground#imagestyle
*/
imageStyle?: ?ImageStyleProp,
/**
* Allows to set a reference to the inner Image component
*
* See https://reactnative.dev/docs/imagebackground#imageref
*/
imageRef?: Ref<Image>,
|}>;

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

@ -142,7 +142,6 @@ static NSDictionary *RCTFormatLocalNotification(UILocalNotification *notificatio
return formattedLocalNotification; return formattedLocalNotification;
} }
API_AVAILABLE(ios(10.0))
static NSDictionary *RCTFormatUNNotification(UNNotification *notification) static NSDictionary *RCTFormatUNNotification(UNNotification *notification)
{ {
NSMutableDictionary *formattedNotification = [NSMutableDictionary dictionary]; NSMutableDictionary *formattedNotification = [NSMutableDictionary dictionary];

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

@ -1 +1 @@
95d762e406bd37c07693e3a5ddbd0f75289e8c3f e8feb11b62e869804970258fa629922edbfc836b

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

@ -7,7 +7,7 @@
* @noflow * @noflow
* @nolint * @nolint
* @preventMunge * @preventMunge
* @generated SignedSource<<1a3cb2d94c0721509af63438d7639b77>> * @generated SignedSource<<65d072c3d2937f89a7fadc55450af2f7>>
*/ */
'use strict'; 'use strict';
@ -2853,6 +2853,7 @@ var enableProfilerTimer = true;
var enableProfilerCommitHooks = true; var enableProfilerCommitHooks = true;
var enableLazyElements = false; var enableLazyElements = false;
var warnAboutStringRefs = false; var warnAboutStringRefs = false;
var warnOnSubscriptionInsideStartTransition = false;
var enableNewReconciler = false; var enableNewReconciler = false;
var enableLazyContextPropagation = false; var enableLazyContextPropagation = false;
@ -2903,21 +2904,25 @@ var HydratingAndUpdate =
var Visibility = var Visibility =
/* */ /* */
4096; 4096;
var LifecycleEffectMask = Passive | Update | Callback | Ref | Snapshot; // Union of all commit flags (flags with the lifetime of a particular commit) var StoreConsistency =
/* */
8192;
var LifecycleEffectMask =
Passive | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit)
var HostEffectMask = var HostEffectMask =
/* */ /* */
8191; // These are not really side effects, but we still reuse this field. 16383; // These are not really side effects, but we still reuse this field.
var Incomplete = var Incomplete =
/* */ /* */
8192; 16384;
var ShouldCapture = var ShouldCapture =
/* */ /* */
16384; 32768;
var ForceUpdateForLegacySuspense = var ForceUpdateForLegacySuspense =
/* */ /* */
32768; 65536;
// e.g. a fiber uses a passive effect (even if there are no updates on this particular render). // e.g. a fiber uses a passive effect (even if there are no updates on this particular render).
// This enables us to defer more work in the unmount case, // This enables us to defer more work in the unmount case,
// since we can defer traversing the tree during layout to look for Passive effects, // since we can defer traversing the tree during layout to look for Passive effects,
@ -2925,22 +2930,22 @@ var ForceUpdateForLegacySuspense =
var RefStatic = var RefStatic =
/* */ /* */
262144; 524288;
var LayoutStatic = var LayoutStatic =
/* */ /* */
524288; 1048576;
var PassiveStatic = var PassiveStatic =
/* */ /* */
1048576; // These flags allow us to traverse to fibers that have effects on mount 2097152; // These flags allow us to traverse to fibers that have effects on mount
// without traversing the entire tree after every commit for // without traversing the entire tree after every commit for
// double invoking // double invoking
var MountLayoutDev = var MountLayoutDev =
/* */ /* */
2097152; 4194304;
var MountPassiveDev = var MountPassiveDev =
/* */ /* */
4194304; // Groups of flags that are used in the commit phase to skip over trees that 8388608; // Groups of flags that are used in the commit phase to skip over trees that
// don't contain effects, by checking subtreeFlags. // don't contain effects, by checking subtreeFlags.
var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility
@ -4499,16 +4504,10 @@ function includesOnlyRetries(lanes) {
function includesOnlyTransitions(lanes) { function includesOnlyTransitions(lanes) {
return (lanes & TransitionLanes) === lanes; return (lanes & TransitionLanes) === lanes;
} }
function shouldTimeSlice(root, lanes) { function includesBlockingLane(root, lanes) {
if ((lanes & root.expiredLanes) !== NoLanes) {
// At least one of these lanes expired. To prevent additional starvation,
// finish rendering without yielding execution.
return false;
}
if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode) { if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode) {
// Concurrent updates by default always use time slicing. // Concurrent updates by default always use time slicing.
return true; return false;
} }
var SyncDefaultLanes = var SyncDefaultLanes =
@ -4516,7 +4515,12 @@ function shouldTimeSlice(root, lanes) {
InputContinuousLane | InputContinuousLane |
DefaultHydrationLane | DefaultHydrationLane |
DefaultLane; DefaultLane;
return (lanes & SyncDefaultLanes) === NoLanes; return (lanes & SyncDefaultLanes) !== NoLanes;
}
function includesExpiredLane(root, lanes) {
// This is a separate check from includesBlockingLane because a lane can
// expire after a render has already started.
return (lanes & root.expiredLanes) !== NoLanes;
} }
function isTransitionLane(lane) { function isTransitionLane(lane) {
return (lane & TransitionLanes) !== 0; return (lane & TransitionLanes) !== 0;
@ -5835,6 +5839,18 @@ function findCurrentUnmaskedContext(fiber) {
var LegacyRoot = 0; var LegacyRoot = 0;
var ConcurrentRoot = 1; var ConcurrentRoot = 1;
/**
* inlined Object.is polyfill to avoid requiring consumers ship their own
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
*/
function is(x, y) {
return (
(x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare
);
}
var objectIs = typeof Object.is === "function" ? Object.is : is;
var syncQueue = null; var syncQueue = null;
var includesLegacySyncCallbacks = false; var includesLegacySyncCallbacks = false;
var isFlushingSyncQueue = false; var isFlushingSyncQueue = false;
@ -5904,7 +5920,7 @@ function flushSyncCallbacks() {
return null; return null;
} }
var ReactVersion = "18.0.0-95d762e40-20210908"; var ReactVersion = "18.0.0-e8feb11b6-20210915";
var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig;
var NoTransition = 0; var NoTransition = 0;
@ -5912,18 +5928,6 @@ function requestCurrentTransition() {
return ReactCurrentBatchConfig.transition; return ReactCurrentBatchConfig.transition;
} }
/**
* inlined Object.is polyfill to avoid requiring consumers ship their own
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
*/
function is(x, y) {
return (
(x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare
);
}
var objectIs = typeof Object.is === "function" ? Object.is : is;
/** /**
* Performs equality by iterating through keys on an object and returning false * Performs equality by iterating through keys on an object and returning false
* when any key has values which are not strictly equal between the arguments. * when any key has values which are not strictly equal between the arguments.
@ -9858,19 +9862,22 @@ function findFirstSuspended(row) {
} }
var NoFlags$1 = var NoFlags$1 =
/* */ /* */
0; // Represents whether effect should fire. 0; // Represents whether effect should fire.
var HasEffect = var HasEffect =
/* */ /* */
1; // Represents the phase in which the effect (not the clean-up) fires. 1; // Represents the phase in which the effect (not the clean-up) fires.
var Insertion =
/* */
2;
var Layout = var Layout =
/* */ /* */
2; 4;
var Passive$1 = var Passive$1 =
/* */ /* */
4; 8;
var isHydrating = false; var isHydrating = false;
@ -10433,7 +10440,8 @@ function updateWorkInProgressHook() {
function createFunctionComponentUpdateQueue() { function createFunctionComponentUpdateQueue() {
return { return {
lastEffect: null lastEffect: null,
stores: null
}; };
} }
@ -10962,6 +10970,7 @@ function updateMutableSource(source, getSnapshot, subscribe) {
} }
function mountSyncExternalStore(subscribe, getSnapshot) { function mountSyncExternalStore(subscribe, getSnapshot) {
var fiber = currentlyRenderingFiber$1;
var hook = mountWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the var hook = mountWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the
// normal rules of React, and only works because store updates are // normal rules of React, and only works because store updates are
// always synchronous. // always synchronous.
@ -10985,11 +10994,43 @@ function mountSyncExternalStore(subscribe, getSnapshot) {
value: nextSnapshot, value: nextSnapshot,
getSnapshot: getSnapshot getSnapshot: getSnapshot
}; };
hook.queue = inst; hook.queue = inst; // Schedule an effect to subscribe to the store.
return useSyncExternalStore(hook, inst, subscribe, getSnapshot, nextSnapshot);
mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]); // Schedule an effect to update the mutable instance fields. We will update
// this whenever subscribe, getSnapshot, or value changes. Because there's no
// clean-up function, and we track the deps correctly, we can call pushEffect
// directly, without storing any additional state. For the same reason, we
// don't need to set a static flag, either.
// TODO: We can move this to the passive phase once we add a pre-commit
// consistency check. See the next comment.
fiber.flags |= Passive;
pushEffect(
HasEffect | Passive$1,
updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot),
undefined,
null
); // Unless we're rendering a blocking lane, schedule a consistency check. Right
// before committing, we will walk the tree and check if any of the stores
// were mutated.
var root = getWorkInProgressRoot();
if (!(root !== null)) {
throw Error(
"Expected a work-in-progress root. This is a bug in React. Please file an issue."
);
}
if (!includesBlockingLane(root, renderLanes)) {
pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
}
return nextSnapshot;
} }
function updateSyncExternalStore(subscribe, getSnapshot) { function updateSyncExternalStore(subscribe, getSnapshot) {
var fiber = currentlyRenderingFiber$1;
var hook = updateWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the var hook = updateWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the
// normal rules of React, and only works because store updates are // normal rules of React, and only works because store updates are
// always synchronous. // always synchronous.
@ -11009,69 +11050,102 @@ function updateSyncExternalStore(subscribe, getSnapshot) {
} }
var prevSnapshot = hook.memoizedState; var prevSnapshot = hook.memoizedState;
var snapshotChanged = !objectIs(prevSnapshot, nextSnapshot);
if (!objectIs(prevSnapshot, nextSnapshot)) { if (snapshotChanged) {
hook.memoizedState = nextSnapshot; hook.memoizedState = nextSnapshot;
markWorkInProgressReceivedUpdate(); markWorkInProgressReceivedUpdate();
} }
var inst = hook.queue; var inst = hook.queue;
return useSyncExternalStore(hook, inst, subscribe, getSnapshot, nextSnapshot); updateEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [
subscribe
]); // Whenever getSnapshot or subscribe changes, we need to check in the
// commit phase if there was an interleaved mutation. In concurrent mode
// this can happen all the time, but even in synchronous mode, an earlier
// effect may have mutated the store.
if (
inst.getSnapshot !== getSnapshot ||
snapshotChanged || // Check if the susbcribe function changed. We can save some memory by
// checking whether we scheduled a subscription effect above.
(workInProgressHook !== null &&
workInProgressHook.memoizedState.tag & HasEffect)
) {
fiber.flags |= Passive;
pushEffect(
HasEffect | Passive$1,
updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot),
undefined,
null
); // Unless we're rendering a blocking lane, schedule a consistency check.
// Right before committing, we will walk the tree and check if any of the
// stores were mutated.
var root = getWorkInProgressRoot();
if (!(root !== null)) {
throw Error(
"Expected a work-in-progress root. This is a bug in React. Please file an issue."
);
}
if (!includesBlockingLane(root, renderLanes)) {
pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
}
}
return nextSnapshot;
} }
function useSyncExternalStore( function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) {
hook, fiber.flags |= StoreConsistency;
inst, var check = {
subscribe, getSnapshot: getSnapshot,
getSnapshot, value: renderedSnapshot
nextSnapshot };
) { var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue;
var fiber = currentlyRenderingFiber$1;
var dispatcher = ReactCurrentDispatcher$1.current; // Track the latest getSnapshot function with a ref. This needs to be updated
// in the layout phase so we can access it during the tearing check that
// happens on subscribe.
// TODO: Circumvent SSR warning
dispatcher.useLayoutEffect( if (componentUpdateQueue === null) {
function() { componentUpdateQueue = createFunctionComponentUpdateQueue();
inst.value = nextSnapshot; currentlyRenderingFiber$1.updateQueue = componentUpdateQueue;
inst.getSnapshot = getSnapshot; // Whenever getSnapshot or subscribe changes, we need to check in the componentUpdateQueue.stores = [check];
// commit phase if there was an interleaved mutation. In concurrent mode } else {
// this can happen all the time, but even in synchronous mode, an earlier var stores = componentUpdateQueue.stores;
// effect may have mutated the store.
// TODO: Move the tearing checks to an earlier, pre-commit phase so that the
// layout effects always observe a consistent tree.
if (checkIfSnapshotChanged(inst)) { if (stores === null) {
// Force a re-render. componentUpdateQueue.stores = [check];
forceStoreRerender(fiber); } else {
} stores.push(check);
}, }
[subscribe, nextSnapshot, getSnapshot] }
); }
dispatcher.useEffect(
function() {
var handleStoreChange = function() {
// TODO: Because there is no cross-renderer API for batching updates, it's
// up to the consumer of this library to wrap their subscription event
// with unstable_batchedUpdates. Should we try to detect when this isn't
// the case and print a warning in development?
// The store changed. Check if the snapshot changed since the last time we
// read from the store.
if (checkIfSnapshotChanged(inst)) {
// Force a re-render.
forceStoreRerender(fiber);
}
}; // Check for changes right before subscribing. Subsequent changes will be
// detected in the subscription handler.
handleStoreChange(); // Subscribe to the store and return a clean-up function. function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) {
// These are updated in the passive phase
inst.value = nextSnapshot;
inst.getSnapshot = getSnapshot; // Something may have been mutated in between render and commit. This could
// have been in an event that fired before the passive effects, or it could
// have been in a layout effect. In that case, we would have used the old
// snapsho and getSnapshot values to bail out. We need to check one more time.
return subscribe(handleStoreChange); if (checkIfSnapshotChanged(inst)) {
}, // Force a re-render.
[subscribe] forceStoreRerender(fiber);
); }
return nextSnapshot; }
function subscribeToStore(fiber, inst, subscribe) {
var handleStoreChange = function() {
// The store changed. Check if the snapshot changed since the last time we
// read from the store.
if (checkIfSnapshotChanged(inst)) {
// Force a re-render.
forceStoreRerender(fiber);
}
}; // Subscribe to the store and return a clean-up function.
return subscribe(handleStoreChange);
} }
function checkIfSnapshotChanged(inst) { function checkIfSnapshotChanged(inst) {
@ -11229,6 +11303,14 @@ function updateEffect(create, deps) {
return updateEffectImpl(Passive, Passive$1, create, deps); return updateEffectImpl(Passive, Passive$1, create, deps);
} }
function mountInsertionEffect(create, deps) {
return mountEffectImpl(Update, Insertion, create, deps);
}
function updateInsertionEffect(create, deps) {
return updateEffectImpl(Update, Insertion, create, deps);
}
function mountLayoutEffect(create, deps) { function mountLayoutEffect(create, deps) {
var fiberFlags = Update; var fiberFlags = Update;
@ -11464,6 +11546,26 @@ function startTransition(setPending, callback) {
} finally { } finally {
setCurrentUpdatePriority(previousPriority); setCurrentUpdatePriority(previousPriority);
ReactCurrentBatchConfig$1.transition = prevTransition; ReactCurrentBatchConfig$1.transition = prevTransition;
{
if (
prevTransition !== 1 &&
warnOnSubscriptionInsideStartTransition &&
ReactCurrentBatchConfig$1._updatedFibers
) {
var updatedFibersCount = ReactCurrentBatchConfig$1._updatedFibers.size;
if (updatedFibersCount > 10) {
warn(
"Detected a large number of updates inside startTransition. " +
"If this is due to a subscription please re-write it to use React provided hooks. " +
"Otherwise concurrent mode guarantees are off the table."
);
}
ReactCurrentBatchConfig$1._updatedFibers.clear();
}
}
} }
} }
@ -11686,6 +11788,7 @@ var ContextOnlyDispatcher = {
useContext: throwInvalidHookError, useContext: throwInvalidHookError,
useEffect: throwInvalidHookError, useEffect: throwInvalidHookError,
useImperativeHandle: throwInvalidHookError, useImperativeHandle: throwInvalidHookError,
useInsertionEffect: throwInvalidHookError,
useLayoutEffect: throwInvalidHookError, useLayoutEffect: throwInvalidHookError,
useMemo: throwInvalidHookError, useMemo: throwInvalidHookError,
useReducer: throwInvalidHookError, useReducer: throwInvalidHookError,
@ -11754,6 +11857,12 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
checkDepsAreArrayDev(deps); checkDepsAreArrayDev(deps);
return mountImperativeHandle(ref, create, deps); return mountImperativeHandle(ref, create, deps);
}, },
useInsertionEffect: function(create, deps) {
currentHookNameInDev = "useInsertionEffect";
mountHookTypesDev();
checkDepsAreArrayDev(deps);
return mountInsertionEffect(create, deps);
},
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
currentHookNameInDev = "useLayoutEffect"; currentHookNameInDev = "useLayoutEffect";
mountHookTypesDev(); mountHookTypesDev();
@ -11859,6 +11968,11 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
updateHookTypesDev(); updateHookTypesDev();
return mountImperativeHandle(ref, create, deps); return mountImperativeHandle(ref, create, deps);
}, },
useInsertionEffect: function(create, deps) {
currentHookNameInDev = "useInsertionEffect";
updateHookTypesDev();
return mountInsertionEffect(create, deps);
},
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
currentHookNameInDev = "useLayoutEffect"; currentHookNameInDev = "useLayoutEffect";
updateHookTypesDev(); updateHookTypesDev();
@ -11962,6 +12076,11 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
updateHookTypesDev(); updateHookTypesDev();
return updateImperativeHandle(ref, create, deps); return updateImperativeHandle(ref, create, deps);
}, },
useInsertionEffect: function(create, deps) {
currentHookNameInDev = "useInsertionEffect";
updateHookTypesDev();
return updateInsertionEffect(create, deps);
},
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
currentHookNameInDev = "useLayoutEffect"; currentHookNameInDev = "useLayoutEffect";
updateHookTypesDev(); updateHookTypesDev();
@ -12065,6 +12184,11 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
updateHookTypesDev(); updateHookTypesDev();
return updateImperativeHandle(ref, create, deps); return updateImperativeHandle(ref, create, deps);
}, },
useInsertionEffect: function(create, deps) {
currentHookNameInDev = "useInsertionEffect";
updateHookTypesDev();
return updateInsertionEffect(create, deps);
},
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
currentHookNameInDev = "useLayoutEffect"; currentHookNameInDev = "useLayoutEffect";
updateHookTypesDev(); updateHookTypesDev();
@ -12173,6 +12297,12 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
mountHookTypesDev(); mountHookTypesDev();
return mountImperativeHandle(ref, create, deps); return mountImperativeHandle(ref, create, deps);
}, },
useInsertionEffect: function(create, deps) {
currentHookNameInDev = "useInsertionEffect";
warnInvalidHookAccess();
mountHookTypesDev();
return mountInsertionEffect(create, deps);
},
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
currentHookNameInDev = "useLayoutEffect"; currentHookNameInDev = "useLayoutEffect";
warnInvalidHookAccess(); warnInvalidHookAccess();
@ -12292,6 +12422,12 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
updateHookTypesDev(); updateHookTypesDev();
return updateImperativeHandle(ref, create, deps); return updateImperativeHandle(ref, create, deps);
}, },
useInsertionEffect: function(create, deps) {
currentHookNameInDev = "useInsertionEffect";
warnInvalidHookAccess();
updateHookTypesDev();
return updateInsertionEffect(create, deps);
},
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
currentHookNameInDev = "useLayoutEffect"; currentHookNameInDev = "useLayoutEffect";
warnInvalidHookAccess(); warnInvalidHookAccess();
@ -12411,6 +12547,12 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
updateHookTypesDev(); updateHookTypesDev();
return updateImperativeHandle(ref, create, deps); return updateImperativeHandle(ref, create, deps);
}, },
useInsertionEffect: function(create, deps) {
currentHookNameInDev = "useInsertionEffect";
warnInvalidHookAccess();
updateHookTypesDev();
return updateInsertionEffect(create, deps);
},
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
currentHookNameInDev = "useLayoutEffect"; currentHookNameInDev = "useLayoutEffect";
warnInvalidHookAccess(); warnInvalidHookAccess();
@ -17387,6 +17529,8 @@ function safelyDetachRef(current, nearestMountedAncestor) {
if (ref !== null) { if (ref !== null) {
if (typeof ref === "function") { if (typeof ref === "function") {
var retVal;
try { try {
if ( if (
enableProfilerTimer && enableProfilerTimer &&
@ -17395,12 +17539,12 @@ function safelyDetachRef(current, nearestMountedAncestor) {
) { ) {
try { try {
startLayoutEffectTimer(); startLayoutEffectTimer();
ref(null); retVal = ref(null);
} finally { } finally {
recordLayoutEffectDuration(current); recordLayoutEffectDuration(current);
} }
} else { } else {
ref(null); retVal = ref(null);
} }
} catch (error) { } catch (error) {
reportUncaughtErrorInDEV(error); reportUncaughtErrorInDEV(error);
@ -17625,6 +17769,16 @@ function commitHookEffectListMount(tag, finishedWork) {
var destroy = effect.destroy; var destroy = effect.destroy;
if (destroy !== undefined && typeof destroy !== "function") { if (destroy !== undefined && typeof destroy !== "function") {
var hookName = void 0;
if ((effect.tag & Layout) !== NoFlags) {
hookName = "useLayoutEffect";
} else if ((effect.tag & Insertion) !== NoFlags) {
hookName = "useInsertionEffect";
} else {
hookName = "useEffect";
}
var addendum = void 0; var addendum = void 0;
if (destroy === null) { if (destroy === null) {
@ -17633,10 +17787,13 @@ function commitHookEffectListMount(tag, finishedWork) {
"up, return undefined (or nothing)."; "up, return undefined (or nothing).";
} else if (typeof destroy.then === "function") { } else if (typeof destroy.then === "function") {
addendum = addendum =
"\n\nIt looks like you wrote useEffect(async () => ...) or returned a Promise. " + "\n\nIt looks like you wrote " +
hookName +
"(async () => ...) or returned a Promise. " +
"Instead, write the async function inside your effect " + "Instead, write the async function inside your effect " +
"and call it immediately:\n\n" + "and call it immediately:\n\n" +
"useEffect(() => {\n" + hookName +
"(() => {\n" +
" async function fetchData() {\n" + " async function fetchData() {\n" +
" // You can await here\n" + " // You can await here\n" +
" const response = await MyAPI.getData(someId);\n" + " const response = await MyAPI.getData(someId);\n" +
@ -17650,8 +17807,9 @@ function commitHookEffectListMount(tag, finishedWork) {
} }
error( error(
"An effect function must not return anything besides a function, " + "%s must not return anything besides a function, " +
"which is used for clean-up.%s", "which is used for clean-up.%s",
hookName,
addendum addendum
); );
} }
@ -18058,15 +18216,17 @@ function commitAttachRef(finishedWork) {
} // Moved outside to ensure DCE works with this flag } // Moved outside to ensure DCE works with this flag
if (typeof ref === "function") { if (typeof ref === "function") {
var retVal;
if (finishedWork.mode & ProfileMode) { if (finishedWork.mode & ProfileMode) {
try { try {
startLayoutEffectTimer(); startLayoutEffectTimer();
ref(instanceToUse); retVal = ref(instanceToUse);
} finally { } finally {
recordLayoutEffectDuration(finishedWork); recordLayoutEffectDuration(finishedWork);
} }
} else { } else {
ref(instanceToUse); retVal = ref(instanceToUse);
} }
} else { } else {
{ {
@ -18130,7 +18290,10 @@ function commitUnmount(finishedRoot, current, nearestMountedAncestor) {
tag = _effect.tag; tag = _effect.tag;
if (destroy !== undefined) { if (destroy !== undefined) {
if ((tag & Layout) !== NoFlags$1) { if (
(tag & Insertion) !== NoFlags$1 ||
(tag & Layout) !== NoFlags$1
) {
if (current.mode & ProfileMode) { if (current.mode & ProfileMode) {
startLayoutEffectTimer(); startLayoutEffectTimer();
safelyCallDestroy(current, nearestMountedAncestor, destroy); safelyCallDestroy(current, nearestMountedAncestor, destroy);
@ -18358,7 +18521,12 @@ function commitWork(current, finishedWork) {
case ForwardRef: case ForwardRef:
case MemoComponent: case MemoComponent:
case SimpleMemoComponent: { case SimpleMemoComponent: {
// Layout effects are destroyed during the mutation phase so that all commitHookEffectListUnmount(
Insertion | HasEffect,
finishedWork,
finishedWork.return
);
commitHookEffectListMount(Insertion | HasEffect, finishedWork); // Layout effects are destroyed during the mutation phase so that all
// destroy functions for all fibers are called before any create functions. // destroy functions for all fibers are called before any create functions.
// This prevents sibling component effects from interfering with each other, // This prevents sibling component effects from interfering with each other,
// e.g. a destroy function in one component should never override a ref set // e.g. a destroy function in one component should never override a ref set
@ -18368,6 +18536,7 @@ function commitWork(current, finishedWork) {
// layout hooks. (However, since we null out the `destroy` function // layout hooks. (However, since we null out the `destroy` function
// right before calling it, the behavior is already correct, so this // right before calling it, the behavior is already correct, so this
// would mostly be for modeling purposes.) // would mostly be for modeling purposes.)
if (finishedWork.mode & ProfileMode) { if (finishedWork.mode & ProfileMode) {
try { try {
startLayoutEffectTimer(); startLayoutEffectTimer();
@ -19223,13 +19392,13 @@ function requestUpdateLane(fiber) {
var isTransition = requestCurrentTransition() !== NoTransition; var isTransition = requestCurrentTransition() !== NoTransition;
if (isTransition) { if (isTransition) {
// The algorithm for assigning an update to a lane should be stable for all
// updates at the same priority within the same event. To do this, the // updates at the same priority within the same event. To do this, the
// inputs to the algorithm must be the same. // inputs to the algorithm must be the same.
// //
// The trick we use is to cache the first of each of these inputs within an // The trick we use is to cache the first of each of these inputs within an
// event. Then reset the cached values once we can be sure the event is // event. Then reset the cached values once we can be sure the event is
// over. Our heuristic for that is whenever we enter a concurrent work loop. // over. Our heuristic for that is whenever we enter a concurrent work loop.
if (currentEventTransitionLane === NoLane) { if (currentEventTransitionLane === NoLane) {
// All transitions within the same event are assigned the same lane. // All transitions within the same event are assigned the same lane.
currentEventTransitionLane = claimNextTransitionLane(); currentEventTransitionLane = claimNextTransitionLane();
@ -19559,38 +19728,26 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
// bug we're still investigating. Once the bug in Scheduler is fixed, // bug we're still investigating. Once the bug in Scheduler is fixed,
// we can remove this, since we track expiration ourselves. // we can remove this, since we track expiration ourselves.
var exitStatus = var shouldTimeSlice =
shouldTimeSlice(root, lanes) && !didTimeout !includesBlockingLane(root, lanes) &&
? renderRootConcurrent(root, lanes) !includesExpiredLane(root, lanes) &&
: renderRootSync(root, lanes); !didTimeout;
var exitStatus = shouldTimeSlice
? renderRootConcurrent(root, lanes)
: renderRootSync(root, lanes);
if (exitStatus !== RootIncomplete) { if (exitStatus !== RootIncomplete) {
if (exitStatus === RootErrored) { if (exitStatus === RootErrored) {
var prevExecutionContext = executionContext; // If something threw an error, try rendering one more time. We'll
executionContext |= RetryAfterError; // If an error occurred during hydration, // render synchronously to block concurrent data mutations, and we'll
// discard server response and fall back to client side render. // includes all pending updates are included. If it still fails after
// the second attempt, we'll give up and commit the resulting tree.
if (root.hydrate) {
root.hydrate = false;
{
errorHydratingContainer(root.containerInfo);
}
clearContainer(root.containerInfo);
} // If something threw an error, try rendering one more time. We'll render
// synchronously to block concurrent data mutations, and we'll includes
// all pending updates are included. If it still fails after the second
// attempt, we'll give up and commit the resulting tree.
var errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); var errorRetryLanes = getLanesToRetrySynchronouslyOnError(root);
if (errorRetryLanes !== NoLanes) { if (errorRetryLanes !== NoLanes) {
lanes = errorRetryLanes; lanes = errorRetryLanes;
exitStatus = renderRootSync(root, errorRetryLanes); exitStatus = recoverFromConcurrentError(root, errorRetryLanes);
} }
executionContext = prevExecutionContext;
} }
if (exitStatus === RootFatalErrored) { if (exitStatus === RootFatalErrored) {
@ -19599,10 +19756,43 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
markRootSuspended$1(root, lanes); markRootSuspended$1(root, lanes);
ensureRootIsScheduled(root, now()); ensureRootIsScheduled(root, now());
throw fatalError; throw fatalError;
} // Check if this render may have yielded to a concurrent event, and if so,
// confirm that any newly rendered stores are consistent.
// TODO: It's possible that even a concurrent render may never have yielded
// to the main thread, if it was fast enough, or if it expired. We could
// skip the consistency check in that case, too.
var renderWasConcurrent = !includesBlockingLane(root, lanes);
var finishedWork = root.current.alternate;
if (
renderWasConcurrent &&
!isRenderConsistentWithExternalStores(finishedWork)
) {
// A store was mutated in an interleaved event. Render again,
// synchronously, to block further mutations.
exitStatus = renderRootSync(root, lanes); // We need to check again if something threw
if (exitStatus === RootErrored) {
var _errorRetryLanes = getLanesToRetrySynchronouslyOnError(root);
if (_errorRetryLanes !== NoLanes) {
lanes = _errorRetryLanes;
exitStatus = recoverFromConcurrentError(root, _errorRetryLanes); // We assume the tree is now consistent because we didn't yield to any
// concurrent events.
}
}
if (exitStatus === RootFatalErrored) {
var _fatalError = workInProgressRootFatalError;
prepareFreshStack(root, NoLanes);
markRootSuspended$1(root, lanes);
ensureRootIsScheduled(root, now());
throw _fatalError;
}
} // We now have a consistent tree. The next step is either to commit it, } // We now have a consistent tree. The next step is either to commit it,
// or, if something suspended, wait to commit it after a timeout. // or, if something suspended, wait to commit it after a timeout.
var finishedWork = root.current.alternate;
root.finishedWork = finishedWork; root.finishedWork = finishedWork;
root.finishedLanes = lanes; root.finishedLanes = lanes;
finishConcurrentRender(root, exitStatus, lanes); finishConcurrentRender(root, exitStatus, lanes);
@ -19619,6 +19809,26 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
return null; return null;
} }
function recoverFromConcurrentError(root, errorRetryLanes) {
var prevExecutionContext = executionContext;
executionContext |= RetryAfterError; // If an error occurred during hydration, discard server response and fall
// back to client side render.
if (root.hydrate) {
root.hydrate = false;
{
errorHydratingContainer(root.containerInfo);
}
clearContainer(root.containerInfo);
}
var exitStatus = renderRootSync(root, errorRetryLanes);
executionContext = prevExecutionContext;
return exitStatus;
}
function finishConcurrentRender(root, exitStatus, lanes) { function finishConcurrentRender(root, exitStatus, lanes) {
switch (exitStatus) { switch (exitStatus) {
case RootIncomplete: case RootIncomplete:
@ -19737,6 +19947,68 @@ function finishConcurrentRender(root, exitStatus, lanes) {
} }
} }
function isRenderConsistentWithExternalStores(finishedWork) {
// Search the rendered tree for external store reads, and check whether the
// stores were mutated in a concurrent event. Intentionally using a iterative
// loop instead of recursion so we can exit early.
var node = finishedWork;
while (true) {
if (node.flags & StoreConsistency) {
var updateQueue = node.updateQueue;
if (updateQueue !== null) {
var checks = updateQueue.stores;
if (checks !== null) {
for (var i = 0; i < checks.length; i++) {
var check = checks[i];
var getSnapshot = check.getSnapshot;
var renderedValue = check.value;
try {
if (!objectIs(getSnapshot(), renderedValue)) {
// Found an inconsistent store.
return false;
}
} catch (error) {
// If `getSnapshot` throws, return `false`. This will schedule
// a re-render, and the error will be rethrown during render.
return false;
}
}
}
}
}
var child = node.child;
if (node.subtreeFlags & StoreConsistency && child !== null) {
child.return = node;
node = child;
continue;
}
if (node === finishedWork) {
return true;
}
while (node.sibling === null) {
if (node.return === null || node.return === finishedWork) {
return true;
}
node = node.return;
}
node.sibling.return = node.return;
node = node.sibling;
} // Flow doesn't know this is unreachable, but eslint does
// eslint-disable-next-line no-unreachable
return true;
}
function markRootSuspended$1(root, suspendedLanes) { function markRootSuspended$1(root, suspendedLanes) {
// When suspending, we should always exclude lanes that were pinged or (more // When suspending, we should always exclude lanes that were pinged or (more
// rarely, since we try to avoid it) updated during the render phase. // rarely, since we try to avoid it) updated during the render phase.
@ -20481,6 +20753,15 @@ function commitRootImpl(root, renderPriorityLevel) {
} // Read this again, since an effect might have updated it } // Read this again, since an effect might have updated it
remainingLanes = root.pendingLanes; // Check if there's remaining work on this root remainingLanes = root.pendingLanes; // Check if there's remaining work on this root
// TODO: This is part of the `componentDidCatch` implementation. Its purpose
// is to detect whether something might have called setState inside
// `componentDidCatch`. The mechanism is known to be flawed because `setState`
// inside `componentDidCatch` is itself flawed — that's why we recommend
// `getDerivedStateFromError` instead. However, it could be improved by
// checking if remainingLanes includes Sync work, instead of whether there's
// any work remaining at all (which would also include stuff like Suspense
// retries or transitions). It's been like this for a while, though, so fixing
// it probably isn't that urgent.
if (remainingLanes === NoLanes) { if (remainingLanes === NoLanes) {
// If there's no remaining work, we can clear the set of already failed // If there's no remaining work, we can clear the set of already failed
@ -20494,22 +20775,6 @@ function commitRootImpl(root, renderPriorityLevel) {
} }
} }
if (includesSomeLane(remainingLanes, SyncLane)) {
{
markNestedUpdateScheduled();
} // Count the number of times the root synchronously re-renders without
// finishing. If there are too many, it indicates an infinite update loop.
if (root === rootWithNestedUpdates) {
nestedUpdateCount++;
} else {
nestedUpdateCount = 0;
rootWithNestedUpdates = root;
}
} else {
nestedUpdateCount = 0;
}
onCommitRoot(finishedWork.stateNode, renderPriorityLevel); onCommitRoot(finishedWork.stateNode, renderPriorityLevel);
{ {
@ -20540,6 +20805,24 @@ function commitRootImpl(root, renderPriorityLevel) {
root.tag !== LegacyRoot root.tag !== LegacyRoot
) { ) {
flushPassiveEffects(); flushPassiveEffects();
} // Read this again, since a passive effect might have updated it
remainingLanes = root.pendingLanes;
if (includesSomeLane(remainingLanes, SyncLane)) {
{
markNestedUpdateScheduled();
} // Count the number of times the root synchronously re-renders without
// finishing. If there are too many, it indicates an infinite update loop.
if (root === rootWithNestedUpdates) {
nestedUpdateCount++;
} else {
nestedUpdateCount = 0;
rootWithNestedUpdates = root;
}
} else {
nestedUpdateCount = 0;
} // If layout work was scheduled, flush it now. } // If layout work was scheduled, flush it now.
flushSyncCallbacks(); flushSyncCallbacks();

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

@ -7,7 +7,7 @@
* @noflow * @noflow
* @nolint * @nolint
* @preventMunge * @preventMunge
* @generated SignedSource<<6fd8e2fc263f451cb6e073eae96b19f3>> * @generated SignedSource<<4538b6a9895755454ebc3d0f7b8f568e>>
*/ */
"use strict"; "use strict";
@ -931,7 +931,7 @@ eventPluginOrder = Array.prototype.slice.call([
"ReactNativeBridgeEventPlugin" "ReactNativeBridgeEventPlugin"
]); ]);
recomputePluginOrdering(); recomputePluginOrdering();
var injectedNamesToPlugins$jscomp$inline_221 = { var injectedNamesToPlugins$jscomp$inline_222 = {
ResponderEventPlugin: ResponderEventPlugin, ResponderEventPlugin: ResponderEventPlugin,
ReactNativeBridgeEventPlugin: { ReactNativeBridgeEventPlugin: {
eventTypes: {}, eventTypes: {},
@ -966,34 +966,34 @@ var injectedNamesToPlugins$jscomp$inline_221 = {
} }
} }
}, },
isOrderingDirty$jscomp$inline_222 = !1, isOrderingDirty$jscomp$inline_223 = !1,
pluginName$jscomp$inline_223; pluginName$jscomp$inline_224;
for (pluginName$jscomp$inline_223 in injectedNamesToPlugins$jscomp$inline_221) for (pluginName$jscomp$inline_224 in injectedNamesToPlugins$jscomp$inline_222)
if ( if (
injectedNamesToPlugins$jscomp$inline_221.hasOwnProperty( injectedNamesToPlugins$jscomp$inline_222.hasOwnProperty(
pluginName$jscomp$inline_223 pluginName$jscomp$inline_224
) )
) { ) {
var pluginModule$jscomp$inline_224 = var pluginModule$jscomp$inline_225 =
injectedNamesToPlugins$jscomp$inline_221[pluginName$jscomp$inline_223]; injectedNamesToPlugins$jscomp$inline_222[pluginName$jscomp$inline_224];
if ( if (
!namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_223) || !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_224) ||
namesToPlugins[pluginName$jscomp$inline_223] !== namesToPlugins[pluginName$jscomp$inline_224] !==
pluginModule$jscomp$inline_224 pluginModule$jscomp$inline_225
) { ) {
if (namesToPlugins[pluginName$jscomp$inline_223]) if (namesToPlugins[pluginName$jscomp$inline_224])
throw Error( throw Error(
"EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" +
pluginName$jscomp$inline_223 + pluginName$jscomp$inline_224 +
"`." "`."
); );
namesToPlugins[ namesToPlugins[
pluginName$jscomp$inline_223 pluginName$jscomp$inline_224
] = pluginModule$jscomp$inline_224; ] = pluginModule$jscomp$inline_225;
isOrderingDirty$jscomp$inline_222 = !0; isOrderingDirty$jscomp$inline_223 = !0;
} }
} }
isOrderingDirty$jscomp$inline_222 && recomputePluginOrdering(); isOrderingDirty$jscomp$inline_223 && recomputePluginOrdering();
function getInstanceFromInstance(instanceHandle) { function getInstanceFromInstance(instanceHandle) {
return instanceHandle; return instanceHandle;
} }
@ -1763,6 +1763,9 @@ function getLanesToRetrySynchronouslyOnError(root) {
root = root.pendingLanes & -1073741825; root = root.pendingLanes & -1073741825;
return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0;
} }
function includesBlockingLane(root, lanes) {
return 0 !== (root.current.mode & 32) ? !1 : 0 !== (lanes & 30);
}
function createLaneMap(initial) { function createLaneMap(initial) {
for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial);
return laneMap; return laneMap;
@ -2085,7 +2088,11 @@ function invalidateContextProvider(workInProgress, type, didChange) {
: pop(didPerformWorkStackCursor); : pop(didPerformWorkStackCursor);
push(didPerformWorkStackCursor, didChange); push(didPerformWorkStackCursor, didChange);
} }
var syncQueue = null, function is(x, y) {
return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
}
var objectIs = "function" === typeof Object.is ? Object.is : is,
syncQueue = null,
includesLegacySyncCallbacks = !1, includesLegacySyncCallbacks = !1,
isFlushingSyncQueue = !1; isFlushingSyncQueue = !1;
function flushSyncCallbacks() { function flushSyncCallbacks() {
@ -2114,10 +2121,6 @@ function flushSyncCallbacks() {
return null; return null;
} }
var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig;
function is(x, y) {
return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
}
var objectIs = "function" === typeof Object.is ? Object.is : is;
function shallowEqual(objA, objB) { function shallowEqual(objA, objB) {
if (objectIs(objA, objB)) return !0; if (objectIs(objA, objB)) return !0;
if ( if (
@ -2402,7 +2405,7 @@ function processUpdateQueue(
newState = workInProgress; newState = workInProgress;
break a; break a;
case 3: case 3:
workInProgress.flags = (workInProgress.flags & -16385) | 128; workInProgress.flags = (workInProgress.flags & -32769) | 128;
case 0: case 0:
workInProgress = update.payload; workInProgress = update.payload;
updateLane = updateLane =
@ -3633,42 +3636,52 @@ function updateMutableSource(source, getSnapshot, subscribe) {
return useMutableSource(hook, source, getSnapshot, subscribe); return useMutableSource(hook, source, getSnapshot, subscribe);
} }
function mountSyncExternalStore(subscribe, getSnapshot) { function mountSyncExternalStore(subscribe, getSnapshot) {
var hook = mountWorkInProgressHook(), var fiber = currentlyRenderingFiber$1,
hook = mountWorkInProgressHook(),
nextSnapshot = getSnapshot(); nextSnapshot = getSnapshot();
hook.memoizedState = nextSnapshot; hook.memoizedState = nextSnapshot;
var inst = { value: nextSnapshot, getSnapshot: getSnapshot }; var inst = { value: nextSnapshot, getSnapshot: getSnapshot };
hook.queue = inst; hook.queue = inst;
return useSyncExternalStore(hook, inst, subscribe, getSnapshot, nextSnapshot); mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]);
} fiber.flags |= 1024;
function useSyncExternalStore( pushEffect(
hook, 9,
inst, updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot),
subscribe, void 0,
getSnapshot, null
nextSnapshot
) {
var fiber = currentlyRenderingFiber$1;
hook = ReactCurrentDispatcher$1.current;
hook.useLayoutEffect(
function() {
inst.value = nextSnapshot;
inst.getSnapshot = getSnapshot;
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
},
[subscribe, nextSnapshot, getSnapshot]
);
hook.useEffect(
function() {
function handleStoreChange() {
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
}
handleStoreChange();
return subscribe(handleStoreChange);
},
[subscribe]
); );
subscribe = workInProgressRoot;
if (null === subscribe)
throw Error(
"Expected a work-in-progress root. This is a bug in React. Please file an issue."
);
includesBlockingLane(subscribe, renderLanes) ||
pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
return nextSnapshot; return nextSnapshot;
} }
function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) {
fiber.flags |= 8192;
fiber = { getSnapshot: getSnapshot, value: renderedSnapshot };
getSnapshot = currentlyRenderingFiber$1.updateQueue;
null === getSnapshot
? ((getSnapshot = { lastEffect: null, stores: null }),
(currentlyRenderingFiber$1.updateQueue = getSnapshot),
(getSnapshot.stores = [fiber]))
: ((renderedSnapshot = getSnapshot.stores),
null === renderedSnapshot
? (getSnapshot.stores = [fiber])
: renderedSnapshot.push(fiber));
}
function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) {
inst.value = nextSnapshot;
inst.getSnapshot = getSnapshot;
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
}
function subscribeToStore(fiber, inst, subscribe) {
return subscribe(function() {
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
});
}
function checkIfSnapshotChanged(inst) { function checkIfSnapshotChanged(inst) {
var latestGetSnapshot = inst.getSnapshot; var latestGetSnapshot = inst.getSnapshot;
inst = inst.value; inst = inst.value;
@ -3703,7 +3716,7 @@ function pushEffect(tag, create, destroy, deps) {
tag = { tag: tag, create: create, destroy: destroy, deps: deps, next: null }; tag = { tag: tag, create: create, destroy: destroy, deps: deps, next: null };
create = currentlyRenderingFiber$1.updateQueue; create = currentlyRenderingFiber$1.updateQueue;
null === create null === create
? ((create = { lastEffect: null }), ? ((create = { lastEffect: null, stores: null }),
(currentlyRenderingFiber$1.updateQueue = create), (currentlyRenderingFiber$1.updateQueue = create),
(create.lastEffect = tag.next = tag)) (create.lastEffect = tag.next = tag))
: ((destroy = create.lastEffect), : ((destroy = create.lastEffect),
@ -3744,13 +3757,16 @@ function updateEffectImpl(fiberFlags, hookFlags, create, deps) {
hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps); hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps);
} }
function mountEffect(create, deps) { function mountEffect(create, deps) {
return mountEffectImpl(1049600, 4, create, deps); return mountEffectImpl(2098176, 8, create, deps);
} }
function updateEffect(create, deps) { function updateEffect(create, deps) {
return updateEffectImpl(1024, 4, create, deps); return updateEffectImpl(1024, 8, create, deps);
}
function updateInsertionEffect(create, deps) {
return updateEffectImpl(4, 2, create, deps);
} }
function updateLayoutEffect(create, deps) { function updateLayoutEffect(create, deps) {
return updateEffectImpl(4, 2, create, deps); return updateEffectImpl(4, 4, create, deps);
} }
function imperativeHandleEffect(create, ref) { function imperativeHandleEffect(create, ref) {
if ("function" === typeof ref) if ("function" === typeof ref)
@ -3774,7 +3790,7 @@ function updateImperativeHandle(ref, create, deps) {
deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null; deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null;
return updateEffectImpl( return updateEffectImpl(
4, 4,
2, 4,
imperativeHandleEffect.bind(null, create, ref), imperativeHandleEffect.bind(null, create, ref),
deps deps
); );
@ -3892,6 +3908,7 @@ var ContextOnlyDispatcher = {
useContext: throwInvalidHookError, useContext: throwInvalidHookError,
useEffect: throwInvalidHookError, useEffect: throwInvalidHookError,
useImperativeHandle: throwInvalidHookError, useImperativeHandle: throwInvalidHookError,
useInsertionEffect: throwInvalidHookError,
useLayoutEffect: throwInvalidHookError, useLayoutEffect: throwInvalidHookError,
useMemo: throwInvalidHookError, useMemo: throwInvalidHookError,
useReducer: throwInvalidHookError, useReducer: throwInvalidHookError,
@ -3920,12 +3937,15 @@ var ContextOnlyDispatcher = {
deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null; deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null;
return mountEffectImpl( return mountEffectImpl(
4, 4,
2, 4,
imperativeHandleEffect.bind(null, create, ref), imperativeHandleEffect.bind(null, create, ref),
deps deps
); );
}, },
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
return mountEffectImpl(4, 4, create, deps);
},
useInsertionEffect: function(create, deps) {
return mountEffectImpl(4, 2, create, deps); return mountEffectImpl(4, 2, create, deps);
}, },
useMemo: function(nextCreate, deps) { useMemo: function(nextCreate, deps) {
@ -4008,6 +4028,7 @@ var ContextOnlyDispatcher = {
useContext: readContext, useContext: readContext,
useEffect: updateEffect, useEffect: updateEffect,
useImperativeHandle: updateImperativeHandle, useImperativeHandle: updateImperativeHandle,
useInsertionEffect: updateInsertionEffect,
useLayoutEffect: updateLayoutEffect, useLayoutEffect: updateLayoutEffect,
useMemo: updateMemo, useMemo: updateMemo,
useReducer: updateReducer, useReducer: updateReducer,
@ -4041,17 +4062,44 @@ var ContextOnlyDispatcher = {
}, },
useMutableSource: updateMutableSource, useMutableSource: updateMutableSource,
useSyncExternalStore: function(subscribe, getSnapshot) { useSyncExternalStore: function(subscribe, getSnapshot) {
var hook = updateWorkInProgressHook(), var fiber = currentlyRenderingFiber$1,
nextSnapshot = getSnapshot(); hook = updateWorkInProgressHook(),
objectIs(hook.memoizedState, nextSnapshot) || nextSnapshot = getSnapshot(),
snapshotChanged = !objectIs(hook.memoizedState, nextSnapshot);
snapshotChanged &&
((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0)); ((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0));
return useSyncExternalStore( hook = hook.queue;
hook, updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [
hook.queue, subscribe
subscribe, ]);
getSnapshot, if (
nextSnapshot hook.getSnapshot !== getSnapshot ||
); snapshotChanged ||
(null !== workInProgressHook &&
workInProgressHook.memoizedState.tag & 1)
) {
fiber.flags |= 1024;
pushEffect(
9,
updateStoreInstance.bind(
null,
fiber,
hook,
nextSnapshot,
getSnapshot
),
void 0,
null
);
subscribe = workInProgressRoot;
if (null === subscribe)
throw Error(
"Expected a work-in-progress root. This is a bug in React. Please file an issue."
);
includesBlockingLane(subscribe, renderLanes) ||
pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
}
return nextSnapshot;
}, },
useOpaqueIdentifier: function() { useOpaqueIdentifier: function() {
return updateReducer(basicStateReducer)[0]; return updateReducer(basicStateReducer)[0];
@ -4064,6 +4112,7 @@ var ContextOnlyDispatcher = {
useContext: readContext, useContext: readContext,
useEffect: updateEffect, useEffect: updateEffect,
useImperativeHandle: updateImperativeHandle, useImperativeHandle: updateImperativeHandle,
useInsertionEffect: updateInsertionEffect,
useLayoutEffect: updateLayoutEffect, useLayoutEffect: updateLayoutEffect,
useMemo: updateMemo, useMemo: updateMemo,
useReducer: rerenderReducer, useReducer: rerenderReducer,
@ -4365,8 +4414,8 @@ function bubbleProperties(completedWork) {
if (didBailout) if (didBailout)
for (var child$39 = completedWork.child; null !== child$39; ) for (var child$39 = completedWork.child; null !== child$39; )
(newChildLanes |= child$39.lanes | child$39.childLanes), (newChildLanes |= child$39.lanes | child$39.childLanes),
(subtreeFlags |= child$39.subtreeFlags & 1835008), (subtreeFlags |= child$39.subtreeFlags & 3670016),
(subtreeFlags |= child$39.flags & 1835008), (subtreeFlags |= child$39.flags & 3670016),
(child$39.return = completedWork), (child$39.return = completedWork),
(child$39 = child$39.sibling); (child$39 = child$39.sibling);
else else
@ -4584,7 +4633,7 @@ function completeWork(current, workInProgress, renderLanes) {
for (newProps = workInProgress.child; null !== newProps; ) for (newProps = workInProgress.child; null !== newProps; )
(renderLanes = newProps), (renderLanes = newProps),
(type = current), (type = current),
(renderLanes.flags &= 1835010), (renderLanes.flags &= 3670018),
(renderedTail = renderLanes.alternate), (renderedTail = renderLanes.alternate),
null === renderedTail null === renderedTail
? ((renderLanes.childLanes = 0), ? ((renderLanes.childLanes = 0),
@ -4810,7 +4859,7 @@ function updateSimpleMemoComponent(
current.ref === workInProgress.ref current.ref === workInProgress.ref
) )
if (((didReceiveUpdate = !1), 0 !== (current.lanes & renderLanes))) if (((didReceiveUpdate = !1), 0 !== (current.lanes & renderLanes)))
0 !== (current.flags & 32768) && (didReceiveUpdate = !0); 0 !== (current.flags & 65536) && (didReceiveUpdate = !0);
else else
return ( return (
(workInProgress.lanes = current.lanes), (workInProgress.lanes = current.lanes),
@ -5425,7 +5474,7 @@ function updateSuspenseFallbackChildren(
primaryChildren primaryChildren
))), ))),
(current.subtreeFlags = (current.subtreeFlags =
currentPrimaryChildFragment.subtreeFlags & 1835008)); currentPrimaryChildFragment.subtreeFlags & 3670016));
null !== currentFallbackChildFragment null !== currentFallbackChildFragment
? (fallbackChildren = createWorkInProgress( ? (fallbackChildren = createWorkInProgress(
currentFallbackChildFragment, currentFallbackChildFragment,
@ -5653,8 +5702,8 @@ function unwindWork(workInProgress) {
case 1: case 1:
isContextProvider(workInProgress.type) && popContext(); isContextProvider(workInProgress.type) && popContext();
var flags = workInProgress.flags; var flags = workInProgress.flags;
return flags & 16384 return flags & 32768
? ((workInProgress.flags = (flags & -16385) | 128), workInProgress) ? ((workInProgress.flags = (flags & -32769) | 128), workInProgress)
: null; : null;
case 3: case 3:
popHostContainer(); popHostContainer();
@ -5666,7 +5715,7 @@ function unwindWork(workInProgress) {
throw Error( throw Error(
"The root failed to unmount after an error. This is likely a bug in React. Please file an issue." "The root failed to unmount after an error. This is likely a bug in React. Please file an issue."
); );
workInProgress.flags = (flags & -16385) | 128; workInProgress.flags = (flags & -32769) | 128;
return workInProgress; return workInProgress;
case 5: case 5:
return popHostContext(workInProgress), null; return popHostContext(workInProgress), null;
@ -5674,8 +5723,8 @@ function unwindWork(workInProgress) {
return ( return (
pop(suspenseStackCursor), pop(suspenseStackCursor),
(flags = workInProgress.flags), (flags = workInProgress.flags),
flags & 16384 flags & 32768
? ((workInProgress.flags = (flags & -16385) | 128), workInProgress) ? ((workInProgress.flags = (flags & -32769) | 128), workInProgress)
: null : null
); );
case 19: case 19:
@ -5831,6 +5880,8 @@ function commitWork(current, finishedWork) {
case 14: case 14:
case 15: case 15:
commitHookEffectListUnmount(3, finishedWork, finishedWork.return); commitHookEffectListUnmount(3, finishedWork, finishedWork.return);
commitHookEffectListMount(3, finishedWork);
commitHookEffectListUnmount(5, finishedWork, finishedWork.return);
return; return;
case 12: case 12:
return; return;
@ -5905,7 +5956,10 @@ function commitMutationEffects(root, firstChild) {
var _effect = effect, var _effect = effect,
destroy = _effect.destroy, destroy = _effect.destroy,
tag = _effect.tag; tag = _effect.tag;
if (void 0 !== destroy && 0 !== (tag & 2)) { if (
void 0 !== destroy &&
(0 !== (tag & 2) || 0 !== (tag & 4))
) {
_effect = current; _effect = current;
var nearestMountedAncestor = root; var nearestMountedAncestor = root;
try { try {
@ -6038,7 +6092,7 @@ function commitLayoutEffects(finishedWork) {
case 0: case 0:
case 11: case 11:
case 15: case 15:
commitHookEffectListMount(3, firstChild); commitHookEffectListMount(5, firstChild);
break; break;
case 1: case 1:
var instance = firstChild.stateNode; var instance = firstChild.stateNode;
@ -6316,15 +6370,15 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
root === workInProgressRoot ? workInProgressRootRenderLanes : 0 root === workInProgressRoot ? workInProgressRootRenderLanes : 0
); );
if (0 === lanes) return null; if (0 === lanes) return null;
var JSCompiler_inline_result = if (
0 !== (lanes & root.expiredLanes) includesBlockingLane(root, lanes) ||
? !1 0 !== (lanes & root.expiredLanes) ||
: 0 !== (root.current.mode & 32) didTimeout
? !0 )
: 0 === (lanes & 30); didTimeout = renderRootSync(root, lanes);
if (JSCompiler_inline_result && !didTimeout) { else {
didTimeout = lanes; didTimeout = lanes;
JSCompiler_inline_result = executionContext; var prevExecutionContext = executionContext;
executionContext |= 2; executionContext |= 2;
var prevDispatcher = pushDispatcher(); var prevDispatcher = pushDispatcher();
if ( if (
@ -6343,30 +6397,44 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
while (1); while (1);
resetContextDependencies(); resetContextDependencies();
ReactCurrentDispatcher$2.current = prevDispatcher; ReactCurrentDispatcher$2.current = prevDispatcher;
executionContext = JSCompiler_inline_result; executionContext = prevExecutionContext;
null !== workInProgress null !== workInProgress
? (didTimeout = 0) ? (didTimeout = 0)
: ((workInProgressRoot = null), : ((workInProgressRoot = null),
(workInProgressRootRenderLanes = 0), (workInProgressRootRenderLanes = 0),
(didTimeout = workInProgressRootExitStatus)); (didTimeout = workInProgressRootExitStatus));
} else didTimeout = renderRootSync(root, lanes); }
if (0 !== didTimeout) { if (0 !== didTimeout) {
2 === didTimeout && 2 === didTimeout &&
((JSCompiler_inline_result = executionContext), ((prevExecutionContext = getLanesToRetrySynchronouslyOnError(root)),
(executionContext |= 8), 0 !== prevExecutionContext &&
root.hydrate && ((root.hydrate = !1), shim(root.containerInfo)), ((lanes = prevExecutionContext),
(prevDispatcher = getLanesToRetrySynchronouslyOnError(root)), (didTimeout = recoverFromConcurrentError(root, prevExecutionContext))));
0 !== prevDispatcher &&
((lanes = prevDispatcher),
(didTimeout = renderRootSync(root, prevDispatcher))),
(executionContext = JSCompiler_inline_result));
if (1 === didTimeout) if (1 === didTimeout)
throw ((originalCallbackNode = workInProgressRootFatalError), throw ((originalCallbackNode = workInProgressRootFatalError),
prepareFreshStack(root, 0), prepareFreshStack(root, 0),
markRootSuspended$1(root, lanes), markRootSuspended$1(root, lanes),
ensureRootIsScheduled(root, now()), ensureRootIsScheduled(root, now()),
originalCallbackNode); originalCallbackNode);
root.finishedWork = root.current.alternate; prevDispatcher = !includesBlockingLane(root, lanes);
prevExecutionContext = root.current.alternate;
if (
prevDispatcher &&
!isRenderConsistentWithExternalStores(prevExecutionContext) &&
((didTimeout = renderRootSync(root, lanes)),
2 === didTimeout &&
((prevDispatcher = getLanesToRetrySynchronouslyOnError(root)),
0 !== prevDispatcher &&
((lanes = prevDispatcher),
(didTimeout = recoverFromConcurrentError(root, prevDispatcher)))),
1 === didTimeout)
)
throw ((originalCallbackNode = workInProgressRootFatalError),
prepareFreshStack(root, 0),
markRootSuspended$1(root, lanes),
ensureRootIsScheduled(root, now()),
originalCallbackNode);
root.finishedWork = prevExecutionContext;
root.finishedLanes = lanes; root.finishedLanes = lanes;
switch (didTimeout) { switch (didTimeout) {
case 0: case 0:
@ -6383,10 +6451,10 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
10 < didTimeout) 10 < didTimeout)
) { ) {
if (0 !== getNextLanes(root, 0)) break; if (0 !== getNextLanes(root, 0)) break;
JSCompiler_inline_result = root.suspendedLanes; prevExecutionContext = root.suspendedLanes;
if ((JSCompiler_inline_result & lanes) !== lanes) { if ((prevExecutionContext & lanes) !== lanes) {
requestEventTime(); requestEventTime();
root.pingedLanes |= root.suspendedLanes & JSCompiler_inline_result; root.pingedLanes |= root.suspendedLanes & prevExecutionContext;
break; break;
} }
root.timeoutHandle = scheduleTimeout( root.timeoutHandle = scheduleTimeout(
@ -6401,15 +6469,14 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
markRootSuspended$1(root, lanes); markRootSuspended$1(root, lanes);
if ((lanes & 4194240) === lanes) break; if ((lanes & 4194240) === lanes) break;
didTimeout = root.eventTimes; didTimeout = root.eventTimes;
for (JSCompiler_inline_result = -1; 0 < lanes; ) { for (prevExecutionContext = -1; 0 < lanes; ) {
var index$4 = 31 - clz32(lanes); var index$4 = 31 - clz32(lanes);
prevDispatcher = 1 << index$4; prevDispatcher = 1 << index$4;
index$4 = didTimeout[index$4]; index$4 = didTimeout[index$4];
index$4 > JSCompiler_inline_result && index$4 > prevExecutionContext && (prevExecutionContext = index$4);
(JSCompiler_inline_result = index$4);
lanes &= ~prevDispatcher; lanes &= ~prevDispatcher;
} }
lanes = JSCompiler_inline_result; lanes = prevExecutionContext;
lanes = now() - lanes; lanes = now() - lanes;
lanes = lanes =
(120 > lanes (120 > lanes
@ -6446,6 +6513,48 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
? performConcurrentWorkOnRoot.bind(null, root) ? performConcurrentWorkOnRoot.bind(null, root)
: null; : null;
} }
function recoverFromConcurrentError(root, errorRetryLanes) {
var prevExecutionContext = executionContext;
executionContext |= 8;
root.hydrate && ((root.hydrate = !1), shim(root.containerInfo));
root = renderRootSync(root, errorRetryLanes);
executionContext = prevExecutionContext;
return root;
}
function isRenderConsistentWithExternalStores(finishedWork) {
for (var node = finishedWork; ; ) {
if (node.flags & 8192) {
var updateQueue = node.updateQueue;
if (
null !== updateQueue &&
((updateQueue = updateQueue.stores), null !== updateQueue)
)
for (var i = 0; i < updateQueue.length; i++) {
var check = updateQueue[i],
getSnapshot = check.getSnapshot;
check = check.value;
try {
if (!objectIs(getSnapshot(), check)) return !1;
} catch (error) {
return !1;
}
}
}
updateQueue = node.child;
if (node.subtreeFlags & 8192 && null !== updateQueue)
(updateQueue.return = node), (node = updateQueue);
else {
if (node === finishedWork) break;
for (; null === node.sibling; ) {
if (null === node.return || node.return === finishedWork) return !0;
node = node.return;
}
node.sibling.return = node.return;
node = node.sibling;
}
}
return !0;
}
function markRootSuspended$1(root, suspendedLanes) { function markRootSuspended$1(root, suspendedLanes) {
suspendedLanes &= ~workInProgressRootPingedLanes; suspendedLanes &= ~workInProgressRootPingedLanes;
suspendedLanes &= ~workInProgressRootUpdatedLanes; suspendedLanes &= ~workInProgressRootUpdatedLanes;
@ -6593,7 +6702,7 @@ function handleError(root$jscomp$0, thrownValue) {
sourceFiber = erroredWork, sourceFiber = erroredWork,
value = thrownValue; value = thrownValue;
thrownValue = workInProgressRootRenderLanes; thrownValue = workInProgressRootRenderLanes;
sourceFiber.flags |= 8192; sourceFiber.flags |= 16384;
if ( if (
null !== value && null !== value &&
"object" === typeof value && "object" === typeof value &&
@ -6644,8 +6753,8 @@ function handleError(root$jscomp$0, thrownValue) {
workInProgress$30 !== returnFiber workInProgress$30 !== returnFiber
) { ) {
workInProgress$30.flags |= 128; workInProgress$30.flags |= 128;
sourceFiber.flags |= 32768; sourceFiber.flags |= 65536;
sourceFiber.flags &= -10053; sourceFiber.flags &= -26437;
if ( if (
enablePersistentOffscreenHostContainer && enablePersistentOffscreenHostContainer &&
null === workInProgress$30.alternate null === workInProgress$30.alternate
@ -6690,7 +6799,7 @@ function handleError(root$jscomp$0, thrownValue) {
); );
wakeable.then(ping, ping); wakeable.then(ping, ping);
} }
workInProgress$30.flags |= 16384; workInProgress$30.flags |= 32768;
workInProgress$30.lanes = thrownValue; workInProgress$30.lanes = thrownValue;
break a; break a;
} }
@ -6709,7 +6818,7 @@ function handleError(root$jscomp$0, thrownValue) {
switch (workInProgress$30.tag) { switch (workInProgress$30.tag) {
case 3: case 3:
root = value; root = value;
workInProgress$30.flags |= 16384; workInProgress$30.flags |= 32768;
thrownValue &= -thrownValue; thrownValue &= -thrownValue;
workInProgress$30.lanes |= thrownValue; workInProgress$30.lanes |= thrownValue;
var update$31 = createRootErrorUpdate( var update$31 = createRootErrorUpdate(
@ -6731,7 +6840,7 @@ function handleError(root$jscomp$0, thrownValue) {
(null === legacyErrorBoundariesThatAlreadyFailed || (null === legacyErrorBoundariesThatAlreadyFailed ||
!legacyErrorBoundariesThatAlreadyFailed.has(instance)))) !legacyErrorBoundariesThatAlreadyFailed.has(instance))))
) { ) {
workInProgress$30.flags |= 16384; workInProgress$30.flags |= 32768;
thrownValue &= -thrownValue; thrownValue &= -thrownValue;
workInProgress$30.lanes |= thrownValue; workInProgress$30.lanes |= thrownValue;
var update$34 = createClassErrorUpdate( var update$34 = createClassErrorUpdate(
@ -6805,7 +6914,7 @@ function completeUnitOfWork(unitOfWork) {
do { do {
var current = completedWork.alternate; var current = completedWork.alternate;
unitOfWork = completedWork.return; unitOfWork = completedWork.return;
if (0 === (completedWork.flags & 8192)) { if (0 === (completedWork.flags & 16384)) {
if ( if (
((current = completeWork(current, completedWork, subtreeRenderLanes)), ((current = completeWork(current, completedWork, subtreeRenderLanes)),
null !== current) null !== current)
@ -6816,12 +6925,12 @@ function completeUnitOfWork(unitOfWork) {
} else { } else {
current = unwindWork(completedWork); current = unwindWork(completedWork);
if (null !== current) { if (null !== current) {
current.flags &= 8191; current.flags &= 16383;
workInProgress = current; workInProgress = current;
return; return;
} }
null !== unitOfWork && null !== unitOfWork &&
((unitOfWork.flags |= 8192), ((unitOfWork.flags |= 16384),
(unitOfWork.subtreeFlags = 0), (unitOfWork.subtreeFlags = 0),
(unitOfWork.deletions = null)); (unitOfWork.deletions = null));
} }
@ -6900,11 +7009,6 @@ function commitRootImpl(root, renderPriorityLevel) {
(pendingPassiveEffectsLanes = lanes)); (pendingPassiveEffectsLanes = lanes));
remainingLanes = root.pendingLanes; remainingLanes = root.pendingLanes;
0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null);
0 !== (remainingLanes & 1)
? root === rootWithNestedUpdates
? nestedUpdateCount++
: ((nestedUpdateCount = 0), (rootWithNestedUpdates = root))
: (nestedUpdateCount = 0);
onCommitRoot(finishedWork.stateNode, renderPriorityLevel); onCommitRoot(finishedWork.stateNode, renderPriorityLevel);
ensureRootIsScheduled(root, now()); ensureRootIsScheduled(root, now());
if (hasUncaughtError) if (hasUncaughtError)
@ -6915,6 +7019,12 @@ function commitRootImpl(root, renderPriorityLevel) {
0 !== (pendingPassiveEffectsLanes & 1) && 0 !== (pendingPassiveEffectsLanes & 1) &&
0 !== root.tag && 0 !== root.tag &&
flushPassiveEffects(); flushPassiveEffects();
remainingLanes = root.pendingLanes;
0 !== (remainingLanes & 1)
? root === rootWithNestedUpdates
? nestedUpdateCount++
: ((nestedUpdateCount = 0), (rootWithNestedUpdates = root))
: (nestedUpdateCount = 0);
flushSyncCallbacks(); flushSyncCallbacks();
return null; return null;
} }
@ -6950,7 +7060,7 @@ function flushPassiveEffects() {
case 0: case 0:
case 11: case 11:
case 15: case 15:
commitHookEffectListUnmount(4, fiber$jscomp$0, fiber); commitHookEffectListUnmount(8, fiber$jscomp$0, fiber);
} }
var child$jscomp$0 = fiber$jscomp$0.child; var child$jscomp$0 = fiber$jscomp$0.child;
if (null !== child$jscomp$0) if (null !== child$jscomp$0)
@ -7000,7 +7110,7 @@ function flushPassiveEffects() {
case 0: case 0:
case 11: case 11:
case 15: case 15:
commitHookEffectListUnmount(5, fiber, fiber.return); commitHookEffectListUnmount(9, fiber, fiber.return);
} }
var sibling$jscomp$0 = fiber.sibling; var sibling$jscomp$0 = fiber.sibling;
if (null !== sibling$jscomp$0) { if (null !== sibling$jscomp$0) {
@ -7026,7 +7136,7 @@ function flushPassiveEffects() {
case 0: case 0:
case 11: case 11:
case 15: case 15:
commitHookEffectListMount(5, deletions); commitHookEffectListMount(9, deletions);
} }
} catch (error) { } catch (error) {
captureCommitPhaseError(deletions, deletions.return, error); captureCommitPhaseError(deletions, deletions.return, error);
@ -7172,7 +7282,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) {
renderLanes renderLanes
) )
); );
didReceiveUpdate = 0 !== (current.flags & 32768) ? !0 : !1; didReceiveUpdate = 0 !== (current.flags & 65536) ? !0 : !1;
} }
else didReceiveUpdate = !1; else didReceiveUpdate = !1;
workInProgress.lanes = 0; workInProgress.lanes = 0;
@ -7638,7 +7748,7 @@ function createWorkInProgress(current, pendingProps) {
(workInProgress.flags = 0), (workInProgress.flags = 0),
(workInProgress.subtreeFlags = 0), (workInProgress.subtreeFlags = 0),
(workInProgress.deletions = null)); (workInProgress.deletions = null));
workInProgress.flags = current.flags & 1835008; workInProgress.flags = current.flags & 3670016;
workInProgress.childLanes = current.childLanes; workInProgress.childLanes = current.childLanes;
workInProgress.lanes = current.lanes; workInProgress.lanes = current.lanes;
workInProgress.child = current.child; workInProgress.child = current.child;
@ -7995,10 +8105,10 @@ batchedUpdatesImpl = function(fn, a) {
} }
}; };
var roots = new Map(), var roots = new Map(),
devToolsConfig$jscomp$inline_953 = { devToolsConfig$jscomp$inline_950 = {
findFiberByHostInstance: getInstanceFromInstance, findFiberByHostInstance: getInstanceFromInstance,
bundleType: 0, bundleType: 0,
version: "18.0.0-95d762e40-20210908", version: "18.0.0-e8feb11b6-20210915",
rendererPackageName: "react-native-renderer", rendererPackageName: "react-native-renderer",
rendererConfig: { rendererConfig: {
getInspectorDataForViewTag: function() { getInspectorDataForViewTag: function() {
@ -8013,11 +8123,11 @@ var roots = new Map(),
}.bind(null, findNodeHandle) }.bind(null, findNodeHandle)
} }
}; };
var internals$jscomp$inline_1194 = { var internals$jscomp$inline_1191 = {
bundleType: devToolsConfig$jscomp$inline_953.bundleType, bundleType: devToolsConfig$jscomp$inline_950.bundleType,
version: devToolsConfig$jscomp$inline_953.version, version: devToolsConfig$jscomp$inline_950.version,
rendererPackageName: devToolsConfig$jscomp$inline_953.rendererPackageName, rendererPackageName: devToolsConfig$jscomp$inline_950.rendererPackageName,
rendererConfig: devToolsConfig$jscomp$inline_953.rendererConfig, rendererConfig: devToolsConfig$jscomp$inline_950.rendererConfig,
overrideHookState: null, overrideHookState: null,
overrideHookStateDeletePath: null, overrideHookStateDeletePath: null,
overrideHookStateRenamePath: null, overrideHookStateRenamePath: null,
@ -8033,7 +8143,7 @@ var internals$jscomp$inline_1194 = {
return null === fiber ? null : fiber.stateNode; return null === fiber ? null : fiber.stateNode;
}, },
findFiberByHostInstance: findFiberByHostInstance:
devToolsConfig$jscomp$inline_953.findFiberByHostInstance || devToolsConfig$jscomp$inline_950.findFiberByHostInstance ||
emptyFindFiberByHostInstance, emptyFindFiberByHostInstance,
findHostInstancesForRefresh: null, findHostInstancesForRefresh: null,
scheduleRefresh: null, scheduleRefresh: null,
@ -8041,19 +8151,19 @@ var internals$jscomp$inline_1194 = {
setRefreshHandler: null, setRefreshHandler: null,
getCurrentFiber: null, getCurrentFiber: null,
getIsStrictMode: null, getIsStrictMode: null,
reconcilerVersion: "18.0.0-95d762e40-20210908" reconcilerVersion: "18.0.0-e8feb11b6-20210915"
}; };
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1195 = __REACT_DEVTOOLS_GLOBAL_HOOK__; var hook$jscomp$inline_1192 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
if ( if (
!hook$jscomp$inline_1195.isDisabled && !hook$jscomp$inline_1192.isDisabled &&
hook$jscomp$inline_1195.supportsFiber hook$jscomp$inline_1192.supportsFiber
) )
try { try {
(rendererID = hook$jscomp$inline_1195.inject( (rendererID = hook$jscomp$inline_1192.inject(
internals$jscomp$inline_1194 internals$jscomp$inline_1191
)), )),
(injectedHook = hook$jscomp$inline_1195); (injectedHook = hook$jscomp$inline_1192);
} catch (err) {} } catch (err) {}
} }
exports.createPortal = function(children, containerTag) { exports.createPortal = function(children, containerTag) {

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

@ -7,7 +7,7 @@
* @noflow * @noflow
* @nolint * @nolint
* @preventMunge * @preventMunge
* @generated SignedSource<<a71955225824e1ab165c975361c725ed>> * @generated SignedSource<<9613963109b67072417dfb9843578a9d>>
*/ */
"use strict"; "use strict";
@ -931,7 +931,7 @@ eventPluginOrder = Array.prototype.slice.call([
"ReactNativeBridgeEventPlugin" "ReactNativeBridgeEventPlugin"
]); ]);
recomputePluginOrdering(); recomputePluginOrdering();
var injectedNamesToPlugins$jscomp$inline_229 = { var injectedNamesToPlugins$jscomp$inline_230 = {
ResponderEventPlugin: ResponderEventPlugin, ResponderEventPlugin: ResponderEventPlugin,
ReactNativeBridgeEventPlugin: { ReactNativeBridgeEventPlugin: {
eventTypes: {}, eventTypes: {},
@ -966,34 +966,34 @@ var injectedNamesToPlugins$jscomp$inline_229 = {
} }
} }
}, },
isOrderingDirty$jscomp$inline_230 = !1, isOrderingDirty$jscomp$inline_231 = !1,
pluginName$jscomp$inline_231; pluginName$jscomp$inline_232;
for (pluginName$jscomp$inline_231 in injectedNamesToPlugins$jscomp$inline_229) for (pluginName$jscomp$inline_232 in injectedNamesToPlugins$jscomp$inline_230)
if ( if (
injectedNamesToPlugins$jscomp$inline_229.hasOwnProperty( injectedNamesToPlugins$jscomp$inline_230.hasOwnProperty(
pluginName$jscomp$inline_231 pluginName$jscomp$inline_232
) )
) { ) {
var pluginModule$jscomp$inline_232 = var pluginModule$jscomp$inline_233 =
injectedNamesToPlugins$jscomp$inline_229[pluginName$jscomp$inline_231]; injectedNamesToPlugins$jscomp$inline_230[pluginName$jscomp$inline_232];
if ( if (
!namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_231) || !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_232) ||
namesToPlugins[pluginName$jscomp$inline_231] !== namesToPlugins[pluginName$jscomp$inline_232] !==
pluginModule$jscomp$inline_232 pluginModule$jscomp$inline_233
) { ) {
if (namesToPlugins[pluginName$jscomp$inline_231]) if (namesToPlugins[pluginName$jscomp$inline_232])
throw Error( throw Error(
"EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" +
pluginName$jscomp$inline_231 + pluginName$jscomp$inline_232 +
"`." "`."
); );
namesToPlugins[ namesToPlugins[
pluginName$jscomp$inline_231 pluginName$jscomp$inline_232
] = pluginModule$jscomp$inline_232; ] = pluginModule$jscomp$inline_233;
isOrderingDirty$jscomp$inline_230 = !0; isOrderingDirty$jscomp$inline_231 = !0;
} }
} }
isOrderingDirty$jscomp$inline_230 && recomputePluginOrdering(); isOrderingDirty$jscomp$inline_231 && recomputePluginOrdering();
function getInstanceFromInstance(instanceHandle) { function getInstanceFromInstance(instanceHandle) {
return instanceHandle; return instanceHandle;
} }
@ -1781,6 +1781,9 @@ function getLanesToRetrySynchronouslyOnError(root) {
root = root.pendingLanes & -1073741825; root = root.pendingLanes & -1073741825;
return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0;
} }
function includesBlockingLane(root, lanes) {
return 0 !== (root.current.mode & 32) ? !1 : 0 !== (lanes & 30);
}
function createLaneMap(initial) { function createLaneMap(initial) {
for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial);
return laneMap; return laneMap;
@ -2133,7 +2136,11 @@ function invalidateContextProvider(workInProgress, type, didChange) {
: pop(didPerformWorkStackCursor); : pop(didPerformWorkStackCursor);
push(didPerformWorkStackCursor, didChange); push(didPerformWorkStackCursor, didChange);
} }
var syncQueue = null, function is(x, y) {
return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
}
var objectIs = "function" === typeof Object.is ? Object.is : is,
syncQueue = null,
includesLegacySyncCallbacks = !1, includesLegacySyncCallbacks = !1,
isFlushingSyncQueue = !1; isFlushingSyncQueue = !1;
function flushSyncCallbacks() { function flushSyncCallbacks() {
@ -2162,10 +2169,6 @@ function flushSyncCallbacks() {
return null; return null;
} }
var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig;
function is(x, y) {
return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
}
var objectIs = "function" === typeof Object.is ? Object.is : is;
function shallowEqual(objA, objB) { function shallowEqual(objA, objB) {
if (objectIs(objA, objB)) return !0; if (objectIs(objA, objB)) return !0;
if ( if (
@ -2450,7 +2453,7 @@ function processUpdateQueue(
newState = workInProgress; newState = workInProgress;
break a; break a;
case 3: case 3:
workInProgress.flags = (workInProgress.flags & -16385) | 128; workInProgress.flags = (workInProgress.flags & -32769) | 128;
case 0: case 0:
workInProgress = update.payload; workInProgress = update.payload;
updateLane = updateLane =
@ -3681,42 +3684,52 @@ function updateMutableSource(source, getSnapshot, subscribe) {
return useMutableSource(hook, source, getSnapshot, subscribe); return useMutableSource(hook, source, getSnapshot, subscribe);
} }
function mountSyncExternalStore(subscribe, getSnapshot) { function mountSyncExternalStore(subscribe, getSnapshot) {
var hook = mountWorkInProgressHook(), var fiber = currentlyRenderingFiber$1,
hook = mountWorkInProgressHook(),
nextSnapshot = getSnapshot(); nextSnapshot = getSnapshot();
hook.memoizedState = nextSnapshot; hook.memoizedState = nextSnapshot;
var inst = { value: nextSnapshot, getSnapshot: getSnapshot }; var inst = { value: nextSnapshot, getSnapshot: getSnapshot };
hook.queue = inst; hook.queue = inst;
return useSyncExternalStore(hook, inst, subscribe, getSnapshot, nextSnapshot); mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]);
} fiber.flags |= 1024;
function useSyncExternalStore( pushEffect(
hook, 9,
inst, updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot),
subscribe, void 0,
getSnapshot, null
nextSnapshot
) {
var fiber = currentlyRenderingFiber$1;
hook = ReactCurrentDispatcher$1.current;
hook.useLayoutEffect(
function() {
inst.value = nextSnapshot;
inst.getSnapshot = getSnapshot;
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
},
[subscribe, nextSnapshot, getSnapshot]
);
hook.useEffect(
function() {
function handleStoreChange() {
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
}
handleStoreChange();
return subscribe(handleStoreChange);
},
[subscribe]
); );
subscribe = workInProgressRoot;
if (null === subscribe)
throw Error(
"Expected a work-in-progress root. This is a bug in React. Please file an issue."
);
includesBlockingLane(subscribe, renderLanes) ||
pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
return nextSnapshot; return nextSnapshot;
} }
function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) {
fiber.flags |= 8192;
fiber = { getSnapshot: getSnapshot, value: renderedSnapshot };
getSnapshot = currentlyRenderingFiber$1.updateQueue;
null === getSnapshot
? ((getSnapshot = { lastEffect: null, stores: null }),
(currentlyRenderingFiber$1.updateQueue = getSnapshot),
(getSnapshot.stores = [fiber]))
: ((renderedSnapshot = getSnapshot.stores),
null === renderedSnapshot
? (getSnapshot.stores = [fiber])
: renderedSnapshot.push(fiber));
}
function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) {
inst.value = nextSnapshot;
inst.getSnapshot = getSnapshot;
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
}
function subscribeToStore(fiber, inst, subscribe) {
return subscribe(function() {
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
});
}
function checkIfSnapshotChanged(inst) { function checkIfSnapshotChanged(inst) {
var latestGetSnapshot = inst.getSnapshot; var latestGetSnapshot = inst.getSnapshot;
inst = inst.value; inst = inst.value;
@ -3751,7 +3764,7 @@ function pushEffect(tag, create, destroy, deps) {
tag = { tag: tag, create: create, destroy: destroy, deps: deps, next: null }; tag = { tag: tag, create: create, destroy: destroy, deps: deps, next: null };
create = currentlyRenderingFiber$1.updateQueue; create = currentlyRenderingFiber$1.updateQueue;
null === create null === create
? ((create = { lastEffect: null }), ? ((create = { lastEffect: null, stores: null }),
(currentlyRenderingFiber$1.updateQueue = create), (currentlyRenderingFiber$1.updateQueue = create),
(create.lastEffect = tag.next = tag)) (create.lastEffect = tag.next = tag))
: ((destroy = create.lastEffect), : ((destroy = create.lastEffect),
@ -3792,13 +3805,16 @@ function updateEffectImpl(fiberFlags, hookFlags, create, deps) {
hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps); hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps);
} }
function mountEffect(create, deps) { function mountEffect(create, deps) {
return mountEffectImpl(1049600, 4, create, deps); return mountEffectImpl(2098176, 8, create, deps);
} }
function updateEffect(create, deps) { function updateEffect(create, deps) {
return updateEffectImpl(1024, 4, create, deps); return updateEffectImpl(1024, 8, create, deps);
}
function updateInsertionEffect(create, deps) {
return updateEffectImpl(4, 2, create, deps);
} }
function updateLayoutEffect(create, deps) { function updateLayoutEffect(create, deps) {
return updateEffectImpl(4, 2, create, deps); return updateEffectImpl(4, 4, create, deps);
} }
function imperativeHandleEffect(create, ref) { function imperativeHandleEffect(create, ref) {
if ("function" === typeof ref) if ("function" === typeof ref)
@ -3822,7 +3838,7 @@ function updateImperativeHandle(ref, create, deps) {
deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null; deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null;
return updateEffectImpl( return updateEffectImpl(
4, 4,
2, 4,
imperativeHandleEffect.bind(null, create, ref), imperativeHandleEffect.bind(null, create, ref),
deps deps
); );
@ -3940,6 +3956,7 @@ var ContextOnlyDispatcher = {
useContext: throwInvalidHookError, useContext: throwInvalidHookError,
useEffect: throwInvalidHookError, useEffect: throwInvalidHookError,
useImperativeHandle: throwInvalidHookError, useImperativeHandle: throwInvalidHookError,
useInsertionEffect: throwInvalidHookError,
useLayoutEffect: throwInvalidHookError, useLayoutEffect: throwInvalidHookError,
useMemo: throwInvalidHookError, useMemo: throwInvalidHookError,
useReducer: throwInvalidHookError, useReducer: throwInvalidHookError,
@ -3968,12 +3985,15 @@ var ContextOnlyDispatcher = {
deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null; deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null;
return mountEffectImpl( return mountEffectImpl(
4, 4,
2, 4,
imperativeHandleEffect.bind(null, create, ref), imperativeHandleEffect.bind(null, create, ref),
deps deps
); );
}, },
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
return mountEffectImpl(4, 4, create, deps);
},
useInsertionEffect: function(create, deps) {
return mountEffectImpl(4, 2, create, deps); return mountEffectImpl(4, 2, create, deps);
}, },
useMemo: function(nextCreate, deps) { useMemo: function(nextCreate, deps) {
@ -4056,6 +4076,7 @@ var ContextOnlyDispatcher = {
useContext: readContext, useContext: readContext,
useEffect: updateEffect, useEffect: updateEffect,
useImperativeHandle: updateImperativeHandle, useImperativeHandle: updateImperativeHandle,
useInsertionEffect: updateInsertionEffect,
useLayoutEffect: updateLayoutEffect, useLayoutEffect: updateLayoutEffect,
useMemo: updateMemo, useMemo: updateMemo,
useReducer: updateReducer, useReducer: updateReducer,
@ -4089,17 +4110,44 @@ var ContextOnlyDispatcher = {
}, },
useMutableSource: updateMutableSource, useMutableSource: updateMutableSource,
useSyncExternalStore: function(subscribe, getSnapshot) { useSyncExternalStore: function(subscribe, getSnapshot) {
var hook = updateWorkInProgressHook(), var fiber = currentlyRenderingFiber$1,
nextSnapshot = getSnapshot(); hook = updateWorkInProgressHook(),
objectIs(hook.memoizedState, nextSnapshot) || nextSnapshot = getSnapshot(),
snapshotChanged = !objectIs(hook.memoizedState, nextSnapshot);
snapshotChanged &&
((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0)); ((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0));
return useSyncExternalStore( hook = hook.queue;
hook, updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [
hook.queue, subscribe
subscribe, ]);
getSnapshot, if (
nextSnapshot hook.getSnapshot !== getSnapshot ||
); snapshotChanged ||
(null !== workInProgressHook &&
workInProgressHook.memoizedState.tag & 1)
) {
fiber.flags |= 1024;
pushEffect(
9,
updateStoreInstance.bind(
null,
fiber,
hook,
nextSnapshot,
getSnapshot
),
void 0,
null
);
subscribe = workInProgressRoot;
if (null === subscribe)
throw Error(
"Expected a work-in-progress root. This is a bug in React. Please file an issue."
);
includesBlockingLane(subscribe, renderLanes) ||
pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
}
return nextSnapshot;
}, },
useOpaqueIdentifier: function() { useOpaqueIdentifier: function() {
return updateReducer(basicStateReducer)[0]; return updateReducer(basicStateReducer)[0];
@ -4112,6 +4160,7 @@ var ContextOnlyDispatcher = {
useContext: readContext, useContext: readContext,
useEffect: updateEffect, useEffect: updateEffect,
useImperativeHandle: updateImperativeHandle, useImperativeHandle: updateImperativeHandle,
useInsertionEffect: updateInsertionEffect,
useLayoutEffect: updateLayoutEffect, useLayoutEffect: updateLayoutEffect,
useMemo: updateMemo, useMemo: updateMemo,
useReducer: rerenderReducer, useReducer: rerenderReducer,
@ -4477,8 +4526,8 @@ function bubbleProperties(completedWork) {
) )
(newChildLanes |= child$43.lanes | child$43.childLanes), (newChildLanes |= child$43.lanes | child$43.childLanes),
(subtreeFlags |= child$43.subtreeFlags & 1835008), (subtreeFlags |= child$43.subtreeFlags & 3670016),
(subtreeFlags |= child$43.flags & 1835008), (subtreeFlags |= child$43.flags & 3670016),
(treeBaseDuration$42 += child$43.treeBaseDuration), (treeBaseDuration$42 += child$43.treeBaseDuration),
(child$43 = child$43.sibling); (child$43 = child$43.sibling);
completedWork.treeBaseDuration = treeBaseDuration$42; completedWork.treeBaseDuration = treeBaseDuration$42;
@ -4490,8 +4539,8 @@ function bubbleProperties(completedWork) {
) )
(newChildLanes |= (newChildLanes |=
treeBaseDuration$42.lanes | treeBaseDuration$42.childLanes), treeBaseDuration$42.lanes | treeBaseDuration$42.childLanes),
(subtreeFlags |= treeBaseDuration$42.subtreeFlags & 1835008), (subtreeFlags |= treeBaseDuration$42.subtreeFlags & 3670016),
(subtreeFlags |= treeBaseDuration$42.flags & 1835008), (subtreeFlags |= treeBaseDuration$42.flags & 3670016),
(treeBaseDuration$42.return = completedWork), (treeBaseDuration$42.return = completedWork),
(treeBaseDuration$42 = treeBaseDuration$42.sibling); (treeBaseDuration$42 = treeBaseDuration$42.sibling);
else if (0 !== (completedWork.mode & 2)) { else if (0 !== (completedWork.mode & 2)) {
@ -4737,7 +4786,7 @@ function completeWork(current, workInProgress, renderLanes) {
for (newProps = workInProgress.child; null !== newProps; ) for (newProps = workInProgress.child; null !== newProps; )
(renderLanes = newProps), (renderLanes = newProps),
(renderedTail = current), (renderedTail = current),
(renderLanes.flags &= 1835010), (renderLanes.flags &= 3670018),
(type = renderLanes.alternate), (type = renderLanes.alternate),
null === type null === type
? ((renderLanes.childLanes = 0), ? ((renderLanes.childLanes = 0),
@ -4965,7 +5014,7 @@ function updateSimpleMemoComponent(
current.ref === workInProgress.ref current.ref === workInProgress.ref
) )
if (((didReceiveUpdate = !1), 0 !== (current.lanes & renderLanes))) if (((didReceiveUpdate = !1), 0 !== (current.lanes & renderLanes)))
0 !== (current.flags & 32768) && (didReceiveUpdate = !0); 0 !== (current.flags & 65536) && (didReceiveUpdate = !0);
else else
return ( return (
(workInProgress.lanes = current.lanes), (workInProgress.lanes = current.lanes),
@ -5596,7 +5645,7 @@ function updateSuspenseFallbackChildren(
primaryChildren primaryChildren
))), ))),
(current.subtreeFlags = (current.subtreeFlags =
currentPrimaryChildFragment.subtreeFlags & 1835008)); currentPrimaryChildFragment.subtreeFlags & 3670016));
null !== currentFallbackChildFragment null !== currentFallbackChildFragment
? (fallbackChildren = createWorkInProgress( ? (fallbackChildren = createWorkInProgress(
currentFallbackChildFragment, currentFallbackChildFragment,
@ -5832,8 +5881,8 @@ function unwindWork(workInProgress) {
case 1: case 1:
isContextProvider(workInProgress.type) && popContext(); isContextProvider(workInProgress.type) && popContext();
var flags = workInProgress.flags; var flags = workInProgress.flags;
return flags & 16384 return flags & 32768
? ((workInProgress.flags = (flags & -16385) | 128), ? ((workInProgress.flags = (flags & -32769) | 128),
0 !== (workInProgress.mode & 2) && 0 !== (workInProgress.mode & 2) &&
transferActualDuration(workInProgress), transferActualDuration(workInProgress),
workInProgress) workInProgress)
@ -5848,7 +5897,7 @@ function unwindWork(workInProgress) {
throw Error( throw Error(
"The root failed to unmount after an error. This is likely a bug in React. Please file an issue." "The root failed to unmount after an error. This is likely a bug in React. Please file an issue."
); );
workInProgress.flags = (flags & -16385) | 128; workInProgress.flags = (flags & -32769) | 128;
return workInProgress; return workInProgress;
case 5: case 5:
return popHostContext(workInProgress), null; return popHostContext(workInProgress), null;
@ -5856,8 +5905,8 @@ function unwindWork(workInProgress) {
return ( return (
pop(suspenseStackCursor), pop(suspenseStackCursor),
(flags = workInProgress.flags), (flags = workInProgress.flags),
flags & 16384 flags & 32768
? ((workInProgress.flags = (flags & -16385) | 128), ? ((workInProgress.flags = (flags & -32769) | 128),
0 !== (workInProgress.mode & 2) && 0 !== (workInProgress.mode & 2) &&
transferActualDuration(workInProgress), transferActualDuration(workInProgress),
workInProgress) workInProgress)
@ -6023,14 +6072,16 @@ function commitWork(current, finishedWork) {
case 11: case 11:
case 14: case 14:
case 15: case 15:
commitHookEffectListUnmount(3, finishedWork, finishedWork.return);
commitHookEffectListMount(3, finishedWork);
if (finishedWork.mode & 2) if (finishedWork.mode & 2)
try { try {
startLayoutEffectTimer(), startLayoutEffectTimer(),
commitHookEffectListUnmount(3, finishedWork, finishedWork.return); commitHookEffectListUnmount(5, finishedWork, finishedWork.return);
} finally { } finally {
recordLayoutEffectDuration(finishedWork); recordLayoutEffectDuration(finishedWork);
} }
else commitHookEffectListUnmount(3, finishedWork, finishedWork.return); else commitHookEffectListUnmount(5, finishedWork, finishedWork.return);
return; return;
case 12: case 12:
return; return;
@ -6120,8 +6171,8 @@ function commitMutationEffects(root, firstChild, committedLanes) {
var _effect = effect, var _effect = effect,
destroy = _effect.destroy, destroy = _effect.destroy,
tag = _effect.tag; tag = _effect.tag;
void 0 !== destroy && void 0 === destroy ||
0 !== (tag & 2) && (0 === (tag & 2) && 0 === (tag & 4)) ||
(current.mode & 2 (current.mode & 2
? (startLayoutEffectTimer(), ? (startLayoutEffectTimer(),
safelyCallDestroy(current, root, destroy), safelyCallDestroy(current, root, destroy),
@ -6271,11 +6322,11 @@ function commitLayoutEffects(finishedWork, root, committedLanes) {
if (committedLanes.mode & 2) if (committedLanes.mode & 2)
try { try {
startLayoutEffectTimer(), startLayoutEffectTimer(),
commitHookEffectListMount(3, committedLanes); commitHookEffectListMount(5, committedLanes);
} finally { } finally {
recordLayoutEffectDuration(committedLanes); recordLayoutEffectDuration(committedLanes);
} }
else commitHookEffectListMount(3, committedLanes); else commitHookEffectListMount(5, committedLanes);
break; break;
case 1: case 1:
var instance = committedLanes.stateNode; var instance = committedLanes.stateNode;
@ -6629,15 +6680,15 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
root === workInProgressRoot ? workInProgressRootRenderLanes : 0 root === workInProgressRoot ? workInProgressRootRenderLanes : 0
); );
if (0 === lanes) return null; if (0 === lanes) return null;
var JSCompiler_inline_result = if (
0 !== (lanes & root.expiredLanes) includesBlockingLane(root, lanes) ||
? !1 0 !== (lanes & root.expiredLanes) ||
: 0 !== (root.current.mode & 32) didTimeout
? !0 )
: 0 === (lanes & 30); didTimeout = renderRootSync(root, lanes);
if (JSCompiler_inline_result && !didTimeout) { else {
didTimeout = lanes; didTimeout = lanes;
JSCompiler_inline_result = executionContext; var prevExecutionContext = executionContext;
executionContext |= 2; executionContext |= 2;
var prevDispatcher = pushDispatcher(); var prevDispatcher = pushDispatcher();
if ( if (
@ -6664,30 +6715,44 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
while (1); while (1);
resetContextDependencies(); resetContextDependencies();
ReactCurrentDispatcher$2.current = prevDispatcher; ReactCurrentDispatcher$2.current = prevDispatcher;
executionContext = JSCompiler_inline_result; executionContext = prevExecutionContext;
null !== workInProgress null !== workInProgress
? (didTimeout = 0) ? (didTimeout = 0)
: ((workInProgressRoot = null), : ((workInProgressRoot = null),
(workInProgressRootRenderLanes = 0), (workInProgressRootRenderLanes = 0),
(didTimeout = workInProgressRootExitStatus)); (didTimeout = workInProgressRootExitStatus));
} else didTimeout = renderRootSync(root, lanes); }
if (0 !== didTimeout) { if (0 !== didTimeout) {
2 === didTimeout && 2 === didTimeout &&
((JSCompiler_inline_result = executionContext), ((prevExecutionContext = getLanesToRetrySynchronouslyOnError(root)),
(executionContext |= 8), 0 !== prevExecutionContext &&
root.hydrate && ((root.hydrate = !1), shim(root.containerInfo)), ((lanes = prevExecutionContext),
(prevDispatcher = getLanesToRetrySynchronouslyOnError(root)), (didTimeout = recoverFromConcurrentError(root, prevExecutionContext))));
0 !== prevDispatcher &&
((lanes = prevDispatcher),
(didTimeout = renderRootSync(root, prevDispatcher))),
(executionContext = JSCompiler_inline_result));
if (1 === didTimeout) if (1 === didTimeout)
throw ((originalCallbackNode = workInProgressRootFatalError), throw ((originalCallbackNode = workInProgressRootFatalError),
prepareFreshStack(root, 0), prepareFreshStack(root, 0),
markRootSuspended$1(root, lanes), markRootSuspended$1(root, lanes),
ensureRootIsScheduled(root, now()), ensureRootIsScheduled(root, now()),
originalCallbackNode); originalCallbackNode);
root.finishedWork = root.current.alternate; prevDispatcher = !includesBlockingLane(root, lanes);
prevExecutionContext = root.current.alternate;
if (
prevDispatcher &&
!isRenderConsistentWithExternalStores(prevExecutionContext) &&
((didTimeout = renderRootSync(root, lanes)),
2 === didTimeout &&
((prevDispatcher = getLanesToRetrySynchronouslyOnError(root)),
0 !== prevDispatcher &&
((lanes = prevDispatcher),
(didTimeout = recoverFromConcurrentError(root, prevDispatcher)))),
1 === didTimeout)
)
throw ((originalCallbackNode = workInProgressRootFatalError),
prepareFreshStack(root, 0),
markRootSuspended$1(root, lanes),
ensureRootIsScheduled(root, now()),
originalCallbackNode);
root.finishedWork = prevExecutionContext;
root.finishedLanes = lanes; root.finishedLanes = lanes;
switch (didTimeout) { switch (didTimeout) {
case 0: case 0:
@ -6704,10 +6769,10 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
10 < didTimeout) 10 < didTimeout)
) { ) {
if (0 !== getNextLanes(root, 0)) break; if (0 !== getNextLanes(root, 0)) break;
JSCompiler_inline_result = root.suspendedLanes; prevExecutionContext = root.suspendedLanes;
if ((JSCompiler_inline_result & lanes) !== lanes) { if ((prevExecutionContext & lanes) !== lanes) {
requestEventTime(); requestEventTime();
root.pingedLanes |= root.suspendedLanes & JSCompiler_inline_result; root.pingedLanes |= root.suspendedLanes & prevExecutionContext;
break; break;
} }
root.timeoutHandle = scheduleTimeout( root.timeoutHandle = scheduleTimeout(
@ -6722,14 +6787,14 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
markRootSuspended$1(root, lanes); markRootSuspended$1(root, lanes);
if ((lanes & 4194240) === lanes) break; if ((lanes & 4194240) === lanes) break;
didTimeout = root.eventTimes; didTimeout = root.eventTimes;
for (JSCompiler_inline_result = -1; 0 < lanes; ) for (prevExecutionContext = -1; 0 < lanes; )
(memoizedUpdaters = 31 - clz32(lanes)), (memoizedUpdaters = 31 - clz32(lanes)),
(prevDispatcher = 1 << memoizedUpdaters), (prevDispatcher = 1 << memoizedUpdaters),
(memoizedUpdaters = didTimeout[memoizedUpdaters]), (memoizedUpdaters = didTimeout[memoizedUpdaters]),
memoizedUpdaters > JSCompiler_inline_result && memoizedUpdaters > prevExecutionContext &&
(JSCompiler_inline_result = memoizedUpdaters), (prevExecutionContext = memoizedUpdaters),
(lanes &= ~prevDispatcher); (lanes &= ~prevDispatcher);
lanes = JSCompiler_inline_result; lanes = prevExecutionContext;
lanes = now() - lanes; lanes = now() - lanes;
lanes = lanes =
(120 > lanes (120 > lanes
@ -6766,6 +6831,48 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
? performConcurrentWorkOnRoot.bind(null, root) ? performConcurrentWorkOnRoot.bind(null, root)
: null; : null;
} }
function recoverFromConcurrentError(root, errorRetryLanes) {
var prevExecutionContext = executionContext;
executionContext |= 8;
root.hydrate && ((root.hydrate = !1), shim(root.containerInfo));
root = renderRootSync(root, errorRetryLanes);
executionContext = prevExecutionContext;
return root;
}
function isRenderConsistentWithExternalStores(finishedWork) {
for (var node = finishedWork; ; ) {
if (node.flags & 8192) {
var updateQueue = node.updateQueue;
if (
null !== updateQueue &&
((updateQueue = updateQueue.stores), null !== updateQueue)
)
for (var i = 0; i < updateQueue.length; i++) {
var check = updateQueue[i],
getSnapshot = check.getSnapshot;
check = check.value;
try {
if (!objectIs(getSnapshot(), check)) return !1;
} catch (error) {
return !1;
}
}
}
updateQueue = node.child;
if (node.subtreeFlags & 8192 && null !== updateQueue)
(updateQueue.return = node), (node = updateQueue);
else {
if (node === finishedWork) break;
for (; null === node.sibling; ) {
if (null === node.return || node.return === finishedWork) return !0;
node = node.return;
}
node.sibling.return = node.return;
node = node.sibling;
}
}
return !0;
}
function markRootSuspended$1(root, suspendedLanes) { function markRootSuspended$1(root, suspendedLanes) {
suspendedLanes &= ~workInProgressRootPingedLanes; suspendedLanes &= ~workInProgressRootPingedLanes;
suspendedLanes &= ~workInProgressRootUpdatedLanes; suspendedLanes &= ~workInProgressRootUpdatedLanes;
@ -6917,7 +7024,7 @@ function handleError(root$jscomp$0, thrownValue) {
sourceFiber = erroredWork, sourceFiber = erroredWork,
value = thrownValue; value = thrownValue;
thrownValue = workInProgressRootRenderLanes; thrownValue = workInProgressRootRenderLanes;
sourceFiber.flags |= 8192; sourceFiber.flags |= 16384;
isDevToolsPresent && restorePendingUpdaters(root, thrownValue); isDevToolsPresent && restorePendingUpdaters(root, thrownValue);
if ( if (
null !== value && null !== value &&
@ -6969,8 +7076,8 @@ function handleError(root$jscomp$0, thrownValue) {
workInProgress$32 !== returnFiber workInProgress$32 !== returnFiber
) { ) {
workInProgress$32.flags |= 128; workInProgress$32.flags |= 128;
sourceFiber.flags |= 32768; sourceFiber.flags |= 65536;
sourceFiber.flags &= -10053; sourceFiber.flags &= -26437;
if ( if (
enablePersistentOffscreenHostContainer && enablePersistentOffscreenHostContainer &&
null === workInProgress$32.alternate null === workInProgress$32.alternate
@ -7016,7 +7123,7 @@ function handleError(root$jscomp$0, thrownValue) {
isDevToolsPresent && restorePendingUpdaters(root, sourceFiber); isDevToolsPresent && restorePendingUpdaters(root, sourceFiber);
wakeable.then(ping, ping); wakeable.then(ping, ping);
} }
workInProgress$32.flags |= 16384; workInProgress$32.flags |= 32768;
workInProgress$32.lanes = thrownValue; workInProgress$32.lanes = thrownValue;
break a; break a;
} }
@ -7035,7 +7142,7 @@ function handleError(root$jscomp$0, thrownValue) {
switch (workInProgress$32.tag) { switch (workInProgress$32.tag) {
case 3: case 3:
root = value; root = value;
workInProgress$32.flags |= 16384; workInProgress$32.flags |= 32768;
thrownValue &= -thrownValue; thrownValue &= -thrownValue;
workInProgress$32.lanes |= thrownValue; workInProgress$32.lanes |= thrownValue;
var update$33 = createRootErrorUpdate( var update$33 = createRootErrorUpdate(
@ -7057,7 +7164,7 @@ function handleError(root$jscomp$0, thrownValue) {
(null === legacyErrorBoundariesThatAlreadyFailed || (null === legacyErrorBoundariesThatAlreadyFailed ||
!legacyErrorBoundariesThatAlreadyFailed.has(instance)))) !legacyErrorBoundariesThatAlreadyFailed.has(instance))))
) { ) {
workInProgress$32.flags |= 16384; workInProgress$32.flags |= 32768;
thrownValue &= -thrownValue; thrownValue &= -thrownValue;
workInProgress$32.lanes |= thrownValue; workInProgress$32.lanes |= thrownValue;
var update$36 = createClassErrorUpdate( var update$36 = createClassErrorUpdate(
@ -7147,7 +7254,7 @@ function completeUnitOfWork(unitOfWork) {
do { do {
var current = completedWork.alternate; var current = completedWork.alternate;
unitOfWork = completedWork.return; unitOfWork = completedWork.return;
if (0 === (completedWork.flags & 8192)) { if (0 === (completedWork.flags & 16384)) {
if (0 === (completedWork.mode & 2)) if (0 === (completedWork.mode & 2))
current = completeWork(current, completedWork, subtreeRenderLanes); current = completeWork(current, completedWork, subtreeRenderLanes);
else { else {
@ -7164,7 +7271,7 @@ function completeUnitOfWork(unitOfWork) {
} else { } else {
current = unwindWork(completedWork); current = unwindWork(completedWork);
if (null !== current) { if (null !== current) {
current.flags &= 8191; current.flags &= 16383;
workInProgress = current; workInProgress = current;
return; return;
} }
@ -7176,7 +7283,7 @@ function completeUnitOfWork(unitOfWork) {
completedWork.actualDuration = current; completedWork.actualDuration = current;
} }
null !== unitOfWork && null !== unitOfWork &&
((unitOfWork.flags |= 8192), ((unitOfWork.flags |= 16384),
(unitOfWork.subtreeFlags = 0), (unitOfWork.subtreeFlags = 0),
(unitOfWork.deletions = null)); (unitOfWork.deletions = null));
} }
@ -7256,12 +7363,6 @@ function commitRootImpl(root, renderPriorityLevel) {
(pendingPassiveEffectsLanes = lanes)); (pendingPassiveEffectsLanes = lanes));
remainingLanes = root.pendingLanes; remainingLanes = root.pendingLanes;
0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null);
0 !== (remainingLanes & 1)
? ((nestedUpdateScheduled = !0),
root === rootWithNestedUpdates
? nestedUpdateCount++
: ((nestedUpdateCount = 0), (rootWithNestedUpdates = root)))
: (nestedUpdateCount = 0);
onCommitRoot(finishedWork.stateNode, renderPriorityLevel); onCommitRoot(finishedWork.stateNode, renderPriorityLevel);
isDevToolsPresent && root.memoizedUpdaters.clear(); isDevToolsPresent && root.memoizedUpdaters.clear();
ensureRootIsScheduled(root, now()); ensureRootIsScheduled(root, now());
@ -7273,6 +7374,13 @@ function commitRootImpl(root, renderPriorityLevel) {
0 !== (pendingPassiveEffectsLanes & 1) && 0 !== (pendingPassiveEffectsLanes & 1) &&
0 !== root.tag && 0 !== root.tag &&
flushPassiveEffects(); flushPassiveEffects();
remainingLanes = root.pendingLanes;
0 !== (remainingLanes & 1)
? ((nestedUpdateScheduled = !0),
root === rootWithNestedUpdates
? nestedUpdateCount++
: ((nestedUpdateCount = 0), (rootWithNestedUpdates = root)))
: (nestedUpdateCount = 0);
flushSyncCallbacks(); flushSyncCallbacks();
return null; return null;
} }
@ -7311,9 +7419,9 @@ function flushPassiveEffects() {
case 15: case 15:
current.mode & 2 current.mode & 2
? ((passiveEffectStartTime = now$1()), ? ((passiveEffectStartTime = now$1()),
commitHookEffectListUnmount(4, current, fiber), commitHookEffectListUnmount(8, current, fiber),
recordPassiveEffectDuration(current)) recordPassiveEffectDuration(current))
: commitHookEffectListUnmount(4, current, fiber); : commitHookEffectListUnmount(8, current, fiber);
} }
var child$jscomp$0 = fiber$jscomp$0.child; var child$jscomp$0 = fiber$jscomp$0.child;
if (null !== child$jscomp$0) if (null !== child$jscomp$0)
@ -7365,9 +7473,9 @@ function flushPassiveEffects() {
case 15: case 15:
i.mode & 2 i.mode & 2
? ((passiveEffectStartTime = now$1()), ? ((passiveEffectStartTime = now$1()),
commitHookEffectListUnmount(5, i, i.return), commitHookEffectListUnmount(9, i, i.return),
recordPassiveEffectDuration(i)) recordPassiveEffectDuration(i))
: commitHookEffectListUnmount(5, i, i.return); : commitHookEffectListUnmount(9, i, i.return);
} }
var sibling$jscomp$0 = fiber.sibling; var sibling$jscomp$0 = fiber.sibling;
if (null !== sibling$jscomp$0) { if (null !== sibling$jscomp$0) {
@ -7396,11 +7504,11 @@ function flushPassiveEffects() {
if (fiberToDelete.mode & 2) { if (fiberToDelete.mode & 2) {
passiveEffectStartTime = now$1(); passiveEffectStartTime = now$1();
try { try {
commitHookEffectListMount(5, fiberToDelete); commitHookEffectListMount(9, fiberToDelete);
} finally { } finally {
recordPassiveEffectDuration(fiberToDelete); recordPassiveEffectDuration(fiberToDelete);
} }
} else commitHookEffectListMount(5, fiberToDelete); } else commitHookEffectListMount(9, fiberToDelete);
} }
} catch (error) { } catch (error) {
captureCommitPhaseError(deletions, deletions.return, error); captureCommitPhaseError(deletions, deletions.return, error);
@ -7595,7 +7703,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) {
renderLanes renderLanes
) )
); );
didReceiveUpdate = 0 !== (current.flags & 32768) ? !0 : !1; didReceiveUpdate = 0 !== (current.flags & 65536) ? !0 : !1;
} }
else didReceiveUpdate = !1; else didReceiveUpdate = !1;
workInProgress.lanes = 0; workInProgress.lanes = 0;
@ -8076,7 +8184,7 @@ function createWorkInProgress(current, pendingProps) {
(workInProgress.deletions = null), (workInProgress.deletions = null),
(workInProgress.actualDuration = 0), (workInProgress.actualDuration = 0),
(workInProgress.actualStartTime = -1)); (workInProgress.actualStartTime = -1));
workInProgress.flags = current.flags & 1835008; workInProgress.flags = current.flags & 3670016;
workInProgress.childLanes = current.childLanes; workInProgress.childLanes = current.childLanes;
workInProgress.lanes = current.lanes; workInProgress.lanes = current.lanes;
workInProgress.child = current.child; workInProgress.child = current.child;
@ -8440,10 +8548,10 @@ batchedUpdatesImpl = function(fn, a) {
} }
}; };
var roots = new Map(), var roots = new Map(),
devToolsConfig$jscomp$inline_983 = { devToolsConfig$jscomp$inline_980 = {
findFiberByHostInstance: getInstanceFromInstance, findFiberByHostInstance: getInstanceFromInstance,
bundleType: 0, bundleType: 0,
version: "18.0.0-95d762e40-20210908", version: "18.0.0-e8feb11b6-20210915",
rendererPackageName: "react-native-renderer", rendererPackageName: "react-native-renderer",
rendererConfig: { rendererConfig: {
getInspectorDataForViewTag: function() { getInspectorDataForViewTag: function() {
@ -8458,11 +8566,11 @@ var roots = new Map(),
}.bind(null, findNodeHandle) }.bind(null, findNodeHandle)
} }
}; };
var internals$jscomp$inline_1244 = { var internals$jscomp$inline_1241 = {
bundleType: devToolsConfig$jscomp$inline_983.bundleType, bundleType: devToolsConfig$jscomp$inline_980.bundleType,
version: devToolsConfig$jscomp$inline_983.version, version: devToolsConfig$jscomp$inline_980.version,
rendererPackageName: devToolsConfig$jscomp$inline_983.rendererPackageName, rendererPackageName: devToolsConfig$jscomp$inline_980.rendererPackageName,
rendererConfig: devToolsConfig$jscomp$inline_983.rendererConfig, rendererConfig: devToolsConfig$jscomp$inline_980.rendererConfig,
overrideHookState: null, overrideHookState: null,
overrideHookStateDeletePath: null, overrideHookStateDeletePath: null,
overrideHookStateRenamePath: null, overrideHookStateRenamePath: null,
@ -8478,7 +8586,7 @@ var internals$jscomp$inline_1244 = {
return null === fiber ? null : fiber.stateNode; return null === fiber ? null : fiber.stateNode;
}, },
findFiberByHostInstance: findFiberByHostInstance:
devToolsConfig$jscomp$inline_983.findFiberByHostInstance || devToolsConfig$jscomp$inline_980.findFiberByHostInstance ||
emptyFindFiberByHostInstance, emptyFindFiberByHostInstance,
findHostInstancesForRefresh: null, findHostInstancesForRefresh: null,
scheduleRefresh: null, scheduleRefresh: null,
@ -8486,19 +8594,19 @@ var internals$jscomp$inline_1244 = {
setRefreshHandler: null, setRefreshHandler: null,
getCurrentFiber: null, getCurrentFiber: null,
getIsStrictMode: null, getIsStrictMode: null,
reconcilerVersion: "18.0.0-95d762e40-20210908" reconcilerVersion: "18.0.0-e8feb11b6-20210915"
}; };
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1245 = __REACT_DEVTOOLS_GLOBAL_HOOK__; var hook$jscomp$inline_1242 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
if ( if (
!hook$jscomp$inline_1245.isDisabled && !hook$jscomp$inline_1242.isDisabled &&
hook$jscomp$inline_1245.supportsFiber hook$jscomp$inline_1242.supportsFiber
) )
try { try {
(rendererID = hook$jscomp$inline_1245.inject( (rendererID = hook$jscomp$inline_1242.inject(
internals$jscomp$inline_1244 internals$jscomp$inline_1241
)), )),
(injectedHook = hook$jscomp$inline_1245); (injectedHook = hook$jscomp$inline_1242);
} catch (err) {} } catch (err) {}
} }
exports.createPortal = function(children, containerTag) { exports.createPortal = function(children, containerTag) {

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

@ -7,7 +7,7 @@
* @noflow * @noflow
* @nolint * @nolint
* @preventMunge * @preventMunge
* @generated SignedSource<<0aa534c810fde3c5289b4c849e474d9e>> * @generated SignedSource<<f868e099a07acdc3cfb6e5c0b1efcb0d>>
*/ */
'use strict'; 'use strict';
@ -3140,6 +3140,7 @@ var enableProfilerTimer = true;
var enableProfilerCommitHooks = true; var enableProfilerCommitHooks = true;
var enableLazyElements = false; var enableLazyElements = false;
var warnAboutStringRefs = false; var warnAboutStringRefs = false;
var warnOnSubscriptionInsideStartTransition = false;
var enableNewReconciler = false; var enableNewReconciler = false;
var enableLazyContextPropagation = false; var enableLazyContextPropagation = false;
@ -3190,21 +3191,25 @@ var HydratingAndUpdate =
var Visibility = var Visibility =
/* */ /* */
4096; 4096;
var LifecycleEffectMask = Passive | Update | Callback | Ref | Snapshot; // Union of all commit flags (flags with the lifetime of a particular commit) var StoreConsistency =
/* */
8192;
var LifecycleEffectMask =
Passive | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit)
var HostEffectMask = var HostEffectMask =
/* */ /* */
8191; // These are not really side effects, but we still reuse this field. 16383; // These are not really side effects, but we still reuse this field.
var Incomplete = var Incomplete =
/* */ /* */
8192; 16384;
var ShouldCapture = var ShouldCapture =
/* */ /* */
16384; 32768;
var ForceUpdateForLegacySuspense = var ForceUpdateForLegacySuspense =
/* */ /* */
32768; 65536;
// e.g. a fiber uses a passive effect (even if there are no updates on this particular render). // e.g. a fiber uses a passive effect (even if there are no updates on this particular render).
// This enables us to defer more work in the unmount case, // This enables us to defer more work in the unmount case,
// since we can defer traversing the tree during layout to look for Passive effects, // since we can defer traversing the tree during layout to look for Passive effects,
@ -3212,22 +3217,22 @@ var ForceUpdateForLegacySuspense =
var RefStatic = var RefStatic =
/* */ /* */
262144; 524288;
var LayoutStatic = var LayoutStatic =
/* */ /* */
524288; 1048576;
var PassiveStatic = var PassiveStatic =
/* */ /* */
1048576; // These flags allow us to traverse to fibers that have effects on mount 2097152; // These flags allow us to traverse to fibers that have effects on mount
// without traversing the entire tree after every commit for // without traversing the entire tree after every commit for
// double invoking // double invoking
var MountLayoutDev = var MountLayoutDev =
/* */ /* */
2097152; 4194304;
var MountPassiveDev = var MountPassiveDev =
/* */ /* */
4194304; // Groups of flags that are used in the commit phase to skip over trees that 8388608; // Groups of flags that are used in the commit phase to skip over trees that
// don't contain effects, by checking subtreeFlags. // don't contain effects, by checking subtreeFlags.
var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility
@ -4742,16 +4747,10 @@ function includesOnlyRetries(lanes) {
function includesOnlyTransitions(lanes) { function includesOnlyTransitions(lanes) {
return (lanes & TransitionLanes) === lanes; return (lanes & TransitionLanes) === lanes;
} }
function shouldTimeSlice(root, lanes) { function includesBlockingLane(root, lanes) {
if ((lanes & root.expiredLanes) !== NoLanes) {
// At least one of these lanes expired. To prevent additional starvation,
// finish rendering without yielding execution.
return false;
}
if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode) { if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode) {
// Concurrent updates by default always use time slicing. // Concurrent updates by default always use time slicing.
return true; return false;
} }
var SyncDefaultLanes = var SyncDefaultLanes =
@ -4759,7 +4758,12 @@ function shouldTimeSlice(root, lanes) {
InputContinuousLane | InputContinuousLane |
DefaultHydrationLane | DefaultHydrationLane |
DefaultLane; DefaultLane;
return (lanes & SyncDefaultLanes) === NoLanes; return (lanes & SyncDefaultLanes) !== NoLanes;
}
function includesExpiredLane(root, lanes) {
// This is a separate check from includesBlockingLane because a lane can
// expire after a render has already started.
return (lanes & root.expiredLanes) !== NoLanes;
} }
function isTransitionLane(lane) { function isTransitionLane(lane) {
return (lane & TransitionLanes) !== 0; return (lane & TransitionLanes) !== 0;
@ -6069,6 +6073,18 @@ function findCurrentUnmaskedContext(fiber) {
var LegacyRoot = 0; var LegacyRoot = 0;
var ConcurrentRoot = 1; var ConcurrentRoot = 1;
/**
* inlined Object.is polyfill to avoid requiring consumers ship their own
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
*/
function is(x, y) {
return (
(x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare
);
}
var objectIs = typeof Object.is === "function" ? Object.is : is;
var syncQueue = null; var syncQueue = null;
var includesLegacySyncCallbacks = false; var includesLegacySyncCallbacks = false;
var isFlushingSyncQueue = false; var isFlushingSyncQueue = false;
@ -6138,7 +6154,7 @@ function flushSyncCallbacks() {
return null; return null;
} }
var ReactVersion = "18.0.0-95d762e40-20210908"; var ReactVersion = "18.0.0-e8feb11b6-20210915";
var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig;
var NoTransition = 0; var NoTransition = 0;
@ -6146,18 +6162,6 @@ function requestCurrentTransition() {
return ReactCurrentBatchConfig.transition; return ReactCurrentBatchConfig.transition;
} }
/**
* inlined Object.is polyfill to avoid requiring consumers ship their own
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
*/
function is(x, y) {
return (
(x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare
);
}
var objectIs = typeof Object.is === "function" ? Object.is : is;
/** /**
* Performs equality by iterating through keys on an object and returning false * Performs equality by iterating through keys on an object and returning false
* when any key has values which are not strictly equal between the arguments. * when any key has values which are not strictly equal between the arguments.
@ -10092,19 +10096,22 @@ function findFirstSuspended(row) {
} }
var NoFlags$1 = var NoFlags$1 =
/* */ /* */
0; // Represents whether effect should fire. 0; // Represents whether effect should fire.
var HasEffect = var HasEffect =
/* */ /* */
1; // Represents the phase in which the effect (not the clean-up) fires. 1; // Represents the phase in which the effect (not the clean-up) fires.
var Insertion =
/* */
2;
var Layout = var Layout =
/* */ /* */
2; 4;
var Passive$1 = var Passive$1 =
/* */ /* */
4; 8;
var isHydrating = false; var isHydrating = false;
@ -10667,7 +10674,8 @@ function updateWorkInProgressHook() {
function createFunctionComponentUpdateQueue() { function createFunctionComponentUpdateQueue() {
return { return {
lastEffect: null lastEffect: null,
stores: null
}; };
} }
@ -11196,6 +11204,7 @@ function updateMutableSource(source, getSnapshot, subscribe) {
} }
function mountSyncExternalStore(subscribe, getSnapshot) { function mountSyncExternalStore(subscribe, getSnapshot) {
var fiber = currentlyRenderingFiber$1;
var hook = mountWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the var hook = mountWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the
// normal rules of React, and only works because store updates are // normal rules of React, and only works because store updates are
// always synchronous. // always synchronous.
@ -11219,11 +11228,43 @@ function mountSyncExternalStore(subscribe, getSnapshot) {
value: nextSnapshot, value: nextSnapshot,
getSnapshot: getSnapshot getSnapshot: getSnapshot
}; };
hook.queue = inst; hook.queue = inst; // Schedule an effect to subscribe to the store.
return useSyncExternalStore(hook, inst, subscribe, getSnapshot, nextSnapshot);
mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]); // Schedule an effect to update the mutable instance fields. We will update
// this whenever subscribe, getSnapshot, or value changes. Because there's no
// clean-up function, and we track the deps correctly, we can call pushEffect
// directly, without storing any additional state. For the same reason, we
// don't need to set a static flag, either.
// TODO: We can move this to the passive phase once we add a pre-commit
// consistency check. See the next comment.
fiber.flags |= Passive;
pushEffect(
HasEffect | Passive$1,
updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot),
undefined,
null
); // Unless we're rendering a blocking lane, schedule a consistency check. Right
// before committing, we will walk the tree and check if any of the stores
// were mutated.
var root = getWorkInProgressRoot();
if (!(root !== null)) {
throw Error(
"Expected a work-in-progress root. This is a bug in React. Please file an issue."
);
}
if (!includesBlockingLane(root, renderLanes)) {
pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
}
return nextSnapshot;
} }
function updateSyncExternalStore(subscribe, getSnapshot) { function updateSyncExternalStore(subscribe, getSnapshot) {
var fiber = currentlyRenderingFiber$1;
var hook = updateWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the var hook = updateWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the
// normal rules of React, and only works because store updates are // normal rules of React, and only works because store updates are
// always synchronous. // always synchronous.
@ -11243,69 +11284,102 @@ function updateSyncExternalStore(subscribe, getSnapshot) {
} }
var prevSnapshot = hook.memoizedState; var prevSnapshot = hook.memoizedState;
var snapshotChanged = !objectIs(prevSnapshot, nextSnapshot);
if (!objectIs(prevSnapshot, nextSnapshot)) { if (snapshotChanged) {
hook.memoizedState = nextSnapshot; hook.memoizedState = nextSnapshot;
markWorkInProgressReceivedUpdate(); markWorkInProgressReceivedUpdate();
} }
var inst = hook.queue; var inst = hook.queue;
return useSyncExternalStore(hook, inst, subscribe, getSnapshot, nextSnapshot); updateEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [
subscribe
]); // Whenever getSnapshot or subscribe changes, we need to check in the
// commit phase if there was an interleaved mutation. In concurrent mode
// this can happen all the time, but even in synchronous mode, an earlier
// effect may have mutated the store.
if (
inst.getSnapshot !== getSnapshot ||
snapshotChanged || // Check if the susbcribe function changed. We can save some memory by
// checking whether we scheduled a subscription effect above.
(workInProgressHook !== null &&
workInProgressHook.memoizedState.tag & HasEffect)
) {
fiber.flags |= Passive;
pushEffect(
HasEffect | Passive$1,
updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot),
undefined,
null
); // Unless we're rendering a blocking lane, schedule a consistency check.
// Right before committing, we will walk the tree and check if any of the
// stores were mutated.
var root = getWorkInProgressRoot();
if (!(root !== null)) {
throw Error(
"Expected a work-in-progress root. This is a bug in React. Please file an issue."
);
}
if (!includesBlockingLane(root, renderLanes)) {
pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
}
}
return nextSnapshot;
} }
function useSyncExternalStore( function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) {
hook, fiber.flags |= StoreConsistency;
inst, var check = {
subscribe, getSnapshot: getSnapshot,
getSnapshot, value: renderedSnapshot
nextSnapshot };
) { var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue;
var fiber = currentlyRenderingFiber$1;
var dispatcher = ReactCurrentDispatcher$1.current; // Track the latest getSnapshot function with a ref. This needs to be updated
// in the layout phase so we can access it during the tearing check that
// happens on subscribe.
// TODO: Circumvent SSR warning
dispatcher.useLayoutEffect( if (componentUpdateQueue === null) {
function() { componentUpdateQueue = createFunctionComponentUpdateQueue();
inst.value = nextSnapshot; currentlyRenderingFiber$1.updateQueue = componentUpdateQueue;
inst.getSnapshot = getSnapshot; // Whenever getSnapshot or subscribe changes, we need to check in the componentUpdateQueue.stores = [check];
// commit phase if there was an interleaved mutation. In concurrent mode } else {
// this can happen all the time, but even in synchronous mode, an earlier var stores = componentUpdateQueue.stores;
// effect may have mutated the store.
// TODO: Move the tearing checks to an earlier, pre-commit phase so that the
// layout effects always observe a consistent tree.
if (checkIfSnapshotChanged(inst)) { if (stores === null) {
// Force a re-render. componentUpdateQueue.stores = [check];
forceStoreRerender(fiber); } else {
} stores.push(check);
}, }
[subscribe, nextSnapshot, getSnapshot] }
); }
dispatcher.useEffect(
function() {
var handleStoreChange = function() {
// TODO: Because there is no cross-renderer API for batching updates, it's
// up to the consumer of this library to wrap their subscription event
// with unstable_batchedUpdates. Should we try to detect when this isn't
// the case and print a warning in development?
// The store changed. Check if the snapshot changed since the last time we
// read from the store.
if (checkIfSnapshotChanged(inst)) {
// Force a re-render.
forceStoreRerender(fiber);
}
}; // Check for changes right before subscribing. Subsequent changes will be
// detected in the subscription handler.
handleStoreChange(); // Subscribe to the store and return a clean-up function. function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) {
// These are updated in the passive phase
inst.value = nextSnapshot;
inst.getSnapshot = getSnapshot; // Something may have been mutated in between render and commit. This could
// have been in an event that fired before the passive effects, or it could
// have been in a layout effect. In that case, we would have used the old
// snapsho and getSnapshot values to bail out. We need to check one more time.
return subscribe(handleStoreChange); if (checkIfSnapshotChanged(inst)) {
}, // Force a re-render.
[subscribe] forceStoreRerender(fiber);
); }
return nextSnapshot; }
function subscribeToStore(fiber, inst, subscribe) {
var handleStoreChange = function() {
// The store changed. Check if the snapshot changed since the last time we
// read from the store.
if (checkIfSnapshotChanged(inst)) {
// Force a re-render.
forceStoreRerender(fiber);
}
}; // Subscribe to the store and return a clean-up function.
return subscribe(handleStoreChange);
} }
function checkIfSnapshotChanged(inst) { function checkIfSnapshotChanged(inst) {
@ -11477,6 +11551,14 @@ function updateEffect(create, deps) {
return updateEffectImpl(Passive, Passive$1, create, deps); return updateEffectImpl(Passive, Passive$1, create, deps);
} }
function mountInsertionEffect(create, deps) {
return mountEffectImpl(Update, Insertion, create, deps);
}
function updateInsertionEffect(create, deps) {
return updateEffectImpl(Update, Insertion, create, deps);
}
function mountLayoutEffect(create, deps) { function mountLayoutEffect(create, deps) {
var fiberFlags = Update; var fiberFlags = Update;
@ -11712,6 +11794,26 @@ function startTransition(setPending, callback) {
} finally { } finally {
setCurrentUpdatePriority(previousPriority); setCurrentUpdatePriority(previousPriority);
ReactCurrentBatchConfig$1.transition = prevTransition; ReactCurrentBatchConfig$1.transition = prevTransition;
{
if (
prevTransition !== 1 &&
warnOnSubscriptionInsideStartTransition &&
ReactCurrentBatchConfig$1._updatedFibers
) {
var updatedFibersCount = ReactCurrentBatchConfig$1._updatedFibers.size;
if (updatedFibersCount > 10) {
warn(
"Detected a large number of updates inside startTransition. " +
"If this is due to a subscription please re-write it to use React provided hooks. " +
"Otherwise concurrent mode guarantees are off the table."
);
}
ReactCurrentBatchConfig$1._updatedFibers.clear();
}
}
} }
} }
@ -11941,6 +12043,7 @@ var ContextOnlyDispatcher = {
useContext: throwInvalidHookError, useContext: throwInvalidHookError,
useEffect: throwInvalidHookError, useEffect: throwInvalidHookError,
useImperativeHandle: throwInvalidHookError, useImperativeHandle: throwInvalidHookError,
useInsertionEffect: throwInvalidHookError,
useLayoutEffect: throwInvalidHookError, useLayoutEffect: throwInvalidHookError,
useMemo: throwInvalidHookError, useMemo: throwInvalidHookError,
useReducer: throwInvalidHookError, useReducer: throwInvalidHookError,
@ -12009,6 +12112,12 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
checkDepsAreArrayDev(deps); checkDepsAreArrayDev(deps);
return mountImperativeHandle(ref, create, deps); return mountImperativeHandle(ref, create, deps);
}, },
useInsertionEffect: function(create, deps) {
currentHookNameInDev = "useInsertionEffect";
mountHookTypesDev();
checkDepsAreArrayDev(deps);
return mountInsertionEffect(create, deps);
},
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
currentHookNameInDev = "useLayoutEffect"; currentHookNameInDev = "useLayoutEffect";
mountHookTypesDev(); mountHookTypesDev();
@ -12114,6 +12223,11 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
updateHookTypesDev(); updateHookTypesDev();
return mountImperativeHandle(ref, create, deps); return mountImperativeHandle(ref, create, deps);
}, },
useInsertionEffect: function(create, deps) {
currentHookNameInDev = "useInsertionEffect";
updateHookTypesDev();
return mountInsertionEffect(create, deps);
},
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
currentHookNameInDev = "useLayoutEffect"; currentHookNameInDev = "useLayoutEffect";
updateHookTypesDev(); updateHookTypesDev();
@ -12217,6 +12331,11 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
updateHookTypesDev(); updateHookTypesDev();
return updateImperativeHandle(ref, create, deps); return updateImperativeHandle(ref, create, deps);
}, },
useInsertionEffect: function(create, deps) {
currentHookNameInDev = "useInsertionEffect";
updateHookTypesDev();
return updateInsertionEffect(create, deps);
},
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
currentHookNameInDev = "useLayoutEffect"; currentHookNameInDev = "useLayoutEffect";
updateHookTypesDev(); updateHookTypesDev();
@ -12320,6 +12439,11 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
updateHookTypesDev(); updateHookTypesDev();
return updateImperativeHandle(ref, create, deps); return updateImperativeHandle(ref, create, deps);
}, },
useInsertionEffect: function(create, deps) {
currentHookNameInDev = "useInsertionEffect";
updateHookTypesDev();
return updateInsertionEffect(create, deps);
},
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
currentHookNameInDev = "useLayoutEffect"; currentHookNameInDev = "useLayoutEffect";
updateHookTypesDev(); updateHookTypesDev();
@ -12428,6 +12552,12 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
mountHookTypesDev(); mountHookTypesDev();
return mountImperativeHandle(ref, create, deps); return mountImperativeHandle(ref, create, deps);
}, },
useInsertionEffect: function(create, deps) {
currentHookNameInDev = "useInsertionEffect";
warnInvalidHookAccess();
mountHookTypesDev();
return mountInsertionEffect(create, deps);
},
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
currentHookNameInDev = "useLayoutEffect"; currentHookNameInDev = "useLayoutEffect";
warnInvalidHookAccess(); warnInvalidHookAccess();
@ -12547,6 +12677,12 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
updateHookTypesDev(); updateHookTypesDev();
return updateImperativeHandle(ref, create, deps); return updateImperativeHandle(ref, create, deps);
}, },
useInsertionEffect: function(create, deps) {
currentHookNameInDev = "useInsertionEffect";
warnInvalidHookAccess();
updateHookTypesDev();
return updateInsertionEffect(create, deps);
},
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
currentHookNameInDev = "useLayoutEffect"; currentHookNameInDev = "useLayoutEffect";
warnInvalidHookAccess(); warnInvalidHookAccess();
@ -12666,6 +12802,12 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
updateHookTypesDev(); updateHookTypesDev();
return updateImperativeHandle(ref, create, deps); return updateImperativeHandle(ref, create, deps);
}, },
useInsertionEffect: function(create, deps) {
currentHookNameInDev = "useInsertionEffect";
warnInvalidHookAccess();
updateHookTypesDev();
return updateInsertionEffect(create, deps);
},
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
currentHookNameInDev = "useLayoutEffect"; currentHookNameInDev = "useLayoutEffect";
warnInvalidHookAccess(); warnInvalidHookAccess();
@ -17437,6 +17579,8 @@ function safelyDetachRef(current, nearestMountedAncestor) {
if (ref !== null) { if (ref !== null) {
if (typeof ref === "function") { if (typeof ref === "function") {
var retVal;
try { try {
if ( if (
enableProfilerTimer && enableProfilerTimer &&
@ -17445,12 +17589,12 @@ function safelyDetachRef(current, nearestMountedAncestor) {
) { ) {
try { try {
startLayoutEffectTimer(); startLayoutEffectTimer();
ref(null); retVal = ref(null);
} finally { } finally {
recordLayoutEffectDuration(current); recordLayoutEffectDuration(current);
} }
} else { } else {
ref(null); retVal = ref(null);
} }
} catch (error) { } catch (error) {
reportUncaughtErrorInDEV(error); reportUncaughtErrorInDEV(error);
@ -17680,6 +17824,16 @@ function commitHookEffectListMount(tag, finishedWork) {
var destroy = effect.destroy; var destroy = effect.destroy;
if (destroy !== undefined && typeof destroy !== "function") { if (destroy !== undefined && typeof destroy !== "function") {
var hookName = void 0;
if ((effect.tag & Layout) !== NoFlags) {
hookName = "useLayoutEffect";
} else if ((effect.tag & Insertion) !== NoFlags) {
hookName = "useInsertionEffect";
} else {
hookName = "useEffect";
}
var addendum = void 0; var addendum = void 0;
if (destroy === null) { if (destroy === null) {
@ -17688,10 +17842,13 @@ function commitHookEffectListMount(tag, finishedWork) {
"up, return undefined (or nothing)."; "up, return undefined (or nothing).";
} else if (typeof destroy.then === "function") { } else if (typeof destroy.then === "function") {
addendum = addendum =
"\n\nIt looks like you wrote useEffect(async () => ...) or returned a Promise. " + "\n\nIt looks like you wrote " +
hookName +
"(async () => ...) or returned a Promise. " +
"Instead, write the async function inside your effect " + "Instead, write the async function inside your effect " +
"and call it immediately:\n\n" + "and call it immediately:\n\n" +
"useEffect(() => {\n" + hookName +
"(() => {\n" +
" async function fetchData() {\n" + " async function fetchData() {\n" +
" // You can await here\n" + " // You can await here\n" +
" const response = await MyAPI.getData(someId);\n" + " const response = await MyAPI.getData(someId);\n" +
@ -17705,8 +17862,9 @@ function commitHookEffectListMount(tag, finishedWork) {
} }
error( error(
"An effect function must not return anything besides a function, " + "%s must not return anything besides a function, " +
"which is used for clean-up.%s", "which is used for clean-up.%s",
hookName,
addendum addendum
); );
} }
@ -18181,15 +18339,17 @@ function commitAttachRef(finishedWork) {
} // Moved outside to ensure DCE works with this flag } // Moved outside to ensure DCE works with this flag
if (typeof ref === "function") { if (typeof ref === "function") {
var retVal;
if (finishedWork.mode & ProfileMode) { if (finishedWork.mode & ProfileMode) {
try { try {
startLayoutEffectTimer(); startLayoutEffectTimer();
ref(instanceToUse); retVal = ref(instanceToUse);
} finally { } finally {
recordLayoutEffectDuration(finishedWork); recordLayoutEffectDuration(finishedWork);
} }
} else { } else {
ref(instanceToUse); retVal = ref(instanceToUse);
} }
} else { } else {
{ {
@ -18253,7 +18413,10 @@ function commitUnmount(finishedRoot, current, nearestMountedAncestor) {
tag = _effect.tag; tag = _effect.tag;
if (destroy !== undefined) { if (destroy !== undefined) {
if ((tag & Layout) !== NoFlags$1) { if (
(tag & Insertion) !== NoFlags$1 ||
(tag & Layout) !== NoFlags$1
) {
if (current.mode & ProfileMode) { if (current.mode & ProfileMode) {
startLayoutEffectTimer(); startLayoutEffectTimer();
safelyCallDestroy(current, nearestMountedAncestor, destroy); safelyCallDestroy(current, nearestMountedAncestor, destroy);
@ -18728,11 +18891,17 @@ function commitWork(current, finishedWork) {
case ForwardRef: case ForwardRef:
case MemoComponent: case MemoComponent:
case SimpleMemoComponent: { case SimpleMemoComponent: {
// Layout effects are destroyed during the mutation phase so that all commitHookEffectListUnmount(
Insertion | HasEffect,
finishedWork,
finishedWork.return
);
commitHookEffectListMount(Insertion | HasEffect, finishedWork); // Layout effects are destroyed during the mutation phase so that all
// destroy functions for all fibers are called before any create functions. // destroy functions for all fibers are called before any create functions.
// This prevents sibling component effects from interfering with each other, // This prevents sibling component effects from interfering with each other,
// e.g. a destroy function in one component should never override a ref set // e.g. a destroy function in one component should never override a ref set
// by a create function in another component during the same commit. // by a create function in another component during the same commit.
if (finishedWork.mode & ProfileMode) { if (finishedWork.mode & ProfileMode) {
try { try {
startLayoutEffectTimer(); startLayoutEffectTimer();
@ -19654,13 +19823,13 @@ function requestUpdateLane(fiber) {
var isTransition = requestCurrentTransition() !== NoTransition; var isTransition = requestCurrentTransition() !== NoTransition;
if (isTransition) { if (isTransition) {
// The algorithm for assigning an update to a lane should be stable for all
// updates at the same priority within the same event. To do this, the // updates at the same priority within the same event. To do this, the
// inputs to the algorithm must be the same. // inputs to the algorithm must be the same.
// //
// The trick we use is to cache the first of each of these inputs within an // The trick we use is to cache the first of each of these inputs within an
// event. Then reset the cached values once we can be sure the event is // event. Then reset the cached values once we can be sure the event is
// over. Our heuristic for that is whenever we enter a concurrent work loop. // over. Our heuristic for that is whenever we enter a concurrent work loop.
if (currentEventTransitionLane === NoLane) { if (currentEventTransitionLane === NoLane) {
// All transitions within the same event are assigned the same lane. // All transitions within the same event are assigned the same lane.
currentEventTransitionLane = claimNextTransitionLane(); currentEventTransitionLane = claimNextTransitionLane();
@ -19990,38 +20159,26 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
// bug we're still investigating. Once the bug in Scheduler is fixed, // bug we're still investigating. Once the bug in Scheduler is fixed,
// we can remove this, since we track expiration ourselves. // we can remove this, since we track expiration ourselves.
var exitStatus = var shouldTimeSlice =
shouldTimeSlice(root, lanes) && !didTimeout !includesBlockingLane(root, lanes) &&
? renderRootConcurrent(root, lanes) !includesExpiredLane(root, lanes) &&
: renderRootSync(root, lanes); !didTimeout;
var exitStatus = shouldTimeSlice
? renderRootConcurrent(root, lanes)
: renderRootSync(root, lanes);
if (exitStatus !== RootIncomplete) { if (exitStatus !== RootIncomplete) {
if (exitStatus === RootErrored) { if (exitStatus === RootErrored) {
var prevExecutionContext = executionContext; // If something threw an error, try rendering one more time. We'll
executionContext |= RetryAfterError; // If an error occurred during hydration, // render synchronously to block concurrent data mutations, and we'll
// discard server response and fall back to client side render. // includes all pending updates are included. If it still fails after
// the second attempt, we'll give up and commit the resulting tree.
if (root.hydrate) {
root.hydrate = false;
{
errorHydratingContainer(root.containerInfo);
}
clearContainer(root.containerInfo);
} // If something threw an error, try rendering one more time. We'll render
// synchronously to block concurrent data mutations, and we'll includes
// all pending updates are included. If it still fails after the second
// attempt, we'll give up and commit the resulting tree.
var errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); var errorRetryLanes = getLanesToRetrySynchronouslyOnError(root);
if (errorRetryLanes !== NoLanes) { if (errorRetryLanes !== NoLanes) {
lanes = errorRetryLanes; lanes = errorRetryLanes;
exitStatus = renderRootSync(root, errorRetryLanes); exitStatus = recoverFromConcurrentError(root, errorRetryLanes);
} }
executionContext = prevExecutionContext;
} }
if (exitStatus === RootFatalErrored) { if (exitStatus === RootFatalErrored) {
@ -20030,10 +20187,43 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
markRootSuspended$1(root, lanes); markRootSuspended$1(root, lanes);
ensureRootIsScheduled(root, now()); ensureRootIsScheduled(root, now());
throw fatalError; throw fatalError;
} // Check if this render may have yielded to a concurrent event, and if so,
// confirm that any newly rendered stores are consistent.
// TODO: It's possible that even a concurrent render may never have yielded
// to the main thread, if it was fast enough, or if it expired. We could
// skip the consistency check in that case, too.
var renderWasConcurrent = !includesBlockingLane(root, lanes);
var finishedWork = root.current.alternate;
if (
renderWasConcurrent &&
!isRenderConsistentWithExternalStores(finishedWork)
) {
// A store was mutated in an interleaved event. Render again,
// synchronously, to block further mutations.
exitStatus = renderRootSync(root, lanes); // We need to check again if something threw
if (exitStatus === RootErrored) {
var _errorRetryLanes = getLanesToRetrySynchronouslyOnError(root);
if (_errorRetryLanes !== NoLanes) {
lanes = _errorRetryLanes;
exitStatus = recoverFromConcurrentError(root, _errorRetryLanes); // We assume the tree is now consistent because we didn't yield to any
// concurrent events.
}
}
if (exitStatus === RootFatalErrored) {
var _fatalError = workInProgressRootFatalError;
prepareFreshStack(root, NoLanes);
markRootSuspended$1(root, lanes);
ensureRootIsScheduled(root, now());
throw _fatalError;
}
} // We now have a consistent tree. The next step is either to commit it, } // We now have a consistent tree. The next step is either to commit it,
// or, if something suspended, wait to commit it after a timeout. // or, if something suspended, wait to commit it after a timeout.
var finishedWork = root.current.alternate;
root.finishedWork = finishedWork; root.finishedWork = finishedWork;
root.finishedLanes = lanes; root.finishedLanes = lanes;
finishConcurrentRender(root, exitStatus, lanes); finishConcurrentRender(root, exitStatus, lanes);
@ -20050,6 +20240,26 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
return null; return null;
} }
function recoverFromConcurrentError(root, errorRetryLanes) {
var prevExecutionContext = executionContext;
executionContext |= RetryAfterError; // If an error occurred during hydration, discard server response and fall
// back to client side render.
if (root.hydrate) {
root.hydrate = false;
{
errorHydratingContainer(root.containerInfo);
}
clearContainer(root.containerInfo);
}
var exitStatus = renderRootSync(root, errorRetryLanes);
executionContext = prevExecutionContext;
return exitStatus;
}
function finishConcurrentRender(root, exitStatus, lanes) { function finishConcurrentRender(root, exitStatus, lanes) {
switch (exitStatus) { switch (exitStatus) {
case RootIncomplete: case RootIncomplete:
@ -20168,6 +20378,68 @@ function finishConcurrentRender(root, exitStatus, lanes) {
} }
} }
function isRenderConsistentWithExternalStores(finishedWork) {
// Search the rendered tree for external store reads, and check whether the
// stores were mutated in a concurrent event. Intentionally using a iterative
// loop instead of recursion so we can exit early.
var node = finishedWork;
while (true) {
if (node.flags & StoreConsistency) {
var updateQueue = node.updateQueue;
if (updateQueue !== null) {
var checks = updateQueue.stores;
if (checks !== null) {
for (var i = 0; i < checks.length; i++) {
var check = checks[i];
var getSnapshot = check.getSnapshot;
var renderedValue = check.value;
try {
if (!objectIs(getSnapshot(), renderedValue)) {
// Found an inconsistent store.
return false;
}
} catch (error) {
// If `getSnapshot` throws, return `false`. This will schedule
// a re-render, and the error will be rethrown during render.
return false;
}
}
}
}
}
var child = node.child;
if (node.subtreeFlags & StoreConsistency && child !== null) {
child.return = node;
node = child;
continue;
}
if (node === finishedWork) {
return true;
}
while (node.sibling === null) {
if (node.return === null || node.return === finishedWork) {
return true;
}
node = node.return;
}
node.sibling.return = node.return;
node = node.sibling;
} // Flow doesn't know this is unreachable, but eslint does
// eslint-disable-next-line no-unreachable
return true;
}
function markRootSuspended$1(root, suspendedLanes) { function markRootSuspended$1(root, suspendedLanes) {
// When suspending, we should always exclude lanes that were pinged or (more // When suspending, we should always exclude lanes that were pinged or (more
// rarely, since we try to avoid it) updated during the render phase. // rarely, since we try to avoid it) updated during the render phase.
@ -20912,6 +21184,15 @@ function commitRootImpl(root, renderPriorityLevel) {
} // Read this again, since an effect might have updated it } // Read this again, since an effect might have updated it
remainingLanes = root.pendingLanes; // Check if there's remaining work on this root remainingLanes = root.pendingLanes; // Check if there's remaining work on this root
// TODO: This is part of the `componentDidCatch` implementation. Its purpose
// is to detect whether something might have called setState inside
// `componentDidCatch`. The mechanism is known to be flawed because `setState`
// inside `componentDidCatch` is itself flawed — that's why we recommend
// `getDerivedStateFromError` instead. However, it could be improved by
// checking if remainingLanes includes Sync work, instead of whether there's
// any work remaining at all (which would also include stuff like Suspense
// retries or transitions). It's been like this for a while, though, so fixing
// it probably isn't that urgent.
if (remainingLanes === NoLanes) { if (remainingLanes === NoLanes) {
// If there's no remaining work, we can clear the set of already failed // If there's no remaining work, we can clear the set of already failed
@ -20925,22 +21206,6 @@ function commitRootImpl(root, renderPriorityLevel) {
} }
} }
if (includesSomeLane(remainingLanes, SyncLane)) {
{
markNestedUpdateScheduled();
} // Count the number of times the root synchronously re-renders without
// finishing. If there are too many, it indicates an infinite update loop.
if (root === rootWithNestedUpdates) {
nestedUpdateCount++;
} else {
nestedUpdateCount = 0;
rootWithNestedUpdates = root;
}
} else {
nestedUpdateCount = 0;
}
onCommitRoot(finishedWork.stateNode, renderPriorityLevel); onCommitRoot(finishedWork.stateNode, renderPriorityLevel);
{ {
@ -20971,6 +21236,24 @@ function commitRootImpl(root, renderPriorityLevel) {
root.tag !== LegacyRoot root.tag !== LegacyRoot
) { ) {
flushPassiveEffects(); flushPassiveEffects();
} // Read this again, since a passive effect might have updated it
remainingLanes = root.pendingLanes;
if (includesSomeLane(remainingLanes, SyncLane)) {
{
markNestedUpdateScheduled();
} // Count the number of times the root synchronously re-renders without
// finishing. If there are too many, it indicates an infinite update loop.
if (root === rootWithNestedUpdates) {
nestedUpdateCount++;
} else {
nestedUpdateCount = 0;
rootWithNestedUpdates = root;
}
} else {
nestedUpdateCount = 0;
} // If layout work was scheduled, flush it now. } // If layout work was scheduled, flush it now.
flushSyncCallbacks(); flushSyncCallbacks();

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

@ -7,7 +7,7 @@
* @noflow * @noflow
* @nolint * @nolint
* @preventMunge * @preventMunge
* @generated SignedSource<<5efc4e18a211a1edf88bf8bd3a184783>> * @generated SignedSource<<5c359ba9bcb80e09d414cf763d94b5d5>>
*/ */
"use strict"; "use strict";
@ -930,7 +930,7 @@ eventPluginOrder = Array.prototype.slice.call([
"ReactNativeBridgeEventPlugin" "ReactNativeBridgeEventPlugin"
]); ]);
recomputePluginOrdering(); recomputePluginOrdering();
var injectedNamesToPlugins$jscomp$inline_224 = { var injectedNamesToPlugins$jscomp$inline_225 = {
ResponderEventPlugin: ResponderEventPlugin, ResponderEventPlugin: ResponderEventPlugin,
ReactNativeBridgeEventPlugin: { ReactNativeBridgeEventPlugin: {
eventTypes: {}, eventTypes: {},
@ -965,34 +965,34 @@ var injectedNamesToPlugins$jscomp$inline_224 = {
} }
} }
}, },
isOrderingDirty$jscomp$inline_225 = !1, isOrderingDirty$jscomp$inline_226 = !1,
pluginName$jscomp$inline_226; pluginName$jscomp$inline_227;
for (pluginName$jscomp$inline_226 in injectedNamesToPlugins$jscomp$inline_224) for (pluginName$jscomp$inline_227 in injectedNamesToPlugins$jscomp$inline_225)
if ( if (
injectedNamesToPlugins$jscomp$inline_224.hasOwnProperty( injectedNamesToPlugins$jscomp$inline_225.hasOwnProperty(
pluginName$jscomp$inline_226 pluginName$jscomp$inline_227
) )
) { ) {
var pluginModule$jscomp$inline_227 = var pluginModule$jscomp$inline_228 =
injectedNamesToPlugins$jscomp$inline_224[pluginName$jscomp$inline_226]; injectedNamesToPlugins$jscomp$inline_225[pluginName$jscomp$inline_227];
if ( if (
!namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_226) || !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_227) ||
namesToPlugins[pluginName$jscomp$inline_226] !== namesToPlugins[pluginName$jscomp$inline_227] !==
pluginModule$jscomp$inline_227 pluginModule$jscomp$inline_228
) { ) {
if (namesToPlugins[pluginName$jscomp$inline_226]) if (namesToPlugins[pluginName$jscomp$inline_227])
throw Error( throw Error(
"EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" +
pluginName$jscomp$inline_226 + pluginName$jscomp$inline_227 +
"`." "`."
); );
namesToPlugins[ namesToPlugins[
pluginName$jscomp$inline_226 pluginName$jscomp$inline_227
] = pluginModule$jscomp$inline_227; ] = pluginModule$jscomp$inline_228;
isOrderingDirty$jscomp$inline_225 = !0; isOrderingDirty$jscomp$inline_226 = !0;
} }
} }
isOrderingDirty$jscomp$inline_225 && recomputePluginOrdering(); isOrderingDirty$jscomp$inline_226 && recomputePluginOrdering();
var instanceCache = new Map(), var instanceCache = new Map(),
instanceProps = new Map(); instanceProps = new Map();
function getInstanceFromTag(tag) { function getInstanceFromTag(tag) {
@ -1841,6 +1841,9 @@ function getLanesToRetrySynchronouslyOnError(root) {
root = root.pendingLanes & -1073741825; root = root.pendingLanes & -1073741825;
return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0;
} }
function includesBlockingLane(root, lanes) {
return 0 !== (root.current.mode & 32) ? !1 : 0 !== (lanes & 30);
}
function createLaneMap(initial) { function createLaneMap(initial) {
for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial);
return laneMap; return laneMap;
@ -2044,7 +2047,11 @@ function invalidateContextProvider(workInProgress, type, didChange) {
: pop(didPerformWorkStackCursor); : pop(didPerformWorkStackCursor);
push(didPerformWorkStackCursor, didChange); push(didPerformWorkStackCursor, didChange);
} }
var syncQueue = null, function is(x, y) {
return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
}
var objectIs = "function" === typeof Object.is ? Object.is : is,
syncQueue = null,
includesLegacySyncCallbacks = !1, includesLegacySyncCallbacks = !1,
isFlushingSyncQueue = !1; isFlushingSyncQueue = !1;
function flushSyncCallbacks() { function flushSyncCallbacks() {
@ -2073,10 +2080,6 @@ function flushSyncCallbacks() {
return null; return null;
} }
var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig;
function is(x, y) {
return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
}
var objectIs = "function" === typeof Object.is ? Object.is : is;
function shallowEqual(objA, objB) { function shallowEqual(objA, objB) {
if (objectIs(objA, objB)) return !0; if (objectIs(objA, objB)) return !0;
if ( if (
@ -2373,7 +2376,7 @@ function processUpdateQueue(
newState = workInProgress; newState = workInProgress;
break a; break a;
case 3: case 3:
workInProgress.flags = (workInProgress.flags & -16385) | 128; workInProgress.flags = (workInProgress.flags & -32769) | 128;
case 0: case 0:
workInProgress = update.payload; workInProgress = update.payload;
updateLane = updateLane =
@ -3604,42 +3607,52 @@ function updateMutableSource(source, getSnapshot, subscribe) {
return useMutableSource(hook, source, getSnapshot, subscribe); return useMutableSource(hook, source, getSnapshot, subscribe);
} }
function mountSyncExternalStore(subscribe, getSnapshot) { function mountSyncExternalStore(subscribe, getSnapshot) {
var hook = mountWorkInProgressHook(), var fiber = currentlyRenderingFiber$1,
hook = mountWorkInProgressHook(),
nextSnapshot = getSnapshot(); nextSnapshot = getSnapshot();
hook.memoizedState = nextSnapshot; hook.memoizedState = nextSnapshot;
var inst = { value: nextSnapshot, getSnapshot: getSnapshot }; var inst = { value: nextSnapshot, getSnapshot: getSnapshot };
hook.queue = inst; hook.queue = inst;
return useSyncExternalStore(hook, inst, subscribe, getSnapshot, nextSnapshot); mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]);
} fiber.flags |= 1024;
function useSyncExternalStore( pushEffect(
hook, 9,
inst, updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot),
subscribe, void 0,
getSnapshot, null
nextSnapshot
) {
var fiber = currentlyRenderingFiber$1;
hook = ReactCurrentDispatcher$1.current;
hook.useLayoutEffect(
function() {
inst.value = nextSnapshot;
inst.getSnapshot = getSnapshot;
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
},
[subscribe, nextSnapshot, getSnapshot]
);
hook.useEffect(
function() {
function handleStoreChange() {
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
}
handleStoreChange();
return subscribe(handleStoreChange);
},
[subscribe]
); );
subscribe = workInProgressRoot;
if (null === subscribe)
throw Error(
"Expected a work-in-progress root. This is a bug in React. Please file an issue."
);
includesBlockingLane(subscribe, renderLanes) ||
pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
return nextSnapshot; return nextSnapshot;
} }
function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) {
fiber.flags |= 8192;
fiber = { getSnapshot: getSnapshot, value: renderedSnapshot };
getSnapshot = currentlyRenderingFiber$1.updateQueue;
null === getSnapshot
? ((getSnapshot = { lastEffect: null, stores: null }),
(currentlyRenderingFiber$1.updateQueue = getSnapshot),
(getSnapshot.stores = [fiber]))
: ((renderedSnapshot = getSnapshot.stores),
null === renderedSnapshot
? (getSnapshot.stores = [fiber])
: renderedSnapshot.push(fiber));
}
function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) {
inst.value = nextSnapshot;
inst.getSnapshot = getSnapshot;
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
}
function subscribeToStore(fiber, inst, subscribe) {
return subscribe(function() {
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
});
}
function checkIfSnapshotChanged(inst) { function checkIfSnapshotChanged(inst) {
var latestGetSnapshot = inst.getSnapshot; var latestGetSnapshot = inst.getSnapshot;
inst = inst.value; inst = inst.value;
@ -3674,7 +3687,7 @@ function pushEffect(tag, create, destroy, deps) {
tag = { tag: tag, create: create, destroy: destroy, deps: deps, next: null }; tag = { tag: tag, create: create, destroy: destroy, deps: deps, next: null };
create = currentlyRenderingFiber$1.updateQueue; create = currentlyRenderingFiber$1.updateQueue;
null === create null === create
? ((create = { lastEffect: null }), ? ((create = { lastEffect: null, stores: null }),
(currentlyRenderingFiber$1.updateQueue = create), (currentlyRenderingFiber$1.updateQueue = create),
(create.lastEffect = tag.next = tag)) (create.lastEffect = tag.next = tag))
: ((destroy = create.lastEffect), : ((destroy = create.lastEffect),
@ -3715,13 +3728,16 @@ function updateEffectImpl(fiberFlags, hookFlags, create, deps) {
hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps); hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps);
} }
function mountEffect(create, deps) { function mountEffect(create, deps) {
return mountEffectImpl(1049600, 4, create, deps); return mountEffectImpl(2098176, 8, create, deps);
} }
function updateEffect(create, deps) { function updateEffect(create, deps) {
return updateEffectImpl(1024, 4, create, deps); return updateEffectImpl(1024, 8, create, deps);
}
function updateInsertionEffect(create, deps) {
return updateEffectImpl(4, 2, create, deps);
} }
function updateLayoutEffect(create, deps) { function updateLayoutEffect(create, deps) {
return updateEffectImpl(4, 2, create, deps); return updateEffectImpl(4, 4, create, deps);
} }
function imperativeHandleEffect(create, ref) { function imperativeHandleEffect(create, ref) {
if ("function" === typeof ref) if ("function" === typeof ref)
@ -3745,7 +3761,7 @@ function updateImperativeHandle(ref, create, deps) {
deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null; deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null;
return updateEffectImpl( return updateEffectImpl(
4, 4,
2, 4,
imperativeHandleEffect.bind(null, create, ref), imperativeHandleEffect.bind(null, create, ref),
deps deps
); );
@ -3863,6 +3879,7 @@ var ContextOnlyDispatcher = {
useContext: throwInvalidHookError, useContext: throwInvalidHookError,
useEffect: throwInvalidHookError, useEffect: throwInvalidHookError,
useImperativeHandle: throwInvalidHookError, useImperativeHandle: throwInvalidHookError,
useInsertionEffect: throwInvalidHookError,
useLayoutEffect: throwInvalidHookError, useLayoutEffect: throwInvalidHookError,
useMemo: throwInvalidHookError, useMemo: throwInvalidHookError,
useReducer: throwInvalidHookError, useReducer: throwInvalidHookError,
@ -3891,12 +3908,15 @@ var ContextOnlyDispatcher = {
deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null; deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null;
return mountEffectImpl( return mountEffectImpl(
4, 4,
2, 4,
imperativeHandleEffect.bind(null, create, ref), imperativeHandleEffect.bind(null, create, ref),
deps deps
); );
}, },
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
return mountEffectImpl(4, 4, create, deps);
},
useInsertionEffect: function(create, deps) {
return mountEffectImpl(4, 2, create, deps); return mountEffectImpl(4, 2, create, deps);
}, },
useMemo: function(nextCreate, deps) { useMemo: function(nextCreate, deps) {
@ -3979,6 +3999,7 @@ var ContextOnlyDispatcher = {
useContext: readContext, useContext: readContext,
useEffect: updateEffect, useEffect: updateEffect,
useImperativeHandle: updateImperativeHandle, useImperativeHandle: updateImperativeHandle,
useInsertionEffect: updateInsertionEffect,
useLayoutEffect: updateLayoutEffect, useLayoutEffect: updateLayoutEffect,
useMemo: updateMemo, useMemo: updateMemo,
useReducer: updateReducer, useReducer: updateReducer,
@ -4012,17 +4033,44 @@ var ContextOnlyDispatcher = {
}, },
useMutableSource: updateMutableSource, useMutableSource: updateMutableSource,
useSyncExternalStore: function(subscribe, getSnapshot) { useSyncExternalStore: function(subscribe, getSnapshot) {
var hook = updateWorkInProgressHook(), var fiber = currentlyRenderingFiber$1,
nextSnapshot = getSnapshot(); hook = updateWorkInProgressHook(),
objectIs(hook.memoizedState, nextSnapshot) || nextSnapshot = getSnapshot(),
snapshotChanged = !objectIs(hook.memoizedState, nextSnapshot);
snapshotChanged &&
((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0)); ((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0));
return useSyncExternalStore( hook = hook.queue;
hook, updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [
hook.queue, subscribe
subscribe, ]);
getSnapshot, if (
nextSnapshot hook.getSnapshot !== getSnapshot ||
); snapshotChanged ||
(null !== workInProgressHook &&
workInProgressHook.memoizedState.tag & 1)
) {
fiber.flags |= 1024;
pushEffect(
9,
updateStoreInstance.bind(
null,
fiber,
hook,
nextSnapshot,
getSnapshot
),
void 0,
null
);
subscribe = workInProgressRoot;
if (null === subscribe)
throw Error(
"Expected a work-in-progress root. This is a bug in React. Please file an issue."
);
includesBlockingLane(subscribe, renderLanes) ||
pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
}
return nextSnapshot;
}, },
useOpaqueIdentifier: function() { useOpaqueIdentifier: function() {
return updateReducer(basicStateReducer)[0]; return updateReducer(basicStateReducer)[0];
@ -4035,6 +4083,7 @@ var ContextOnlyDispatcher = {
useContext: readContext, useContext: readContext,
useEffect: updateEffect, useEffect: updateEffect,
useImperativeHandle: updateImperativeHandle, useImperativeHandle: updateImperativeHandle,
useInsertionEffect: updateInsertionEffect,
useLayoutEffect: updateLayoutEffect, useLayoutEffect: updateLayoutEffect,
useMemo: updateMemo, useMemo: updateMemo,
useReducer: rerenderReducer, useReducer: rerenderReducer,
@ -4204,8 +4253,8 @@ function bubbleProperties(completedWork) {
if (didBailout) if (didBailout)
for (var child$39 = completedWork.child; null !== child$39; ) for (var child$39 = completedWork.child; null !== child$39; )
(newChildLanes |= child$39.lanes | child$39.childLanes), (newChildLanes |= child$39.lanes | child$39.childLanes),
(subtreeFlags |= child$39.subtreeFlags & 1835008), (subtreeFlags |= child$39.subtreeFlags & 3670016),
(subtreeFlags |= child$39.flags & 1835008), (subtreeFlags |= child$39.flags & 3670016),
(child$39.return = completedWork), (child$39.return = completedWork),
(child$39 = child$39.sibling); (child$39 = child$39.sibling);
else else
@ -4419,7 +4468,7 @@ function completeWork(current, workInProgress, renderLanes) {
for (newProps = workInProgress.child; null !== newProps; ) for (newProps = workInProgress.child; null !== newProps; )
(renderLanes = newProps), (renderLanes = newProps),
(type = current), (type = current),
(renderLanes.flags &= 1835010), (renderLanes.flags &= 3670018),
(updatePayload = renderLanes.alternate), (updatePayload = renderLanes.alternate),
null === updatePayload null === updatePayload
? ((renderLanes.childLanes = 0), ? ((renderLanes.childLanes = 0),
@ -4649,7 +4698,7 @@ function updateSimpleMemoComponent(
current.ref === workInProgress.ref current.ref === workInProgress.ref
) )
if (((didReceiveUpdate = !1), 0 !== (current.lanes & renderLanes))) if (((didReceiveUpdate = !1), 0 !== (current.lanes & renderLanes)))
0 !== (current.flags & 32768) && (didReceiveUpdate = !0); 0 !== (current.flags & 65536) && (didReceiveUpdate = !0);
else else
return ( return (
(workInProgress.lanes = current.lanes), (workInProgress.lanes = current.lanes),
@ -5193,7 +5242,7 @@ function updateSuspenseFallbackChildren(
(primaryChildren.pendingProps = primaryChildProps), (primaryChildren.pendingProps = primaryChildProps),
(workInProgress.deletions = null)) (workInProgress.deletions = null))
: ((primaryChildren = createWorkInProgress(current, primaryChildProps)), : ((primaryChildren = createWorkInProgress(current, primaryChildProps)),
(primaryChildren.subtreeFlags = current.subtreeFlags & 1835008)); (primaryChildren.subtreeFlags = current.subtreeFlags & 3670016));
null !== currentFallbackChildFragment null !== currentFallbackChildFragment
? (fallbackChildren = createWorkInProgress( ? (fallbackChildren = createWorkInProgress(
currentFallbackChildFragment, currentFallbackChildFragment,
@ -5421,8 +5470,8 @@ function unwindWork(workInProgress) {
case 1: case 1:
isContextProvider(workInProgress.type) && popContext(); isContextProvider(workInProgress.type) && popContext();
var flags = workInProgress.flags; var flags = workInProgress.flags;
return flags & 16384 return flags & 32768
? ((workInProgress.flags = (flags & -16385) | 128), workInProgress) ? ((workInProgress.flags = (flags & -32769) | 128), workInProgress)
: null; : null;
case 3: case 3:
popHostContainer(); popHostContainer();
@ -5434,7 +5483,7 @@ function unwindWork(workInProgress) {
throw Error( throw Error(
"The root failed to unmount after an error. This is likely a bug in React. Please file an issue." "The root failed to unmount after an error. This is likely a bug in React. Please file an issue."
); );
workInProgress.flags = (flags & -16385) | 128; workInProgress.flags = (flags & -32769) | 128;
return workInProgress; return workInProgress;
case 5: case 5:
return popHostContext(workInProgress), null; return popHostContext(workInProgress), null;
@ -5442,8 +5491,8 @@ function unwindWork(workInProgress) {
return ( return (
pop(suspenseStackCursor), pop(suspenseStackCursor),
(flags = workInProgress.flags), (flags = workInProgress.flags),
flags & 16384 flags & 32768
? ((workInProgress.flags = (flags & -16385) | 128), workInProgress) ? ((workInProgress.flags = (flags & -32769) | 128), workInProgress)
: null : null
); );
case 19: case 19:
@ -5596,7 +5645,10 @@ function commitUnmount(finishedRoot, current, nearestMountedAncestor$jscomp$0) {
var _effect = effect, var _effect = effect,
destroy = _effect.destroy; destroy = _effect.destroy;
_effect = _effect.tag; _effect = _effect.tag;
if (void 0 !== destroy && 0 !== (_effect & 2)) { if (
void 0 !== destroy &&
(0 !== (_effect & 2) || 0 !== (_effect & 4))
) {
_effect = current; _effect = current;
var nearestMountedAncestor = nearestMountedAncestor$jscomp$0; var nearestMountedAncestor = nearestMountedAncestor$jscomp$0;
try { try {
@ -5923,6 +5975,8 @@ function commitWork(current, finishedWork) {
case 14: case 14:
case 15: case 15:
commitHookEffectListUnmount(3, finishedWork, finishedWork.return); commitHookEffectListUnmount(3, finishedWork, finishedWork.return);
commitHookEffectListMount(3, finishedWork);
commitHookEffectListUnmount(5, finishedWork, finishedWork.return);
return; return;
case 1: case 1:
return; return;
@ -6157,7 +6211,7 @@ function commitLayoutEffects(finishedWork) {
case 0: case 0:
case 11: case 11:
case 15: case 15:
commitHookEffectListMount(3, firstChild); commitHookEffectListMount(5, firstChild);
break; break;
case 1: case 1:
var instance = firstChild.stateNode; var instance = firstChild.stateNode;
@ -6421,15 +6475,15 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
root === workInProgressRoot ? workInProgressRootRenderLanes : 0 root === workInProgressRoot ? workInProgressRootRenderLanes : 0
); );
if (0 === lanes) return null; if (0 === lanes) return null;
var JSCompiler_inline_result = if (
0 !== (lanes & root.expiredLanes) includesBlockingLane(root, lanes) ||
? !1 0 !== (lanes & root.expiredLanes) ||
: 0 !== (root.current.mode & 32) didTimeout
? !0 )
: 0 === (lanes & 30); didTimeout = renderRootSync(root, lanes);
if (JSCompiler_inline_result && !didTimeout) { else {
didTimeout = lanes; didTimeout = lanes;
JSCompiler_inline_result = executionContext; var prevExecutionContext = executionContext;
executionContext |= 2; executionContext |= 2;
var prevDispatcher = pushDispatcher(); var prevDispatcher = pushDispatcher();
if ( if (
@ -6448,30 +6502,44 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
while (1); while (1);
resetContextDependencies(); resetContextDependencies();
ReactCurrentDispatcher$2.current = prevDispatcher; ReactCurrentDispatcher$2.current = prevDispatcher;
executionContext = JSCompiler_inline_result; executionContext = prevExecutionContext;
null !== workInProgress null !== workInProgress
? (didTimeout = 0) ? (didTimeout = 0)
: ((workInProgressRoot = null), : ((workInProgressRoot = null),
(workInProgressRootRenderLanes = 0), (workInProgressRootRenderLanes = 0),
(didTimeout = workInProgressRootExitStatus)); (didTimeout = workInProgressRootExitStatus));
} else didTimeout = renderRootSync(root, lanes); }
if (0 !== didTimeout) { if (0 !== didTimeout) {
2 === didTimeout && 2 === didTimeout &&
((JSCompiler_inline_result = executionContext), ((prevExecutionContext = getLanesToRetrySynchronouslyOnError(root)),
(executionContext |= 8), 0 !== prevExecutionContext &&
root.hydrate && (root.hydrate = !1), ((lanes = prevExecutionContext),
(prevDispatcher = getLanesToRetrySynchronouslyOnError(root)), (didTimeout = recoverFromConcurrentError(root, prevExecutionContext))));
0 !== prevDispatcher &&
((lanes = prevDispatcher),
(didTimeout = renderRootSync(root, prevDispatcher))),
(executionContext = JSCompiler_inline_result));
if (1 === didTimeout) if (1 === didTimeout)
throw ((originalCallbackNode = workInProgressRootFatalError), throw ((originalCallbackNode = workInProgressRootFatalError),
prepareFreshStack(root, 0), prepareFreshStack(root, 0),
markRootSuspended$1(root, lanes), markRootSuspended$1(root, lanes),
ensureRootIsScheduled(root, now()), ensureRootIsScheduled(root, now()),
originalCallbackNode); originalCallbackNode);
root.finishedWork = root.current.alternate; prevDispatcher = !includesBlockingLane(root, lanes);
prevExecutionContext = root.current.alternate;
if (
prevDispatcher &&
!isRenderConsistentWithExternalStores(prevExecutionContext) &&
((didTimeout = renderRootSync(root, lanes)),
2 === didTimeout &&
((prevDispatcher = getLanesToRetrySynchronouslyOnError(root)),
0 !== prevDispatcher &&
((lanes = prevDispatcher),
(didTimeout = recoverFromConcurrentError(root, prevDispatcher)))),
1 === didTimeout)
)
throw ((originalCallbackNode = workInProgressRootFatalError),
prepareFreshStack(root, 0),
markRootSuspended$1(root, lanes),
ensureRootIsScheduled(root, now()),
originalCallbackNode);
root.finishedWork = prevExecutionContext;
root.finishedLanes = lanes; root.finishedLanes = lanes;
switch (didTimeout) { switch (didTimeout) {
case 0: case 0:
@ -6488,10 +6556,10 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
10 < didTimeout) 10 < didTimeout)
) { ) {
if (0 !== getNextLanes(root, 0)) break; if (0 !== getNextLanes(root, 0)) break;
JSCompiler_inline_result = root.suspendedLanes; prevExecutionContext = root.suspendedLanes;
if ((JSCompiler_inline_result & lanes) !== lanes) { if ((prevExecutionContext & lanes) !== lanes) {
requestEventTime(); requestEventTime();
root.pingedLanes |= root.suspendedLanes & JSCompiler_inline_result; root.pingedLanes |= root.suspendedLanes & prevExecutionContext;
break; break;
} }
root.timeoutHandle = scheduleTimeout( root.timeoutHandle = scheduleTimeout(
@ -6506,15 +6574,14 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
markRootSuspended$1(root, lanes); markRootSuspended$1(root, lanes);
if ((lanes & 4194240) === lanes) break; if ((lanes & 4194240) === lanes) break;
didTimeout = root.eventTimes; didTimeout = root.eventTimes;
for (JSCompiler_inline_result = -1; 0 < lanes; ) { for (prevExecutionContext = -1; 0 < lanes; ) {
var index$5 = 31 - clz32(lanes); var index$5 = 31 - clz32(lanes);
prevDispatcher = 1 << index$5; prevDispatcher = 1 << index$5;
index$5 = didTimeout[index$5]; index$5 = didTimeout[index$5];
index$5 > JSCompiler_inline_result && index$5 > prevExecutionContext && (prevExecutionContext = index$5);
(JSCompiler_inline_result = index$5);
lanes &= ~prevDispatcher; lanes &= ~prevDispatcher;
} }
lanes = JSCompiler_inline_result; lanes = prevExecutionContext;
lanes = now() - lanes; lanes = now() - lanes;
lanes = lanes =
(120 > lanes (120 > lanes
@ -6551,6 +6618,48 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
? performConcurrentWorkOnRoot.bind(null, root) ? performConcurrentWorkOnRoot.bind(null, root)
: null; : null;
} }
function recoverFromConcurrentError(root, errorRetryLanes) {
var prevExecutionContext = executionContext;
executionContext |= 8;
root.hydrate && (root.hydrate = !1);
root = renderRootSync(root, errorRetryLanes);
executionContext = prevExecutionContext;
return root;
}
function isRenderConsistentWithExternalStores(finishedWork) {
for (var node = finishedWork; ; ) {
if (node.flags & 8192) {
var updateQueue = node.updateQueue;
if (
null !== updateQueue &&
((updateQueue = updateQueue.stores), null !== updateQueue)
)
for (var i = 0; i < updateQueue.length; i++) {
var check = updateQueue[i],
getSnapshot = check.getSnapshot;
check = check.value;
try {
if (!objectIs(getSnapshot(), check)) return !1;
} catch (error) {
return !1;
}
}
}
updateQueue = node.child;
if (node.subtreeFlags & 8192 && null !== updateQueue)
(updateQueue.return = node), (node = updateQueue);
else {
if (node === finishedWork) break;
for (; null === node.sibling; ) {
if (null === node.return || node.return === finishedWork) return !0;
node = node.return;
}
node.sibling.return = node.return;
node = node.sibling;
}
}
return !0;
}
function markRootSuspended$1(root, suspendedLanes) { function markRootSuspended$1(root, suspendedLanes) {
suspendedLanes &= ~workInProgressRootPingedLanes; suspendedLanes &= ~workInProgressRootPingedLanes;
suspendedLanes &= ~workInProgressRootUpdatedLanes; suspendedLanes &= ~workInProgressRootUpdatedLanes;
@ -6698,7 +6807,7 @@ function handleError(root$jscomp$0, thrownValue) {
sourceFiber = erroredWork, sourceFiber = erroredWork,
value = thrownValue; value = thrownValue;
thrownValue = workInProgressRootRenderLanes; thrownValue = workInProgressRootRenderLanes;
sourceFiber.flags |= 8192; sourceFiber.flags |= 16384;
if ( if (
null !== value && null !== value &&
"object" === typeof value && "object" === typeof value &&
@ -6749,8 +6858,8 @@ function handleError(root$jscomp$0, thrownValue) {
workInProgress$32 !== returnFiber workInProgress$32 !== returnFiber
) { ) {
workInProgress$32.flags |= 128; workInProgress$32.flags |= 128;
sourceFiber.flags |= 32768; sourceFiber.flags |= 65536;
sourceFiber.flags &= -10053; sourceFiber.flags &= -26437;
if (1 === sourceFiber.tag) if (1 === sourceFiber.tag)
if (null === sourceFiber.alternate) sourceFiber.tag = 17; if (null === sourceFiber.alternate) sourceFiber.tag = 17;
else { else {
@ -6781,7 +6890,7 @@ function handleError(root$jscomp$0, thrownValue) {
); );
wakeable.then(ping, ping); wakeable.then(ping, ping);
} }
workInProgress$32.flags |= 16384; workInProgress$32.flags |= 32768;
workInProgress$32.lanes = thrownValue; workInProgress$32.lanes = thrownValue;
break a; break a;
} }
@ -6800,7 +6909,7 @@ function handleError(root$jscomp$0, thrownValue) {
switch (workInProgress$32.tag) { switch (workInProgress$32.tag) {
case 3: case 3:
root = value; root = value;
workInProgress$32.flags |= 16384; workInProgress$32.flags |= 32768;
thrownValue &= -thrownValue; thrownValue &= -thrownValue;
workInProgress$32.lanes |= thrownValue; workInProgress$32.lanes |= thrownValue;
var update$33 = createRootErrorUpdate( var update$33 = createRootErrorUpdate(
@ -6822,7 +6931,7 @@ function handleError(root$jscomp$0, thrownValue) {
(null === legacyErrorBoundariesThatAlreadyFailed || (null === legacyErrorBoundariesThatAlreadyFailed ||
!legacyErrorBoundariesThatAlreadyFailed.has(instance)))) !legacyErrorBoundariesThatAlreadyFailed.has(instance))))
) { ) {
workInProgress$32.flags |= 16384; workInProgress$32.flags |= 32768;
thrownValue &= -thrownValue; thrownValue &= -thrownValue;
workInProgress$32.lanes |= thrownValue; workInProgress$32.lanes |= thrownValue;
var update$36 = createClassErrorUpdate( var update$36 = createClassErrorUpdate(
@ -6896,7 +7005,7 @@ function completeUnitOfWork(unitOfWork) {
do { do {
var current = completedWork.alternate; var current = completedWork.alternate;
unitOfWork = completedWork.return; unitOfWork = completedWork.return;
if (0 === (completedWork.flags & 8192)) { if (0 === (completedWork.flags & 16384)) {
if ( if (
((current = completeWork(current, completedWork, subtreeRenderLanes)), ((current = completeWork(current, completedWork, subtreeRenderLanes)),
null !== current) null !== current)
@ -6907,12 +7016,12 @@ function completeUnitOfWork(unitOfWork) {
} else { } else {
current = unwindWork(completedWork); current = unwindWork(completedWork);
if (null !== current) { if (null !== current) {
current.flags &= 8191; current.flags &= 16383;
workInProgress = current; workInProgress = current;
return; return;
} }
null !== unitOfWork && null !== unitOfWork &&
((unitOfWork.flags |= 8192), ((unitOfWork.flags |= 16384),
(unitOfWork.subtreeFlags = 0), (unitOfWork.subtreeFlags = 0),
(unitOfWork.deletions = null)); (unitOfWork.deletions = null));
} }
@ -6991,11 +7100,6 @@ function commitRootImpl(root, renderPriorityLevel) {
(pendingPassiveEffectsLanes = lanes)); (pendingPassiveEffectsLanes = lanes));
remainingLanes = root.pendingLanes; remainingLanes = root.pendingLanes;
0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null);
0 !== (remainingLanes & 1)
? root === rootWithNestedUpdates
? nestedUpdateCount++
: ((nestedUpdateCount = 0), (rootWithNestedUpdates = root))
: (nestedUpdateCount = 0);
onCommitRoot(finishedWork.stateNode, renderPriorityLevel); onCommitRoot(finishedWork.stateNode, renderPriorityLevel);
ensureRootIsScheduled(root, now()); ensureRootIsScheduled(root, now());
if (hasUncaughtError) if (hasUncaughtError)
@ -7006,6 +7110,12 @@ function commitRootImpl(root, renderPriorityLevel) {
0 !== (pendingPassiveEffectsLanes & 1) && 0 !== (pendingPassiveEffectsLanes & 1) &&
0 !== root.tag && 0 !== root.tag &&
flushPassiveEffects(); flushPassiveEffects();
remainingLanes = root.pendingLanes;
0 !== (remainingLanes & 1)
? root === rootWithNestedUpdates
? nestedUpdateCount++
: ((nestedUpdateCount = 0), (rootWithNestedUpdates = root))
: (nestedUpdateCount = 0);
flushSyncCallbacks(); flushSyncCallbacks();
return null; return null;
} }
@ -7041,7 +7151,7 @@ function flushPassiveEffects() {
case 0: case 0:
case 11: case 11:
case 15: case 15:
commitHookEffectListUnmount(4, fiber$jscomp$0, fiber); commitHookEffectListUnmount(8, fiber$jscomp$0, fiber);
} }
var child$jscomp$0 = fiber$jscomp$0.child; var child$jscomp$0 = fiber$jscomp$0.child;
if (null !== child$jscomp$0) if (null !== child$jscomp$0)
@ -7091,7 +7201,7 @@ function flushPassiveEffects() {
case 0: case 0:
case 11: case 11:
case 15: case 15:
commitHookEffectListUnmount(5, fiber, fiber.return); commitHookEffectListUnmount(9, fiber, fiber.return);
} }
var sibling$jscomp$0 = fiber.sibling; var sibling$jscomp$0 = fiber.sibling;
if (null !== sibling$jscomp$0) { if (null !== sibling$jscomp$0) {
@ -7117,7 +7227,7 @@ function flushPassiveEffects() {
case 0: case 0:
case 11: case 11:
case 15: case 15:
commitHookEffectListMount(5, deletions); commitHookEffectListMount(9, deletions);
} }
} catch (error) { } catch (error) {
captureCommitPhaseError(deletions, deletions.return, error); captureCommitPhaseError(deletions, deletions.return, error);
@ -7263,7 +7373,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) {
renderLanes renderLanes
) )
); );
didReceiveUpdate = 0 !== (current.flags & 32768) ? !0 : !1; didReceiveUpdate = 0 !== (current.flags & 65536) ? !0 : !1;
} }
else didReceiveUpdate = !1; else didReceiveUpdate = !1;
workInProgress.lanes = 0; workInProgress.lanes = 0;
@ -7729,7 +7839,7 @@ function createWorkInProgress(current, pendingProps) {
(workInProgress.flags = 0), (workInProgress.flags = 0),
(workInProgress.subtreeFlags = 0), (workInProgress.subtreeFlags = 0),
(workInProgress.deletions = null)); (workInProgress.deletions = null));
workInProgress.flags = current.flags & 1835008; workInProgress.flags = current.flags & 3670016;
workInProgress.childLanes = current.childLanes; workInProgress.childLanes = current.childLanes;
workInProgress.lanes = current.lanes; workInProgress.lanes = current.lanes;
workInProgress.child = current.child; workInProgress.child = current.child;
@ -8086,10 +8196,10 @@ batchedUpdatesImpl = function(fn, a) {
} }
}; };
var roots = new Map(), var roots = new Map(),
devToolsConfig$jscomp$inline_989 = { devToolsConfig$jscomp$inline_986 = {
findFiberByHostInstance: getInstanceFromTag, findFiberByHostInstance: getInstanceFromTag,
bundleType: 0, bundleType: 0,
version: "18.0.0-95d762e40-20210908", version: "18.0.0-e8feb11b6-20210915",
rendererPackageName: "react-native-renderer", rendererPackageName: "react-native-renderer",
rendererConfig: { rendererConfig: {
getInspectorDataForViewTag: function() { getInspectorDataForViewTag: function() {
@ -8104,11 +8214,11 @@ var roots = new Map(),
}.bind(null, findNodeHandle) }.bind(null, findNodeHandle)
} }
}; };
var internals$jscomp$inline_1242 = { var internals$jscomp$inline_1239 = {
bundleType: devToolsConfig$jscomp$inline_989.bundleType, bundleType: devToolsConfig$jscomp$inline_986.bundleType,
version: devToolsConfig$jscomp$inline_989.version, version: devToolsConfig$jscomp$inline_986.version,
rendererPackageName: devToolsConfig$jscomp$inline_989.rendererPackageName, rendererPackageName: devToolsConfig$jscomp$inline_986.rendererPackageName,
rendererConfig: devToolsConfig$jscomp$inline_989.rendererConfig, rendererConfig: devToolsConfig$jscomp$inline_986.rendererConfig,
overrideHookState: null, overrideHookState: null,
overrideHookStateDeletePath: null, overrideHookStateDeletePath: null,
overrideHookStateRenamePath: null, overrideHookStateRenamePath: null,
@ -8124,7 +8234,7 @@ var internals$jscomp$inline_1242 = {
return null === fiber ? null : fiber.stateNode; return null === fiber ? null : fiber.stateNode;
}, },
findFiberByHostInstance: findFiberByHostInstance:
devToolsConfig$jscomp$inline_989.findFiberByHostInstance || devToolsConfig$jscomp$inline_986.findFiberByHostInstance ||
emptyFindFiberByHostInstance, emptyFindFiberByHostInstance,
findHostInstancesForRefresh: null, findHostInstancesForRefresh: null,
scheduleRefresh: null, scheduleRefresh: null,
@ -8132,19 +8242,19 @@ var internals$jscomp$inline_1242 = {
setRefreshHandler: null, setRefreshHandler: null,
getCurrentFiber: null, getCurrentFiber: null,
getIsStrictMode: null, getIsStrictMode: null,
reconcilerVersion: "18.0.0-95d762e40-20210908" reconcilerVersion: "18.0.0-e8feb11b6-20210915"
}; };
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1243 = __REACT_DEVTOOLS_GLOBAL_HOOK__; var hook$jscomp$inline_1240 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
if ( if (
!hook$jscomp$inline_1243.isDisabled && !hook$jscomp$inline_1240.isDisabled &&
hook$jscomp$inline_1243.supportsFiber hook$jscomp$inline_1240.supportsFiber
) )
try { try {
(rendererID = hook$jscomp$inline_1243.inject( (rendererID = hook$jscomp$inline_1240.inject(
internals$jscomp$inline_1242 internals$jscomp$inline_1239
)), )),
(injectedHook = hook$jscomp$inline_1243); (injectedHook = hook$jscomp$inline_1240);
} catch (err) {} } catch (err) {}
} }
exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {

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

@ -7,7 +7,7 @@
* @noflow * @noflow
* @nolint * @nolint
* @preventMunge * @preventMunge
* @generated SignedSource<<ad111484ca10270c3a7cd031b1e7fd26>> * @generated SignedSource<<fde7e13d1ac4bc64f671a420c5af657b>>
*/ */
"use strict"; "use strict";
@ -930,7 +930,7 @@ eventPluginOrder = Array.prototype.slice.call([
"ReactNativeBridgeEventPlugin" "ReactNativeBridgeEventPlugin"
]); ]);
recomputePluginOrdering(); recomputePluginOrdering();
var injectedNamesToPlugins$jscomp$inline_232 = { var injectedNamesToPlugins$jscomp$inline_233 = {
ResponderEventPlugin: ResponderEventPlugin, ResponderEventPlugin: ResponderEventPlugin,
ReactNativeBridgeEventPlugin: { ReactNativeBridgeEventPlugin: {
eventTypes: {}, eventTypes: {},
@ -965,34 +965,34 @@ var injectedNamesToPlugins$jscomp$inline_232 = {
} }
} }
}, },
isOrderingDirty$jscomp$inline_233 = !1, isOrderingDirty$jscomp$inline_234 = !1,
pluginName$jscomp$inline_234; pluginName$jscomp$inline_235;
for (pluginName$jscomp$inline_234 in injectedNamesToPlugins$jscomp$inline_232) for (pluginName$jscomp$inline_235 in injectedNamesToPlugins$jscomp$inline_233)
if ( if (
injectedNamesToPlugins$jscomp$inline_232.hasOwnProperty( injectedNamesToPlugins$jscomp$inline_233.hasOwnProperty(
pluginName$jscomp$inline_234 pluginName$jscomp$inline_235
) )
) { ) {
var pluginModule$jscomp$inline_235 = var pluginModule$jscomp$inline_236 =
injectedNamesToPlugins$jscomp$inline_232[pluginName$jscomp$inline_234]; injectedNamesToPlugins$jscomp$inline_233[pluginName$jscomp$inline_235];
if ( if (
!namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_234) || !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_235) ||
namesToPlugins[pluginName$jscomp$inline_234] !== namesToPlugins[pluginName$jscomp$inline_235] !==
pluginModule$jscomp$inline_235 pluginModule$jscomp$inline_236
) { ) {
if (namesToPlugins[pluginName$jscomp$inline_234]) if (namesToPlugins[pluginName$jscomp$inline_235])
throw Error( throw Error(
"EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" +
pluginName$jscomp$inline_234 + pluginName$jscomp$inline_235 +
"`." "`."
); );
namesToPlugins[ namesToPlugins[
pluginName$jscomp$inline_234 pluginName$jscomp$inline_235
] = pluginModule$jscomp$inline_235; ] = pluginModule$jscomp$inline_236;
isOrderingDirty$jscomp$inline_233 = !0; isOrderingDirty$jscomp$inline_234 = !0;
} }
} }
isOrderingDirty$jscomp$inline_233 && recomputePluginOrdering(); isOrderingDirty$jscomp$inline_234 && recomputePluginOrdering();
var instanceCache = new Map(), var instanceCache = new Map(),
instanceProps = new Map(); instanceProps = new Map();
function getInstanceFromTag(tag) { function getInstanceFromTag(tag) {
@ -1859,6 +1859,9 @@ function getLanesToRetrySynchronouslyOnError(root) {
root = root.pendingLanes & -1073741825; root = root.pendingLanes & -1073741825;
return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0;
} }
function includesBlockingLane(root, lanes) {
return 0 !== (root.current.mode & 32) ? !1 : 0 !== (lanes & 30);
}
function createLaneMap(initial) { function createLaneMap(initial) {
for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial);
return laneMap; return laneMap;
@ -2092,7 +2095,11 @@ function invalidateContextProvider(workInProgress, type, didChange) {
: pop(didPerformWorkStackCursor); : pop(didPerformWorkStackCursor);
push(didPerformWorkStackCursor, didChange); push(didPerformWorkStackCursor, didChange);
} }
var syncQueue = null, function is(x, y) {
return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
}
var objectIs = "function" === typeof Object.is ? Object.is : is,
syncQueue = null,
includesLegacySyncCallbacks = !1, includesLegacySyncCallbacks = !1,
isFlushingSyncQueue = !1; isFlushingSyncQueue = !1;
function flushSyncCallbacks() { function flushSyncCallbacks() {
@ -2121,10 +2128,6 @@ function flushSyncCallbacks() {
return null; return null;
} }
var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig;
function is(x, y) {
return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
}
var objectIs = "function" === typeof Object.is ? Object.is : is;
function shallowEqual(objA, objB) { function shallowEqual(objA, objB) {
if (objectIs(objA, objB)) return !0; if (objectIs(objA, objB)) return !0;
if ( if (
@ -2421,7 +2424,7 @@ function processUpdateQueue(
newState = workInProgress; newState = workInProgress;
break a; break a;
case 3: case 3:
workInProgress.flags = (workInProgress.flags & -16385) | 128; workInProgress.flags = (workInProgress.flags & -32769) | 128;
case 0: case 0:
workInProgress = update.payload; workInProgress = update.payload;
updateLane = updateLane =
@ -3652,42 +3655,52 @@ function updateMutableSource(source, getSnapshot, subscribe) {
return useMutableSource(hook, source, getSnapshot, subscribe); return useMutableSource(hook, source, getSnapshot, subscribe);
} }
function mountSyncExternalStore(subscribe, getSnapshot) { function mountSyncExternalStore(subscribe, getSnapshot) {
var hook = mountWorkInProgressHook(), var fiber = currentlyRenderingFiber$1,
hook = mountWorkInProgressHook(),
nextSnapshot = getSnapshot(); nextSnapshot = getSnapshot();
hook.memoizedState = nextSnapshot; hook.memoizedState = nextSnapshot;
var inst = { value: nextSnapshot, getSnapshot: getSnapshot }; var inst = { value: nextSnapshot, getSnapshot: getSnapshot };
hook.queue = inst; hook.queue = inst;
return useSyncExternalStore(hook, inst, subscribe, getSnapshot, nextSnapshot); mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]);
} fiber.flags |= 1024;
function useSyncExternalStore( pushEffect(
hook, 9,
inst, updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot),
subscribe, void 0,
getSnapshot, null
nextSnapshot
) {
var fiber = currentlyRenderingFiber$1;
hook = ReactCurrentDispatcher$1.current;
hook.useLayoutEffect(
function() {
inst.value = nextSnapshot;
inst.getSnapshot = getSnapshot;
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
},
[subscribe, nextSnapshot, getSnapshot]
);
hook.useEffect(
function() {
function handleStoreChange() {
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
}
handleStoreChange();
return subscribe(handleStoreChange);
},
[subscribe]
); );
subscribe = workInProgressRoot;
if (null === subscribe)
throw Error(
"Expected a work-in-progress root. This is a bug in React. Please file an issue."
);
includesBlockingLane(subscribe, renderLanes) ||
pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
return nextSnapshot; return nextSnapshot;
} }
function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) {
fiber.flags |= 8192;
fiber = { getSnapshot: getSnapshot, value: renderedSnapshot };
getSnapshot = currentlyRenderingFiber$1.updateQueue;
null === getSnapshot
? ((getSnapshot = { lastEffect: null, stores: null }),
(currentlyRenderingFiber$1.updateQueue = getSnapshot),
(getSnapshot.stores = [fiber]))
: ((renderedSnapshot = getSnapshot.stores),
null === renderedSnapshot
? (getSnapshot.stores = [fiber])
: renderedSnapshot.push(fiber));
}
function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) {
inst.value = nextSnapshot;
inst.getSnapshot = getSnapshot;
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
}
function subscribeToStore(fiber, inst, subscribe) {
return subscribe(function() {
checkIfSnapshotChanged(inst) && scheduleUpdateOnFiber(fiber, 1, -1);
});
}
function checkIfSnapshotChanged(inst) { function checkIfSnapshotChanged(inst) {
var latestGetSnapshot = inst.getSnapshot; var latestGetSnapshot = inst.getSnapshot;
inst = inst.value; inst = inst.value;
@ -3722,7 +3735,7 @@ function pushEffect(tag, create, destroy, deps) {
tag = { tag: tag, create: create, destroy: destroy, deps: deps, next: null }; tag = { tag: tag, create: create, destroy: destroy, deps: deps, next: null };
create = currentlyRenderingFiber$1.updateQueue; create = currentlyRenderingFiber$1.updateQueue;
null === create null === create
? ((create = { lastEffect: null }), ? ((create = { lastEffect: null, stores: null }),
(currentlyRenderingFiber$1.updateQueue = create), (currentlyRenderingFiber$1.updateQueue = create),
(create.lastEffect = tag.next = tag)) (create.lastEffect = tag.next = tag))
: ((destroy = create.lastEffect), : ((destroy = create.lastEffect),
@ -3763,13 +3776,16 @@ function updateEffectImpl(fiberFlags, hookFlags, create, deps) {
hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps); hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps);
} }
function mountEffect(create, deps) { function mountEffect(create, deps) {
return mountEffectImpl(1049600, 4, create, deps); return mountEffectImpl(2098176, 8, create, deps);
} }
function updateEffect(create, deps) { function updateEffect(create, deps) {
return updateEffectImpl(1024, 4, create, deps); return updateEffectImpl(1024, 8, create, deps);
}
function updateInsertionEffect(create, deps) {
return updateEffectImpl(4, 2, create, deps);
} }
function updateLayoutEffect(create, deps) { function updateLayoutEffect(create, deps) {
return updateEffectImpl(4, 2, create, deps); return updateEffectImpl(4, 4, create, deps);
} }
function imperativeHandleEffect(create, ref) { function imperativeHandleEffect(create, ref) {
if ("function" === typeof ref) if ("function" === typeof ref)
@ -3793,7 +3809,7 @@ function updateImperativeHandle(ref, create, deps) {
deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null; deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null;
return updateEffectImpl( return updateEffectImpl(
4, 4,
2, 4,
imperativeHandleEffect.bind(null, create, ref), imperativeHandleEffect.bind(null, create, ref),
deps deps
); );
@ -3911,6 +3927,7 @@ var ContextOnlyDispatcher = {
useContext: throwInvalidHookError, useContext: throwInvalidHookError,
useEffect: throwInvalidHookError, useEffect: throwInvalidHookError,
useImperativeHandle: throwInvalidHookError, useImperativeHandle: throwInvalidHookError,
useInsertionEffect: throwInvalidHookError,
useLayoutEffect: throwInvalidHookError, useLayoutEffect: throwInvalidHookError,
useMemo: throwInvalidHookError, useMemo: throwInvalidHookError,
useReducer: throwInvalidHookError, useReducer: throwInvalidHookError,
@ -3939,12 +3956,15 @@ var ContextOnlyDispatcher = {
deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null; deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null;
return mountEffectImpl( return mountEffectImpl(
4, 4,
2, 4,
imperativeHandleEffect.bind(null, create, ref), imperativeHandleEffect.bind(null, create, ref),
deps deps
); );
}, },
useLayoutEffect: function(create, deps) { useLayoutEffect: function(create, deps) {
return mountEffectImpl(4, 4, create, deps);
},
useInsertionEffect: function(create, deps) {
return mountEffectImpl(4, 2, create, deps); return mountEffectImpl(4, 2, create, deps);
}, },
useMemo: function(nextCreate, deps) { useMemo: function(nextCreate, deps) {
@ -4027,6 +4047,7 @@ var ContextOnlyDispatcher = {
useContext: readContext, useContext: readContext,
useEffect: updateEffect, useEffect: updateEffect,
useImperativeHandle: updateImperativeHandle, useImperativeHandle: updateImperativeHandle,
useInsertionEffect: updateInsertionEffect,
useLayoutEffect: updateLayoutEffect, useLayoutEffect: updateLayoutEffect,
useMemo: updateMemo, useMemo: updateMemo,
useReducer: updateReducer, useReducer: updateReducer,
@ -4060,17 +4081,44 @@ var ContextOnlyDispatcher = {
}, },
useMutableSource: updateMutableSource, useMutableSource: updateMutableSource,
useSyncExternalStore: function(subscribe, getSnapshot) { useSyncExternalStore: function(subscribe, getSnapshot) {
var hook = updateWorkInProgressHook(), var fiber = currentlyRenderingFiber$1,
nextSnapshot = getSnapshot(); hook = updateWorkInProgressHook(),
objectIs(hook.memoizedState, nextSnapshot) || nextSnapshot = getSnapshot(),
snapshotChanged = !objectIs(hook.memoizedState, nextSnapshot);
snapshotChanged &&
((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0)); ((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0));
return useSyncExternalStore( hook = hook.queue;
hook, updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [
hook.queue, subscribe
subscribe, ]);
getSnapshot, if (
nextSnapshot hook.getSnapshot !== getSnapshot ||
); snapshotChanged ||
(null !== workInProgressHook &&
workInProgressHook.memoizedState.tag & 1)
) {
fiber.flags |= 1024;
pushEffect(
9,
updateStoreInstance.bind(
null,
fiber,
hook,
nextSnapshot,
getSnapshot
),
void 0,
null
);
subscribe = workInProgressRoot;
if (null === subscribe)
throw Error(
"Expected a work-in-progress root. This is a bug in React. Please file an issue."
);
includesBlockingLane(subscribe, renderLanes) ||
pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
}
return nextSnapshot;
}, },
useOpaqueIdentifier: function() { useOpaqueIdentifier: function() {
return updateReducer(basicStateReducer)[0]; return updateReducer(basicStateReducer)[0];
@ -4083,6 +4131,7 @@ var ContextOnlyDispatcher = {
useContext: readContext, useContext: readContext,
useEffect: updateEffect, useEffect: updateEffect,
useImperativeHandle: updateImperativeHandle, useImperativeHandle: updateImperativeHandle,
useInsertionEffect: updateInsertionEffect,
useLayoutEffect: updateLayoutEffect, useLayoutEffect: updateLayoutEffect,
useMemo: updateMemo, useMemo: updateMemo,
useReducer: rerenderReducer, useReducer: rerenderReducer,
@ -4316,8 +4365,8 @@ function bubbleProperties(completedWork) {
) )
(newChildLanes |= child$43.lanes | child$43.childLanes), (newChildLanes |= child$43.lanes | child$43.childLanes),
(subtreeFlags |= child$43.subtreeFlags & 1835008), (subtreeFlags |= child$43.subtreeFlags & 3670016),
(subtreeFlags |= child$43.flags & 1835008), (subtreeFlags |= child$43.flags & 3670016),
(treeBaseDuration$42 += child$43.treeBaseDuration), (treeBaseDuration$42 += child$43.treeBaseDuration),
(child$43 = child$43.sibling); (child$43 = child$43.sibling);
completedWork.treeBaseDuration = treeBaseDuration$42; completedWork.treeBaseDuration = treeBaseDuration$42;
@ -4329,8 +4378,8 @@ function bubbleProperties(completedWork) {
) )
(newChildLanes |= (newChildLanes |=
treeBaseDuration$42.lanes | treeBaseDuration$42.childLanes), treeBaseDuration$42.lanes | treeBaseDuration$42.childLanes),
(subtreeFlags |= treeBaseDuration$42.subtreeFlags & 1835008), (subtreeFlags |= treeBaseDuration$42.subtreeFlags & 3670016),
(subtreeFlags |= treeBaseDuration$42.flags & 1835008), (subtreeFlags |= treeBaseDuration$42.flags & 3670016),
(treeBaseDuration$42.return = completedWork), (treeBaseDuration$42.return = completedWork),
(treeBaseDuration$42 = treeBaseDuration$42.sibling); (treeBaseDuration$42 = treeBaseDuration$42.sibling);
else if (0 !== (completedWork.mode & 2)) { else if (0 !== (completedWork.mode & 2)) {
@ -4572,7 +4621,7 @@ function completeWork(current, workInProgress, renderLanes) {
for (newProps = workInProgress.child; null !== newProps; ) for (newProps = workInProgress.child; null !== newProps; )
(renderLanes = newProps), (renderLanes = newProps),
(updatePayload = current), (updatePayload = current),
(renderLanes.flags &= 1835010), (renderLanes.flags &= 3670018),
(type = renderLanes.alternate), (type = renderLanes.alternate),
null === type null === type
? ((renderLanes.childLanes = 0), ? ((renderLanes.childLanes = 0),
@ -4804,7 +4853,7 @@ function updateSimpleMemoComponent(
current.ref === workInProgress.ref current.ref === workInProgress.ref
) )
if (((didReceiveUpdate = !1), 0 !== (current.lanes & renderLanes))) if (((didReceiveUpdate = !1), 0 !== (current.lanes & renderLanes)))
0 !== (current.flags & 32768) && (didReceiveUpdate = !0); 0 !== (current.flags & 65536) && (didReceiveUpdate = !0);
else else
return ( return (
(workInProgress.lanes = current.lanes), (workInProgress.lanes = current.lanes),
@ -5362,7 +5411,7 @@ function updateSuspenseFallbackChildren(
(primaryChildren.treeBaseDuration = current.treeBaseDuration)), (primaryChildren.treeBaseDuration = current.treeBaseDuration)),
(workInProgress.deletions = null)) (workInProgress.deletions = null))
: ((primaryChildren = createWorkInProgress(current, primaryChildProps)), : ((primaryChildren = createWorkInProgress(current, primaryChildProps)),
(primaryChildren.subtreeFlags = current.subtreeFlags & 1835008)); (primaryChildren.subtreeFlags = current.subtreeFlags & 3670016));
null !== currentFallbackChildFragment null !== currentFallbackChildFragment
? (fallbackChildren = createWorkInProgress( ? (fallbackChildren = createWorkInProgress(
currentFallbackChildFragment, currentFallbackChildFragment,
@ -5598,8 +5647,8 @@ function unwindWork(workInProgress) {
case 1: case 1:
isContextProvider(workInProgress.type) && popContext(); isContextProvider(workInProgress.type) && popContext();
var flags = workInProgress.flags; var flags = workInProgress.flags;
return flags & 16384 return flags & 32768
? ((workInProgress.flags = (flags & -16385) | 128), ? ((workInProgress.flags = (flags & -32769) | 128),
0 !== (workInProgress.mode & 2) && 0 !== (workInProgress.mode & 2) &&
transferActualDuration(workInProgress), transferActualDuration(workInProgress),
workInProgress) workInProgress)
@ -5614,7 +5663,7 @@ function unwindWork(workInProgress) {
throw Error( throw Error(
"The root failed to unmount after an error. This is likely a bug in React. Please file an issue." "The root failed to unmount after an error. This is likely a bug in React. Please file an issue."
); );
workInProgress.flags = (flags & -16385) | 128; workInProgress.flags = (flags & -32769) | 128;
return workInProgress; return workInProgress;
case 5: case 5:
return popHostContext(workInProgress), null; return popHostContext(workInProgress), null;
@ -5622,8 +5671,8 @@ function unwindWork(workInProgress) {
return ( return (
pop(suspenseStackCursor), pop(suspenseStackCursor),
(flags = workInProgress.flags), (flags = workInProgress.flags),
flags & 16384 flags & 32768
? ((workInProgress.flags = (flags & -16385) | 128), ? ((workInProgress.flags = (flags & -32769) | 128),
0 !== (workInProgress.mode & 2) && 0 !== (workInProgress.mode & 2) &&
transferActualDuration(workInProgress), transferActualDuration(workInProgress),
workInProgress) workInProgress)
@ -5787,8 +5836,8 @@ function commitUnmount(finishedRoot, current, nearestMountedAncestor) {
var _effect = effect, var _effect = effect,
destroy = _effect.destroy; destroy = _effect.destroy;
_effect = _effect.tag; _effect = _effect.tag;
void 0 !== destroy && void 0 === destroy ||
0 !== (_effect & 2) && (0 === (_effect & 2) && 0 === (_effect & 4)) ||
(current.mode & 2 (current.mode & 2
? (startLayoutEffectTimer(), ? (startLayoutEffectTimer(),
safelyCallDestroy(current, nearestMountedAncestor, destroy), safelyCallDestroy(current, nearestMountedAncestor, destroy),
@ -6111,14 +6160,16 @@ function commitWork(current, finishedWork) {
case 11: case 11:
case 14: case 14:
case 15: case 15:
commitHookEffectListUnmount(3, finishedWork, finishedWork.return);
commitHookEffectListMount(3, finishedWork);
if (finishedWork.mode & 2) if (finishedWork.mode & 2)
try { try {
startLayoutEffectTimer(), startLayoutEffectTimer(),
commitHookEffectListUnmount(3, finishedWork, finishedWork.return); commitHookEffectListUnmount(5, finishedWork, finishedWork.return);
} finally { } finally {
recordLayoutEffectDuration(finishedWork); recordLayoutEffectDuration(finishedWork);
} }
else commitHookEffectListUnmount(3, finishedWork, finishedWork.return); else commitHookEffectListUnmount(5, finishedWork, finishedWork.return);
return; return;
case 1: case 1:
return; return;
@ -6379,11 +6430,11 @@ function commitLayoutEffects(finishedWork, root, committedLanes) {
if (committedLanes.mode & 2) if (committedLanes.mode & 2)
try { try {
startLayoutEffectTimer(), startLayoutEffectTimer(),
commitHookEffectListMount(3, committedLanes); commitHookEffectListMount(5, committedLanes);
} finally { } finally {
recordLayoutEffectDuration(committedLanes); recordLayoutEffectDuration(committedLanes);
} }
else commitHookEffectListMount(3, committedLanes); else commitHookEffectListMount(5, committedLanes);
break; break;
case 1: case 1:
var instance = committedLanes.stateNode; var instance = committedLanes.stateNode;
@ -6722,15 +6773,15 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
root === workInProgressRoot ? workInProgressRootRenderLanes : 0 root === workInProgressRoot ? workInProgressRootRenderLanes : 0
); );
if (0 === lanes) return null; if (0 === lanes) return null;
var JSCompiler_inline_result = if (
0 !== (lanes & root.expiredLanes) includesBlockingLane(root, lanes) ||
? !1 0 !== (lanes & root.expiredLanes) ||
: 0 !== (root.current.mode & 32) didTimeout
? !0 )
: 0 === (lanes & 30); didTimeout = renderRootSync(root, lanes);
if (JSCompiler_inline_result && !didTimeout) { else {
didTimeout = lanes; didTimeout = lanes;
JSCompiler_inline_result = executionContext; var prevExecutionContext = executionContext;
executionContext |= 2; executionContext |= 2;
var prevDispatcher = pushDispatcher(); var prevDispatcher = pushDispatcher();
if ( if (
@ -6757,30 +6808,44 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
while (1); while (1);
resetContextDependencies(); resetContextDependencies();
ReactCurrentDispatcher$2.current = prevDispatcher; ReactCurrentDispatcher$2.current = prevDispatcher;
executionContext = JSCompiler_inline_result; executionContext = prevExecutionContext;
null !== workInProgress null !== workInProgress
? (didTimeout = 0) ? (didTimeout = 0)
: ((workInProgressRoot = null), : ((workInProgressRoot = null),
(workInProgressRootRenderLanes = 0), (workInProgressRootRenderLanes = 0),
(didTimeout = workInProgressRootExitStatus)); (didTimeout = workInProgressRootExitStatus));
} else didTimeout = renderRootSync(root, lanes); }
if (0 !== didTimeout) { if (0 !== didTimeout) {
2 === didTimeout && 2 === didTimeout &&
((JSCompiler_inline_result = executionContext), ((prevExecutionContext = getLanesToRetrySynchronouslyOnError(root)),
(executionContext |= 8), 0 !== prevExecutionContext &&
root.hydrate && (root.hydrate = !1), ((lanes = prevExecutionContext),
(prevDispatcher = getLanesToRetrySynchronouslyOnError(root)), (didTimeout = recoverFromConcurrentError(root, prevExecutionContext))));
0 !== prevDispatcher &&
((lanes = prevDispatcher),
(didTimeout = renderRootSync(root, prevDispatcher))),
(executionContext = JSCompiler_inline_result));
if (1 === didTimeout) if (1 === didTimeout)
throw ((originalCallbackNode = workInProgressRootFatalError), throw ((originalCallbackNode = workInProgressRootFatalError),
prepareFreshStack(root, 0), prepareFreshStack(root, 0),
markRootSuspended$1(root, lanes), markRootSuspended$1(root, lanes),
ensureRootIsScheduled(root, now()), ensureRootIsScheduled(root, now()),
originalCallbackNode); originalCallbackNode);
root.finishedWork = root.current.alternate; prevDispatcher = !includesBlockingLane(root, lanes);
prevExecutionContext = root.current.alternate;
if (
prevDispatcher &&
!isRenderConsistentWithExternalStores(prevExecutionContext) &&
((didTimeout = renderRootSync(root, lanes)),
2 === didTimeout &&
((prevDispatcher = getLanesToRetrySynchronouslyOnError(root)),
0 !== prevDispatcher &&
((lanes = prevDispatcher),
(didTimeout = recoverFromConcurrentError(root, prevDispatcher)))),
1 === didTimeout)
)
throw ((originalCallbackNode = workInProgressRootFatalError),
prepareFreshStack(root, 0),
markRootSuspended$1(root, lanes),
ensureRootIsScheduled(root, now()),
originalCallbackNode);
root.finishedWork = prevExecutionContext;
root.finishedLanes = lanes; root.finishedLanes = lanes;
switch (didTimeout) { switch (didTimeout) {
case 0: case 0:
@ -6797,10 +6862,10 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
10 < didTimeout) 10 < didTimeout)
) { ) {
if (0 !== getNextLanes(root, 0)) break; if (0 !== getNextLanes(root, 0)) break;
JSCompiler_inline_result = root.suspendedLanes; prevExecutionContext = root.suspendedLanes;
if ((JSCompiler_inline_result & lanes) !== lanes) { if ((prevExecutionContext & lanes) !== lanes) {
requestEventTime(); requestEventTime();
root.pingedLanes |= root.suspendedLanes & JSCompiler_inline_result; root.pingedLanes |= root.suspendedLanes & prevExecutionContext;
break; break;
} }
root.timeoutHandle = scheduleTimeout( root.timeoutHandle = scheduleTimeout(
@ -6815,14 +6880,14 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
markRootSuspended$1(root, lanes); markRootSuspended$1(root, lanes);
if ((lanes & 4194240) === lanes) break; if ((lanes & 4194240) === lanes) break;
didTimeout = root.eventTimes; didTimeout = root.eventTimes;
for (JSCompiler_inline_result = -1; 0 < lanes; ) for (prevExecutionContext = -1; 0 < lanes; )
(memoizedUpdaters = 31 - clz32(lanes)), (memoizedUpdaters = 31 - clz32(lanes)),
(prevDispatcher = 1 << memoizedUpdaters), (prevDispatcher = 1 << memoizedUpdaters),
(memoizedUpdaters = didTimeout[memoizedUpdaters]), (memoizedUpdaters = didTimeout[memoizedUpdaters]),
memoizedUpdaters > JSCompiler_inline_result && memoizedUpdaters > prevExecutionContext &&
(JSCompiler_inline_result = memoizedUpdaters), (prevExecutionContext = memoizedUpdaters),
(lanes &= ~prevDispatcher); (lanes &= ~prevDispatcher);
lanes = JSCompiler_inline_result; lanes = prevExecutionContext;
lanes = now() - lanes; lanes = now() - lanes;
lanes = lanes =
(120 > lanes (120 > lanes
@ -6859,6 +6924,48 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
? performConcurrentWorkOnRoot.bind(null, root) ? performConcurrentWorkOnRoot.bind(null, root)
: null; : null;
} }
function recoverFromConcurrentError(root, errorRetryLanes) {
var prevExecutionContext = executionContext;
executionContext |= 8;
root.hydrate && (root.hydrate = !1);
root = renderRootSync(root, errorRetryLanes);
executionContext = prevExecutionContext;
return root;
}
function isRenderConsistentWithExternalStores(finishedWork) {
for (var node = finishedWork; ; ) {
if (node.flags & 8192) {
var updateQueue = node.updateQueue;
if (
null !== updateQueue &&
((updateQueue = updateQueue.stores), null !== updateQueue)
)
for (var i = 0; i < updateQueue.length; i++) {
var check = updateQueue[i],
getSnapshot = check.getSnapshot;
check = check.value;
try {
if (!objectIs(getSnapshot(), check)) return !1;
} catch (error) {
return !1;
}
}
}
updateQueue = node.child;
if (node.subtreeFlags & 8192 && null !== updateQueue)
(updateQueue.return = node), (node = updateQueue);
else {
if (node === finishedWork) break;
for (; null === node.sibling; ) {
if (null === node.return || node.return === finishedWork) return !0;
node = node.return;
}
node.sibling.return = node.return;
node = node.sibling;
}
}
return !0;
}
function markRootSuspended$1(root, suspendedLanes) { function markRootSuspended$1(root, suspendedLanes) {
suspendedLanes &= ~workInProgressRootPingedLanes; suspendedLanes &= ~workInProgressRootPingedLanes;
suspendedLanes &= ~workInProgressRootUpdatedLanes; suspendedLanes &= ~workInProgressRootUpdatedLanes;
@ -7010,7 +7117,7 @@ function handleError(root$jscomp$0, thrownValue) {
sourceFiber = erroredWork, sourceFiber = erroredWork,
value = thrownValue; value = thrownValue;
thrownValue = workInProgressRootRenderLanes; thrownValue = workInProgressRootRenderLanes;
sourceFiber.flags |= 8192; sourceFiber.flags |= 16384;
isDevToolsPresent && restorePendingUpdaters(root, thrownValue); isDevToolsPresent && restorePendingUpdaters(root, thrownValue);
if ( if (
null !== value && null !== value &&
@ -7062,8 +7169,8 @@ function handleError(root$jscomp$0, thrownValue) {
workInProgress$34 !== returnFiber workInProgress$34 !== returnFiber
) { ) {
workInProgress$34.flags |= 128; workInProgress$34.flags |= 128;
sourceFiber.flags |= 32768; sourceFiber.flags |= 65536;
sourceFiber.flags &= -10053; sourceFiber.flags &= -26437;
if (1 === sourceFiber.tag) if (1 === sourceFiber.tag)
if (null === sourceFiber.alternate) sourceFiber.tag = 17; if (null === sourceFiber.alternate) sourceFiber.tag = 17;
else { else {
@ -7095,7 +7202,7 @@ function handleError(root$jscomp$0, thrownValue) {
isDevToolsPresent && restorePendingUpdaters(root, sourceFiber); isDevToolsPresent && restorePendingUpdaters(root, sourceFiber);
wakeable.then(ping, ping); wakeable.then(ping, ping);
} }
workInProgress$34.flags |= 16384; workInProgress$34.flags |= 32768;
workInProgress$34.lanes = thrownValue; workInProgress$34.lanes = thrownValue;
break a; break a;
} }
@ -7114,7 +7221,7 @@ function handleError(root$jscomp$0, thrownValue) {
switch (workInProgress$34.tag) { switch (workInProgress$34.tag) {
case 3: case 3:
root = value; root = value;
workInProgress$34.flags |= 16384; workInProgress$34.flags |= 32768;
thrownValue &= -thrownValue; thrownValue &= -thrownValue;
workInProgress$34.lanes |= thrownValue; workInProgress$34.lanes |= thrownValue;
var update$35 = createRootErrorUpdate( var update$35 = createRootErrorUpdate(
@ -7136,7 +7243,7 @@ function handleError(root$jscomp$0, thrownValue) {
(null === legacyErrorBoundariesThatAlreadyFailed || (null === legacyErrorBoundariesThatAlreadyFailed ||
!legacyErrorBoundariesThatAlreadyFailed.has(instance)))) !legacyErrorBoundariesThatAlreadyFailed.has(instance))))
) { ) {
workInProgress$34.flags |= 16384; workInProgress$34.flags |= 32768;
thrownValue &= -thrownValue; thrownValue &= -thrownValue;
workInProgress$34.lanes |= thrownValue; workInProgress$34.lanes |= thrownValue;
var update$38 = createClassErrorUpdate( var update$38 = createClassErrorUpdate(
@ -7226,7 +7333,7 @@ function completeUnitOfWork(unitOfWork) {
do { do {
var current = completedWork.alternate; var current = completedWork.alternate;
unitOfWork = completedWork.return; unitOfWork = completedWork.return;
if (0 === (completedWork.flags & 8192)) { if (0 === (completedWork.flags & 16384)) {
if (0 === (completedWork.mode & 2)) if (0 === (completedWork.mode & 2))
current = completeWork(current, completedWork, subtreeRenderLanes); current = completeWork(current, completedWork, subtreeRenderLanes);
else { else {
@ -7243,7 +7350,7 @@ function completeUnitOfWork(unitOfWork) {
} else { } else {
current = unwindWork(completedWork); current = unwindWork(completedWork);
if (null !== current) { if (null !== current) {
current.flags &= 8191; current.flags &= 16383;
workInProgress = current; workInProgress = current;
return; return;
} }
@ -7255,7 +7362,7 @@ function completeUnitOfWork(unitOfWork) {
completedWork.actualDuration = current; completedWork.actualDuration = current;
} }
null !== unitOfWork && null !== unitOfWork &&
((unitOfWork.flags |= 8192), ((unitOfWork.flags |= 16384),
(unitOfWork.subtreeFlags = 0), (unitOfWork.subtreeFlags = 0),
(unitOfWork.deletions = null)); (unitOfWork.deletions = null));
} }
@ -7335,12 +7442,6 @@ function commitRootImpl(root, renderPriorityLevel) {
(pendingPassiveEffectsLanes = lanes)); (pendingPassiveEffectsLanes = lanes));
remainingLanes = root.pendingLanes; remainingLanes = root.pendingLanes;
0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null);
0 !== (remainingLanes & 1)
? ((nestedUpdateScheduled = !0),
root === rootWithNestedUpdates
? nestedUpdateCount++
: ((nestedUpdateCount = 0), (rootWithNestedUpdates = root)))
: (nestedUpdateCount = 0);
onCommitRoot(finishedWork.stateNode, renderPriorityLevel); onCommitRoot(finishedWork.stateNode, renderPriorityLevel);
isDevToolsPresent && root.memoizedUpdaters.clear(); isDevToolsPresent && root.memoizedUpdaters.clear();
ensureRootIsScheduled(root, now()); ensureRootIsScheduled(root, now());
@ -7352,6 +7453,13 @@ function commitRootImpl(root, renderPriorityLevel) {
0 !== (pendingPassiveEffectsLanes & 1) && 0 !== (pendingPassiveEffectsLanes & 1) &&
0 !== root.tag && 0 !== root.tag &&
flushPassiveEffects(); flushPassiveEffects();
remainingLanes = root.pendingLanes;
0 !== (remainingLanes & 1)
? ((nestedUpdateScheduled = !0),
root === rootWithNestedUpdates
? nestedUpdateCount++
: ((nestedUpdateCount = 0), (rootWithNestedUpdates = root)))
: (nestedUpdateCount = 0);
flushSyncCallbacks(); flushSyncCallbacks();
return null; return null;
} }
@ -7390,9 +7498,9 @@ function flushPassiveEffects() {
case 15: case 15:
current.mode & 2 current.mode & 2
? ((passiveEffectStartTime = now$1()), ? ((passiveEffectStartTime = now$1()),
commitHookEffectListUnmount(4, current, fiber), commitHookEffectListUnmount(8, current, fiber),
recordPassiveEffectDuration(current)) recordPassiveEffectDuration(current))
: commitHookEffectListUnmount(4, current, fiber); : commitHookEffectListUnmount(8, current, fiber);
} }
var child$jscomp$0 = fiber$jscomp$0.child; var child$jscomp$0 = fiber$jscomp$0.child;
if (null !== child$jscomp$0) if (null !== child$jscomp$0)
@ -7444,9 +7552,9 @@ function flushPassiveEffects() {
case 15: case 15:
i.mode & 2 i.mode & 2
? ((passiveEffectStartTime = now$1()), ? ((passiveEffectStartTime = now$1()),
commitHookEffectListUnmount(5, i, i.return), commitHookEffectListUnmount(9, i, i.return),
recordPassiveEffectDuration(i)) recordPassiveEffectDuration(i))
: commitHookEffectListUnmount(5, i, i.return); : commitHookEffectListUnmount(9, i, i.return);
} }
var sibling$jscomp$0 = fiber.sibling; var sibling$jscomp$0 = fiber.sibling;
if (null !== sibling$jscomp$0) { if (null !== sibling$jscomp$0) {
@ -7475,11 +7583,11 @@ function flushPassiveEffects() {
if (fiberToDelete.mode & 2) { if (fiberToDelete.mode & 2) {
passiveEffectStartTime = now$1(); passiveEffectStartTime = now$1();
try { try {
commitHookEffectListMount(5, fiberToDelete); commitHookEffectListMount(9, fiberToDelete);
} finally { } finally {
recordPassiveEffectDuration(fiberToDelete); recordPassiveEffectDuration(fiberToDelete);
} }
} else commitHookEffectListMount(5, fiberToDelete); } else commitHookEffectListMount(9, fiberToDelete);
} }
} catch (error) { } catch (error) {
captureCommitPhaseError(deletions, deletions.return, error); captureCommitPhaseError(deletions, deletions.return, error);
@ -7674,7 +7782,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) {
renderLanes renderLanes
) )
); );
didReceiveUpdate = 0 !== (current.flags & 32768) ? !0 : !1; didReceiveUpdate = 0 !== (current.flags & 65536) ? !0 : !1;
} }
else didReceiveUpdate = !1; else didReceiveUpdate = !1;
workInProgress.lanes = 0; workInProgress.lanes = 0;
@ -8155,7 +8263,7 @@ function createWorkInProgress(current, pendingProps) {
(workInProgress.deletions = null), (workInProgress.deletions = null),
(workInProgress.actualDuration = 0), (workInProgress.actualDuration = 0),
(workInProgress.actualStartTime = -1)); (workInProgress.actualStartTime = -1));
workInProgress.flags = current.flags & 1835008; workInProgress.flags = current.flags & 3670016;
workInProgress.childLanes = current.childLanes; workInProgress.childLanes = current.childLanes;
workInProgress.lanes = current.lanes; workInProgress.lanes = current.lanes;
workInProgress.child = current.child; workInProgress.child = current.child;
@ -8519,10 +8627,10 @@ batchedUpdatesImpl = function(fn, a) {
} }
}; };
var roots = new Map(), var roots = new Map(),
devToolsConfig$jscomp$inline_1019 = { devToolsConfig$jscomp$inline_1016 = {
findFiberByHostInstance: getInstanceFromTag, findFiberByHostInstance: getInstanceFromTag,
bundleType: 0, bundleType: 0,
version: "18.0.0-95d762e40-20210908", version: "18.0.0-e8feb11b6-20210915",
rendererPackageName: "react-native-renderer", rendererPackageName: "react-native-renderer",
rendererConfig: { rendererConfig: {
getInspectorDataForViewTag: function() { getInspectorDataForViewTag: function() {
@ -8537,11 +8645,11 @@ var roots = new Map(),
}.bind(null, findNodeHandle) }.bind(null, findNodeHandle)
} }
}; };
var internals$jscomp$inline_1292 = { var internals$jscomp$inline_1289 = {
bundleType: devToolsConfig$jscomp$inline_1019.bundleType, bundleType: devToolsConfig$jscomp$inline_1016.bundleType,
version: devToolsConfig$jscomp$inline_1019.version, version: devToolsConfig$jscomp$inline_1016.version,
rendererPackageName: devToolsConfig$jscomp$inline_1019.rendererPackageName, rendererPackageName: devToolsConfig$jscomp$inline_1016.rendererPackageName,
rendererConfig: devToolsConfig$jscomp$inline_1019.rendererConfig, rendererConfig: devToolsConfig$jscomp$inline_1016.rendererConfig,
overrideHookState: null, overrideHookState: null,
overrideHookStateDeletePath: null, overrideHookStateDeletePath: null,
overrideHookStateRenamePath: null, overrideHookStateRenamePath: null,
@ -8557,7 +8665,7 @@ var internals$jscomp$inline_1292 = {
return null === fiber ? null : fiber.stateNode; return null === fiber ? null : fiber.stateNode;
}, },
findFiberByHostInstance: findFiberByHostInstance:
devToolsConfig$jscomp$inline_1019.findFiberByHostInstance || devToolsConfig$jscomp$inline_1016.findFiberByHostInstance ||
emptyFindFiberByHostInstance, emptyFindFiberByHostInstance,
findHostInstancesForRefresh: null, findHostInstancesForRefresh: null,
scheduleRefresh: null, scheduleRefresh: null,
@ -8565,19 +8673,19 @@ var internals$jscomp$inline_1292 = {
setRefreshHandler: null, setRefreshHandler: null,
getCurrentFiber: null, getCurrentFiber: null,
getIsStrictMode: null, getIsStrictMode: null,
reconcilerVersion: "18.0.0-95d762e40-20210908" reconcilerVersion: "18.0.0-e8feb11b6-20210915"
}; };
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1293 = __REACT_DEVTOOLS_GLOBAL_HOOK__; var hook$jscomp$inline_1290 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
if ( if (
!hook$jscomp$inline_1293.isDisabled && !hook$jscomp$inline_1290.isDisabled &&
hook$jscomp$inline_1293.supportsFiber hook$jscomp$inline_1290.supportsFiber
) )
try { try {
(rendererID = hook$jscomp$inline_1293.inject( (rendererID = hook$jscomp$inline_1290.inject(
internals$jscomp$inline_1292 internals$jscomp$inline_1289
)), )),
(injectedHook = hook$jscomp$inline_1293); (injectedHook = hook$jscomp$inline_1290);
} catch (err) {} } catch (err) {}
} }
exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {

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

@ -288,20 +288,10 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
@"streetAddressLine2": UITextContentTypeStreetAddressLine2, @"streetAddressLine2": UITextContentTypeStreetAddressLine2,
@"sublocality": UITextContentTypeSublocality, @"sublocality": UITextContentTypeSublocality,
@"telephoneNumber": UITextContentTypeTelephoneNumber, @"telephoneNumber": UITextContentTypeTelephoneNumber,
@"username": UITextContentTypeUsername,
@"password": UITextContentTypePassword,
}; };
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
if (@available(iOS 11.0, *)) {
NSDictionary<NSString *, NSString *> * iOS11extras = @{@"username": UITextContentTypeUsername,
@"password": UITextContentTypePassword};
NSMutableDictionary<NSString *, NSString *> * iOS11baseMap = [contentTypeMap mutableCopy];
[iOS11baseMap addEntriesFromDictionary:iOS11extras];
contentTypeMap = [iOS11baseMap copy];
}
#endif
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 120000 /* __IPHONE_12_0 */ #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 120000 /* __IPHONE_12_0 */
if (@available(iOS 12.0, *)) { if (@available(iOS 12.0, *)) {
NSDictionary<NSString *, NSString *> * iOS12extras = @{@"newPassword": UITextContentTypeNewPassword, NSDictionary<NSString *, NSString *> * iOS12extras = @{@"newPassword": UITextContentTypeNewPassword,

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

@ -30,21 +30,17 @@
_heightConstraint = [_safeAreaContainer.heightAnchor constraintEqualToConstant:0]; _heightConstraint = [_safeAreaContainer.heightAnchor constraintEqualToConstant:0];
_heightConstraint.active = YES; _heightConstraint.active = YES;
#if !TARGET_OS_OSX // TODO(macOS GH#774) #if !TARGET_OS_OSX // [TODO(macOS GH#774)
if (@available(iOS 11.0, *)) { [_safeAreaContainer.bottomAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.bottomAnchor].active = YES;
[_safeAreaContainer.bottomAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.bottomAnchor].active = YES; [_safeAreaContainer.topAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor].active = YES;
[_safeAreaContainer.topAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor].active = YES; [_safeAreaContainer.leadingAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.leadingAnchor].active = YES;
[_safeAreaContainer.leadingAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.leadingAnchor].active = YES; [_safeAreaContainer.trailingAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.trailingAnchor].active = YES;
[_safeAreaContainer.trailingAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.trailingAnchor].active = YES; #else // TODO(macOS GH#774)
} else { [_safeAreaContainer.bottomAnchor constraintEqualToAnchor:self.bottomAnchor].active = YES;
#endif // TODO(macOS GH#774) [_safeAreaContainer.topAnchor constraintEqualToAnchor:self.topAnchor].active = YES;
[_safeAreaContainer.bottomAnchor constraintEqualToAnchor:self.bottomAnchor].active = YES; [_safeAreaContainer.leadingAnchor constraintEqualToAnchor:self.leadingAnchor].active = YES;
[_safeAreaContainer.topAnchor constraintEqualToAnchor:self.topAnchor].active = YES; [_safeAreaContainer.trailingAnchor constraintEqualToAnchor:self.trailingAnchor].active = YES;
[_safeAreaContainer.leadingAnchor constraintEqualToAnchor:self.leadingAnchor].active = YES; #endif // ]TODO(macOS GH#774)
[_safeAreaContainer.trailingAnchor constraintEqualToAnchor:self.trailingAnchor].active = YES;
#if !TARGET_OS_OSX // TODO(macOS GH#774)
}
#endif // TODO(macOS GH#774)
} }
return self; return self;
} }

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

@ -16,12 +16,6 @@ RCT_EXTERN NSString *const RCTUserInterfaceStyleDidChangeNotificationTraitCollec
RCT_EXTERN BOOL RCTExperimentGetPreemptiveViewAllocationDisabled(void); RCT_EXTERN BOOL RCTExperimentGetPreemptiveViewAllocationDisabled(void);
RCT_EXTERN void RCTExperimentSetPreemptiveViewAllocationDisabled(BOOL value); RCT_EXTERN void RCTExperimentSetPreemptiveViewAllocationDisabled(BOOL value);
/*
* Initial maximum surface size
*/
RCT_EXTERN BOOL RCTGetInitialMaxSizeEnabled(void);
RCT_EXTERN void RCTSetInitialMaxSizeEnabled(BOOL value);
/* /*
* Remove clipped subviews * Remove clipped subviews
*/ */

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

@ -25,21 +25,6 @@ void RCTExperimentSetPreemptiveViewAllocationDisabled(BOOL value)
RCTExperimentPreemptiveViewAllocationDisabled = value; RCTExperimentPreemptiveViewAllocationDisabled = value;
} }
/*
* Initial maximum surface size
*/
static BOOL RCTInitialMaxSizeEnabled = NO;
BOOL RCTGetInitialMaxSizeEnabled()
{
return RCTInitialMaxSizeEnabled;
}
void RCTSetInitialMaxSizeEnabled(BOOL value)
{
RCTInitialMaxSizeEnabled = value;
}
/* /*
* Remove clipped subviews * Remove clipped subviews
*/ */

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

@ -76,7 +76,7 @@ typedef NSURL RCTFileURL;
#endif #endif
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
+ (WKDataDetectorTypes)WKDataDetectorTypes:(id)json API_AVAILABLE(ios(10.0)); + (WKDataDetectorTypes)WKDataDetectorTypes:(id)json;
#endif #endif
+ (UIViewContentMode)UIViewContentMode:(id)json; + (UIViewContentMode)UIViewContentMode:(id)json;

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

@ -41,10 +41,6 @@
__weak RCTUIView *_cachedRootView; // TODO(macOS GH#774) __weak RCTUIView *_cachedRootView; // TODO(macOS GH#774)
// See Touch.h and usage. This gives us a time-basis for a monotonic
// clock that acts like a timestamp of milliseconds elapsed since UNIX epoch.
NSTimeInterval _unixEpochBasisTime;
uint16_t _coalescingKey; uint16_t _coalescingKey;
#if TARGET_OS_OSX// [TODO(macOS GH#774) #if TARGET_OS_OSX// [TODO(macOS GH#774)
BOOL _shouldSendMouseUpOnSystemBehalf; BOOL _shouldSendMouseUpOnSystemBehalf;
@ -62,9 +58,6 @@
_reactTouches = [NSMutableArray new]; _reactTouches = [NSMutableArray new];
_touchViews = [NSMutableArray new]; _touchViews = [NSMutableArray new];
// Get a UNIX epoch basis time:
_unixEpochBasisTime = [[NSDate date] timeIntervalSince1970] - [NSProcessInfo processInfo].systemUptime;
#if !TARGET_OS_OSX // TODO(macOS GH#774) #if !TARGET_OS_OSX // TODO(macOS GH#774)
// `cancelsTouchesInView` and `delaysTouches*` are needed in order to be used as a top level // `cancelsTouchesInView` and `delaysTouches*` are needed in order to be used as a top level
// event delegated recognizer. Otherwise, lower-level components not built // event delegated recognizer. Otherwise, lower-level components not built
@ -236,7 +229,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)coder)
reactTouch[@"pageY"] = @(RCTSanitizeNaNValue(rootViewLocation.y, @"touchEvent.pageY")); reactTouch[@"pageY"] = @(RCTSanitizeNaNValue(rootViewLocation.y, @"touchEvent.pageY"));
reactTouch[@"locationX"] = @(RCTSanitizeNaNValue(touchViewLocation.x, @"touchEvent.locationX")); reactTouch[@"locationX"] = @(RCTSanitizeNaNValue(touchViewLocation.x, @"touchEvent.locationX"));
reactTouch[@"locationY"] = @(RCTSanitizeNaNValue(touchViewLocation.y, @"touchEvent.locationY")); reactTouch[@"locationY"] = @(RCTSanitizeNaNValue(touchViewLocation.y, @"touchEvent.locationY"));
reactTouch[@"timestamp"] = @((_unixEpochBasisTime + nativeTouch.timestamp) * 1000); // in ms, for JS reactTouch[@"timestamp"] = @(nativeTouch.timestamp * 1000); // in ms, for JS
#if !TARGET_OS_OSX // TODO(macOS GH#774) #if !TARGET_OS_OSX // TODO(macOS GH#774)
// TODO: force for a 'normal' touch is usually 1.0; // TODO: force for a 'normal' touch is usually 1.0;

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

@ -40,6 +40,9 @@ RCT_EXTERN void RCTExecuteOnMainQueue(dispatch_block_t block);
// Please do not use this unless you know what you're doing. // Please do not use this unless you know what you're doing.
RCT_EXTERN void RCTUnsafeExecuteOnMainQueueSync(dispatch_block_t block); RCT_EXTERN void RCTUnsafeExecuteOnMainQueueSync(dispatch_block_t block);
// Get screen scale, can be only used on main
RCT_EXTERN void RCTComputeScreenScale(void);
// Get screen metrics in a thread-safe way // Get screen metrics in a thread-safe way
RCT_EXTERN CGFloat RCTScreenScale(void); RCT_EXTERN CGFloat RCTScreenScale(void);
RCT_EXTERN CGFloat RCTFontSizeMultiplier(void); RCT_EXTERN CGFloat RCTFontSizeMultiplier(void);

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

@ -297,16 +297,23 @@ static void RCTUnsafeExecuteOnMainQueueOnceSync(dispatch_once_t *onceToken, disp
} }
#if !TARGET_OS_OSX // TODO(macOS GH#774) #if !TARGET_OS_OSX // TODO(macOS GH#774)
static dispatch_once_t onceTokenScreenScale;
static CGFloat screenScale;
void RCTComputeScreenScale()
{
dispatch_once(&onceTokenScreenScale, ^{
screenScale = [UIScreen mainScreen].scale;
});
}
CGFloat RCTScreenScale() CGFloat RCTScreenScale()
{ {
static dispatch_once_t onceToken; RCTUnsafeExecuteOnMainQueueOnceSync(&onceTokenScreenScale, ^{
static CGFloat scale; screenScale = [UIScreen mainScreen].scale;
RCTUnsafeExecuteOnMainQueueOnceSync(&onceToken, ^{
scale = [UIScreen mainScreen].scale;
}); });
return scale; return screenScale;
} }
CGFloat RCTFontSizeMultiplier() CGFloat RCTFontSizeMultiplier()
@ -335,7 +342,7 @@ CGFloat RCTFontSizeMultiplier()
CGSize RCTScreenSize() CGSize RCTScreenSize()
{ {
// FIXME: this caches the bounds at app start, whatever those were, and then // FIXME: this caches whatever the bounds were when it was first called, and then
// doesn't update when the device is rotated. We need to find another thread- // doesn't update when the device is rotated. We need to find another thread-
// safe way to get the screen size. // safe way to get the screen size.

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

@ -120,6 +120,8 @@ RCT_EXPORT_METHOD(showActionSheetWithOptions
#if !TARGET_OS_OSX // TODO(macOS GH#774) #if !TARGET_OS_OSX // TODO(macOS GH#774)
UIViewController *controller = RCTPresentedViewController(); UIViewController *controller = RCTPresentedViewController();
UIColor *tintColor = [RCTConvert UIColor:options.tintColor() ? @(*options.tintColor()) : nil]; UIColor *tintColor = [RCTConvert UIColor:options.tintColor() ? @(*options.tintColor()) : nil];
UIColor *cancelButtonTintColor =
[RCTConvert UIColor:options.cancelButtonTintColor() ? @(*options.cancelButtonTintColor()) : nil];
if (controller == nil) { if (controller == nil) {
RCTLogError( RCTLogError(
@ -131,6 +133,7 @@ RCT_EXPORT_METHOD(showActionSheetWithOptions
@"destructiveButtonIndices" : destructiveButtonIndices ?: [NSNull null], @"destructiveButtonIndices" : destructiveButtonIndices ?: [NSNull null],
@"anchor" : anchor ?: [NSNull null], @"anchor" : anchor ?: [NSNull null],
@"tintColor" : tintColor ?: [NSNull null], @"tintColor" : tintColor ?: [NSNull null],
@"cancelButtonTintColor" : cancelButtonTintColor ?: [NSNull null],
@"disabledButtonIndices" : disabledButtonIndices ?: [NSNull null], @"disabledButtonIndices" : disabledButtonIndices ?: [NSNull null],
}); /* // TODO(macOS GH#774): nil check our dict values before inserting them or we may crash ] */ }); /* // TODO(macOS GH#774): nil check our dict values before inserting them or we may crash ] */
return; return;
@ -149,20 +152,26 @@ RCT_EXPORT_METHOD(showActionSheetWithOptions
preferredStyle:UIAlertControllerStyleActionSheet]; preferredStyle:UIAlertControllerStyleActionSheet];
NSInteger index = 0; NSInteger index = 0;
bool isCancelButtonIndex = false;
for (NSString *option in buttons) { for (NSString *option in buttons) {
UIAlertActionStyle style = UIAlertActionStyleDefault; UIAlertActionStyle style = UIAlertActionStyleDefault;
if ([destructiveButtonIndices containsObject:@(index)]) { if ([destructiveButtonIndices containsObject:@(index)]) {
style = UIAlertActionStyleDestructive; style = UIAlertActionStyleDestructive;
} else if (index == cancelButtonIndex) { } else if (index == cancelButtonIndex) {
style = UIAlertActionStyleCancel; style = UIAlertActionStyleCancel;
isCancelButtonIndex = true;
} }
NSInteger localIndex = index; NSInteger localIndex = index;
[alertController addAction:[UIAlertAction actionWithTitle:option UIAlertAction *actionButton = [UIAlertAction actionWithTitle:option
style:style style:style
handler:^(__unused UIAlertAction *action) { handler:^(__unused UIAlertAction *action) {
callback(@[ @(localIndex) ]); callback(@[ @(localIndex) ]);
}]]; }];
if (isCancelButtonIndex) {
[actionButton setValue:cancelButtonTintColor forKey:@"titleTextColor"];
}
[alertController addAction:actionButton];
index++; index++;
} }

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

@ -128,16 +128,11 @@ RCT_EXPORT_MODULE()
#if !TARGET_OS_OSX // TODO(macOS GH#774) #if !TARGET_OS_OSX // TODO(macOS GH#774)
CGSize screenSize = [UIScreen mainScreen].bounds.size; CGSize screenSize = [UIScreen mainScreen].bounds.size;
if (@available(iOS 11.0, *)) { UIWindow *window = RCTSharedApplication().keyWindow;
UIWindow *window = RCTSharedApplication().keyWindow; self->_window =
self->_window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, screenSize.width, window.safeAreaInsets.top + 10)];
[[UIWindow alloc] initWithFrame:CGRectMake(0, 0, screenSize.width, window.safeAreaInsets.top + 10)]; self->_label =
self->_label = [[UILabel alloc] initWithFrame:CGRectMake(0, window.safeAreaInsets.top - 10, screenSize.width, 20)];
[[UILabel alloc] initWithFrame:CGRectMake(0, window.safeAreaInsets.top - 10, screenSize.width, 20)];
} else {
self->_window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, screenSize.width, 20)];
self->_label = [[UILabel alloc] initWithFrame:self->_window.bounds];
}
[self->_window addSubview:self->_label]; [self->_window addSubview:self->_label];
self->_window.windowLevel = UIWindowLevelStatusBar + 1; self->_window.windowLevel = UIWindowLevelStatusBar + 1;

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

@ -206,11 +206,7 @@
- (NSInteger)bottomSafeViewHeight - (NSInteger)bottomSafeViewHeight
{ {
if (@available(iOS 11.0, *)) { return RCTSharedApplication().delegate.window.safeAreaInsets.bottom;
return RCTSharedApplication().delegate.window.safeAreaInsets.bottom;
} else {
return 0;
}
} }
RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder) RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)

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

@ -59,6 +59,9 @@ typedef void (^RCTConnectedHandler)(void);
/** Disconnects and removes all handlers. */ /** Disconnects and removes all handlers. */
- (void)stop; - (void)stop;
/** Reconnect with given packager server. */
- (void)reconnect:(NSString *)packagerServerHostPort;
/** /**
* Historically no distinction was made between notification and request * Historically no distinction was made between notification and request
* handlers. If you use this method, it will be registered as *both* a * handlers. If you use this method, it will be registered as *both* a

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

@ -125,28 +125,32 @@ static RCTReconnectingWebSocket *socketForLocation(NSString *const serverHostPor
_requestRegistrations.clear(); _requestRegistrations.clear();
} }
- (void)bundleURLSettingsChanged - (void)reconnect:(NSString *)packagerServerHostPort
{ {
std::lock_guard<std::mutex> l(_mutex); std::lock_guard<std::mutex> l(_mutex);
if (_socket == nil) { if (_socket == nil) {
return; // already stopped return; // already stopped
} }
NSString *const serverHostPort = [[RCTBundleURLProvider sharedSettings] packagerServerHostPort];
NSString *const serverScheme = [[RCTBundleURLProvider sharedSettings] packagerScheme]; NSString *const serverScheme = [[RCTBundleURLProvider sharedSettings] packagerScheme];
if ([serverHostPort isEqual:_serverHostPortForSocket] && [serverScheme isEqual:_serverSchemeForSocket]) { if ([packagerServerHostPort isEqual:_serverHostPortForSocket] && [serverScheme isEqual:_serverSchemeForSocket]) {
return; // unchanged return; // unchanged
} }
_socket.delegate = nil; _socket.delegate = nil;
[_socket stop]; [_socket stop];
_serverHostPortForSocket = serverHostPort; _serverHostPortForSocket = packagerServerHostPort;
_serverSchemeForSocket = serverScheme; _serverSchemeForSocket = serverScheme;
_socket = socketForLocation(serverHostPort, serverScheme); _socket = socketForLocation(packagerServerHostPort, serverScheme);
_socket.delegate = self; _socket.delegate = self;
[_socket start]; [_socket start];
} }
- (void)bundleURLSettingsChanged
{
[self reconnect:[[RCTBundleURLProvider sharedSettings] packagerServerHostPort]];
}
- (RCTHandlerToken)addNotificationHandler:(RCTNotificationHandler)handler - (RCTHandlerToken)addNotificationHandler:(RCTNotificationHandler)handler
queue:(dispatch_queue_t)queue queue:(dispatch_queue_t)queue
forMethod:(NSString *)method forMethod:(NSString *)method

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

@ -133,15 +133,6 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg
[self.scrollViewDelegateSplitter removeAllDelegates]; [self.scrollViewDelegateSplitter removeAllDelegates];
} }
- (void)layoutSubviews
{
[super layoutSubviews];
if (_subviewClippingEnabled) {
[self _remountChildren];
}
}
- (RCTGenericDelegateSplitter<id<UIScrollViewDelegate>> *)scrollViewDelegateSplitter - (RCTGenericDelegateSplitter<id<UIScrollViewDelegate>> *)scrollViewDelegateSplitter
{ {
return ((RCTEnhancedScrollView *)_scrollView).delegateSplitter; return ((RCTEnhancedScrollView *)_scrollView).delegateSplitter;
@ -611,6 +602,11 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg
#pragma mark - Child views mounting #pragma mark - Child views mounting
- (void)updateClippedSubviewsWithClipRect:(CGRect)clipRect relativeToView:(UIView *)clipView
{
// Do nothing. ScrollView manages its subview clipping individually in `_remountChildren`.
}
- (void)_remountChildrenIfNeeded - (void)_remountChildrenIfNeeded
{ {
CGPoint contentOffset = _scrollView.contentOffset; CGPoint contentOffset = _scrollView.contentOffset;

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

@ -331,11 +331,7 @@ using namespace facebook::react;
// `accessibilityIgnoresInvertColors` // `accessibilityIgnoresInvertColors`
if (oldViewProps.accessibilityIgnoresInvertColors != newViewProps.accessibilityIgnoresInvertColors) { if (oldViewProps.accessibilityIgnoresInvertColors != newViewProps.accessibilityIgnoresInvertColors) {
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */ self.accessibilityIgnoresInvertColors = newViewProps.accessibilityIgnoresInvertColors;
if (@available(iOS 11.0, *)) {
self.accessibilityIgnoresInvertColors = newViewProps.accessibilityIgnoresInvertColors;
}
#endif
} }
// `accessibilityValue` // `accessibilityValue`

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

@ -122,8 +122,8 @@ class LayoutAnimationDelegateProxy : public LayoutAnimationStatusDelegate, publi
if (reactNativeConfig->getBool("react_fabric:enabled_layout_animations_ios")) { if (reactNativeConfig->getBool("react_fabric:enabled_layout_animations_ios")) {
_layoutAnimationDelegateProxy = std::make_shared<LayoutAnimationDelegateProxy>((__bridge void *)self); _layoutAnimationDelegateProxy = std::make_shared<LayoutAnimationDelegateProxy>((__bridge void *)self);
_animationDriver = _animationDriver = std::make_shared<LayoutAnimationDriver>(
std::make_shared<LayoutAnimationDriver>(toolbox.runtimeExecutor, _layoutAnimationDelegateProxy.get()); toolbox.runtimeExecutor, toolbox.contextContainer, _layoutAnimationDelegateProxy.get());
if (reactNativeConfig->getBool("react_fabric:enabled_skip_invalidated_key_frames_ios")) { if (reactNativeConfig->getBool("react_fabric:enabled_skip_invalidated_key_frames_ios")) {
_animationDriver->enableSkipInvalidatedKeyFrames(); _animationDriver->enableSkipInvalidatedKeyFrames();
} }

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

@ -261,10 +261,6 @@ static BackgroundExecutor RCTGetBackgroundExecutor()
RCTSetRemoveClippedSubviewsEnabled(YES); RCTSetRemoveClippedSubviewsEnabled(YES);
} }
if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:enable_initial_max_size_ios")) {
RCTSetInitialMaxSizeEnabled(YES);
}
auto componentRegistryFactory = auto componentRegistryFactory =
[factory = wrapManagedObject(_mountingManager.componentViewRegistry.componentViewFactory)]( [factory = wrapManagedObject(_mountingManager.componentViewRegistry.componentViewFactory)](
EventDispatcher::Weak const &eventDispatcher, ContextContainer::Shared const &contextContainer) { EventDispatcher::Weak const &eventDispatcher, ContextContainer::Shared const &contextContainer) {

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

@ -10,7 +10,6 @@
#import <React/RCTUtils.h> #import <React/RCTUtils.h>
#import <React/RCTViewComponentView.h> #import <React/RCTViewComponentView.h>
#import <UIKit/UIGestureRecognizerSubclass.h> #import <UIKit/UIGestureRecognizerSubclass.h>
#import <UIKit/UIKit.h>
#import "RCTConversions.h" #import "RCTConversions.h"
#import "RCTTouchableComponentViewProtocol.h" #import "RCTTouchableComponentViewProtocol.h"
@ -83,8 +82,7 @@ static void UpdateActiveTouchWithUITouch(
ActiveTouch &activeTouch, ActiveTouch &activeTouch,
UITouch *uiTouch, UITouch *uiTouch,
UIView *rootComponentView, UIView *rootComponentView,
CGPoint rootViewOriginOffset, CGPoint rootViewOriginOffset)
NSTimeInterval unixTimestampBasis)
{ {
CGPoint offsetPoint = [uiTouch locationInView:activeTouch.componentView]; CGPoint offsetPoint = [uiTouch locationInView:activeTouch.componentView];
CGPoint screenPoint = [uiTouch locationInView:uiTouch.window]; CGPoint screenPoint = [uiTouch locationInView:uiTouch.window];
@ -95,18 +93,14 @@ static void UpdateActiveTouchWithUITouch(
activeTouch.touch.screenPoint = RCTPointFromCGPoint(screenPoint); activeTouch.touch.screenPoint = RCTPointFromCGPoint(screenPoint);
activeTouch.touch.pagePoint = RCTPointFromCGPoint(pagePoint); activeTouch.touch.pagePoint = RCTPointFromCGPoint(pagePoint);
activeTouch.touch.timestamp = unixTimestampBasis + uiTouch.timestamp; activeTouch.touch.timestamp = uiTouch.timestamp;
if (RCTForceTouchAvailable()) { if (RCTForceTouchAvailable()) {
activeTouch.touch.force = RCTZeroIfNaN(uiTouch.force / uiTouch.maximumPossibleForce); activeTouch.touch.force = RCTZeroIfNaN(uiTouch.force / uiTouch.maximumPossibleForce);
} }
} }
static ActiveTouch CreateTouchWithUITouch( static ActiveTouch CreateTouchWithUITouch(UITouch *uiTouch, UIView *rootComponentView, CGPoint rootViewOriginOffset)
UITouch *uiTouch,
UIView *rootComponentView,
CGPoint rootViewOriginOffset,
NSTimeInterval unixTimestampBasis)
{ {
ActiveTouch activeTouch = {}; ActiveTouch activeTouch = {};
@ -123,7 +117,7 @@ static ActiveTouch CreateTouchWithUITouch(
componentView = componentView.superview; componentView = componentView.superview;
} }
UpdateActiveTouchWithUITouch(activeTouch, uiTouch, rootComponentView, rootViewOriginOffset, unixTimestampBasis); UpdateActiveTouchWithUITouch(activeTouch, uiTouch, rootComponentView, rootViewOriginOffset);
return activeTouch; return activeTouch;
} }
@ -173,12 +167,6 @@ struct PointerHasher {
*/ */
__weak UIView *_rootComponentView; __weak UIView *_rootComponentView;
IdentifierPool<11> _identifierPool; IdentifierPool<11> _identifierPool;
/*
* See Touch.h and usage. This gives us a time-basis for a monotonic
* clock that acts like a timestamp of milliseconds elapsed since UNIX epoch.
*/
NSTimeInterval _unixEpochBasisTime;
} }
- (instancetype)init - (instancetype)init
@ -193,8 +181,6 @@ struct PointerHasher {
self.delaysTouchesEnded = NO; self.delaysTouchesEnded = NO;
self.delegate = self; self.delegate = self;
_unixEpochBasisTime = [[NSDate date] timeIntervalSince1970] - [NSProcessInfo processInfo].systemUptime;
} }
return self; return self;
@ -222,7 +208,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithTarget : (id)target action : (SEL)act
- (void)_registerTouches:(NSSet<UITouch *> *)touches - (void)_registerTouches:(NSSet<UITouch *> *)touches
{ {
for (UITouch *touch in touches) { for (UITouch *touch in touches) {
auto activeTouch = CreateTouchWithUITouch(touch, _rootComponentView, _viewOriginOffset, _unixEpochBasisTime); auto activeTouch = CreateTouchWithUITouch(touch, _rootComponentView, _viewOriginOffset);
activeTouch.touch.identifier = _identifierPool.dequeue(); activeTouch.touch.identifier = _identifierPool.dequeue();
_activeTouches.emplace(touch, activeTouch); _activeTouches.emplace(touch, activeTouch);
} }
@ -237,7 +223,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithTarget : (id)target action : (SEL)act
continue; continue;
} }
UpdateActiveTouchWithUITouch(iterator->second, touch, _rootComponentView, _viewOriginOffset, _unixEpochBasisTime); UpdateActiveTouchWithUITouch(iterator->second, touch, _rootComponentView, _viewOriginOffset);
} }
} }

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

@ -61,9 +61,7 @@ using namespace facebook::react;
[_surfacePresenter registerSurface:self]; [_surfacePresenter registerSurface:self];
if (RCTGetInitialMaxSizeEnabled()) { [self setMinimumSize:CGSizeZero maximumSize:RCTViewportSize()];
[self setMinimumSize:CGSizeZero maximumSize:RCTViewportSize()];
}
[self _updateLayoutContext]; [self _updateLayoutContext];

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

@ -344,12 +344,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused)
if (bundle) { if (bundle) {
NSURL *url = [bundle URLForResource:@"Localizable" withExtension:@"strings"]; NSURL *url = [bundle URLForResource:@"Localizable" withExtension:@"strings"];
if (@available(iOS 11.0, *)) { rolesAndStatesDescription = [NSDictionary dictionaryWithContentsOfURL:url error:nil];
rolesAndStatesDescription = [NSDictionary dictionaryWithContentsOfURL:url error:nil];
} else {
// Fallback on earlier versions
rolesAndStatesDescription = [NSDictionary dictionaryWithContentsOfURL:url];
}
} }
if (rolesAndStatesDescription == nil) { if (rolesAndStatesDescription == nil) {
// Falling back to hardcoded English list. // Falling back to hardcoded English list.

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

@ -54,13 +54,9 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame)
- (UIEdgeInsets)safeAreaInsetsIfSupportedAndEnabled - (UIEdgeInsets)safeAreaInsetsIfSupportedAndEnabled
{ {
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
if (self.isSupportedByOS) { if (self.isSupportedByOS) {
if (@available(iOS 11.0, *)) { return self.safeAreaInsets;
return self.safeAreaInsets;
}
} }
#endif
return self.emulateUnlessSupported ? self.emulatedSafeAreaInsets : UIEdgeInsetsZero; return self.emulateUnlessSupported ? self.emulatedSafeAreaInsets : UIEdgeInsetsZero;
} }

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

@ -276,10 +276,8 @@
self.contentOffset = originalOffset; self.contentOffset = originalOffset;
} else { } else {
#if !TARGET_OS_OSX // [TODO(macOS GH#774) #if !TARGET_OS_OSX // [TODO(macOS GH#774)
if (@available(iOS 11.0, *)) { if (!UIEdgeInsetsEqualToEdgeInsets(UIEdgeInsetsZero, self.adjustedContentInset)) {
if (!UIEdgeInsetsEqualToEdgeInsets(UIEdgeInsetsZero, self.adjustedContentInset)) { contentInset = self.adjustedContentInset;
contentInset = self.adjustedContentInset;
}
} }
#endif // [TODO(macOS GH#774) #endif // [TODO(macOS GH#774)
CGSize boundsSize = self.bounds.size; CGSize boundsSize = self.bounds.size;
@ -409,17 +407,15 @@
#pragma clang diagnostic push // TODO(OSS Candidate ISS#2710739) #pragma clang diagnostic push // TODO(OSS Candidate ISS#2710739)
#pragma clang diagnostic ignored "-Wunguarded-availability" // TODO(OSS Candidate ISS#2710739) #pragma clang diagnostic ignored "-Wunguarded-availability" // TODO(OSS Candidate ISS#2710739)
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */ #if !TARGET_OS_OSX // [TODO(macOS GH#774)
// `contentInsetAdjustmentBehavior` is only available since iOS 11. // `contentInsetAdjustmentBehavior` is only available since iOS 11.
// We set the default behavior to "never" so that iOS // We set the default behavior to "never" so that iOS
// doesn't do weird things to UIScrollView insets automatically // doesn't do weird things to UIScrollView insets automatically
// and keeps it as an opt-in behavior. // and keeps it as an opt-in behavior.
if ([_scrollView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) { if ([_scrollView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) {
if (@available(iOS 11.0, *)) { _scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
_scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
} }
#endif #endif // ]TODO(macOS GH#774)
#pragma clang diagnostic pop // TODO(OSS Candidate ISS#2710739) #pragma clang diagnostic pop // TODO(OSS Candidate ISS#2710739)
_automaticallyAdjustContentInsets = YES; _automaticallyAdjustContentInsets = YES;
@ -1302,19 +1298,17 @@ RCT_SET_AND_PRESERVE_OFFSET(setScrollIndicatorInsets, scrollIndicatorInsets, UIE
} }
#endif #endif
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */ #if !TARGET_OS_OSX // [TODO(macOS GH#774)
- (void)setContentInsetAdjustmentBehavior:(UIScrollViewContentInsetAdjustmentBehavior)behavior API_AVAILABLE(ios(11.0)) - (void)setContentInsetAdjustmentBehavior:(UIScrollViewContentInsetAdjustmentBehavior)behavior
{ {
// `contentInsetAdjustmentBehavior` is available since iOS 11. // `contentInsetAdjustmentBehavior` is available since iOS 11.
if ([_scrollView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) { if ([_scrollView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) {
CGPoint contentOffset = _scrollView.contentOffset; CGPoint contentOffset = _scrollView.contentOffset;
if (@available(iOS 11.0, *)) { _scrollView.contentInsetAdjustmentBehavior = behavior;
_scrollView.contentInsetAdjustmentBehavior = behavior;
}
_scrollView.contentOffset = contentOffset; _scrollView.contentOffset = contentOffset;
} }
} }
#endif #endif // ]TODO(macOS GH#774)
#pragma clang diagnostic pop // TODO(OSS Candidate ISS#2710739) #pragma clang diagnostic pop // TODO(OSS Candidate ISS#2710739)
- (void)sendScrollEventWithName:(NSString *)eventName - (void)sendScrollEventWithName:(NSString *)eventName

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

@ -37,9 +37,6 @@ RCT_ENUM_CONVERTER(
UIScrollViewIndicatorStyleDefault, UIScrollViewIndicatorStyleDefault,
integerValue) integerValue)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
RCT_ENUM_CONVERTER( RCT_ENUM_CONVERTER(
UIScrollViewContentInsetAdjustmentBehavior, UIScrollViewContentInsetAdjustmentBehavior,
(@{ (@{
@ -50,8 +47,6 @@ RCT_ENUM_CONVERTER(
}), }),
UIScrollViewContentInsetAdjustmentNever, UIScrollViewContentInsetAdjustmentNever,
integerValue) integerValue)
#endif
#pragma clang diagnostic pop
@end @end
#endif // TODO(OSS Candidate ISS#2710739) #endif // TODO(OSS Candidate ISS#2710739)
@ -109,9 +104,7 @@ RCT_EXPORT_VIEW_PROPERTY(inverted, BOOL)
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 /* __IPHONE_13_0 */ #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 /* __IPHONE_13_0 */
RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustsScrollIndicatorInsets, BOOL) RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustsScrollIndicatorInsets, BOOL)
#endif #endif
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
RCT_EXPORT_VIEW_PROPERTY(contentInsetAdjustmentBehavior, UIScrollViewContentInsetAdjustmentBehavior) RCT_EXPORT_VIEW_PROPERTY(contentInsetAdjustmentBehavior, UIScrollViewContentInsetAdjustmentBehavior)
#endif
// overflow is used both in css-layout as well as by react-native. In css-layout // overflow is used both in css-layout as well as by react-native. In css-layout
// we always want to treat overflow as scroll but depending on what the overflow // we always want to treat overflow as scroll but depending on what the overflow

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

@ -47,21 +47,12 @@
- (BOOL)shouldAccessibilityIgnoresInvertColors - (BOOL)shouldAccessibilityIgnoresInvertColors
{ {
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */ return self.accessibilityIgnoresInvertColors;
if (@available(iOS 11.0, *)) {
return self.accessibilityIgnoresInvertColors;
}
#endif
return NO;
} }
- (void)setShouldAccessibilityIgnoresInvertColors:(BOOL)shouldAccessibilityIgnoresInvertColors - (void)setShouldAccessibilityIgnoresInvertColors:(BOOL)shouldAccessibilityIgnoresInvertColors
{ {
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */ self.accessibilityIgnoresInvertColors = shouldAccessibilityIgnoresInvertColors;
if (@available(iOS 11.0, *)) {
self.accessibilityIgnoresInvertColors = shouldAccessibilityIgnoresInvertColors;
}
#endif
} }
- (BOOL)isReactRootView - (BOOL)isReactRootView

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

@ -219,6 +219,7 @@ public class ReactInstanceManager {
@Nullable String jsMainModulePath, @Nullable String jsMainModulePath,
List<ReactPackage> packages, List<ReactPackage> packages,
boolean useDeveloperSupport, boolean useDeveloperSupport,
DevSupportManagerFactory devSupportManagerFactory,
boolean requireActivity, boolean requireActivity,
@Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener, @Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener,
LifecycleState initialLifecycleState, LifecycleState initialLifecycleState,
@ -250,7 +251,7 @@ public class ReactInstanceManager {
Systrace.beginSection( Systrace.beginSection(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstanceManager.initDevSupportManager"); Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstanceManager.initDevSupportManager");
mDevSupportManager = mDevSupportManager =
DevSupportManagerFactory.create( devSupportManagerFactory.create(
applicationContext, applicationContext,
createDevHelperInterface(), createDevHelperInterface(),
mJSMainModulePath, mJSMainModulePath,
@ -1225,7 +1226,8 @@ public class ReactInstanceManager {
// If we can't get a UIManager something has probably gone horribly wrong // If we can't get a UIManager something has probably gone horribly wrong
if (uiManager == null) { if (uiManager == null) {
throw new IllegalStateException( throw new IllegalStateException(
"Unable to attach a rootView to ReactInstance when UIManager is not properly initialized."); "Unable to attach a rootView to ReactInstance when UIManager is not properly"
+ " initialized.");
} }
@Nullable Bundle initialProperties = reactRoot.getAppProperties(); @Nullable Bundle initialProperties = reactRoot.getAppProperties();
@ -1366,10 +1368,6 @@ public class ReactInstanceManager {
} }
} }
if (ReactFeatureFlags.enableRuntimeScheduler) {
catalystInstance.installRuntimeScheduler();
}
if (mJSIModulePackage != null) { if (mJSIModulePackage != null) {
catalystInstance.addJSIModules( catalystInstance.addJSIModules(
mJSIModulePackage.getJSIModules( mJSIModulePackage.getJSIModules(

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

@ -22,6 +22,8 @@ import com.facebook.react.bridge.JavaScriptExecutorFactory;
import com.facebook.react.bridge.NativeModuleCallExceptionHandler; import com.facebook.react.bridge.NativeModuleCallExceptionHandler;
import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener; import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener;
import com.facebook.react.common.LifecycleState; import com.facebook.react.common.LifecycleState;
import com.facebook.react.devsupport.DefaultDevSupportManagerFactory;
import com.facebook.react.devsupport.DevSupportManagerFactory;
import com.facebook.react.devsupport.RedBoxHandler; import com.facebook.react.devsupport.RedBoxHandler;
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
import com.facebook.react.devsupport.interfaces.DevSupportManager; import com.facebook.react.devsupport.interfaces.DevSupportManager;
@ -45,6 +47,7 @@ public class ReactInstanceManagerBuilder {
private @Nullable NotThreadSafeBridgeIdleDebugListener mBridgeIdleDebugListener; private @Nullable NotThreadSafeBridgeIdleDebugListener mBridgeIdleDebugListener;
private @Nullable Application mApplication; private @Nullable Application mApplication;
private boolean mUseDeveloperSupport; private boolean mUseDeveloperSupport;
private @Nullable DevSupportManagerFactory mDevSupportManagerFactory;
private boolean mRequireActivity; private boolean mRequireActivity;
private @Nullable LifecycleState mInitialLifecycleState; private @Nullable LifecycleState mInitialLifecycleState;
private @Nullable UIImplementationProvider mUIImplementationProvider; private @Nullable UIImplementationProvider mUIImplementationProvider;
@ -172,6 +175,16 @@ public class ReactInstanceManagerBuilder {
return this; return this;
} }
/**
* Set the custom {@link DevSupportManagerFactory}. If not set, will use {@link
* DefaultDevSupportManagerFactory}.
*/
public ReactInstanceManagerBuilder setDevSupportManagerFactory(
final DevSupportManagerFactory devSupportManagerFactory) {
mDevSupportManagerFactory = devSupportManagerFactory;
return this;
}
/** /**
* When {@code false}, indicates that correct usage of React Native will NOT involve an Activity. * When {@code false}, indicates that correct usage of React Native will NOT involve an Activity.
* For the vast majority of Android apps in the ecosystem, this will not need to change. Unless * For the vast majority of Android apps in the ecosystem, this will not need to change. Unless
@ -294,6 +307,9 @@ public class ReactInstanceManagerBuilder {
mJSMainModulePath, mJSMainModulePath,
mPackages, mPackages,
mUseDeveloperSupport, mUseDeveloperSupport,
mDevSupportManagerFactory == null
? new DefaultDevSupportManagerFactory()
: mDevSupportManagerFactory,
mRequireActivity, mRequireActivity,
mBridgeIdleDebugListener, mBridgeIdleDebugListener,
Assertions.assertNotNull(mInitialLifecycleState, "Initial lifecycle state was not set"), Assertions.assertNotNull(mInitialLifecycleState, "Initial lifecycle state was not set"),

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

@ -15,6 +15,7 @@ import com.facebook.react.bridge.JavaScriptExecutorFactory;
import com.facebook.react.bridge.ReactMarker; import com.facebook.react.bridge.ReactMarker;
import com.facebook.react.bridge.ReactMarkerConstants; import com.facebook.react.bridge.ReactMarkerConstants;
import com.facebook.react.common.LifecycleState; import com.facebook.react.common.LifecycleState;
import com.facebook.react.devsupport.DevSupportManagerFactory;
import com.facebook.react.devsupport.RedBoxHandler; import com.facebook.react.devsupport.RedBoxHandler;
import com.facebook.react.uimanager.UIImplementationProvider; import com.facebook.react.uimanager.UIImplementationProvider;
import java.util.List; import java.util.List;
@ -68,6 +69,7 @@ public abstract class ReactNativeHost {
.setApplication(mApplication) .setApplication(mApplication)
.setJSMainModulePath(getJSMainModuleName()) .setJSMainModulePath(getJSMainModuleName())
.setUseDeveloperSupport(getUseDeveloperSupport()) .setUseDeveloperSupport(getUseDeveloperSupport())
.setDevSupportManagerFactory(getDevSupportManagerFactory())
.setRequireActivity(getShouldRequireActivity()) .setRequireActivity(getShouldRequireActivity())
.setRedBoxHandler(getRedBoxHandler()) .setRedBoxHandler(getRedBoxHandler())
.setJavaScriptExecutorFactory(getJavaScriptExecutorFactory()) .setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
@ -160,6 +162,11 @@ public abstract class ReactNativeHost {
/** Returns whether dev mode should be enabled. This enables e.g. the dev menu. */ /** Returns whether dev mode should be enabled. This enables e.g. the dev menu. */
public abstract boolean getUseDeveloperSupport(); public abstract boolean getUseDeveloperSupport();
/** Get the {@link DevSupportManagerFactory}. Override this to use a custom dev support manager */
protected @Nullable DevSupportManagerFactory getDevSupportManagerFactory() {
return null;
}
/** /**
* Returns a list of {@link ReactPackage} used by the app. You'll most likely want to return at * Returns a list of {@link ReactPackage} used by the app. You'll most likely want to return at
* least the {@code MainReactPackage}. If your app uses additional views or modules besides the * least the {@code MainReactPackage}. If your app uses additional views or modules besides the

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

@ -16,8 +16,10 @@ import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.DisplayCutout;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.Surface; import android.view.Surface;
@ -647,6 +649,11 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
mJSTouchDispatcher = new JSTouchDispatcher(this); mJSTouchDispatcher = new JSTouchDispatcher(this);
} }
@VisibleForTesting
/* package */ void simulateCheckForKeyboardForTesting() {
getCustomGlobalLayoutListener().checkForKeyboardEvents();
}
private CustomGlobalLayoutListener getCustomGlobalLayoutListener() { private CustomGlobalLayoutListener getCustomGlobalLayoutListener() {
if (mCustomGlobalLayoutListener == null) { if (mCustomGlobalLayoutListener == null) {
mCustomGlobalLayoutListener = new CustomGlobalLayoutListener(); mCustomGlobalLayoutListener = new CustomGlobalLayoutListener();
@ -766,8 +773,17 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
private void checkForKeyboardEvents() { private void checkForKeyboardEvents() {
getRootView().getWindowVisibleDisplayFrame(mVisibleViewArea); getRootView().getWindowVisibleDisplayFrame(mVisibleViewArea);
int notchHeight = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
DisplayCutout displayCutout = getRootView().getRootWindowInsets().getDisplayCutout();
if (displayCutout != null) {
notchHeight = displayCutout.getSafeInsetTop();
}
}
final int heightDiff = final int heightDiff =
DisplayMetricsHolder.getWindowDisplayMetrics().heightPixels - mVisibleViewArea.bottom; DisplayMetricsHolder.getWindowDisplayMetrics().heightPixels
- mVisibleViewArea.bottom
+ notchHeight;
boolean isKeyboardShowingOrKeyboardHeightChanged = boolean isKeyboardShowingOrKeyboardHeightChanged =
mKeyboardHeight != heightDiff && heightDiff > mMinKeyboardHeightDetected; mKeyboardHeight != heightDiff && heightDiff > mMinKeyboardHeightDetected;

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

@ -113,8 +113,6 @@ public interface CatalystInstance
RuntimeScheduler getRuntimeScheduler(); RuntimeScheduler getRuntimeScheduler();
void installRuntimeScheduler();
void addJSIModules(List<JSIModuleSpec> jsiModules); void addJSIModules(List<JSIModuleSpec> jsiModules);
/** /**

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

@ -108,7 +108,8 @@ public class CatalystInstanceImpl implements CatalystInstance {
// C++ parts // C++ parts
private final HybridData mHybridData; private final HybridData mHybridData;
private static native HybridData initHybrid(); private static native HybridData initHybrid(
boolean enableRuntimeScheduler, boolean enableRuntimeSchedulerInTurboModule);
public native CallInvokerHolderImpl getJSCallInvokerHolder(); public native CallInvokerHolderImpl getJSCallInvokerHolder();
@ -123,7 +124,15 @@ public class CatalystInstanceImpl implements CatalystInstance {
FLog.d(ReactConstants.TAG, "Initializing React Xplat Bridge."); FLog.d(ReactConstants.TAG, "Initializing React Xplat Bridge.");
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createCatalystInstanceImpl"); Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createCatalystInstanceImpl");
mHybridData = initHybrid(); if (ReactFeatureFlags.enableRuntimeSchedulerInTurboModule
&& !ReactFeatureFlags.enableRuntimeScheduler) {
Assertions.assertUnreachable();
}
mHybridData =
initHybrid(
ReactFeatureFlags.enableRuntimeScheduler,
ReactFeatureFlags.enableRuntimeSchedulerInTurboModule);
mReactQueueConfiguration = mReactQueueConfiguration =
ReactQueueConfigurationImpl.create( ReactQueueConfigurationImpl.create(
@ -560,8 +569,6 @@ public class CatalystInstanceImpl implements CatalystInstance {
public native RuntimeScheduler getRuntimeScheduler(); public native RuntimeScheduler getRuntimeScheduler();
public native void installRuntimeScheduler();
@Override @Override
public void addJSIModules(List<JSIModuleSpec> jsiModules) { public void addJSIModules(List<JSIModuleSpec> jsiModules) {
mJSIModuleRegistry.registerModules(jsiModules); mJSIModuleRegistry.registerModules(jsiModules);

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

@ -1,4 +1,4 @@
load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_build_config", "rn_android_library") load("//tools/build_defs/oss:rn_defs.bzl", "HERMES_BYTECODE_VERSION", "react_native_dep", "rn_android_build_config", "rn_android_library")
SUB_PROJECTS = [ SUB_PROJECTS = [
"network/**/*", "network/**/*",
@ -41,7 +41,7 @@ rn_android_build_config(
package = "com.facebook.react", package = "com.facebook.react",
values = [ values = [
"boolean IS_INTERNAL_BUILD = true", "boolean IS_INTERNAL_BUILD = true",
"int HERMES_BYTECODE_VERSION = 0", "int HERMES_BYTECODE_VERSION = {}".format(HERMES_BYTECODE_VERSION),
], ],
visibility = [ visibility = [
"PUBLIC", "PUBLIC",

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

@ -72,6 +72,8 @@ public class ReactFeatureFlags {
public static boolean enableRuntimeScheduler = false; public static boolean enableRuntimeScheduler = false;
public static boolean enableRuntimeSchedulerInTurboModule = false;
/** Enables a more aggressive cleanup during destruction of ReactContext */ /** Enables a more aggressive cleanup during destruction of ReactContext */
public static boolean enableReactContextCleanupFix = false; public static boolean enableReactContextCleanupFix = false;
@ -95,4 +97,6 @@ public class ReactFeatureFlags {
public static boolean enableLockFreeEventDispatcher = false; public static boolean enableLockFreeEventDispatcher = false;
public static boolean enableAggressiveEventEmitterCleanup = false; public static boolean enableAggressiveEventEmitterCleanup = false;
public static boolean insertZReorderBarriersOnViewGroupChildren = true;
} }

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

@ -0,0 +1,97 @@
/*
* 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.
*/
package com.facebook.react.devsupport;
import android.content.Context;
import androidx.annotation.Nullable;
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
import com.facebook.react.devsupport.interfaces.DevSupportManager;
import com.facebook.react.packagerconnection.RequestHandler;
import java.lang.reflect.Constructor;
import java.util.Map;
/**
* A simple factory that creates instances of {@link DevSupportManager} implementations. Uses
* reflection to create BridgeDevSupportManager if it exists. This allows ProGuard to strip that
* class and its dependencies in release builds. If the class isn't found, {@link
* DisabledDevSupportManager} is returned instead.
*/
public class DefaultDevSupportManagerFactory implements DevSupportManagerFactory {
private static final String DEVSUPPORT_IMPL_PACKAGE = "com.facebook.react.devsupport";
private static final String DEVSUPPORT_IMPL_CLASS = "BridgeDevSupportManager";
public DevSupportManager create(
Context applicationContext,
ReactInstanceDevHelper reactInstanceDevHelper,
@Nullable String packagerPathForJSBundleName,
boolean enableOnCreate,
int minNumShakes) {
return create(
applicationContext,
reactInstanceDevHelper,
packagerPathForJSBundleName,
enableOnCreate,
null,
null,
minNumShakes,
null);
}
@Override
public DevSupportManager create(
Context applicationContext,
ReactInstanceDevHelper reactInstanceManagerHelper,
@Nullable String packagerPathForJSBundleName,
boolean enableOnCreate,
@Nullable RedBoxHandler redBoxHandler,
@Nullable DevBundleDownloadListener devBundleDownloadListener,
int minNumShakes,
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers) {
if (!enableOnCreate) {
return new DisabledDevSupportManager();
}
try {
// ProGuard is surprisingly smart in this case and will keep a class if it detects a call to
// Class.forName() with a static string. So instead we generate a quasi-dynamic string to
// confuse it.
String className =
new StringBuilder(DEVSUPPORT_IMPL_PACKAGE)
.append(".")
.append(DEVSUPPORT_IMPL_CLASS)
.toString();
Class<?> devSupportManagerClass = Class.forName(className);
Constructor constructor =
devSupportManagerClass.getConstructor(
Context.class,
ReactInstanceDevHelper.class,
String.class,
boolean.class,
RedBoxHandler.class,
DevBundleDownloadListener.class,
int.class,
Map.class);
return (DevSupportManager)
constructor.newInstance(
applicationContext,
reactInstanceManagerHelper,
packagerPathForJSBundleName,
true,
redBoxHandler,
devBundleDownloadListener,
minNumShakes,
customPackagerCommandHandlers);
} catch (Exception e) {
throw new RuntimeException(
"Requested enabled DevSupportManager, but BridgeDevSupportManager class was not found"
+ " or could not be created",
e);
}
}
}

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

@ -12,39 +12,10 @@ import androidx.annotation.Nullable;
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
import com.facebook.react.devsupport.interfaces.DevSupportManager; import com.facebook.react.devsupport.interfaces.DevSupportManager;
import com.facebook.react.packagerconnection.RequestHandler; import com.facebook.react.packagerconnection.RequestHandler;
import java.lang.reflect.Constructor;
import java.util.Map; import java.util.Map;
/** public interface DevSupportManagerFactory {
* A simple factory that creates instances of {@link DevSupportManager} implementations. Uses DevSupportManager create(
* reflection to create BridgeDevSupportManager if it exists. This allows ProGuard to strip that
* class and its dependencies in release builds. If the class isn't found, {@link
* DisabledDevSupportManager} is returned instead.
*/
public class DevSupportManagerFactory {
private static final String DEVSUPPORT_IMPL_PACKAGE = "com.facebook.react.devsupport";
private static final String DEVSUPPORT_IMPL_CLASS = "BridgeDevSupportManager";
public static DevSupportManager create(
Context applicationContext,
ReactInstanceDevHelper reactInstanceDevHelper,
@Nullable String packagerPathForJSBundleName,
boolean enableOnCreate,
int minNumShakes) {
return create(
applicationContext,
reactInstanceDevHelper,
packagerPathForJSBundleName,
enableOnCreate,
null,
null,
minNumShakes,
null);
}
public static DevSupportManager create(
Context applicationContext, Context applicationContext,
ReactInstanceDevHelper reactInstanceManagerHelper, ReactInstanceDevHelper reactInstanceManagerHelper,
@Nullable String packagerPathForJSBundleName, @Nullable String packagerPathForJSBundleName,
@ -52,45 +23,5 @@ public class DevSupportManagerFactory {
@Nullable RedBoxHandler redBoxHandler, @Nullable RedBoxHandler redBoxHandler,
@Nullable DevBundleDownloadListener devBundleDownloadListener, @Nullable DevBundleDownloadListener devBundleDownloadListener,
int minNumShakes, int minNumShakes,
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers) { @Nullable Map<String, RequestHandler> customPackagerCommandHandlers);
if (!enableOnCreate) {
return new DisabledDevSupportManager();
}
try {
// ProGuard is surprisingly smart in this case and will keep a class if it detects a call to
// Class.forName() with a static string. So instead we generate a quasi-dynamic string to
// confuse it.
String className =
new StringBuilder(DEVSUPPORT_IMPL_PACKAGE)
.append(".")
.append(DEVSUPPORT_IMPL_CLASS)
.toString();
Class<?> devSupportManagerClass = Class.forName(className);
Constructor constructor =
devSupportManagerClass.getConstructor(
Context.class,
ReactInstanceDevHelper.class,
String.class,
boolean.class,
RedBoxHandler.class,
DevBundleDownloadListener.class,
int.class,
Map.class);
return (DevSupportManager)
constructor.newInstance(
applicationContext,
reactInstanceManagerHelper,
packagerPathForJSBundleName,
true,
redBoxHandler,
devBundleDownloadListener,
minNumShakes,
customPackagerCommandHandlers);
} catch (Exception e) {
throw new RuntimeException(
"Requested enabled DevSupportManager, but BridgeDevSupportManager class was not found"
+ " or could not be created",
e);
}
}
} }

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

@ -0,0 +1,69 @@
/*
* 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.
*/
#include <jsi/jsi.h>
#include <react/renderer/core/EventBeat.h>
#include <react/renderer/uimanager/primitives.h>
#include "AsyncEventBeatV2.h"
namespace facebook::react {
AsyncEventBeatV2::AsyncEventBeatV2(
EventBeat::SharedOwnerBox const &ownerBox,
EventBeatManager *eventBeatManager,
RuntimeExecutor runtimeExecutor,
jni::global_ref<jobject> javaUIManager)
: EventBeat(ownerBox),
eventBeatManager_(eventBeatManager),
runtimeExecutor_(runtimeExecutor),
javaUIManager_(javaUIManager) {
eventBeatManager->addObserver(*this);
}
AsyncEventBeatV2::~AsyncEventBeatV2() {
eventBeatManager_->removeObserver(*this);
}
void AsyncEventBeatV2::tick() const {
if (!isRequested_ || isBeatCallbackScheduled_) {
return;
}
isRequested_ = false;
isBeatCallbackScheduled_ = true;
runtimeExecutor_([this, ownerBox = ownerBox_](jsi::Runtime &runtime) {
isBeatCallbackScheduled_ = false;
auto owner = ownerBox->owner.lock();
if (!owner) {
return;
}
if (beatCallback_) {
beatCallback_(runtime);
}
});
}
void AsyncEventBeatV2::induce() const {
tick();
}
void AsyncEventBeatV2::request() const {
bool alreadyRequested = isRequested_;
EventBeat::request();
if (!alreadyRequested) {
// Notifies java side that an event will be dispatched (e.g. LayoutEvent)
static auto onRequestEventBeat =
jni::findClassStatic("com/facebook/react/fabric/FabricUIManager")
->getMethod<void()>("onRequestEventBeat");
onRequestEventBeat(javaUIManager_);
}
}
} // namespace facebook::react

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

@ -0,0 +1,40 @@
/*
* 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.
*/
#pragma once
#include <react/renderer/core/EventBeat.h>
#include "EventBeatManager.h"
namespace facebook::react {
class AsyncEventBeatV2 final : public EventBeat,
public EventBeatManagerObserver {
public:
AsyncEventBeatV2(
EventBeat::SharedOwnerBox const &ownerBox,
EventBeatManager *eventBeatManager,
RuntimeExecutor runtimeExecutor,
jni::global_ref<jobject> javaUIManager);
~AsyncEventBeatV2() override;
void tick() const override;
void induce() const override;
void request() const override;
private:
EventBeatManager *eventBeatManager_;
RuntimeExecutor runtimeExecutor_;
jni::global_ref<jobject> javaUIManager_;
mutable std::atomic<bool> isBeatCallbackScheduled_{false};
};
} // namespace facebook::react

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

@ -7,6 +7,7 @@
#include "Binding.h" #include "Binding.h"
#include "AsyncEventBeat.h" #include "AsyncEventBeat.h"
#include "AsyncEventBeatV2.h"
#include "EventEmitterWrapper.h" #include "EventEmitterWrapper.h"
#include "ReactNativeConfigHolder.h" #include "ReactNativeConfigHolder.h"
#include "StateWrapperImpl.h" #include "StateWrapperImpl.h"
@ -529,7 +530,7 @@ void Binding::installFabricUIManager(
auto runtimeExecutor = runtimeExecutorHolder->cthis()->get(); auto runtimeExecutor = runtimeExecutorHolder->cthis()->get();
if (runtimeSchedulerHolder) { if (runtimeSchedulerHolder) {
auto runtimeScheduler = runtimeSchedulerHolder->cthis()->get(); auto runtimeScheduler = runtimeSchedulerHolder->cthis()->get().lock();
if (runtimeScheduler) { if (runtimeScheduler) {
runtimeScheduler->setEnableYielding(config->getBool( runtimeScheduler->setEnableYielding(config->getBool(
"react_native_new_architecture:runtimescheduler_enable_yielding_android")); "react_native_new_architecture:runtimescheduler_enable_yielding_android"));
@ -541,22 +542,39 @@ void Binding::installFabricUIManager(
} }
} }
auto enableV2AsynchronousEventBeat =
config->getBool("react_fabric:enable_asynchronous_event_beat_v2_android");
// TODO: T31905686 Create synchronous Event Beat // TODO: T31905686 Create synchronous Event Beat
jni::global_ref<jobject> localJavaUIManager = javaUIManager_; jni::global_ref<jobject> localJavaUIManager = javaUIManager_;
EventBeat::Factory synchronousBeatFactory = EventBeat::Factory synchronousBeatFactory =
[eventBeatManager, runtimeExecutor, localJavaUIManager]( [eventBeatManager,
EventBeat::SharedOwnerBox const &ownerBox) runtimeExecutor,
localJavaUIManager,
enableV2AsynchronousEventBeat](EventBeat::SharedOwnerBox const &ownerBox)
-> std::unique_ptr<EventBeat> { -> std::unique_ptr<EventBeat> {
return std::make_unique<AsyncEventBeat>( if (enableV2AsynchronousEventBeat) {
ownerBox, eventBeatManager, runtimeExecutor, localJavaUIManager); return std::make_unique<AsyncEventBeatV2>(
ownerBox, eventBeatManager, runtimeExecutor, localJavaUIManager);
} else {
return std::make_unique<AsyncEventBeat>(
ownerBox, eventBeatManager, runtimeExecutor, localJavaUIManager);
}
}; };
EventBeat::Factory asynchronousBeatFactory = EventBeat::Factory asynchronousBeatFactory =
[eventBeatManager, runtimeExecutor, localJavaUIManager]( [eventBeatManager,
EventBeat::SharedOwnerBox const &ownerBox) runtimeExecutor,
localJavaUIManager,
enableV2AsynchronousEventBeat](EventBeat::SharedOwnerBox const &ownerBox)
-> std::unique_ptr<EventBeat> { -> std::unique_ptr<EventBeat> {
return std::make_unique<AsyncEventBeat>( if (enableV2AsynchronousEventBeat) {
ownerBox, eventBeatManager, runtimeExecutor, localJavaUIManager); return std::make_unique<AsyncEventBeatV2>(
ownerBox, eventBeatManager, runtimeExecutor, localJavaUIManager);
} else {
return std::make_unique<AsyncEventBeat>(
ownerBox, eventBeatManager, runtimeExecutor, localJavaUIManager);
}
}; };
contextContainer->insert("ReactNativeConfig", config); contextContainer->insert("ReactNativeConfig", config);
@ -587,8 +605,8 @@ void Binding::installFabricUIManager(
toolbox.backgroundExecutor = backgroundExecutor_->get(); toolbox.backgroundExecutor = backgroundExecutor_->get();
} }
animationDriver_ = animationDriver_ = std::make_shared<LayoutAnimationDriver>(
std::make_shared<LayoutAnimationDriver>(runtimeExecutor, this); runtimeExecutor, contextContainer, this);
scheduler_ = std::make_shared<Scheduler>( scheduler_ = std::make_shared<Scheduler>(
toolbox, (animationDriver_ ? animationDriver_.get() : nullptr), this); toolbox, (animationDriver_ ? animationDriver_.get() : nullptr), this);
} }

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

@ -17,7 +17,9 @@ import androidx.annotation.Nullable;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.touch.ReactHitSlopView; import com.facebook.react.touch.ReactHitSlopView;
import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List;
/** /**
* Class responsible for identifying which react view should handle a given {@link MotionEvent}. It * Class responsible for identifying which react view should handle a given {@link MotionEvent}. It
@ -81,7 +83,7 @@ public class TouchTargetHelper {
// Store eventCoords in array so that they are modified to be relative to the targetView found. // Store eventCoords in array so that they are modified to be relative to the targetView found.
viewCoords[0] = eventX; viewCoords[0] = eventX;
viewCoords[1] = eventY; viewCoords[1] = eventY;
View nativeTargetView = findTouchTargetViewWithPointerEvents(viewCoords, viewGroup); View nativeTargetView = findTouchTargetViewWithPointerEvents(viewCoords, viewGroup, null);
if (nativeTargetView != null) { if (nativeTargetView != null) {
View reactTargetView = findClosestReactAncestor(nativeTargetView); View reactTargetView = findClosestReactAncestor(nativeTargetView);
if (reactTargetView != null) { if (reactTargetView != null) {
@ -94,6 +96,39 @@ public class TouchTargetHelper {
return targetTag; return targetTag;
} }
/**
* Find touch event target view within the provided container given the coordinates provided via
* {@link MotionEvent}.
*
* @param eventX the X screen coordinate of the touch location
* @param eventY the Y screen coordinate of the touch location
* @param viewGroup the container view to traverse
* @param viewCoords an out parameter that will return the X,Y value in the target view
* @return If a target was found, returns a path through the view tree of all react tags that are
* a container for the touch target, ordered from target to root (last element)
*/
public static List<Integer> findTargetPathAndCoordinatesForTouch(
float eventX, float eventY, ViewGroup viewGroup, float[] viewCoords) {
UiThreadUtil.assertOnUiThread();
// Store eventCoords in array so that they are modified to be relative to the targetView found.
viewCoords[0] = eventX;
viewCoords[1] = eventY;
List<Integer> pathAccumulator = new ArrayList<>();
View targetView = findTouchTargetViewWithPointerEvents(viewCoords, viewGroup, pathAccumulator);
if (targetView != null) {
View reactTargetView = findClosestReactAncestor(targetView);
int targetTag = getTouchTargetForView(reactTargetView, viewCoords[0], viewCoords[1]);
if (targetTag != pathAccumulator.get(0)) {
pathAccumulator.add(0, targetTag);
}
}
return pathAccumulator;
}
private static View findClosestReactAncestor(View view) { private static View findClosestReactAncestor(View view) {
while (view != null && view.getId() <= 0) { while (view != null && view.getId() <= 0) {
view = (View) view.getParent(); view = (View) view.getParent();
@ -121,7 +156,10 @@ public class TouchTargetHelper {
* relative to the targetView found. * relative to the targetView found.
*/ */
private static View findTouchTargetView( private static View findTouchTargetView(
float[] eventCoords, View view, EnumSet<TouchTargetReturnType> allowReturnTouchTargetTypes) { float[] eventCoords,
View view,
EnumSet<TouchTargetReturnType> allowReturnTouchTargetTypes,
List<Integer> pathAccumulator) {
// We prefer returning a child, so we check for a child that can handle the touch first // We prefer returning a child, so we check for a child that can handle the touch first
if (allowReturnTouchTargetTypes.contains(TouchTargetReturnType.CHILD) if (allowReturnTouchTargetTypes.contains(TouchTargetReturnType.CHILD)
&& view instanceof ViewGroup) { && view instanceof ViewGroup) {
@ -143,7 +181,7 @@ public class TouchTargetHelper {
float restoreY = eventCoords[1]; float restoreY = eventCoords[1];
eventCoords[0] = childPoint.x; eventCoords[0] = childPoint.x;
eventCoords[1] = childPoint.y; eventCoords[1] = childPoint.y;
View targetView = findTouchTargetViewWithPointerEvents(eventCoords, child); View targetView = findTouchTargetViewWithPointerEvents(eventCoords, child, pathAccumulator);
if (targetView != null) { if (targetView != null) {
// We don't allow touches on views that are outside the bounds of an `overflow: hidden` // We don't allow touches on views that are outside the bounds of an `overflow: hidden`
@ -224,7 +262,7 @@ public class TouchTargetHelper {
* its descendants are the touch target. * its descendants are the touch target.
*/ */
private static @Nullable View findTouchTargetViewWithPointerEvents( private static @Nullable View findTouchTargetViewWithPointerEvents(
float eventCoords[], View view) { float eventCoords[], View view, @Nullable List<Integer> pathAccumulator) {
PointerEvents pointerEvents = PointerEvents pointerEvents =
view instanceof ReactPointerEventsView view instanceof ReactPointerEventsView
? ((ReactPointerEventsView) view).getPointerEvents() ? ((ReactPointerEventsView) view).getPointerEvents()
@ -247,13 +285,23 @@ public class TouchTargetHelper {
} else if (pointerEvents == PointerEvents.BOX_ONLY) { } else if (pointerEvents == PointerEvents.BOX_ONLY) {
// This view may be the target, its children don't matter // This view may be the target, its children don't matter
return findTouchTargetView(eventCoords, view, EnumSet.of(TouchTargetReturnType.SELF)); View targetView =
findTouchTargetView(
eventCoords, view, EnumSet.of(TouchTargetReturnType.SELF), pathAccumulator);
if (targetView != null && pathAccumulator != null) {
pathAccumulator.add(view.getId());
}
return targetView;
} else if (pointerEvents == PointerEvents.BOX_NONE) { } else if (pointerEvents == PointerEvents.BOX_NONE) {
// This view can't be the target, but its children might. // This view can't be the target, but its children might.
View targetView = View targetView =
findTouchTargetView(eventCoords, view, EnumSet.of(TouchTargetReturnType.CHILD)); findTouchTargetView(
eventCoords, view, EnumSet.of(TouchTargetReturnType.CHILD), pathAccumulator);
if (targetView != null) { if (targetView != null) {
if (pathAccumulator != null) {
pathAccumulator.add(view.getId());
}
return targetView; return targetView;
} }
@ -266,8 +314,11 @@ public class TouchTargetHelper {
if (view instanceof ReactCompoundView if (view instanceof ReactCompoundView
&& isTouchPointInView(eventCoords[0], eventCoords[1], view)) { && isTouchPointInView(eventCoords[0], eventCoords[1], view)) {
int reactTag = ((ReactCompoundView) view).reactTagForTouch(eventCoords[0], eventCoords[1]); int reactTag = ((ReactCompoundView) view).reactTagForTouch(eventCoords[0], eventCoords[1]);
// make sure we exclude the View itself because of the PointerEvents.BOX_NONE
if (reactTag != view.getId()) { if (reactTag != view.getId()) {
// make sure we exclude the View itself because of the PointerEvents.BOX_NONE if (pathAccumulator != null) {
pathAccumulator.add(view.getId());
}
return view; return view;
} }
} }
@ -279,10 +330,22 @@ public class TouchTargetHelper {
if (view instanceof ReactCompoundViewGroup if (view instanceof ReactCompoundViewGroup
&& isTouchPointInView(eventCoords[0], eventCoords[1], view) && isTouchPointInView(eventCoords[0], eventCoords[1], view)
&& ((ReactCompoundViewGroup) view).interceptsTouchEvent(eventCoords[0], eventCoords[1])) { && ((ReactCompoundViewGroup) view).interceptsTouchEvent(eventCoords[0], eventCoords[1])) {
if (pathAccumulator != null) {
pathAccumulator.add(view.getId());
}
return view; return view;
} }
return findTouchTargetView(
eventCoords, view, EnumSet.of(TouchTargetReturnType.SELF, TouchTargetReturnType.CHILD)); View result =
findTouchTargetView(
eventCoords,
view,
EnumSet.of(TouchTargetReturnType.SELF, TouchTargetReturnType.CHILD),
pathAccumulator);
if (result != null && pathAccumulator != null) {
pathAccumulator.add(view.getId());
}
return result;
} else { } else {
throw new JSApplicationIllegalArgumentException( throw new JSApplicationIllegalArgumentException(

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

@ -40,15 +40,6 @@ public abstract class Event<T extends Event> {
private long mTimestampMs; private long mTimestampMs;
private int mUniqueID = sUniqueID++; private int mUniqueID = sUniqueID++;
// Android native Event times use 'uptimeMillis', and historically we've used `uptimeMillis`
// throughout this Event class as the coalescing key for events, and for other purposes.
// To get an accurate(ish) absolute UNIX time for the event, we store the initial clock time here.
// uptimeMillis can then be added to this to get an accurate UNIX time.
// However, we still default to uptimeMillis: you must explicitly request UNIX time if you want
// that; see `getUnixTimestampMs`.
public static final long sInitialClockTimeUnixOffset =
SystemClock.currentTimeMillis() - SystemClock.uptimeMillis();
protected Event() {} protected Event() {}
@Deprecated @Deprecated
@ -65,8 +56,16 @@ public abstract class Event<T extends Event> {
init(-1, viewTag); init(-1, viewTag);
} }
/** This method needs to be called before event is sent to event dispatcher. */
protected void init(int surfaceId, int viewTag) { protected void init(int surfaceId, int viewTag) {
init(surfaceId, viewTag, SystemClock.uptimeMillis());
}
/**
* This method needs to be called before event is sent to event dispatcher. Event timestamps can
* optionally be dated/backdated to a custom time: for example, touch events should be dated with
* the system event time.
*/
protected void init(int surfaceId, int viewTag, long timestampMs) {
mSurfaceId = surfaceId; mSurfaceId = surfaceId;
mViewTag = viewTag; mViewTag = viewTag;
@ -82,9 +81,7 @@ public abstract class Event<T extends Event> {
// At some point it would be great to pass the SurfaceContext here instead. // At some point it would be great to pass the SurfaceContext here instead.
mUIManagerType = (surfaceId == -1 ? UIManagerType.DEFAULT : UIManagerType.FABRIC); mUIManagerType = (surfaceId == -1 ? UIManagerType.DEFAULT : UIManagerType.FABRIC);
// This is a *relative* time. See `getUnixTimestampMs`. mTimestampMs = timestampMs;
mTimestampMs = SystemClock.uptimeMillis();
mInitialized = true; mInitialized = true;
} }
@ -106,11 +103,6 @@ public abstract class Event<T extends Event> {
return mTimestampMs; return mTimestampMs;
} }
/** @return the time at which the event happened as a UNIX timestamp, in milliseconds. */
public final long getUnixTimestampMs() {
return sInitialClockTimeUnixOffset + mTimestampMs;
}
/** @return false if this Event can *never* be coalesced */ /** @return false if this Event can *never* be coalesced */
public boolean canCoalesce() { public boolean canCoalesce() {
return true; return true;
@ -174,7 +166,7 @@ public abstract class Event<T extends Event> {
WritableMap eventData = getEventData(); WritableMap eventData = getEventData();
if (eventData == null) { if (eventData == null) {
throw new IllegalViewOperationException( throw new IllegalViewOperationException(
"Event: you must return a valid, non-null value from `getEventData`, or override `dispatch` and `disatchModern`. Event: " "Event: you must return a valid, non-null value from `getEventData`, or override `dispatch` and `dispatchModern`. Event: "
+ getEventName()); + getEventName());
} }
rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData); rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData);
@ -224,7 +216,7 @@ public abstract class Event<T extends Event> {
getEventName(), getEventName(),
canCoalesce(), canCoalesce(),
getCoalescingKey(), getCoalescingKey(),
getEventData()); eventData);
return; return;
} }
} }

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

@ -52,7 +52,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/ */
public class LockFreeEventDispatcherImpl implements EventDispatcher, LifecycleEventListener { public class LockFreeEventDispatcherImpl implements EventDispatcher, LifecycleEventListener {
private final boolean DEBUG_MODE = true && ReactBuildConfig.DEBUG; private final boolean DEBUG_MODE = ReactBuildConfig.DEBUG;
private final String TAG = LockFreeEventDispatcherImpl.class.getSimpleName(); private final String TAG = LockFreeEventDispatcherImpl.class.getSimpleName();
private final ReactApplicationContext mReactContext; private final ReactApplicationContext mReactContext;
@ -77,7 +77,7 @@ public class LockFreeEventDispatcherImpl implements EventDispatcher, LifecycleEv
Assertions.assertNotNull(mReactEventEmitter); Assertions.assertNotNull(mReactEventEmitter);
if (DEBUG_MODE) { if (DEBUG_MODE) {
FLog.d(TAG, "dispatchEvent: " + event.toString()); FLog.v(TAG, "dispatchEvent: " + event.toString());
} }
for (EventDispatcherListener listener : mListeners) { for (EventDispatcherListener listener : mListeners) {

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

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

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

@ -96,7 +96,7 @@ public class TouchEvent extends Event<TouchEvent> {
float viewX, float viewX,
float viewY, float viewY,
TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) { TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) {
super.init(surfaceId, viewTag); super.init(surfaceId, viewTag, motionEventToCopy.getEventTime());
SoftAssertions.assertCondition( SoftAssertions.assertCondition(
gestureStartTime != UNSET, "Gesture start time must be initialized"); gestureStartTime != UNSET, "Gesture start time must be initialized");

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

@ -64,7 +64,7 @@ public class TouchesHelper {
touch.putDouble(LOCATION_Y_KEY, PixelUtil.toDIPFromPixel(locationY)); touch.putDouble(LOCATION_Y_KEY, PixelUtil.toDIPFromPixel(locationY));
touch.putInt(TARGET_SURFACE_KEY, surfaceId); touch.putInt(TARGET_SURFACE_KEY, surfaceId);
touch.putInt(TARGET_KEY, reactTarget); touch.putInt(TARGET_KEY, reactTarget);
touch.putDouble(TIMESTAMP_KEY, event.getUnixTimestampMs()); touch.putDouble(TIMESTAMP_KEY, event.getTimestampMs());
touch.putDouble(POINTER_IDENTIFIER_KEY, motionEvent.getPointerId(index)); touch.putDouble(POINTER_IDENTIFIER_KEY, motionEvent.getPointerId(index));
touches.pushMap(touch); touches.pushMap(touch);
} }

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

@ -0,0 +1,92 @@
/*
* 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.
*/
package com.facebook.react.views.view;
import android.annotation.SuppressLint;
import android.graphics.Canvas;
import android.os.Build;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.annotation.Nullable;
/**
* Copied from <a
* href="https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/CanvasUtils.android.kt;drc=3b2dde134afab8d58b9c39ad4820eaf9a6e014a9">
* Compose canvas utils </a>
*/
public class CanvasUtil {
private CanvasUtil() {}
private @Nullable static Method mReorderBarrierMethod = null;
private @Nullable static Method mInorderBarrierMethod = null;
private static boolean mOrderMethodsFetched = false;
/**
* Enables Z support for the Canvas. The method is publicly available starting from API 29 and was
* hidden before, so we have to resort to reflection tricks to ensure we can use this API.
*/
@SuppressLint({"SoonBlockedPrivateApi", "PrivateApi"})
public static void enableZ(Canvas canvas, boolean enable) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
if (Build.VERSION.SDK_INT >= 29) {
if (enable) {
canvas.enableZ();
} else {
canvas.disableZ();
}
} else {
fetchOrderMethods();
try {
if (enable && mReorderBarrierMethod != null) {
mReorderBarrierMethod.invoke(canvas);
}
if (!enable && mInorderBarrierMethod != null) {
mInorderBarrierMethod.invoke(canvas);
}
} catch (IllegalAccessException | InvocationTargetException ignore) {
// Do nothing
}
}
}
private static void fetchOrderMethods() {
if (!mOrderMethodsFetched) {
try {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P) {
// use double reflection to avoid grey list on P
Method getDeclaredMethod =
Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class);
mReorderBarrierMethod =
(Method) getDeclaredMethod.invoke(Canvas.class, "insertReorderBarrier", new Class[0]);
mInorderBarrierMethod =
(Method) getDeclaredMethod.invoke(Canvas.class, "insertInorderBarrier", new Class[0]);
} else {
mReorderBarrierMethod = Canvas.class.getDeclaredMethod("insertReorderBarrier");
mInorderBarrierMethod = Canvas.class.getDeclaredMethod("insertInorderBarrier");
}
if (mReorderBarrierMethod == null || mInorderBarrierMethod == null) {
return;
}
mReorderBarrierMethod.setAccessible(true);
mInorderBarrierMethod.setAccessible(true);
} catch (IllegalAccessException ignore) {
// Do nothing
} catch (InvocationTargetException ignore) {
// Do nothing
} catch (NoSuchMethodException ignore) {
// Do nothing
}
mOrderMethodsFetched = true;
}
}
}

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

@ -33,6 +33,7 @@ import com.facebook.react.bridge.ReactNoCrashSoftException;
import com.facebook.react.bridge.ReactSoftExceptionLogger; import com.facebook.react.bridge.ReactSoftExceptionLogger;
import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.modules.i18nmanager.I18nUtil; import com.facebook.react.modules.i18nmanager.I18nUtil;
import com.facebook.react.touch.OnInterceptTouchEventListener; import com.facebook.react.touch.OnInterceptTouchEventListener;
import com.facebook.react.touch.ReactHitSlopView; import com.facebook.react.touch.ReactHitSlopView;
@ -759,6 +760,23 @@ public class ReactViewGroup extends ViewGroup
} }
} }
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
boolean drawWithZ =
child.getElevation() > 0 && ReactFeatureFlags.insertZReorderBarriersOnViewGroupChildren;
if (drawWithZ) {
CanvasUtil.enableZ(canvas, false);
}
boolean result = super.drawChild(canvas, child, drawingTime);
if (drawWithZ) {
CanvasUtil.enableZ(canvas, true);
}
return result;
}
private void dispatchOverflowDraw(Canvas canvas) { private void dispatchOverflowDraw(Canvas canvas) {
if (mOverflow != null) { if (mOverflow != null) {
switch (mOverflow) { switch (mOverflow) {

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

@ -29,6 +29,7 @@
#include <glog/logging.h> #include <glog/logging.h>
#include <react/renderer/runtimescheduler/RuntimeScheduler.h> #include <react/renderer/runtimescheduler/RuntimeScheduler.h>
#include <react/renderer/runtimescheduler/RuntimeSchedulerBinding.h> #include <react/renderer/runtimescheduler/RuntimeSchedulerBinding.h>
#include <react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.h>
#include <logger/react_native_log.h> #include <logger/react_native_log.h>
@ -92,12 +93,21 @@ class JInstanceCallback : public InstanceCallback {
} // namespace } // namespace
jni::local_ref<CatalystInstanceImpl::jhybriddata> jni::local_ref<CatalystInstanceImpl::jhybriddata>
CatalystInstanceImpl::initHybrid(jni::alias_ref<jclass>) { CatalystInstanceImpl::initHybrid(
return makeCxxInstance(); jni::alias_ref<jclass>,
bool enableRuntimeScheduler,
bool enableRuntimeSchedulerInTurboModule) {
return makeCxxInstance(
enableRuntimeScheduler, enableRuntimeSchedulerInTurboModule);
} }
CatalystInstanceImpl::CatalystInstanceImpl() CatalystInstanceImpl::CatalystInstanceImpl(
: instance_(std::make_unique<Instance>()) {} bool enableRuntimeScheduler,
bool enableRuntimeSchedulerInTurboModule)
: instance_(std::make_unique<Instance>()),
enableRuntimeScheduler_(enableRuntimeScheduler),
enableRuntimeSchedulerInTurboModule_(
enableRuntimeScheduler && enableRuntimeSchedulerInTurboModule) {}
void CatalystInstanceImpl::warnOnLegacyNativeModuleSystemUse() { void CatalystInstanceImpl::warnOnLegacyNativeModuleSystemUse() {
CxxNativeModule::setShouldWarnOnUse(true); CxxNativeModule::setShouldWarnOnUse(true);
@ -140,9 +150,6 @@ void CatalystInstanceImpl::registerNatives() {
"getRuntimeExecutor", CatalystInstanceImpl::getRuntimeExecutor), "getRuntimeExecutor", CatalystInstanceImpl::getRuntimeExecutor),
makeNativeMethod( makeNativeMethod(
"getRuntimeScheduler", CatalystInstanceImpl::getRuntimeScheduler), "getRuntimeScheduler", CatalystInstanceImpl::getRuntimeScheduler),
makeNativeMethod(
"installRuntimeScheduler",
CatalystInstanceImpl::installRuntimeScheduler),
makeNativeMethod( makeNativeMethod(
"warnOnLegacyNativeModuleSystemUse", "warnOnLegacyNativeModuleSystemUse",
CatalystInstanceImpl::warnOnLegacyNativeModuleSystemUse), CatalystInstanceImpl::warnOnLegacyNativeModuleSystemUse),
@ -347,10 +354,18 @@ void CatalystInstanceImpl::handleMemoryPressure(int pressureLevel) {
jni::alias_ref<CallInvokerHolder::javaobject> jni::alias_ref<CallInvokerHolder::javaobject>
CatalystInstanceImpl::getJSCallInvokerHolder() { CatalystInstanceImpl::getJSCallInvokerHolder() {
if (!jsCallInvokerHolder_) { if (!jsCallInvokerHolder_) {
jsCallInvokerHolder_ = jni::make_global( if (enableRuntimeSchedulerInTurboModule_) {
CallInvokerHolder::newObjectCxxArgs(instance_->getJSCallInvoker())); auto runtimeScheduler = getRuntimeScheduler();
auto runtimeSchedulerCallInvoker =
std::make_shared<RuntimeSchedulerCallInvoker>(
runtimeScheduler->cthis()->get());
jsCallInvokerHolder_ = jni::make_global(
CallInvokerHolder::newObjectCxxArgs(runtimeSchedulerCallInvoker));
} else {
jsCallInvokerHolder_ = jni::make_global(
CallInvokerHolder::newObjectCxxArgs(instance_->getJSCallInvoker()));
}
} }
return jsCallInvokerHolder_; return jsCallInvokerHolder_;
} }
@ -397,11 +412,7 @@ CatalystInstanceImpl::getRuntimeExecutor() {
jni::alias_ref<JRuntimeScheduler::javaobject> jni::alias_ref<JRuntimeScheduler::javaobject>
CatalystInstanceImpl::getRuntimeScheduler() { CatalystInstanceImpl::getRuntimeScheduler() {
return runtimeScheduler_; if (enableRuntimeScheduler_ && !runtimeScheduler_) {
}
void CatalystInstanceImpl::installRuntimeScheduler() {
if (!runtimeScheduler_) {
auto runtimeExecutor = instance_->getRuntimeExecutor(); auto runtimeExecutor = instance_->getRuntimeExecutor();
auto runtimeScheduler = std::make_shared<RuntimeScheduler>(runtimeExecutor); auto runtimeScheduler = std::make_shared<RuntimeScheduler>(runtimeExecutor);
@ -413,6 +424,8 @@ void CatalystInstanceImpl::installRuntimeScheduler() {
runtime, runtimeScheduler); runtime, runtimeScheduler);
}); });
} }
return runtimeScheduler_;
} }
} // namespace react } // namespace react

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

@ -37,7 +37,10 @@ class CatalystInstanceImpl : public jni::HybridClass<CatalystInstanceImpl> {
static constexpr auto kJavaDescriptor = static constexpr auto kJavaDescriptor =
"Lcom/facebook/react/bridge/CatalystInstanceImpl;"; "Lcom/facebook/react/bridge/CatalystInstanceImpl;";
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jclass>); static jni::local_ref<jhybriddata> initHybrid(
jni::alias_ref<jclass>,
bool enableRuntimeScheduler,
bool enableRuntimeSchedulerInTurboModule);
static void registerNatives(); static void registerNatives();
@ -48,7 +51,9 @@ class CatalystInstanceImpl : public jni::HybridClass<CatalystInstanceImpl> {
private: private:
friend HybridBase; friend HybridBase;
CatalystInstanceImpl(); CatalystInstanceImpl(
bool enableRuntimeScheduler,
bool enableRuntimeSchedulerInTurboModule);
void initializeBridge( void initializeBridge(
jni::alias_ref<ReactCallback::javaobject> callback, jni::alias_ref<ReactCallback::javaobject> callback,
@ -100,11 +105,12 @@ class CatalystInstanceImpl : public jni::HybridClass<CatalystInstanceImpl> {
jni::alias_ref<CallInvokerHolder::javaobject> getNativeCallInvokerHolder(); jni::alias_ref<CallInvokerHolder::javaobject> getNativeCallInvokerHolder();
jni::alias_ref<JRuntimeExecutor::javaobject> getRuntimeExecutor(); jni::alias_ref<JRuntimeExecutor::javaobject> getRuntimeExecutor();
jni::alias_ref<JRuntimeScheduler::javaobject> getRuntimeScheduler(); jni::alias_ref<JRuntimeScheduler::javaobject> getRuntimeScheduler();
void installRuntimeScheduler();
void setGlobalVariable(std::string propName, std::string &&jsonValue); void setGlobalVariable(std::string propName, std::string &&jsonValue);
jlong getJavaScriptContext(); jlong getJavaScriptContext();
void handleMemoryPressure(int pressureLevel); void handleMemoryPressure(int pressureLevel);
void createAndInstallRuntimeSchedulerIfNecessary();
// This should be the only long-lived strong reference, but every C++ class // This should be the only long-lived strong reference, but every C++ class
// will have a weak reference. // will have a weak reference.
std::shared_ptr<Instance> instance_; std::shared_ptr<Instance> instance_;
@ -114,6 +120,9 @@ class CatalystInstanceImpl : public jni::HybridClass<CatalystInstanceImpl> {
jni::global_ref<CallInvokerHolder::javaobject> nativeCallInvokerHolder_; jni::global_ref<CallInvokerHolder::javaobject> nativeCallInvokerHolder_;
jni::global_ref<JRuntimeExecutor::javaobject> runtimeExecutor_; jni::global_ref<JRuntimeExecutor::javaobject> runtimeExecutor_;
jni::global_ref<JRuntimeScheduler::javaobject> runtimeScheduler_; jni::global_ref<JRuntimeScheduler::javaobject> runtimeScheduler_;
bool const enableRuntimeScheduler_;
bool const enableRuntimeSchedulerInTurboModule_;
}; };
} // namespace react } // namespace react

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

@ -11,10 +11,10 @@ namespace facebook {
namespace react { namespace react {
JRuntimeScheduler::JRuntimeScheduler( JRuntimeScheduler::JRuntimeScheduler(
std::shared_ptr<RuntimeScheduler> const &runtimeScheduler) std::weak_ptr<RuntimeScheduler> runtimeScheduler)
: runtimeScheduler_(runtimeScheduler) {} : runtimeScheduler_(runtimeScheduler) {}
std::shared_ptr<RuntimeScheduler> JRuntimeScheduler::get() { std::weak_ptr<RuntimeScheduler> JRuntimeScheduler::get() {
return runtimeScheduler_; return runtimeScheduler_;
} }

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

@ -18,12 +18,12 @@ class JRuntimeScheduler : public jni::HybridClass<JRuntimeScheduler> {
static auto constexpr kJavaDescriptor = static auto constexpr kJavaDescriptor =
"Lcom/facebook/react/bridge/RuntimeScheduler;"; "Lcom/facebook/react/bridge/RuntimeScheduler;";
std::shared_ptr<RuntimeScheduler> get(); std::weak_ptr<RuntimeScheduler> get();
private: private:
friend HybridBase; friend HybridBase;
JRuntimeScheduler(std::shared_ptr<RuntimeScheduler> const &runtimeScheduler); JRuntimeScheduler(std::weak_ptr<RuntimeScheduler> runtimeScheduler);
std::shared_ptr<RuntimeScheduler> runtimeScheduler_; std::weak_ptr<RuntimeScheduler> runtimeScheduler_;
}; };
} // namespace react } // namespace react

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

@ -16,6 +16,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.graphics.Rect;
import android.view.MotionEvent; import android.view.MotionEvent;
import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.CatalystInstance; import com.facebook.react.bridge.CatalystInstance;
@ -25,7 +26,9 @@ import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactTestHelper; import com.facebook.react.bridge.ReactTestHelper;
import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.SystemClock; import com.facebook.react.common.SystemClock;
import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter;
import com.facebook.react.uimanager.DisplayMetricsHolder; import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.events.Event; import com.facebook.react.uimanager.events.Event;
@ -37,6 +40,7 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock; import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer; import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito; import org.powermock.api.mockito.PowerMockito;
@ -209,4 +213,43 @@ public class RootViewTest {
rootView.unmountReactApplication(); rootView.unmountReactApplication();
rootView.startReactApplication(instanceManager, ""); rootView.startReactApplication(instanceManager, "");
} }
@Test
public void testCheckForKeyboardEvents() {
ReactInstanceManager instanceManager = mock(ReactInstanceManager.class);
RCTDeviceEventEmitter eventEmitterModuleMock = mock(RCTDeviceEventEmitter.class);
when(instanceManager.getCurrentReactContext()).thenReturn(mReactContext);
when(mReactContext.getJSModule(RCTDeviceEventEmitter.class)).thenReturn(eventEmitterModuleMock);
ReactRootView rootView =
new ReactRootView(mReactContext) {
@Override
public void getWindowVisibleDisplayFrame(Rect outRect) {
if (outRect.bottom == 0) {
outRect.bottom += 100;
outRect.right += 370;
} else {
outRect.bottom += 370;
}
}
};
rootView.startReactApplication(instanceManager, "");
rootView.simulateCheckForKeyboardForTesting();
WritableMap params = Arguments.createMap();
WritableMap endCoordinates = Arguments.createMap();
double screenHeight = 470.0;
double keyboardHeight = 100.0;
params.putDouble("duration", 0.0);
endCoordinates.putDouble("width", screenHeight - keyboardHeight);
endCoordinates.putDouble("screenX", 0.0);
endCoordinates.putDouble("height", screenHeight - keyboardHeight);
endCoordinates.putDouble("screenY", keyboardHeight);
params.putMap("endCoordinates", endCoordinates);
params.putString("easing", "keyboard");
verify(eventEmitterModuleMock, Mockito.times(1)).emit("keyboardDidShow", params);
}
} }

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

@ -1,4 +1,4 @@
load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "rn_xplat_cxx_library", "subdir_glob") load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "CXX", "rn_xplat_cxx_library", "subdir_glob")
rn_xplat_cxx_library( rn_xplat_cxx_library(
name = "callinvoker", name = "callinvoker",
@ -17,7 +17,7 @@ rn_xplat_cxx_library(
"-Wall", "-Wall",
], ],
labels = ["supermodule:xplat/default/public.react_native.infra"], labels = ["supermodule:xplat/default/public.react_native.infra"],
platforms = (ANDROID, APPLE), platforms = (ANDROID, APPLE, CXX),
preferred_linkage = "static", preferred_linkage = "static",
preprocessor_flags = [ preprocessor_flags = [
"-DLOG_TAG=\"ReactNative\"", "-DLOG_TAG=\"ReactNative\"",

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

@ -18,8 +18,12 @@ class LayoutAnimationDriver : public LayoutAnimationKeyFrameManager {
public: public:
LayoutAnimationDriver( LayoutAnimationDriver(
RuntimeExecutor runtimeExecutor, RuntimeExecutor runtimeExecutor,
ContextContainer::Shared &contextContainer,
LayoutAnimationStatusDelegate *delegate) LayoutAnimationStatusDelegate *delegate)
: LayoutAnimationKeyFrameManager(runtimeExecutor, delegate) {} : LayoutAnimationKeyFrameManager(
runtimeExecutor,
contextContainer,
delegate) {}
protected: protected:
virtual void animationMutationsForFrame( virtual void animationMutationsForFrame(

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

@ -94,8 +94,10 @@ interpolateFloats(float coefficient, float oldValue, float newValue) {
LayoutAnimationKeyFrameManager::LayoutAnimationKeyFrameManager( LayoutAnimationKeyFrameManager::LayoutAnimationKeyFrameManager(
RuntimeExecutor runtimeExecutor, RuntimeExecutor runtimeExecutor,
ContextContainer::Shared &contextContainer,
LayoutAnimationStatusDelegate *delegate) LayoutAnimationStatusDelegate *delegate)
: runtimeExecutor_(runtimeExecutor), : runtimeExecutor_(runtimeExecutor),
contextContainer_(contextContainer),
layoutAnimationStatusDelegate_(delegate), layoutAnimationStatusDelegate_(delegate),
now_([]() { now_([]() {
return std::chrono::duration_cast<std::chrono::milliseconds>( return std::chrono::duration_cast<std::chrono::milliseconds>(
@ -228,14 +230,7 @@ LayoutAnimationKeyFrameManager::pullTransaction(
LOG(ERROR) << "BEGINNING DONE DISPLAYING ONGOING inflightAnimations_!"; LOG(ERROR) << "BEGINNING DONE DISPLAYING ONGOING inflightAnimations_!";
#endif #endif
// Stub PropsParserContext used for cloneProps. PropsParserContext propsParserContext{surfaceId, *contextContainer_};
// This is/should be safe because cloning doesn't actually need to
// parse props, and just copies them; therefore there should be no
// need to actually use anything in the PropsParserContext.
// If this ever changes, the LayoutAnimations API will need to change
// to pass in a real PropsParserContext.
ContextContainer contextContainer{};
PropsParserContext propsParserContext{surfaceId, contextContainer};
// What to do if we detect a conflict? Get current value and make // What to do if we detect a conflict? Get current value and make
// that the baseline of the next animation. Scale the remaining time // that the baseline of the next animation. Scale the remaining time
@ -1131,15 +1126,6 @@ ShadowView LayoutAnimationKeyFrameManager::createInterpolatedShadowView(
return finalView; return finalView;
} }
// Stub PropsParserContext used for interpolateProps.
// This is/should be safe because interpolating doesn't actually need to
// parse props, and just copies them; therefore there should be no
// need to actually use anything in the PropsParserContext.
// If this ever changes, the LayoutAnimations API will need to change
// to pass in a real PropsParserContext.
ContextContainer contextContainer{};
PropsParserContext propsParserContext{-1, contextContainer};
ComponentDescriptor const &componentDescriptor = ComponentDescriptor const &componentDescriptor =
getComponentDescriptorForShadowView(startingView); getComponentDescriptorForShadowView(startingView);
@ -1160,6 +1146,8 @@ ShadowView LayoutAnimationKeyFrameManager::createInterpolatedShadowView(
} }
// Animate opacity or scale/transform // Animate opacity or scale/transform
PropsParserContext propsParserContext{
finalView.surfaceId, *contextContainer_};
mutatedShadowView.props = componentDescriptor.interpolateProps( mutatedShadowView.props = componentDescriptor.interpolateProps(
propsParserContext, progress, startingView.props, finalView.props); propsParserContext, progress, startingView.props, finalView.props);
react_native_assert(mutatedShadowView.props != nullptr); react_native_assert(mutatedShadowView.props != nullptr);
@ -1202,7 +1190,7 @@ void LayoutAnimationKeyFrameManager::queueFinalMutationsForCompletedKeyFrame(
AnimationKeyFrame const &keyframe, AnimationKeyFrame const &keyframe,
ShadowViewMutation::List &mutationsList, ShadowViewMutation::List &mutationsList,
bool interrupted, bool interrupted,
std::string logPrefix) const { const std::string &logPrefix) const {
if (skipInvalidatedKeyFrames_ && keyframe.invalidated) { if (skipInvalidatedKeyFrames_ && keyframe.invalidated) {
return; return;
} }

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

@ -41,6 +41,7 @@ class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate,
public: public:
LayoutAnimationKeyFrameManager( LayoutAnimationKeyFrameManager(
RuntimeExecutor runtimeExecutor, RuntimeExecutor runtimeExecutor,
ContextContainer::Shared &contextContainer,
LayoutAnimationStatusDelegate *delegate); LayoutAnimationStatusDelegate *delegate);
#pragma mark - UIManagerAnimationDelegate methods #pragma mark - UIManagerAnimationDelegate methods
@ -138,10 +139,12 @@ class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate,
AnimationKeyFrame const &keyframe, AnimationKeyFrame const &keyframe,
ShadowViewMutation::List &mutationsList, ShadowViewMutation::List &mutationsList,
bool interrupted, bool interrupted,
std::string logPrefix) const; const std::string &logPrefix) const;
private: private:
RuntimeExecutor runtimeExecutor_; RuntimeExecutor runtimeExecutor_;
ContextContainer::Shared contextContainer_;
mutable std::mutex layoutAnimationStatusDelegateMutex_; mutable std::mutex layoutAnimationStatusDelegateMutex_;
mutable LayoutAnimationStatusDelegate *layoutAnimationStatusDelegate_{}; mutable LayoutAnimationStatusDelegate *layoutAnimationStatusDelegate_{};
mutable std::mutex surfaceIdsToStopMutex_; mutable std::mutex surfaceIdsToStopMutex_;

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

@ -51,7 +51,7 @@ static void testShadowNodeTreeLifeCycleLayoutAnimations(
auto entropy = seed == 0 ? Entropy() : Entropy(seed); auto entropy = seed == 0 ? Entropy() : Entropy(seed);
auto eventDispatcher = EventDispatcher::Shared{}; auto eventDispatcher = EventDispatcher::Shared{};
auto contextContainer = std::make_shared<ContextContainer>(); auto contextContainer = std::make_shared<ContextContainer const>();
auto componentDescriptorParameters = auto componentDescriptorParameters =
ComponentDescriptorParameters{eventDispatcher, contextContainer, nullptr}; ComponentDescriptorParameters{eventDispatcher, contextContainer, nullptr};
auto viewComponentDescriptor = auto viewComponentDescriptor =
@ -77,8 +77,8 @@ static void testShadowNodeTreeLifeCycleLayoutAnimations(
concreteComponentDescriptorProvider<ViewComponentDescriptor>()); concreteComponentDescriptorProvider<ViewComponentDescriptor>());
// Create Animation Driver // Create Animation Driver
auto animationDriver = auto animationDriver = std::make_shared<LayoutAnimationDriver>(
std::make_shared<LayoutAnimationDriver>(runtimeExecutor, nullptr); runtimeExecutor, contextContainer, nullptr);
animationDriver->setComponentDescriptorRegistry(componentDescriptorRegistry); animationDriver->setComponentDescriptorRegistry(componentDescriptorRegistry);
// Mock animation timers // Mock animation timers

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

@ -52,38 +52,7 @@ struct Touch {
Float force; Float force;
/* /*
* The time in seconds (with fractional milliseconds) when the touch occurred * The time in seconds when the touch occurred or when it was last mutated.
* or when it was last mutated.
*
* Whenever possible this should be computed as:
* 1. Pick MONO_CLOCK_NOW, a monotonic system clock. Generally, something like
* `systemUptimeMillis`.
* 2. BASIS_TIME = unix timestamp from unix epoch (ms) - MONO_CLOCK_NOW
* 3. Then assign timestamp = BASIS_TIME + MONO_CLOCK_NOW
*
* The effect should be UNIX timestamp from UNIX epoch, but as a monotonic
* clock (if you just assign to current system time, it can move backwards due
* to clock adjustements, leap seconds, etc etc). So the vast majority of the
* time it will look identical to current UNIX time, but there are some
* edge-cases where it can drift.
*
* If you are not able to use the scheme above for some reason, prefer to use
* a monotonic clock. This timestamp MUST be monotonic. Do NOT just pass along
* system time.
*
* The goal is to allow touch latency to be computed in JS. JS does not have
* access to something like `systemUptimeMillis`, it generally can only access
* the current system time. This *does* mean that the touch latency could be
* computed incorrectly in cases of clock drift, so you should only use this
* as telemetry to get a decent, but not totally perfect, idea of performance.
* Do not use this latency information for anything "mission critical". You
* can assume it's probably reasonably accurate 99% of the time.
*
* Note that we attempt to adhere to the spec of timestamp here:
* https://dom.spec.whatwg.org/#dom-event-timestamp
* Notably, since `global` is not a Window object in React Native, we have
* some flexibility in how we define the time origin:
* https://w3c.github.io/hr-time/#dfn-time-origin
*/ */
Float timestamp; Float timestamp;

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

@ -1,24 +0,0 @@
/*
* 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.
*/
#include "Constants.h"
namespace facebook {
namespace react {
static bool isPropsForwardingEnabled = false;
void Constants::setPropsForwardingEnabled(bool propsForwardingEnabled) {
isPropsForwardingEnabled = propsForwardingEnabled;
}
bool Constants::getPropsForwardingEnabled() {
return isPropsForwardingEnabled;
}
} // namespace react
} // namespace facebook

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

@ -1,23 +0,0 @@
/*
* 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.
*/
#pragma once
namespace facebook {
namespace react {
struct Constants {
/*
Flag controlling props forwarding when shadow node is cloned on Android.
Has no effect on iOS.
*/
static void setPropsForwardingEnabled(bool propsForwardingEnabled);
static bool getPropsForwardingEnabled();
};
} // namespace react
} // namespace facebook

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

@ -6,7 +6,6 @@
*/ */
#include "ShadowNode.h" #include "ShadowNode.h"
#include "Constants.h"
#include "DynamicPropsUtilities.h" #include "DynamicPropsUtilities.h"
#include "ShadowNodeFragment.h" #include "ShadowNodeFragment.h"
@ -39,15 +38,13 @@ SharedProps ShadowNode::propsForClonedShadowNode(
ShadowNode const &sourceShadowNode, ShadowNode const &sourceShadowNode,
Props::Shared const &props) { Props::Shared const &props) {
#ifdef ANDROID #ifdef ANDROID
if (Constants::getPropsForwardingEnabled()) { bool hasBeenMounted = sourceShadowNode.hasBeenMounted_;
bool hasBeenMounted = sourceShadowNode.hasBeenMounted_; bool sourceNodeHasRawProps = !sourceShadowNode.getProps()->rawProps.empty();
bool sourceNodeHasRawProps = !sourceShadowNode.getProps()->rawProps.empty(); if (!hasBeenMounted && sourceNodeHasRawProps && props) {
if (!hasBeenMounted && sourceNodeHasRawProps && props) { auto &castedProps = const_cast<Props &>(*props);
auto &castedProps = const_cast<Props &>(*props); castedProps.rawProps = mergeDynamicProps(
castedProps.rawProps = mergeDynamicProps( sourceShadowNode.getProps()->rawProps, props->rawProps);
sourceShadowNode.getProps()->rawProps, props->rawProps); return props;
return props;
}
} }
#endif #endif
return props ? props : sourceShadowNode.getProps(); return props ? props : sourceShadowNode.getProps();

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

@ -15,7 +15,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../../ LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../../
LOCAL_SHARED_LIBRARIES := libruntimeexecutor libreact_render_core libreact_debug libjsi LOCAL_SHARED_LIBRARIES := libruntimeexecutor libreact_render_core libreact_debug libjsi callinvoker
LOCAL_CFLAGS := \ LOCAL_CFLAGS := \
-DLOG_TAG=\"Fabric\" -DLOG_TAG=\"Fabric\"
@ -25,3 +25,4 @@ LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)
$(call import-module,runtimeexecutor) $(call import-module,runtimeexecutor)
$(call import-module,callinvoker)

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

@ -53,6 +53,7 @@ rn_xplat_cxx_library(
react_native_xplat_target("runtimeexecutor:runtimeexecutor"), react_native_xplat_target("runtimeexecutor:runtimeexecutor"),
react_native_xplat_target("react/renderer/debug:debug"), react_native_xplat_target("react/renderer/debug:debug"),
react_native_xplat_target("better:better"), react_native_xplat_target("better:better"),
react_native_xplat_target("callinvoker:callinvoker"),
], ],
) )

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

@ -0,0 +1,32 @@
/*
* 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.
*/
#include "RuntimeSchedulerCallInvoker.h"
namespace facebook {
namespace react {
RuntimeSchedulerCallInvoker::RuntimeSchedulerCallInvoker(
std::weak_ptr<RuntimeScheduler> runtimeScheduler)
: runtimeScheduler_(runtimeScheduler) {}
void RuntimeSchedulerCallInvoker::invokeAsync(std::function<void()> &&func) {
if (auto runtimeScheduler = runtimeScheduler_.lock()) {
runtimeScheduler->scheduleWork(
[func = std::move(func)](jsi::Runtime &) { func(); });
}
}
void RuntimeSchedulerCallInvoker::invokeSync(std::function<void()> &&func) {
if (auto runtimeScheduler = runtimeScheduler_.lock()) {
runtimeScheduler->executeNowOnTheSameThread(
[func = std::move(func)](jsi::Runtime &) { func(); });
}
}
} // namespace react
} // namespace facebook

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

@ -0,0 +1,36 @@
/*
* 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.
*/
#pragma once
#include <ReactCommon/CallInvoker.h>
#include <react/renderer/runtimescheduler/RuntimeScheduler.h>
namespace facebook {
namespace react {
/*
* Exposes RuntimeScheduler to native modules. All calls invonked on JavaScript
* queue from native modules will be funneled through RuntimeScheduler.
*/
class RuntimeSchedulerCallInvoker : public CallInvoker {
public:
RuntimeSchedulerCallInvoker(std::weak_ptr<RuntimeScheduler> runtimeScheduler);
void invokeAsync(std::function<void()> &&func) override;
void invokeSync(std::function<void()> &&func) override;
private:
/*
* RuntimeScheduler is retained by the runtime. It must not be
* retained by anything beyond the runtime.
*/
std::weak_ptr<RuntimeScheduler> runtimeScheduler_;
};
} // namespace react
} // namespace facebook

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

@ -12,7 +12,6 @@
#include <react/debug/react_native_assert.h> #include <react/debug/react_native_assert.h>
#include <react/renderer/componentregistry/ComponentDescriptorRegistry.h> #include <react/renderer/componentregistry/ComponentDescriptorRegistry.h>
#include <react/renderer/core/Constants.h>
#include <react/renderer/core/EventQueueProcessor.h> #include <react/renderer/core/EventQueueProcessor.h>
#include <react/renderer/core/LayoutContext.h> #include <react/renderer/core/LayoutContext.h>
#include <react/renderer/debug/SystraceSection.h> #include <react/renderer/debug/SystraceSection.h>
@ -119,8 +118,6 @@ Scheduler::Scheduler(
#ifdef ANDROID #ifdef ANDROID
removeOutstandingSurfacesOnDestruction_ = reactNativeConfig_->getBool( removeOutstandingSurfacesOnDestruction_ = reactNativeConfig_->getBool(
"react_fabric:remove_outstanding_surfaces_on_destruction_android"); "react_fabric:remove_outstanding_surfaces_on_destruction_android");
Constants::setPropsForwardingEnabled(reactNativeConfig_->getBool(
"react_fabric:enable_props_forwarding_android"));
#else #else
removeOutstandingSurfacesOnDestruction_ = reactNativeConfig_->getBool( removeOutstandingSurfacesOnDestruction_ = reactNativeConfig_->getBool(
"react_fabric:remove_outstanding_surfaces_on_destruction_ios"); "react_fabric:remove_outstanding_surfaces_on_destruction_ios");

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

@ -7,7 +7,6 @@
buildscript { buildscript {
repositories { repositories {
mavenLocal()
google() google()
mavenCentral() mavenCentral()
} }
@ -31,7 +30,6 @@ allprojects {
// All of Detox's artifacts are provided via the npm module // All of Detox's artifacts are provided via the npm module
url = uri("$rootDir/node_modules/detox/Detox-android") url = uri("$rootDir/node_modules/detox/Detox-android")
} }
mavenLocal()
google() google()
mavenCentral() mavenCentral()
} }

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

@ -41,7 +41,6 @@
"scripts/compose-source-maps.js", "scripts/compose-source-maps.js",
"scripts/find-node.sh", "scripts/find-node.sh",
"scripts/fixmacscripts.sh", "scripts/fixmacscripts.sh",
"scripts/generate-specs.sh",
"scripts/generate-specs-cli.js", "scripts/generate-specs-cli.js",
"scripts/ios-configure-glog.sh", "scripts/ios-configure-glog.sh",
"scripts/launchPackager.bat", "scripts/launchPackager.bat",
@ -153,7 +152,7 @@
"eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-react-native": "^3.11.0", "eslint-plugin-react-native": "^3.11.0",
"eslint-plugin-relay": "1.8.1", "eslint-plugin-relay": "1.8.1",
"flow-bin": "^0.159.0", "flow-bin": "^0.160.2",
"jest": "^26.6.3", "jest": "^26.6.3",
"jest-junit": "^10.0.0", "jest-junit": "^10.0.0",
"jscodeshift": "^0.11.0", "jscodeshift": "^0.11.0",

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

@ -22,7 +22,7 @@ interface NativeCommands {
+scrollTo: (viewRef: React.ElementRef<NativeType>, y: Int32, animated: boolean) => void, +scrollTo: (viewRef: React.ElementRef<NativeType>, y: Int32, animated: boolean) => void,
} }
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
const { const {
dispatchCommand dispatchCommand
@ -84,7 +84,7 @@ interface NativeCommands {
+scrollTo: (viewRef: React.ElementRef<NativeType>, y: Int32, animated: boolean) => void, +scrollTo: (viewRef: React.ElementRef<NativeType>, y: Int32, animated: boolean) => void,
} }
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
const { const {
dispatchCommand dispatchCommand

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

@ -1,6 +1,6 @@
{ {
"name": "react-native-codegen", "name": "react-native-codegen",
"version": "0.0.7", "version": "0.0.8",
"description": "⚛️ Code generation tools for React Native", "description": "⚛️ Code generation tools for React Native",
"homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-codegen", "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-codegen",
"repository": { "repository": {

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

@ -177,7 +177,7 @@ function buildViewConfig(
switch (extendProps.knownTypeName) { switch (extendProps.knownTypeName) {
case 'ReactNativeCoreViewProps': case 'ReactNativeCoreViewProps':
imports.add( imports.add(
"const NativeComponentRegistry = require('NativeComponentRegistry');", "const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');",
); );
return; return;

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

@ -16,7 +16,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'ArrayPropsNativeComponent'; let nativeComponentName = 'ArrayPropsNativeComponent';
@ -61,7 +61,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'ArrayPropsNativeComponent'; let nativeComponentName = 'ArrayPropsNativeComponent';
@ -92,7 +92,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'BooleanPropNativeComponent'; let nativeComponentName = 'BooleanPropNativeComponent';
@ -123,7 +123,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'ColorPropNativeComponent'; let nativeComponentName = 'ColorPropNativeComponent';
@ -156,7 +156,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
const {dispatchCommand} = require(\\"react-native/Libraries/Renderer/shims/ReactNative\\"); const {dispatchCommand} = require(\\"react-native/Libraries/Renderer/shims/ReactNative\\");
let nativeComponentName = 'CommandNativeComponent'; let nativeComponentName = 'CommandNativeComponent';
@ -195,7 +195,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
const {dispatchCommand} = require(\\"react-native/Libraries/Renderer/shims/ReactNative\\"); const {dispatchCommand} = require(\\"react-native/Libraries/Renderer/shims/ReactNative\\");
let nativeComponentName = 'CommandNativeComponent'; let nativeComponentName = 'CommandNativeComponent';
@ -237,7 +237,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'DoublePropNativeComponent'; let nativeComponentName = 'DoublePropNativeComponent';
@ -273,7 +273,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'EventsNestedObjectNativeComponent'; let nativeComponentName = 'EventsNestedObjectNativeComponent';
@ -314,7 +314,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'EventsNativeComponent'; let nativeComponentName = 'EventsNativeComponent';
@ -375,7 +375,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'RCTInterfaceOnlyComponent'; let nativeComponentName = 'RCTInterfaceOnlyComponent';
@ -433,7 +433,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'ExcludedAndroidComponent'; let nativeComponentName = 'ExcludedAndroidComponent';
@ -461,7 +461,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'ExcludedAndroidIosComponent'; let nativeComponentName = 'ExcludedAndroidIosComponent';
@ -489,7 +489,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'FloatPropNativeComponent'; let nativeComponentName = 'FloatPropNativeComponent';
@ -525,7 +525,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'ImagePropNativeComponent'; let nativeComponentName = 'ImagePropNativeComponent';
@ -558,7 +558,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'InsetsPropNativeComponent'; let nativeComponentName = 'InsetsPropNativeComponent';
@ -591,7 +591,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'Int32EnumPropsNativeComponent'; let nativeComponentName = 'Int32EnumPropsNativeComponent';
@ -622,7 +622,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'IntegerPropNativeComponent'; let nativeComponentName = 'IntegerPropNativeComponent';
@ -655,7 +655,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'RCTInterfaceOnlyComponent'; let nativeComponentName = 'RCTInterfaceOnlyComponent';
@ -696,7 +696,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'ImageColorPropNativeComponent'; let nativeComponentName = 'ImageColorPropNativeComponent';
@ -741,7 +741,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'NoPropsNoEventsComponent'; let nativeComponentName = 'NoPropsNoEventsComponent';
@ -769,7 +769,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'ObjectProps'; let nativeComponentName = 'ObjectProps';
@ -800,7 +800,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'PointPropNativeComponent'; let nativeComponentName = 'PointPropNativeComponent';
@ -833,7 +833,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'StringEnumPropsNativeComponent'; let nativeComponentName = 'StringEnumPropsNativeComponent';
@ -864,7 +864,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'StringPropComponent'; let nativeComponentName = 'StringPropComponent';
@ -896,7 +896,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'MultiFile1NativeComponent'; let nativeComponentName = 'MultiFile1NativeComponent';
@ -937,7 +937,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'MultiComponent1NativeComponent'; let nativeComponentName = 'MultiComponent1NativeComponent';
@ -978,7 +978,7 @@ Map {
'use strict'; 'use strict';
const NativeComponentRegistry = require('NativeComponentRegistry'); const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
const {UIManager} = require(\\"react-native\\") const {UIManager} = require(\\"react-native\\")
let nativeComponentName = 'NativeComponentName'; let nativeComponentName = 'NativeComponentName';

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

@ -0,0 +1,16 @@
# react-native-gradle-plugin
[![Version][version-badge]][package]
A Gradle Plugin used to support development of React Native applications for Android.
## Installation
```
yarn add react-native-gradle-plugin
```
*Note: We're using `yarn` to install deps. Feel free to change commands to use `npm` 3+ and `npx` if you like*
[version-badge]: https://img.shields.io/npm/v/react-native-gradle-plugin?style=flat-square
[package]: https://www.npmjs.com/package/react-native-gradle-plugin

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

@ -20,9 +20,9 @@ repositories {
gradlePlugin { gradlePlugin {
plugins { plugins {
create("reactApp") { create("react") {
id = "com.facebook.react" id = "com.facebook.react"
implementationClass = "com.facebook.react.ReactAppPlugin" implementationClass = "com.facebook.react.ReactPlugin"
} }
} }
} }

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

@ -0,0 +1,30 @@
{
"name": "react-native-gradle-plugin",
"version": "0.0.1",
"description": "⚛️ Gradle Plugin for React Native",
"homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-gradle-plugin",
"repository": {
"type": "git",
"url": "git@github.com:facebook/react-native.git",
"directory": "packages/react-native-gradle-plugin"
},
"scripts": {
"build": "./gradlew build",
"clean": "./gradlew clean",
"test": "./gradlew check"
},
"license": "MIT",
"files": [
"settings.gradle.kts",
"build.gradle.kts",
"gradle",
"gradlew",
"gradlew.bat",
"src",
"README.md"
],
"dependencies": {
"react-native-codegen": "*"
},
"devDependencies": {}
}

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

@ -30,7 +30,7 @@ import java.util.stream.Collectors;
* generator is isolated to a single schema, and a single Java package output. * generator is isolated to a single schema, and a single Java package output.
*/ */
public final class JavaGenerator { public final class JavaGenerator {
public static String LICENSE_HEADER = public static final String LICENSE_HEADER =
"/*\n" "/*\n"
+ " * Copyright (c) Facebook, Inc. and its affiliates.\n" + " * Copyright (c) Facebook, Inc. and its affiliates.\n"
+ " *\n" + " *\n"

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

@ -1,153 +0,0 @@
/*
* 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.
*/
package com.facebook.react.codegen.plugin;
import com.android.build.gradle.BaseExtension;
import com.facebook.react.ReactExtension;
import com.facebook.react.codegen.generator.JavaGenerator;
import com.facebook.react.tasks.BuildCodegenCLITask;
import com.facebook.react.tasks.GenerateCodegenSchemaTask;
import com.facebook.react.utils.GradleUtils;
import com.facebook.react.utils.PathUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.io.File;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.tasks.Exec;
import org.gradle.api.tasks.TaskProvider;
/**
* A Gradle plugin to enable react-native-codegen in Gradle environment. See the Gradle API docs for
* more information: https://docs.gradle.org/6.5.1/javadoc/org/gradle/api/Project.html
*/
public class CodegenPlugin {
public void apply(final Project project) {
final ReactExtension extension =
GradleUtils.createOrGet(project.getExtensions(), "react", ReactExtension.class, project);
// 1. Set up build dir.
final File generatedSrcDir = new File(project.getBuildDir(), "generated/source/codegen");
final File generatedSchemaFile = new File(generatedSrcDir, "schema.json");
// 2. Task: produce schema from JS files.
String os = System.getProperty("os.name").toLowerCase();
TaskProvider<BuildCodegenCLITask> buildCodegenTask =
project
.getTasks()
.register(
"buildCodegenCLI",
BuildCodegenCLITask.class,
task -> {
task.getCodegenDir().set(extension.getCodegenDir());
String bashWindowsHome = (String) project.findProperty("REACT_WINDOWS_BASH");
task.getBashWindowsHome().set(bashWindowsHome);
});
TaskProvider<GenerateCodegenSchemaTask> generateCodegenSchemaTask =
project
.getTasks()
.register(
"generateCodegenSchemaFromJavaScript",
GenerateCodegenSchemaTask.class,
task -> {
task.getJsRootDir().set(extension.getJsRootDir());
task.getNodeExecutableAndArgs().set(extension.getNodeExecutableAndArgs());
task.getCodegenDir().set(extension.getCodegenDir());
task.getGeneratedSrcDir().set(generatedSrcDir);
task.dependsOn(buildCodegenTask);
});
// 3. Task: generate Java code from schema.
project
.getTasks()
.register(
"generateCodegenArtifactsFromSchema",
Exec.class,
task -> {
task.dependsOn(generateCodegenSchemaTask);
task.getInputs()
.files(
project.fileTree(
ImmutableMap.of("dir", extension.getCodegenDir().getAsFile().get())));
task.getInputs()
.files(PathUtils.codegenGenerateSchemaCLI(extension).getAbsolutePath());
task.getInputs().files(generatedSchemaFile);
task.getOutputs().dir(generatedSrcDir);
if (extension.getUseJavaGenerator().get()) {
task.doLast(
s -> {
generateJavaFromSchemaWithJavaGenerator(
generatedSchemaFile,
extension.getCodegenJavaPackageName().get(),
generatedSrcDir);
});
}
ImmutableList<String> execCommands =
new ImmutableList.Builder<String>()
.add(os.contains("windows") ? "yarn.cmd" : "yarn")
.addAll(ImmutableList.copyOf(extension.getNodeExecutableAndArgs().get()))
.add(
PathUtils.codegenGenerateNativeModuleSpecsCLI(extension)
.getAbsolutePath())
.add("android")
.add(generatedSchemaFile.getAbsolutePath())
.add(generatedSrcDir.getAbsolutePath())
.add(extension.getLibraryName().get())
.add(extension.getCodegenJavaPackageName().get())
.build();
task.commandLine(execCommands);
});
// 4. Add dependencies & generated sources to the project.
// Note: This last step needs to happen after the project has been evaluated.
project.afterEvaluate(
s -> {
// `preBuild` is one of the base tasks automatically registered by Gradle.
// This will invoke the codegen before compiling the entire project.
Task preBuild = project.getTasks().findByName("preBuild");
if (preBuild != null) {
preBuild.dependsOn("generateCodegenArtifactsFromSchema");
}
/**
* Finally, update the android configuration to include the generated sources. This
* equivalent to this DSL:
*
* <p>android { sourceSets { main { java { srcDirs += "$generatedSrcDir/java" } } } }
*
* <p>See documentation at
* https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.BaseExtension.html.
*/
BaseExtension android = (BaseExtension) project.getExtensions().getByName("android");
android
.getSourceSets()
.getByName("main")
.getJava()
.srcDir(new File(generatedSrcDir, "java"));
});
}
// Use Java-based generator implementation to produce the source files, instead of using the
// JS-based generator.
private void generateJavaFromSchemaWithJavaGenerator(
final File schemaFile, final String javaPackageName, final File outputDir) {
final JavaGenerator generator = new JavaGenerator(schemaFile, javaPackageName, outputDir);
try {
generator.build();
} catch (final Exception ex) {
throw new GradleException("Failed to generate Java from schema.", ex);
}
}
}

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

@ -1,47 +0,0 @@
/*
* 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.
*/
package com.facebook.react
import com.android.build.gradle.AppExtension
import com.android.build.gradle.BaseExtension
import com.android.build.gradle.LibraryExtension
import com.facebook.react.codegen.plugin.CodegenPlugin
import com.facebook.react.utils.GradleUtils.createOrGet
import org.gradle.api.Plugin
import org.gradle.api.Project
class ReactAppPlugin : Plugin<Project> {
override fun apply(project: Project) {
applyAppPlugin(project)
applyCodegenPlugin(project)
}
private fun applyAppPlugin(project: Project) {
val config = project.extensions.createOrGet("react", ReactExtension::class.java, project)
if (config.applyAppPlugin.getOrElse(false)) {
project.afterEvaluate {
val androidConfiguration = project.extensions.getByType(BaseExtension::class.java)
project.configureDevPorts(androidConfiguration)
val isAndroidLibrary = project.plugins.hasPlugin("com.android.library")
val variants =
if (isAndroidLibrary) {
project.extensions.getByType(LibraryExtension::class.java).libraryVariants
} else {
project.extensions.getByType(AppExtension::class.java).applicationVariants
}
variants.all { project.configureReactTasks(variant = it, config = config) }
}
}
}
private fun applyCodegenPlugin(project: Project) {
CodegenPlugin().apply(project)
}
}

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

@ -0,0 +1,109 @@
/*
* 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.
*/
package com.facebook.react
import com.android.build.gradle.AppExtension
import com.android.build.gradle.BaseExtension
import com.android.build.gradle.LibraryExtension
import com.android.build.gradle.internal.tasks.factory.dependsOn
import com.facebook.react.tasks.BuildCodegenCLITask
import com.facebook.react.tasks.GenerateCodegenArtifactsTask
import com.facebook.react.tasks.GenerateCodegenSchemaTask
import java.io.File
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
class ReactPlugin : Plugin<Project> {
override fun apply(project: Project) {
val extension = project.extensions.create("react", ReactExtension::class.java, project)
applyAppPlugin(project, extension)
applyCodegenPlugin(project, extension)
}
private fun applyAppPlugin(project: Project, config: ReactExtension) {
if (config.applyAppPlugin.getOrElse(false)) {
project.afterEvaluate {
val androidConfiguration = project.extensions.getByType(BaseExtension::class.java)
project.configureDevPorts(androidConfiguration)
val isAndroidLibrary = project.plugins.hasPlugin("com.android.library")
val variants =
if (isAndroidLibrary) {
project.extensions.getByType(LibraryExtension::class.java).libraryVariants
} else {
project.extensions.getByType(AppExtension::class.java).applicationVariants
}
variants.all { project.configureReactTasks(variant = it, config = config) }
}
}
}
/**
* A plugin to enable react-native-codegen in Gradle environment. See the Gradle API docs for more
* information: https://docs.gradle.org/6.5.1/javadoc/org/gradle/api/Project.html
*/
private fun applyCodegenPlugin(project: Project, extension: ReactExtension) {
// 1. Set up build dir.
val generatedSrcDir = File(project.buildDir, "generated/source/codegen")
val buildCodegenTask =
project.tasks.register("buildCodegenCLI", BuildCodegenCLITask::class.java) {
it.codegenDir.set(extension.codegenDir)
val bashWindowsHome = project.findProperty("REACT_WINDOWS_BASH") as String?
it.bashWindowsHome.set(bashWindowsHome)
}
// 2. Task: produce schema from JS files.
val generateCodegenSchemaTask =
project.tasks.register(
"generateCodegenSchemaFromJavaScript", GenerateCodegenSchemaTask::class.java) {
it.dependsOn(buildCodegenTask)
it.jsRootDir.set(extension.jsRootDir)
it.nodeExecutableAndArgs.set(extension.nodeExecutableAndArgs)
it.codegenDir.set(extension.codegenDir)
it.generatedSrcDir.set(generatedSrcDir)
}
// 3. Task: generate Java code from schema.
val generateCodegenArtifactsTask =
project.tasks.register(
"generateCodegenArtifactsFromSchema", GenerateCodegenArtifactsTask::class.java) {
it.dependsOn(generateCodegenSchemaTask)
it.reactRoot.set(extension.reactRoot)
it.nodeExecutableAndArgs.set(extension.nodeExecutableAndArgs)
it.codegenDir.set(extension.codegenDir)
it.useJavaGenerator.set(extension.useJavaGenerator)
it.codegenJavaPackageName.set(extension.codegenJavaPackageName)
it.libraryName.set(extension.libraryName)
it.generatedSrcDir.set(generatedSrcDir)
}
// 4. Add dependencies & generated sources to the project.
// Note: This last step needs to happen after the project has been evaluated.
project.afterEvaluate {
// `preBuild` is one of the base tasks automatically registered by Gradle.
// This will invoke the codegen before compiling the entire project.
project.tasks.named("preBuild", Task::class.java).dependsOn(generateCodegenArtifactsTask)
/**
* Finally, update the android configuration to include the generated sources. This equivalent
* to this DSL:
*
* android { sourceSets { main { java { srcDirs += "$generatedSrcDir/java" } } } }
*
* See documentation at
* https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.BaseExtension.html.
*/
val android = project.extensions.getByName("android") as BaseExtension
android.sourceSets.getByName("main").java.srcDir(File(generatedSrcDir, "java"))
}
}
}

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

@ -19,7 +19,9 @@ import com.facebook.react.utils.detectedHermesCommand
import java.io.File import java.io.File
import java.util.* import java.util.*
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.tasks.Copy import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.TaskProvider
private const val REACT_GROUP = "react" private const val REACT_GROUP = "react"
@ -134,6 +136,8 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactExte
is LibraryVariant -> variant.packageLibraryProvider is LibraryVariant -> variant.packageLibraryProvider
else -> tasks.named("package$targetName") else -> tasks.named("package$targetName")
} }
val stripDebugSymbolsTask: TaskProvider<Task>? = tasks.named("strip${targetName}DebugSymbols")
val mergeNativeLibsTask: TaskProvider<Task>? = tasks.named("merge${targetName}NativeLibs")
val mergeResourcesTask = variant.mergeResourcesProvider val mergeResourcesTask = variant.mergeResourcesProvider
val mergeAssetsTask = variant.mergeAssetsProvider val mergeAssetsTask = variant.mergeAssetsProvider
@ -160,7 +164,25 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactExte
packageTask.configure { packageTask.configure {
if (config.enableVmCleanup.get()) { if (config.enableVmCleanup.get()) {
it.doFirst { cleanupVMFiles(enableHermes, isRelease, targetPath) } val libDir = "$buildDir/intermediates/transforms/"
val targetVariant = ".*/transforms/[^/]*/$targetPath/.*".toRegex()
it.doFirst { cleanupVMFiles(libDir, targetVariant, enableHermes, isRelease) }
}
}
stripDebugSymbolsTask?.configure {
if (config.enableVmCleanup.get()) {
val libDir = "$buildDir/intermediates/stripped_native_libs/${targetPath}/out/lib/"
val targetVariant = ".*/stripped_native_libs/$targetPath/out/lib/.*".toRegex()
it.doLast { cleanupVMFiles(libDir, targetVariant, enableHermes, isRelease) }
}
}
mergeNativeLibsTask?.configure {
if (config.enableVmCleanup.get()) {
val libDir = "$buildDir/intermediates/merged_native_libs/${targetPath}/out/lib/"
val targetVariant = ".*/merged_native_libs/$targetPath/out/lib/.*".toRegex()
it.doLast { cleanupVMFiles(libDir, targetVariant, enableHermes, isRelease) }
} }
} }
@ -191,14 +213,18 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactExte
preBundleTask.dependsOn(currentAssetsCopyTask) preBundleTask.dependsOn(currentAssetsCopyTask)
} }
private fun Project.cleanupVMFiles(enableHermes: Boolean, isRelease: Boolean, targetPath: String) { private fun Project.cleanupVMFiles(
libDir: String,
targetVariant: Regex,
enableHermes: Boolean,
isRelease: Boolean
) {
// Delete the VM related libraries that this build doesn't need. // Delete the VM related libraries that this build doesn't need.
// The application can manage this manually by setting 'enableVmCleanup: false' // The application can manage this manually by setting 'enableVmCleanup: false'
// //
// This should really be done by packaging all Hermes related libs into // This should really be done by packaging all Hermes related libs into
// two separate HermesDebug and HermesRelease AARs, but until then we'll // two separate HermesDebug and HermesRelease AARs, but until then we'll
// kludge it by deleting the .so files out of the /transforms/ directory. // kludge it by deleting the .so files out of the /transforms/ directory.
val libDir = "$buildDir/intermediates/transforms/"
fileTree(libDir) { fileTree(libDir) {
if (enableHermes) { if (enableHermes) {
// For Hermes, delete all the libjsc* files // For Hermes, delete all the libjsc* files
@ -208,18 +234,23 @@ private fun Project.cleanupVMFiles(enableHermes: Boolean, isRelease: Boolean, ta
// Reduce size by deleting the debugger/inspector // Reduce size by deleting the debugger/inspector
it.include("**/libhermes-inspector.so") it.include("**/libhermes-inspector.so")
it.include("**/libhermes-executor-debug.so") it.include("**/libhermes-executor-debug.so")
it.include("**/libhermes-executor-common-debug.so")
} else { } else {
// Release libs take precedence and must be removed // Release libs take precedence and must be removed
// to allow debugging // to allow debugging
it.include("**/libhermes-executor-release.so") it.include("**/libhermes-executor-release.so")
it.include("**/libhermes-executor-common-release.so")
} }
} else { } else {
// For JSC, delete all the libhermes* files // For JSC, delete all the libhermes* files
it.include("**/libhermes*.so") it.include("**/libhermes*.so")
// Delete the libjscexecutor from release build
if (isRelease) {
it.include("**/libjscexecutor.so")
}
} }
} }
.visit { visit -> .visit { visit ->
val targetVariant = ".*/transforms/[^/]*/$targetPath/.*".toRegex()
val path = visit.file.absolutePath.replace(File.separatorChar, '/') val path = visit.file.absolutePath.replace(File.separatorChar, '/')
if (path.matches(targetVariant) && visit.file.isFile) { if (path.matches(targetVariant) && visit.file.isFile) {
visit.file.delete() visit.file.delete()

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

@ -27,10 +27,12 @@ abstract class BuildCodegenCLITask : Exec() {
@get:Internal abstract val bashWindowsHome: Property<String> @get:Internal abstract val bashWindowsHome: Property<String>
@get:InputFiles @get:InputFiles
val input: FileCollection = val input: FileCollection by lazy {
codegenDir.files("scripts", "src", "package.json", ".babelrc", ".prettierrc") codegenDir.get().files("scripts", "src", "package.json", ".babelrc", ".prettierrc")
}
@get:OutputFiles val output: FileCollection = codegenDir.files("lib", "node_modules") @get:OutputDirectories
val output: FileCollection by lazy { codegenDir.get().files("lib", "node_modules") }
init { init {
// We need this condition as we want a single instance of BuildCodegenCLITask to execute // We need this condition as we want a single instance of BuildCodegenCLITask to execute

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

@ -0,0 +1,79 @@
/*
* 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.
*/
package com.facebook.react.tasks
import com.facebook.react.codegen.generator.JavaGenerator
import com.facebook.react.utils.windowsAwareYarn
import org.gradle.api.GradleException
import org.gradle.api.file.Directory
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.RegularFile
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.*
abstract class GenerateCodegenArtifactsTask : Exec() {
@get:Internal abstract val reactRoot: DirectoryProperty
@get:Internal abstract val codegenDir: DirectoryProperty
@get:Internal abstract val generatedSrcDir: DirectoryProperty
@get:Input abstract val nodeExecutableAndArgs: ListProperty<String>
@get:Input abstract val useJavaGenerator: Property<Boolean>
@get:Input abstract val codegenJavaPackageName: Property<String>
@get:Input abstract val libraryName: Property<String>
@get:InputFile
val combineJsToSchemaCli: Provider<RegularFile> =
codegenDir.file("lib/cli/combine/combine-js-to-schema-cli.js")
@get:InputFile
val generatedSchemaFile: Provider<RegularFile> = generatedSrcDir.file("schema.json")
@get:OutputDirectory val generatedJavaFiles: Provider<Directory> = generatedSrcDir.dir("java")
@get:OutputDirectory val generatedJniFiles: Provider<Directory> = generatedSrcDir.dir("jni")
override fun exec() {
setupCommandLine()
super.exec()
}
internal fun setupCommandLine() {
if (useJavaGenerator.getOrElse(false)) {
// Use Java-based generator implementation to produce the source files,
// instead of using the JS-based generator.
try {
JavaGenerator(
generatedSchemaFile.get().asFile,
codegenJavaPackageName.get(),
generatedSrcDir.get().asFile)
.build()
} catch (e: Exception) {
throw GradleException("Failed to generate Java from schema.", e)
}
commandLine("echo", "Used JavaGenerator to generate files instead of generate-specs-cli.js")
} else {
commandLine(
windowsAwareYarn(
*nodeExecutableAndArgs.get().toTypedArray(),
reactRoot.file("scripts/generate-specs-cli.js").get().asFile.absolutePath,
"android",
generatedSchemaFile.get().asFile.absolutePath,
generatedSrcDir.get().asFile.absolutePath,
libraryName.get(),
codegenJavaPackageName.get()))
}
}
}

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

@ -35,11 +35,19 @@ abstract class GenerateCodegenSchemaTask : Exec() {
val generatedSchemaFile: Provider<RegularFile> = generatedSrcDir.file("schema.json") val generatedSchemaFile: Provider<RegularFile> = generatedSrcDir.file("schema.json")
override fun exec() { override fun exec() {
wipeOutputDir()
setupCommandLine()
super.exec()
}
internal fun wipeOutputDir() {
generatedSrcDir.asFile.get().apply { generatedSrcDir.asFile.get().apply {
delete() deleteRecursively()
mkdirs() mkdirs()
} }
}
internal fun setupCommandLine() {
commandLine( commandLine(
windowsAwareYarn( windowsAwareYarn(
*nodeExecutableAndArgs.get().toTypedArray(), *nodeExecutableAndArgs.get().toTypedArray(),
@ -51,6 +59,5 @@ abstract class GenerateCodegenSchemaTask : Exec() {
generatedSchemaFile.get().asFile.absolutePath, generatedSchemaFile.get().asFile.absolutePath,
jsRootDir.asFile.get().absolutePath, jsRootDir.asFile.get().absolutePath,
)) ))
super.exec()
} }
} }

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

@ -1,18 +0,0 @@
/*
* 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.
*/
package com.facebook.react.utils
import org.gradle.api.Project
import org.gradle.api.plugins.ExtensionContainer
object GradleUtils {
@JvmStatic
fun <T> ExtensionContainer.createOrGet(name: String, type: Class<T>, target: Project): T =
this.findByType(type) ?: this.create(name, type, target)
}

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

@ -122,9 +122,3 @@ internal fun projectPathToLibraryName(projectPath: String): String =
.split(':', '-', '_', '.') .split(':', '-', '_', '.')
.joinToString("") { it.capitalize(Locale.ROOT) } .joinToString("") { it.capitalize(Locale.ROOT) }
.plus("Spec") .plus("Spec")
fun codegenGenerateSchemaCLI(config: ReactExtension): File =
config.codegenDir.file("lib/cli/combine/combine-js-to-schema-cli.js").get().asFile
fun codegenGenerateNativeModuleSpecsCLI(config: ReactExtension): File =
config.reactRoot.file("scripts/generate-specs-cli.js").get().asFile

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

@ -0,0 +1,75 @@
/*
* 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.
*/
package com.facebook.react.tasks
import com.facebook.react.tests.createTestTask
import java.io.File
import org.gradle.api.tasks.*
import org.junit.Assert.*
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
class BuildCodegenCLITaskTest {
@get:Rule val tempFolder = TemporaryFolder()
@Test
fun buildCodegenCli_input_isSetCorrectly() {
val task = createTestTask<BuildCodegenCLITask> { it.codegenDir.set(tempFolder.root) }
assertTrue(task.input.contains(File(tempFolder.root, "scripts")))
assertTrue(task.input.contains(File(tempFolder.root, "src")))
assertTrue(task.input.contains(File(tempFolder.root, "package.json")))
assertTrue(task.input.contains(File(tempFolder.root, ".babelrc")))
assertTrue(task.input.contains(File(tempFolder.root, ".prettierrc")))
}
@Test
fun buildCodegenCli_output_isSetCorrectly() {
val task = createTestTask<BuildCodegenCLITask> { it.codegenDir.set(tempFolder.root) }
assertTrue(task.output.contains(File(tempFolder.root, "lib")))
assertTrue(task.output.contains(File(tempFolder.root, "node_modules")))
}
@Test
fun buildCodegenCli_bashWindowsHome_isSetCorrectly() {
val bashPath = tempFolder.newFile("bash").absolutePath
val task = createTestTask<BuildCodegenCLITask> { it.bashWindowsHome.set(bashPath) }
assertEquals(bashPath, task.bashWindowsHome.get())
}
@Test
fun buildCodegenCli_onlyIf_withMissingDirectory_isSatisfied() {
File(tempFolder.root, "lib/cli/").apply { mkdirs() }
val task = createTestTask<BuildCodegenCLITask> { it.codegenDir.set(tempFolder.root) }
assertTrue(task.onlyIf.isSatisfiedBy(task))
}
@Test
fun buildCodegenCli_onlyIf_withEmptyDirectory_isSatisfied() {
File(tempFolder.root, "lib/cli/").apply { mkdirs() }
val task = createTestTask<BuildCodegenCLITask> { it.codegenDir.set(tempFolder.root) }
assertTrue(task.onlyIf.isSatisfiedBy(task))
}
@Test
fun buildCodegenCli_onlyIf_withExistingDirtyDirectory_isNotSatisfied() {
File(tempFolder.root, "lib/cli/a-file").apply {
parentFile.mkdirs()
writeText("¯\\_(ツ)_/¯")
}
val task = createTestTask<BuildCodegenCLITask> { it.codegenDir.set(tempFolder.root) }
assertFalse(task.onlyIf.isSatisfiedBy(task))
}
}

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