diff --git a/.circleci/config.yml b/.circleci/config.yml index 7ee106ab67709b..b21fba58c1bb6c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -69,11 +69,11 @@ aliases: - &restore-cache-buck keys: - - v1-buck-{{ arch }}-v2017.09.04.02 + - v1-buck-{{ arch }}-v2017.11.16.01 - &save-cache-buck paths: - ~/buck - key: v1-buck-{{ arch }}-v2017.09.04.02 + key: v1-buck-{{ arch }}-v2017.11.16.01 - &restore-cache-watchman keys: @@ -239,17 +239,22 @@ jobs: command: | cd website npm install --no-package-lock --no-spin --no-progress +# The CIRCLE_PROJECT_USERNAME and CIRCLE_PR_USERNAME checks below +# ensure deploys only happen on projects owned by "facebook", +# never on a forked PR build. - run: name: Build and Deploy Static Website command: | - if [[ $CIRCLE_PROJECT_USERNAME == "facebook" && -z $CI_PULL_REQUEST && -z $CIRCLE_PR_USERNAME ]]; then + if [[ $CIRCLE_PROJECT_USERNAME == "facebook" && -z $CIRCLE_PR_USERNAME ]]; then git config --global user.email "reactjs-bot@users.noreply.github.com" git config --global user.name "Website Deployment Script" echo "machine github.com login reactjs-bot password $GITHUB_TOKEN" > ~/.netrc echo "Deploying website..." cd website && GIT_USER=reactjs-bot npm run gh-pages + elif [[ -n $CIRCLE_PR_USERNAME ]]; then + echo "Skipping website deploy, this is a forked PR build." else - echo "Skipping deploy." + echo "Skipping website deploy." fi # Build JavaScript bundle for Android tests @@ -329,7 +334,7 @@ jobs: name: Install Buck command: | if [[ ! -e ~/buck ]]; then - git clone https://github.com/facebook/buck.git ~/buck --branch v2017.09.04.02 --depth=1 + git clone https://github.com/facebook/buck.git ~/buck --branch v2017.11.16.01 --depth=1 fi cd ~/buck && ant buck --version @@ -438,10 +443,12 @@ jobs: - checkout - restore-cache: *restore-cache-analysis - run: *install-node-dependencies +# The CIRCLE_PR_NUMBER checks below ensure +# code analysis only runs on forked PR builds. - run: name: Install Dependencies command: | - if [ -n "$CIRCLE_PULL_REQUEST" ]; then + if [ -n "$CIRCLE_PR_NUMBER" ]; then npm install github@0.2.4 cd danger npm install --no-package-lock --no-spin --no-progress @@ -453,17 +460,17 @@ jobs: - run: name: Analyze Pull Request command: | - if [ -n "$CIRCLE_PULL_REQUEST" ]; then + if [ -n "$CIRCLE_PR_NUMBER" ]; then cd danger && DANGER_GITHUB_API_TOKEN="e622517d9f1136ea8900""07c6373666312cdfaa69" npm run danger else echo "Skipping pull request analysis." fi when: always -# Run eslint +# Run eslint - run: name: Analyze Code command: | - if [ -n "$CIRCLE_PULL_REQUEST" ]; then + if [ -n "$CIRCLE_PR_NUMBER" && -n "$CIRCLE_PROJECT_USERNAME" && -n "$CIRCLE_PROJECT_REPONAME" ]; then cat <(echo eslint; npm run lint --silent -- --format=json; echo flow; npm run flow --silent -- check --json) | GITHUB_TOKEN="af6ef0d15709bc91d""06a6217a5a826a226fb57b7" CI_USER=$CIRCLE_PROJECT_USERNAME CI_REPO=$CIRCLE_PROJECT_REPONAME PULL_REQUEST_NUMBER=$CIRCLE_PR_NUMBER node bots/code-analysis-bot.js else echo "Skipping code analysis." diff --git a/.flowconfig b/.flowconfig index 7b6a007cfe3422..fc9fe6762baa0f 100644 --- a/.flowconfig +++ b/.flowconfig @@ -46,12 +46,12 @@ suppress_type=$FlowFixMeProps suppress_type=$FlowFixMeState suppress_type=$FixMe -suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-8]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*[react_native_oss|react_native_fb][a-z,_]*\\)?)\\) -suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-8]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*[react_native_oss|react_native_fb][a-z,_]*\\)?)\\)?:? #[0-9]+ +suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-9]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*[react_native_oss|react_native_fb][a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-9]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*[react_native_oss|react_native_fb][a-z,_]*\\)?)\\)?:? #[0-9]+ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError unsafe.enable_getters_and_setters=true [version] -^0.58.0 +^0.59.0 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 126b18a9854ac3..0eb04255aa8a06 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -27,7 +27,7 @@ Help reviewers and the release process by writing your own release notes [----------] TYPE [ CLI ] [-------------] LOCATION [ DOCS ] [ BREAKING ] [-------------] -[ GENERAl ] [ BUGFIX ] [-{Component}-] +[ GENERAL ] [ BUGFIX ] [-{Component}-] [ INTERNAL ] [ ENHANCEMENT ] [ {File} ] [ IOS ] [ FEATURE ] [ {Directory} ] |-----------| [ ANDROID ] [ MINOR ] [ {Framework} ] - | {Message} | diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0d9e9d7eccf64d..541ea2ea9206cb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -96,11 +96,11 @@ Please make sure the following is done when submitting a pull request: 1. Fork [the repository](https://github.com/facebook/react-native) and create your branch from `master`. 2. Add the copyright notice to the top of any new files you've added. -3. Describe your [**test plan**](/react-native/docs/contributing.html#test-plan) in your pull request description. Make sure to [test your changes](/react-native/docs/testing.html)! +3. Describe your [**test plan**](https://facebook.github.io/react-native/docs/contributing.html#test-plan) in your pull request description. Make sure to [test your changes](https://facebook.github.io/react-native/docs/testing.html)! 4. Make sure your code lints (`npm run lint`). 5. If you haven't already, [sign the CLA](https://code.facebook.com/cla). -All pull requests should be opened against the `master` branch. After opening your pull request, ensure [**all tests pass**](/react-native/docs/contributing.html#contrinuous-integration-tests) on Circle CI. If a test fails and you believe it is unrelated to your change, leave a comment on the pull request explaining why. +All pull requests should be opened against the `master` branch. After opening your pull request, ensure [**all tests pass**](https://facebook.github.io/react-native/docs/contributing.html#contrinuous-integration-tests) on Circle CI. If a test fails and you believe it is unrelated to your change, leave a comment on the pull request explaining why. > **Note:** It is not necessary to keep clicking `Merge master to your branch` on the PR page. You would want to merge master if there are conflicts or tests are failing. The Facebook-GitHub-Bot ultimately squashes all commits to a single one before merging your PR. @@ -116,7 +116,7 @@ See [What is a Test Plan?](https://medium.com/@martinkonicek/what-is-a-test-plan #### Continuous integration tests -Make sure all **tests pass** on [Circle CI][circle]. PRs that break tests are unlikely to be merged. Learn more about [testing your changes here](/react-native/docs/testing.html). +Make sure all **tests pass** on [Circle CI][circle]. PRs that break tests are unlikely to be merged. Learn more about [testing your changes here](https://facebook.github.io/react-native/docs/testing.html). [circle]: http://circleci.com/gh/facebook/react-native diff --git a/Libraries/ActionSheetIOS/ActionSheetIOS.js b/Libraries/ActionSheetIOS/ActionSheetIOS.js index 8c3dbe55a1dc7a..531fa8fc87e304 100644 --- a/Libraries/ActionSheetIOS/ActionSheetIOS.js +++ b/Libraries/ActionSheetIOS/ActionSheetIOS.js @@ -16,33 +16,27 @@ var RCTActionSheetManager = require('NativeModules').ActionSheetManager; var invariant = require('fbjs/lib/invariant'); var processColor = require('processColor'); +/** + * Display action sheets and share sheets on iOS. + * + * See http://facebook.github.io/react-native/docs/actionsheetios.html + */ var ActionSheetIOS = { /** - * Display an iOS action sheet. The `options` object must contain one or more - * of: - * + * Display an iOS action sheet. + * + * The `options` object must contain one or more of: + * * - `options` (array of strings) - a list of button titles (required) * - `cancelButtonIndex` (int) - index of cancel button in `options` * - `destructiveButtonIndex` (int) - index of destructive button in `options` * - `title` (string) - a title to show above the action sheet * - `message` (string) - a message to show below the title - * + * * The 'callback' function takes one parameter, the zero-based index * of the selected item. - * - * Minimal example: * - * ``` - * ActionSheetIOS.showActionSheetWithOptions({ - * options: ['Remove', 'Cancel'], - * destructiveButtonIndex: 1, - * cancelButtonIndex: 0, - * }, - * (buttonIndex) => { - * if (buttonIndex === 1) { // destructive action } - * }); - * ``` - * + * See http://facebook.github.io/react-native/docs/actionsheetios.html#showactionsheetwithoptions */ showActionSheetWithOptions(options: Object, callback: Function) { invariant( @@ -67,11 +61,9 @@ var ActionSheetIOS = { * - `url` (string) - a URL to share * - `message` (string) - a message to share * - `subject` (string) - a subject for the message - * - `excludedActivityTypes` (array) - the activities to exclude from the ActionSheet - * - * NOTE: if `url` points to a local file, or is a base64-encoded - * uri, the file it points to will be loaded and shared directly. - * In this way, you can share images, videos, PDF files, etc. + * - `excludedActivityTypes` (array) - the activities to exclude from + * the ActionSheet + * - `tintColor` (color) - tint color of the buttons * * The 'failureCallback' function takes one parameter, an error object. * The only property defined on this object is an optional `stack` property @@ -81,6 +73,8 @@ var ActionSheetIOS = { * * - a boolean value signifying success or failure * - a string that, in the case of success, indicates the method of sharing + * + * See http://facebook.github.io/react-native/docs/actionsheetios.html#showshareactionsheetwithoptions */ showShareActionSheetWithOptions( options: Object, diff --git a/Libraries/Alert/Alert.js b/Libraries/Alert/Alert.js index 40666f70e35076..3f2e2379eeb44a 100644 --- a/Libraries/Alert/Alert.js +++ b/Libraries/Alert/Alert.js @@ -30,54 +30,16 @@ type Options = { /** * Launches an alert dialog with the specified title and message. - * - * Optionally provide a list of buttons. Tapping any button will fire the - * respective onPress callback and dismiss the alert. By default, the only - * button will be an 'OK' button. - * - * This is an API that works both on iOS and Android and can show static - * alerts. To show an alert that prompts the user to enter some information, - * see `AlertIOS`; entering text in an alert is common on iOS only. - * - * ## iOS - * - * On iOS you can specify any number of buttons. Each button can optionally - * specify a style, which is one of 'default', 'cancel' or 'destructive'. - * - * ## Android - * - * On Android at most three buttons can be specified. Android has a concept - * of a neutral, negative and a positive button: - * - * - If you specify one button, it will be the 'positive' one (such as 'OK') - * - Two buttons mean 'negative', 'positive' (such as 'Cancel', 'OK') - * - Three buttons mean 'neutral', 'negative', 'positive' (such as 'Later', 'Cancel', 'OK') - * - * By default alerts on Android can be dismissed by tapping outside of the alert - * box. This event can be handled by providing an optional `options` parameter, - * with an `onDismiss` callback property `{ onDismiss: () => {} }`. - * - * Alternatively, the dismissing behavior can be disabled altogether by providing - * an optional `options` parameter with the `cancelable` property set to `false` - * i.e. `{ cancelable: false }` - * - * Example usage: - * ``` - * // Works on both iOS and Android - * Alert.alert( - * 'Alert Title', - * 'My Alert Msg', - * [ - * {text: 'Ask me later', onPress: () => console.log('Ask me later pressed')}, - * {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'}, - * {text: 'OK', onPress: () => console.log('OK Pressed')}, - * ], - * { cancelable: false } - * ) - * ``` + * + * See http://facebook.github.io/react-native/docs/alert.html */ class Alert { + /** + * Launches an alert dialog with the specified title and message. + * + * See http://facebook.github.io/react-native/docs/alert.html#alert + */ static alert( title: ?string, message?: ?string, diff --git a/Libraries/Alert/AlertIOS.js b/Libraries/Alert/AlertIOS.js index 375a4db56c96a2..b42b57c29ae481 100644 --- a/Libraries/Alert/AlertIOS.js +++ b/Libraries/Alert/AlertIOS.js @@ -77,60 +77,15 @@ export type ButtonsArray = Array<{ }>; /** - * @description - * `AlertIOS` provides functionality to create an iOS alert dialog with a - * message or create a prompt for user input. - * - * Creating an iOS alert: - * - * ``` - * AlertIOS.alert( - * 'Sync Complete', - * 'All your data are belong to us.' - * ); - * ``` - * - * Creating an iOS prompt: - * - * ``` - * AlertIOS.prompt( - * 'Enter a value', - * null, - * text => console.log("You entered "+text) - * ); - * ``` - * - * We recommend using the [`Alert.alert`](docs/alert.html) method for - * cross-platform support if you don't need to create iOS-only prompts. + * Use `AlertIOS` to display an alert dialog with a message or to create a prompt for user input on iOS. If you don't need to prompt for user input, we recommend using `Alert.alert() for cross-platform support. * + * See http://facebook.github.io/react-native/docs/alertios.html */ class AlertIOS { /** * Create and display a popup alert. - * @static - * @method alert - * @param title The dialog's title. Passing null or '' will hide the title. - * @param message An optional message that appears below - * the dialog's title. - * @param callbackOrButtons This optional argument should - * be either a single-argument function or an array of buttons. If passed - * a function, it will be called when the user taps 'OK'. - * - * If passed an array of button configurations, each button should include - * a `text` key, as well as optional `onPress` and `style` keys. `style` - * should be one of 'default', 'cancel' or 'destructive'. - * @param type Deprecated, do not use. * - * @example Example with custom buttons - * - * AlertIOS.alert( - * 'Update available', - * 'Keep your app up to date to enjoy the latest features', - * [ - * {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'}, - * {text: 'Install', onPress: () => console.log('Install Pressed')}, - * ], - * ); + * See http://facebook.github.io/react-native/docs/alertios.html#alert */ static alert( title: ?string, @@ -148,48 +103,8 @@ class AlertIOS { /** * Create and display a prompt to enter some text. - * @static - * @method prompt - * @param title The dialog's title. - * @param message An optional message that appears above the text - * input. - * @param callbackOrButtons This optional argument should - * be either a single-argument function or an array of buttons. If passed - * a function, it will be called with the prompt's value when the user - * taps 'OK'. - * - * If passed an array of button configurations, each button should include - * a `text` key, as well as optional `onPress` and `style` keys (see - * example). `style` should be one of 'default', 'cancel' or 'destructive'. - * @param type This configures the text input. One of 'plain-text', - * 'secure-text' or 'login-password'. - * @param defaultValue The default text in text input. - * @param keyboardType The keyboard type of first text field(if exists). - * One of 'default', 'email-address', 'numeric', 'phone-pad', - * 'ascii-capable', 'numbers-and-punctuation', 'url', 'number-pad', - * 'name-phone-pad', 'decimal-pad', 'twitter' or 'web-search'. - * - * @example Example with custom buttons - * - * AlertIOS.prompt( - * 'Enter password', - * 'Enter your password to claim your $1.5B in lottery winnings', - * [ - * {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'}, - * {text: 'OK', onPress: password => console.log('OK Pressed, password: ' + password)}, - * ], - * 'secure-text' - * ); - * - * @example Example with the default button and a custom callback - * - * AlertIOS.prompt( - * 'Update username', - * null, - * text => console.log("Your username is "+text), - * null, - * 'default' - * ); + * + * See http://facebook.github.io/react-native/docs/alertios.html#prompt */ static prompt( title: ?string, diff --git a/Libraries/Animated/src/AnimatedImplementation.js b/Libraries/Animated/src/AnimatedImplementation.js index 71d616026f0b57..5baf8446c1c64a 100644 --- a/Libraries/Animated/src/AnimatedImplementation.js +++ b/Libraries/Animated/src/AnimatedImplementation.js @@ -510,183 +510,33 @@ const event = function(argMapping: Array, config?: EventConfig): any { * between inputs and outputs, with configurable transforms in between, and * simple `start`/`stop` methods to control time-based animation execution. * - * The simplest workflow for creating an animation is to create an - * `Animated.Value`, hook it up to one or more style attributes of an animated - * component, and then drive updates via animations using `Animated.timing()`: - * - * ```javascript - * Animated.timing( // Animate value over time - * this.state.fadeAnim, // The value to drive - * { - * toValue: 1, // Animate to final value of 1 - * } - * ).start(); // Start the animation - * ``` - * - * Refer to the [Animations](docs/animations.html#animated-api) guide to see - * additional examples of `Animated` in action. - * - * ## Overview - * - * There are two value types you can use with `Animated`: - * - * - [`Animated.Value()`](docs/animated.html#value) for single values - * - [`Animated.ValueXY()`](docs/animated.html#valuexy) for vectors - * - * `Animated.Value` can bind to style properties or other props, and can be - * interpolated as well. A single `Animated.Value` can drive any number of - * properties. - * - * ### Configuring animations - * - * `Animated` provides three types of animation types. Each animation type - * provides a particular animation curve that controls how your values animate - * from their initial value to the final value: - * - * - [`Animated.decay()`](docs/animated.html#decay) starts with an initial - * velocity and gradually slows to a stop. - * - [`Animated.spring()`](docs/animated.html#spring) provides a simple - * spring physics model. - * - [`Animated.timing()`](docs/animated.html#timing) animates a value over time - * using [easing functions](docs/easing.html). - * - * In most cases, you will be using `timing()`. By default, it uses a symmetric - * easeInOut curve that conveys the gradual acceleration of an object to full - * speed and concludes by gradually decelerating to a stop. - * - * ### Working with animations - * - * Animations are started by calling `start()` on your animation. `start()` - * takes a completion callback that will be called when the animation is done. - * If the animation finished running normally, the completion callback will be - * invoked with `{finished: true}`. If the animation is done because `stop()` - * was called on it before it could finish (e.g. because it was interrupted by a - * gesture or another animation), then it will receive `{finished: false}`. - * - * ### Using the native driver - * - * By using the native driver, we send everything about the animation to native - * before starting the animation, allowing native code to perform the animation - * on the UI thread without having to go through the bridge on every frame. - * Once the animation has started, the JS thread can be blocked without - * affecting the animation. - * - * You can use the native driver by specifying `useNativeDriver: true` in your - * animation configuration. See the - * [Animations](docs/animations.html#using-the-native-driver) guide to learn - * more. - * - * ### Animatable components - * - * Only animatable components can be animated. These special components do the - * magic of binding the animated values to the properties, and do targeted - * native updates to avoid the cost of the react render and reconciliation - * process on every frame. They also handle cleanup on unmount so they are safe - * by default. - * - * - [`createAnimatedComponent()`](docs/animated.html#createanimatedcomponent) - * can be used to make a component animatable. - * - * `Animated` exports the following animatable components using the above - * wrapper: - * - * - `Animated.Image` - * - `Animated.ScrollView` - * - `Animated.Text` - * - `Animated.View` - * - * ### Composing animations - * - * Animations can also be combined in complex ways using composition functions: - * - * - [`Animated.delay()`](docs/animated.html#delay) starts an animation after - * a given delay. - * - [`Animated.parallel()`](docs/animated.html#parallel) starts a number of - * animations at the same time. - * - [`Animated.sequence()`](docs/animated.html#sequence) starts the animations - * in order, waiting for each to complete before starting the next. - * - [`Animated.stagger()`](docs/animated.html#stagger) starts animations in - * order and in parallel, but with successive delays. - * - * Animations can also be chained together simply by setting the `toValue` of - * one animation to be another `Animated.Value`. See - * [Tracking dynamic values](docs/animations.html#tracking-dynamic-values) in - * the Animations guide. - * - * By default, if one animation is stopped or interrupted, then all other - * animations in the group are also stopped. - * - * ### Combining animated values - * - * You can combine two animated values via addition, multiplication, division, - * or modulo to make a new animated value: - * - * - [`Animated.add()`](docs/animated.html#add) - * - [`Animated.divide()`](docs/animated.html#divide) - * - [`Animated.modulo()`](docs/animated.html#modulo) - * - [`Animated.multiply()`](docs/animated.html#multiply) - * - * ### Interpolation - * - * The `interpolate()` function allows input ranges to map to different output - * ranges. By default, it will extrapolate the curve beyond the ranges given, - * but you can also have it clamp the output value. It uses lineal interpolation - * by default but also supports easing functions. - * - * - [`interpolate()`](docs/animated.html#interpolate) - * - * Read more about interpolation in the - * [Animation](docs/animations.html#interpolation) guide. - * - * ### Handling gestures and other events - * - * Gestures, like panning or scrolling, and other events can map directly to - * animated values using `Animated.event()`. This is done with a structured map - * syntax so that values can be extracted from complex event objects. The first - * level is an array to allow mapping across multiple args, and that array - * contains nested objects. - * - * - [`Animated.event()`](docs/animated.html#event) - * - * For example, when working with horizontal scrolling gestures, you would do - * the following in order to map `event.nativeEvent.contentOffset.x` to - * `scrollX` (an `Animated.Value`): - * - * ```javascript - * onScroll={Animated.event( - * // scrollX = e.nativeEvent.contentOffset.x - * [{ nativeEvent: { - * contentOffset: { - * x: scrollX - * } - * } - * }] - * )} - * ``` - * + * See http://facebook.github.io/react-native/docs/animated.html */ module.exports = { /** * Standard value class for driving animations. Typically initialized with * `new Animated.Value(0);` * - * See also [`AnimatedValue`](docs/animated.html#animatedvalue). + * See http://facebook.github.io/react-native/docs/animated.html#value */ Value: AnimatedValue, /** * 2D value class for driving 2D animations, such as pan gestures. * - * See also [`AnimatedValueXY`](docs/animated.html#animatedvaluexy). + * See http://facebook.github.io/react-native/docs/animated.html#valuexy */ ValueXY: AnimatedValueXY, /** - * exported to use the Interpolation type in flow - * - * See also [`AnimatedInterpolation`](docs/animated.html#animatedinterpolation). + * Exported to use the Interpolation type in flow. + * + * See http://facebook.github.io/react-native/docs/animated.html#interpolation */ Interpolation: AnimatedInterpolation, /** - * Exported for ease of type checking. All animated values derive from this class. + * Exported for ease of type checking. All animated values derive from this + * class. + * + * See http://facebook.github.io/react-native/docs/animated.html#node */ Node: AnimatedNode, @@ -694,185 +544,130 @@ module.exports = { * Animates a value from an initial velocity to zero based on a decay * coefficient. * - * Config is an object that may have the following options: - * - * - `velocity`: Initial velocity. Required. - * - `deceleration`: Rate of decay. Default 0.997. - * - `isInteraction`: Whether or not this animation creates an "interaction handle" on the - * `InteractionManager`. Default true. - * - `useNativeDriver`: Uses the native driver when true. Default false. + * See http://facebook.github.io/react-native/docs/animated.html#decay */ decay, /** - * Animates a value along a timed easing curve. The - * [`Easing`](docs/easing.html) module has tons of predefined curves, or you - * can use your own function. + * Animates a value along a timed easing curve. The Easing module has tons of + * predefined curves, or you can use your own function. * - * Config is an object that may have the following options: - * - * - `duration`: Length of animation (milliseconds). Default 500. - * - `easing`: Easing function to define curve. - * Default is `Easing.inOut(Easing.ease)`. - * - `delay`: Start the animation after delay (milliseconds). Default 0. - * - `isInteraction`: Whether or not this animation creates an "interaction handle" on the - * `InteractionManager`. Default true. - * - `useNativeDriver`: Uses the native driver when true. Default false. + * See http://facebook.github.io/react-native/docs/animated.html#timing */ timing, /** * Animates a value according to an analytical spring model based on - * [damped harmonic oscillation](https://en.wikipedia.org/wiki/Harmonic_oscillator#Damped_harmonic_oscillator). - * Tracks velocity state to create fluid motions as the `toValue` updates, and - * can be chained together. - * - * Config is an object that may have the following options. - * - * Note that you can only define one of bounciness/speed, tension/friction, or - * stiffness/damping/mass, but not more than one: - * - * The friction/tension or bounciness/speed options match the spring model in - * [Facebook Pop](https://github.com/facebook/pop), [Rebound](http://facebook.github.io/rebound/), - * and [Origami](http://origami.design/). - * - * - `friction`: Controls "bounciness"/overshoot. Default 7. - * - `tension`: Controls speed. Default 40. - * - `speed`: Controls speed of the animation. Default 12. - * - `bounciness`: Controls bounciness. Default 8. - * - * Specifying stiffness/damping/mass as parameters makes `Animated.spring` use an - * analytical spring model based on the motion equations of a [damped harmonic - * oscillator](https://en.wikipedia.org/wiki/Harmonic_oscillator#Damped_harmonic_oscillator). - * This behavior is slightly more precise and faithful to the physics behind - * spring dynamics, and closely mimics the implementation in iOS's - * CASpringAnimation primitive. - * - * - `stiffness`: The spring stiffness coefficient. Default 100. - * - `damping`: Defines how the spring’s motion should be damped due to the forces of friction. - * Default 10. - * - `mass`: The mass of the object attached to the end of the spring. Default 1. - * - * Other configuration options are as follows: - * - * - `velocity`: The initial velocity of the object attached to the spring. Default 0 (object - * is at rest). - * - `overshootClamping`: Boolean indiciating whether the spring should be clamped and not - * bounce. Default false. - * - `restDisplacementThreshold`: The threshold of displacement from rest below which the - * spring should be considered at rest. Default 0.001. - * - `restSpeedThreshold`: The speed at which the spring should be considered at rest in pixels - * per second. Default 0.001. - * - `delay`: Start the animation after delay (milliseconds). Default 0. - * - `isInteraction`: Whether or not this animation creates an "interaction handle" on the - * `InteractionManager`. Default true. - * - `useNativeDriver`: Uses the native driver when true. Default false. + * damped harmonic oscillation. + * + * See http://facebook.github.io/react-native/docs/animated.html#spring */ spring, /** * Creates a new Animated value composed from two Animated values added * together. + * + * See http://facebook.github.io/react-native/docs/animated.html#add */ add, /** * Creates a new Animated value composed by dividing the first Animated value * by the second Animated value. + * + * See http://facebook.github.io/react-native/docs/animated.html#divide */ divide, /** * Creates a new Animated value composed from two Animated values multiplied * together. + * + * See http://facebook.github.io/react-native/docs/animated.html#multiply */ multiply, /** * Creates a new Animated value that is the (non-negative) modulo of the - * provided Animated value + * provided Animated value. + * + * See http://facebook.github.io/react-native/docs/animated.html#modulo */ modulo, /** * Create a new Animated value that is limited between 2 values. It uses the - * difference between the last value so even if the value is far from the bounds - * it will start changing when the value starts getting closer again. - * (`value = clamp(value + diff, min, max)`). - * - * This is useful with scroll events, for example, to show the navbar when - * scrolling up and to hide it when scrolling down. + * difference between the last value so even if the value is far from the + * bounds it will start changing when the value starts getting closer again. + * + * See http://facebook.github.io/react-native/docs/animated.html#diffclamp */ diffClamp, /** * Starts an animation after the given delay. + * + * See http://facebook.github.io/react-native/docs/animated.html#delay */ delay, /** * Starts an array of animations in order, waiting for each to complete - * before starting the next. If the current running animation is stopped, no + * before starting the next. If the current running animation is stopped, no * following animations will be started. + * + * See http://facebook.github.io/react-native/docs/animated.html#sequence */ sequence, /** - * Starts an array of animations all at the same time. By default, if one - * of the animations is stopped, they will all be stopped. You can override + * Starts an array of animations all at the same time. By default, if one + * of the animations is stopped, they will all be stopped. You can override * this with the `stopTogether` flag. + * + * See http://facebook.github.io/react-native/docs/animated.html#parallel */ parallel, /** * Array of animations may run in parallel (overlap), but are started in * sequence with successive delays. Nice for doing trailing effects. + * + * See http://facebook.github.io/react-native/docs/animated.html#stagger */ stagger, /** - * Loops a given animation continuously, so that each time it reaches the - * end, it resets and begins again from the start. Can specify number of - * times to loop using the key `iterations` in the config. Will loop without - * blocking the UI thread if the child animation is set to `useNativeDriver: true`. - * In addition, loops can prevent `VirtualizedList`-based components from rendering - * more rows while the animation is running. You can pass `isInteraction: false` in the - * child animation config to fix this. + * Loops a given animation continuously, so that each time it reaches the + * end, it resets and begins again from the start. + * + * See http://facebook.github.io/react-native/docs/animated.html#loop */ loop, /** * Takes an array of mappings and extracts values from each arg accordingly, - * then calls `setValue` on the mapped outputs. e.g. - * - *```javascript - * onScroll={Animated.event( - * [{nativeEvent: {contentOffset: {x: this._scrollX}}}], - * {listener: (event) => console.log(event)}, // Optional async listener - * )} - * ... - * onPanResponderMove: Animated.event([ - * null, // raw event arg ignored - * {dx: this._panX}, // gestureState arg - {listener: (event, gestureState) => console.log(event, gestureState)}, // Optional async listener - * ]), - *``` - * - * Config is an object that may have the following options: - * - * - `listener`: Optional async listener. - * - `useNativeDriver`: Uses the native driver when true. Default false. + * then calls `setValue` on the mapped outputs. + * + * See http://facebook.github.io/react-native/docs/animated.html#event */ event, /** * Make any React component Animatable. Used to create `Animated.View`, etc. + * + * See http://facebook.github.io/react-native/docs/animated.html#createanimatedcomponent */ createAnimatedComponent, /** - * Imperative API to attach an animated value to an event on a view. Prefer using - * `Animated.event` with `useNativeDrive: true` if possible. + * Imperative API to attach an animated value to an event on a view. Prefer + * using `Animated.event` with `useNativeDrive: true` if possible. + * + * See http://facebook.github.io/react-native/docs/animated.html#attachnativeevent */ attachNativeEvent, /** - * Advanced imperative API for snooping on animated events that are passed in through props. Use - * values directly where possible. + * Advanced imperative API for snooping on animated events that are passed in + * through props. Use values directly where possible. + * + * See http://facebook.github.io/react-native/docs/animated.html#forkevent */ forkEvent, unforkEvent, diff --git a/Libraries/Animated/src/Easing.js b/Libraries/Animated/src/Easing.js index 7b396ea4c0564c..ddd86557c5d637 100644 --- a/Libraries/Animated/src/Easing.js +++ b/Libraries/Animated/src/Easing.js @@ -62,6 +62,10 @@ class Easing { /** * A stepping function, returns 1 for any positive value of `n`. */ + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an error + * caught by Flow 0.59 which was not caught before. Most likely, this error + * is because an exported function parameter is missing an annotation. + * Without an annotation, these parameters are uncovered by Flow. */ static step0(n) { return n > 0 ? 1 : 0; } @@ -69,6 +73,10 @@ class Easing { /** * A stepping function, returns 1 if `n` is greater than or equal to 1. */ + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an error + * caught by Flow 0.59 which was not caught before. Most likely, this error + * is because an exported function parameter is missing an annotation. + * Without an annotation, these parameters are uncovered by Flow. */ static step1(n) { return n >= 1 ? 1 : 0; } @@ -79,6 +87,10 @@ class Easing { * * http://cubic-bezier.com/#0,0,1,1 */ + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an error + * caught by Flow 0.59 which was not caught before. Most likely, this error + * is because an exported function parameter is missing an annotation. + * Without an annotation, these parameters are uncovered by Flow. */ static linear(t) { return t; } @@ -102,6 +114,10 @@ class Easing { * * http://easings.net/#easeInQuad */ + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an error + * caught by Flow 0.59 which was not caught before. Most likely, this error + * is because an exported function parameter is missing an annotation. + * Without an annotation, these parameters are uncovered by Flow. */ static quad(t) { return t * t; } @@ -112,6 +128,10 @@ class Easing { * * http://easings.net/#easeInCubic */ + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an error + * caught by Flow 0.59 which was not caught before. Most likely, this error + * is because an exported function parameter is missing an annotation. + * Without an annotation, these parameters are uncovered by Flow. */ static cubic(t) { return t * t * t; } @@ -122,7 +142,16 @@ class Easing { * n = 4: http://easings.net/#easeInQuart * n = 5: http://easings.net/#easeInQuint */ + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an error + * caught by Flow 0.59 which was not caught before. Most likely, this error + * is because an exported function parameter is missing an annotation. + * Without an annotation, these parameters are uncovered by Flow. */ static poly(n) { + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an + * error caught by Flow 0.59 which was not caught before. Most likely, this + * error is because an exported function parameter is missing an + * annotation. Without an annotation, these parameters are uncovered by + * Flow. */ return (t) => Math.pow(t, n); } @@ -131,6 +160,10 @@ class Easing { * * http://easings.net/#easeInSine */ + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an error + * caught by Flow 0.59 which was not caught before. Most likely, this error + * is because an exported function parameter is missing an annotation. + * Without an annotation, these parameters are uncovered by Flow. */ static sin(t) { return 1 - Math.cos(t * Math.PI / 2); } @@ -140,6 +173,10 @@ class Easing { * * http://easings.net/#easeInCirc */ + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an error + * caught by Flow 0.59 which was not caught before. Most likely, this error + * is because an exported function parameter is missing an annotation. + * Without an annotation, these parameters are uncovered by Flow. */ static circle(t) { return 1 - Math.sqrt(1 - t * t); } @@ -149,6 +186,10 @@ class Easing { * * http://easings.net/#easeInExpo */ + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an error + * caught by Flow 0.59 which was not caught before. Most likely, this error + * is because an exported function parameter is missing an annotation. + * Without an annotation, these parameters are uncovered by Flow. */ static exp(t) { return Math.pow(2, 10 * (t - 1)); } diff --git a/Libraries/Animated/src/nodes/AnimatedValue.js b/Libraries/Animated/src/nodes/AnimatedValue.js index ebe0210aa59a3e..03a8077e2cb3d6 100644 --- a/Libraries/Animated/src/nodes/AnimatedValue.js +++ b/Libraries/Animated/src/nodes/AnimatedValue.js @@ -68,6 +68,8 @@ function _flush(rootNode: AnimatedValue): void { * multiple properties in a synchronized fashion, but can only be driven by one * mechanism at a time. Using a new mechanism (e.g. starting a new animation, * or calling `setValue`) will stop any previous ones. + * + * See http://facebook.github.io/react-native/docs/animatedvalue.html */ class AnimatedValue extends AnimatedWithChildren { _value: number; @@ -106,6 +108,8 @@ class AnimatedValue extends AnimatedWithChildren { /** * Directly set the value. This will stop any animations running on the value * and update all the bound properties. + * + * See http://facebook.github.io/react-native/docs/animatedvalue.html#setvalue */ setValue(value: number): void { if (this._animation) { @@ -125,6 +129,8 @@ class AnimatedValue extends AnimatedWithChildren { * Sets an offset that is applied on top of whatever value is set, whether via * `setValue`, an animation, or `Animated.event`. Useful for compensating * things like the start of a pan gesture. + * + * See http://facebook.github.io/react-native/docs/animatedvalue.html#setoffset */ setOffset(offset: number): void { this._offset = offset; @@ -136,6 +142,8 @@ class AnimatedValue extends AnimatedWithChildren { /** * Merges the offset value into the base value and resets the offset to zero. * The final output of the value is unchanged. + * + * See http://facebook.github.io/react-native/docs/animatedvalue.html#flattenoffset */ flattenOffset(): void { this._value += this._offset; @@ -148,6 +156,8 @@ class AnimatedValue extends AnimatedWithChildren { /** * Sets the offset value to the base value, and resets the base value to zero. * The final output of the value is unchanged. + * + * See http://facebook.github.io/react-native/docs/animatedvalue.html#extractoffset */ extractOffset(): void { this._offset += this._value; @@ -161,6 +171,8 @@ class AnimatedValue extends AnimatedWithChildren { * Adds an asynchronous listener to the value so you can observe updates from * animations. This is useful because there is no way to * synchronously read the value because it might be driven natively. + * + * See http://facebook.github.io/react-native/docs/animatedvalue.html#addlistener */ addListener(callback: ValueListenerCallback): string { const id = String(_uniqueId++); @@ -171,6 +183,12 @@ class AnimatedValue extends AnimatedWithChildren { return id; } + /** + * Unregister a listener. The `id` param shall match the identifier + * previously returned by `addListener()`. + * + * See http://facebook.github.io/react-native/docs/animatedvalue.html#removelistener + */ removeListener(id: string): void { delete this._listeners[id]; if (this.__isNative && Object.keys(this._listeners).length === 0) { @@ -178,6 +196,11 @@ class AnimatedValue extends AnimatedWithChildren { } } + /** + * Remove all registered listeners. + * + * See http://facebook.github.io/react-native/docs/animatedvalue.html#removealllisteners + */ removeAllListeners(): void { this._listeners = {}; if (this.__isNative) { @@ -213,9 +236,11 @@ class AnimatedValue extends AnimatedWithChildren { } /** - * Stops any running animation or tracking. `callback` is invoked with the + * Stops any running animation or tracking. `callback` is invoked with the * final value after stopping the animation, which is useful for updating * state to match the animation position with layout. + * + * See http://facebook.github.io/react-native/docs/animatedvalue.html#stopanimation */ stopAnimation(callback?: ?(value: number) => void): void { this.stopTracking(); @@ -225,8 +250,10 @@ class AnimatedValue extends AnimatedWithChildren { } /** - * Stops any animation and resets the value to its original - */ + * Stops any animation and resets the value to its original. + * + * See http://facebook.github.io/react-native/docs/animatedvalue.html#resetanimation + */ resetAnimation(callback?: ?(value: number) => void): void { this.stopAnimation(callback); this._value = this._startingValue; @@ -243,6 +270,8 @@ class AnimatedValue extends AnimatedWithChildren { /** * Typically only used internally, but could be used by a custom Animation * class. + * + * See http://facebook.github.io/react-native/docs/animatedvalue.html#animate */ animate(animation: Animation, callback: ?EndCallback): void { let handle = null; diff --git a/Libraries/Animated/src/nodes/AnimatedValueXY.js b/Libraries/Animated/src/nodes/AnimatedValueXY.js index 8d26560ea6e04d..d04fe0940cc43f 100644 --- a/Libraries/Animated/src/nodes/AnimatedValueXY.js +++ b/Libraries/Animated/src/nodes/AnimatedValueXY.js @@ -22,44 +22,10 @@ type ValueXYListenerCallback = (value: {x: number, y: number}) => void; let _uniqueId = 1; /** - * 2D Value for driving 2D animations, such as pan gestures. Almost identical - * API to normal `Animated.Value`, but multiplexed. Contains two regular - * `Animated.Value`s under the hood. - * - * #### Example - * - *```javascript - * class DraggableView extends React.Component { - * constructor(props) { - * super(props); - * this.state = { - * pan: new Animated.ValueXY(), // inits to zero - * }; - * this.state.panResponder = PanResponder.create({ - * onStartShouldSetPanResponder: () => true, - * onPanResponderMove: Animated.event([null, { - * dx: this.state.pan.x, // x,y are Animated.Value - * dy: this.state.pan.y, - * }]), - * onPanResponderRelease: () => { - * Animated.spring( - * this.state.pan, // Auto-multiplexed - * {toValue: {x: 0, y: 0}} // Back to zero - * ).start(); - * }, - * }); - * } - * render() { - * return ( - * - * {this.props.children} - * - * ); - * } - * } - *``` + * 2D Value for driving 2D animations, such as pan gestures. Almost identical + * API to normal `Animated.Value`, but multiplexed. + * + * See http://facebook.github.io/react-native/docs/animatedvaluexy.html */ class AnimatedValueXY extends AnimatedWithChildren { x: AnimatedValue; @@ -86,21 +52,46 @@ class AnimatedValueXY extends AnimatedWithChildren { this._listeners = {}; } + /** + * Directly set the value. This will stop any animations running on the value + * and update all the bound properties. + * + * See http://facebook.github.io/react-native/docs/animatedvaluexy.html#setvalue + */ setValue(value: {x: number, y: number}) { this.x.setValue(value.x); this.y.setValue(value.y); } + /** + * Sets an offset that is applied on top of whatever value is set, whether + * via `setValue`, an animation, or `Animated.event`. Useful for compensating + * things like the start of a pan gesture. + * + * See http://facebook.github.io/react-native/docs/animatedvaluexy.html#setoffset + */ setOffset(offset: {x: number, y: number}) { this.x.setOffset(offset.x); this.y.setOffset(offset.y); } + /** + * Merges the offset value into the base value and resets the offset to zero. + * The final output of the value is unchanged. + * + * See http://facebook.github.io/react-native/docs/animatedvaluexy.html#flattenoffset + */ flattenOffset(): void { this.x.flattenOffset(); this.y.flattenOffset(); } + /** + * Sets the offset value to the base value, and resets the base value to + * zero. The final output of the value is unchanged. + * + * See http://facebook.github.io/react-native/docs/animatedvaluexy.html#extractoffset + */ extractOffset(): void { this.x.extractOffset(); this.y.extractOffset(); @@ -113,18 +104,39 @@ class AnimatedValueXY extends AnimatedWithChildren { }; } + /** + * Stops any animation and resets the value to its original. + * + * See http://facebook.github.io/react-native/docs/animatedvaluexy.html#resetanimation + */ resetAnimation(callback?: (value: {x: number, y: number}) => void): void { this.x.resetAnimation(); this.y.resetAnimation(); callback && callback(this.__getValue()); } + /** + * Stops any running animation or tracking. `callback` is invoked with the + * final value after stopping the animation, which is useful for updating + * state to match the animation position with layout. + * + * See http://facebook.github.io/react-native/docs/animatedvaluexy.html#stopanimation + */ stopAnimation(callback?: (value: {x: number, y: number}) => void): void { this.x.stopAnimation(); this.y.stopAnimation(); callback && callback(this.__getValue()); } + /** + * Adds an asynchronous listener to the value so you can observe updates from + * animations. This is useful because there is no way to synchronously read + * the value because it might be driven natively. + * + * Returns a string that serves as an identifier for the listener. + * + * See http://facebook.github.io/react-native/docs/animatedvaluexy.html#addlistener + */ addListener(callback: ValueXYListenerCallback): string { const id = String(_uniqueId++); const jointCallback = ({value: number}) => { @@ -137,12 +149,23 @@ class AnimatedValueXY extends AnimatedWithChildren { return id; } + /** + * Unregister a listener. The `id` param shall match the identifier + * previously returned by `addListener()`. + * + * See http://facebook.github.io/react-native/docs/animatedvaluexy.html#removelistener + */ removeListener(id: string): void { this.x.removeListener(this._listeners[id].x); this.y.removeListener(this._listeners[id].y); delete this._listeners[id]; } + /** + * Remove all registered listeners. + * + * See http://facebook.github.io/react-native/docs/animatedvaluexy.html#removealllisteners + */ removeAllListeners(): void { this.x.removeAllListeners(); this.y.removeAllListeners(); @@ -150,11 +173,9 @@ class AnimatedValueXY extends AnimatedWithChildren { } /** - * Converts `{x, y}` into `{left, top}` for use in style, e.g. - * - *```javascript - * style={this.state.anim.getLayout()} - *``` + * Converts `{x, y}` into `{left, top}` for use in style. + * + * See http://facebook.github.io/react-native/docs/animatedvaluexy.html#getlayout */ getLayout(): {[key: string]: AnimatedValue} { return { @@ -164,13 +185,9 @@ class AnimatedValueXY extends AnimatedWithChildren { } /** - * Converts `{x, y}` into a useable translation transform, e.g. - * - *```javascript - * style={{ - * transform: this.state.anim.getTranslateTransform() - * }} - *``` + * Converts `{x, y}` into a useable translation transform. + * + * See http://facebook.github.io/react-native/docs/animatedvaluexy.html#gettranslatetransform */ getTranslateTransform(): Array<{[key: string]: AnimatedValue}> { return [{translateX: this.x}, {translateY: this.y}]; diff --git a/Libraries/AppState/AppState.js b/Libraries/AppState/AppState.js index 61cfd5d0c9770b..ebdb6d54913bb4 100644 --- a/Libraries/AppState/AppState.js +++ b/Libraries/AppState/AppState.js @@ -23,66 +23,8 @@ const invariant = require('fbjs/lib/invariant'); * `AppState` can tell you if the app is in the foreground or background, * and notify you when the state changes. * - * AppState is frequently used to determine the intent and proper behavior when - * handling push notifications. - * - * ### App States - * - * - `active` - The app is running in the foreground - * - `background` - The app is running in the background. The user is either - * in another app or on the home screen - * - `inactive` - This is a state that occurs when transitioning between - * foreground & background, and during periods of inactivity such as - * entering the Multitasking view or in the event of an incoming call - * - * For more information, see - * [Apple's documentation](https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html) - * - * ### Basic Usage - * - * To see the current state, you can check `AppState.currentState`, which - * will be kept up-to-date. However, `currentState` will be null at launch - * while `AppState` retrieves it over the bridge. - * - * ``` - * import React, {Component} from 'react' - * import {AppState, Text} from 'react-native' - * - * class AppStateExample extends Component { - * - * state = { - * appState: AppState.currentState - * } - * - * componentDidMount() { - * AppState.addEventListener('change', this._handleAppStateChange); - * } - * - * componentWillUnmount() { - * AppState.removeEventListener('change', this._handleAppStateChange); - * } - * - * _handleAppStateChange = (nextAppState) => { - * if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') { - * console.log('App has come to the foreground!') - * } - * this.setState({appState: nextAppState}); - * } - * - * render() { - * return ( - * Current state is: {this.state.appState} - * ); - * } - * - * } - * ``` - * - * This example will only ever appear to say "Current state is: active" because - * the app is only visible to the user when in the `active` state, and the null - * state will happen only momentarily. + * See http://facebook.github.io/react-native/docs/appstate.html */ - class AppState extends NativeEventEmitter { _eventHandlers: Object; @@ -104,10 +46,10 @@ class AppState extends NativeEventEmitter { let eventUpdated = false; - // TODO: this is a terrible solution - in order to ensure `currentState` prop - // is up to date, we have to register an observer that updates it whenever - // the state changes, even if nobody cares. We should just deprecate the - // `currentState` property and get rid of this. + // TODO: this is a terrible solution - in order to ensure `currentState` + // prop is up to date, we have to register an observer that updates it + // whenever the state changes, even if nobody cares. We should just + // deprecate the `currentState` property and get rid of this. this.addListener( 'appStateDidChange', (appStateData) => { @@ -117,8 +59,8 @@ class AppState extends NativeEventEmitter { ); // TODO: see above - this request just populates the value of `currentState` - // when the module is first initialized. Would be better to get rid of the prop - // and expose `getCurrentAppState` method directly. + // when the module is first initialized. Would be better to get rid of the + // prop and expose `getCurrentAppState` method directly. RCTAppState.getCurrentAppState( (appStateData) => { if (!eventUpdated) { @@ -129,15 +71,16 @@ class AppState extends NativeEventEmitter { ); } - /** + // TODO: now that AppState is a subclass of NativeEventEmitter, we could + // deprecate `addEventListener` and `removeEventListener` and just use + // addListener` and `listener.remove()` directly. That will be a breaking + // change though, as both the method and event names are different + // (addListener events are currently required to be globally unique). + /** * Add a handler to AppState changes by listening to the `change` event type - * and providing the handler - * - * TODO: now that AppState is a subclass of NativeEventEmitter, we could deprecate - * `addEventListener` and `removeEventListener` and just use `addListener` and - * `listener.remove()` directly. That will be a breaking change though, as both - * the method and event names are different (addListener events are currently - * required to be globally unique). + * and providing the handler. + * + * See http://facebook.github.io/react-native/docs/appstate.html#addeventlistener */ addEventListener( type: string, @@ -163,7 +106,9 @@ class AppState extends NativeEventEmitter { } /** - * Remove a handler by passing the `change` event type and the handler + * Remove a handler by passing the `change` event type and the handler. + * + * See http://facebook.github.io/react-native/docs/appstate.html#removeeventlistener */ removeEventListener( type: string, @@ -200,9 +145,10 @@ if (__DEV__ && !RCTAppState) { } } - // This module depends on the native `RCTAppState` module. If you don't include it, - // `AppState.isAvailable` will return `false`, and any method calls will throw. - // We reassign the class variable to keep the autodoc generator happy. + // This module depends on the native `RCTAppState` module. If you don't + // include it, `AppState.isAvailable` will return `false`, and any method + // calls will throw. We reassign the class variable to keep the autodoc + // generator happy. AppState = new MissingNativeAppStateShim(); } else { AppState = new AppState(); diff --git a/Libraries/CameraRoll/CameraRoll.js b/Libraries/CameraRoll/CameraRoll.js index 66d8bd3eb2bf81..596aec7e3b2f4b 100644 --- a/Libraries/CameraRoll/CameraRoll.js +++ b/Libraries/CameraRoll/CameraRoll.js @@ -215,8 +215,8 @@ class CameraRoll { * - `speed`: {number} * - `page_info` : {object} : An object with the following shape: * - `has_next_page`: {boolean} - * - `start_cursor`: {boolean} - * - `end_cursor`: {boolean} + * - `start_cursor`: {string} + * - `end_cursor`: {string} * * Loading images: * ``` @@ -255,6 +255,10 @@ class CameraRoll { * } * ``` */ + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an error + * caught by Flow 0.59 which was not caught before. Most likely, this error + * is because an exported function parameter is missing an annotation. + * Without an annotation, these parameters are uncovered by Flow. */ static getPhotos(params) { if (__DEV__) { checkPropTypes( diff --git a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js index 47afbe2a3ed36c..2fb4517714a588 100644 --- a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js +++ b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js @@ -24,6 +24,16 @@ type ChangeEventName = $Enum<{ var _subscriptions = new Map(); +/** + * Sometimes it's useful to know whether or not the device has a screen reader + * that is currently active. The `AccessibilityInfo` API is designed for this + * purpose. You can use it to query the current state of the screen reader as + * well as to register to be notified when the state of the screen reader + * changes. + * + * See http://facebook.github.io/react-native/docs/accessibilityinfo.html + */ + var AccessibilityInfo = { fetch: function(): Promise { diff --git a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.ios.js b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.ios.js index 65f7af70d17d26..fb3ce8095c0e61 100644 --- a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.ios.js +++ b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.ios.js @@ -28,61 +28,23 @@ type ChangeEventName = $Enum<{ var _subscriptions = new Map(); /** - * Sometimes it's useful to know whether or not the device has a screen reader that is currently active. The - * `AccessibilityInfo` API is designed for this purpose. You can use it to query the current state of the - * screen reader as well as to register to be notified when the state of the screen reader changes. + * Sometimes it's useful to know whether or not the device has a screen reader + * that is currently active. The `AccessibilityInfo` API is designed for this + * purpose. You can use it to query the current state of the screen reader as + * well as to register to be notified when the state of the screen reader + * changes. * - * Here's a small example illustrating how to use `AccessibilityInfo`: - * - * ```javascript - * class ScreenReaderStatusExample extends React.Component { - * state = { - * screenReaderEnabled: false, - * } - * - * componentDidMount() { - * AccessibilityInfo.addEventListener( - * 'change', - * this._handleScreenReaderToggled - * ); - * AccessibilityInfo.fetch().done((isEnabled) => { - * this.setState({ - * screenReaderEnabled: isEnabled - * }); - * }); - * } - * - * componentWillUnmount() { - * AccessibilityInfo.removeEventListener( - * 'change', - * this._handleScreenReaderToggled - * ); - * } - * - * _handleScreenReaderToggled = (isEnabled) => { - * this.setState({ - * screenReaderEnabled: isEnabled, - * }); - * } - * - * render() { - * return ( - * - * - * The screen reader is {this.state.screenReaderEnabled ? 'enabled' : 'disabled'}. - * - * - * ); - * } - * } - * ``` + * See http://facebook.github.io/react-native/docs/accessibilityinfo.html */ var AccessibilityInfo = { /** - * Query whether a screen reader is currently enabled. Returns a promise which - * resolves to a boolean. The result is `true` when a screen reader is enabled - * and `false` otherwise. + * Query whether a screen reader is currently enabled. + * + * Returns a promise which resolves to a boolean. + * The result is `true` when a screen reader is enabledand `false` otherwise. + * + * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#fetch */ fetch: function(): Promise { return new Promise((resolve, reject) => { @@ -100,10 +62,13 @@ var AccessibilityInfo = { * to the event handler is a boolean. The boolean is `true` when a screen * reader is enabled and `false` otherwise. * - `announcementFinished`: iOS-only event. Fires when the screen reader has - * finished making an announcement. The argument to the event handler is a dictionary - * with these keys: + * finished making an announcement. The argument to the event handler is a + * dictionary with these keys: * - `announcement`: The string announced by the screen reader. - * - `success`: A boolean indicating whether the announcement was successfully made. + * - `success`: A boolean indicating whether the announcement was + * successfully made. + * + * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#addeventlistener */ addEventListener: function ( eventName: ChangeEventName, @@ -130,7 +95,11 @@ var AccessibilityInfo = { }, /** - * iOS-Only. Set accessibility focus to a react component. + * Set accessibility focus to a react component. + * + * @platform ios + * + * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#setaccessibilityfocus */ setAccessibilityFocus: function( reactTag: number @@ -139,7 +108,11 @@ var AccessibilityInfo = { }, /** - * iOS-Only. Post a string to be announced by the screen reader. + * Post a string to be announced by the screen reader. + * + * @platform ios + * + * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#announceforaccessibility */ announceForAccessibility: function( announcement: string @@ -149,6 +122,8 @@ var AccessibilityInfo = { /** * Remove an event handler. + * + * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#removeeventlistener */ removeEventListener: function( eventName: ChangeEventName, diff --git a/Libraries/Components/ActivityIndicator/ActivityIndicator.js b/Libraries/Components/ActivityIndicator/ActivityIndicator.js index c16a9f61e91908..6ea90069cdb125 100644 --- a/Libraries/Components/ActivityIndicator/ActivityIndicator.js +++ b/Libraries/Components/ActivityIndicator/ActivityIndicator.js @@ -38,45 +38,7 @@ type DefaultProps = { /** * Displays a circular loading indicator. * - * ### Example - * - * ```ReactNativeWebPlayer - * import React, { Component } from 'react' - * import { - * ActivityIndicator, - * AppRegistry, - * StyleSheet, - * Text, - * View, - * } from 'react-native' - * - * class App extends Component { - * render() { - * return ( - * - * - * - * - * - * - * ) - * } - * } - * - * const styles = StyleSheet.create({ - * container: { - * flex: 1, - * justifyContent: 'center' - * }, - * horizontal: { - * flexDirection: 'row', - * justifyContent: 'space-around', - * padding: 10 - * } - * }) - * - * AppRegistry.registerComponent('App', () => App) - * ``` + * See http://facebook.github.io/react-native/docs/activityindicator.html */ const ActivityIndicator = createReactClass({ displayName: 'ActivityIndicator', @@ -86,15 +48,21 @@ const ActivityIndicator = createReactClass({ ...ViewPropTypes, /** * Whether to show the indicator (true, the default) or hide it (false). + * + * See http://facebook.github.io/react-native/docs/activityindicator.html#animating */ animating: PropTypes.bool, /** * The foreground color of the spinner (default is gray). + * + * See http://facebook.github.io/react-native/docs/activityindicator.html#color */ color: ColorPropType, /** * Size of the indicator (default is 'small'). * Passing a number to the size prop is only supported on Android. + * + * See http://facebook.github.io/react-native/docs/activityindicator.html#size */ size: PropTypes.oneOfType([ PropTypes.oneOf([ 'small', 'large' ]), @@ -104,6 +72,8 @@ const ActivityIndicator = createReactClass({ * Whether the indicator should hide when not animating (true by default). * * @platform ios + * + * See http://facebook.github.io/react-native/docs/activityindicator.html#hideswhenstopped */ hidesWhenStopped: PropTypes.bool, }, diff --git a/Libraries/Components/CheckBox/CheckBox.android.js b/Libraries/Components/CheckBox/CheckBox.android.js index 5d2e8924cfbcfd..ef1a84730b4655 100644 --- a/Libraries/Components/CheckBox/CheckBox.android.js +++ b/Libraries/Components/CheckBox/CheckBox.android.js @@ -34,6 +34,50 @@ type DefaultProps = { * If the `value` prop is not updated, the component will continue to render * the supplied `value` prop instead of the expected result of any user actions. * + * ``` + * import React from 'react'; + * import { AppRegistry, StyleSheet, Text, View, CheckBox } from 'react-native'; + * + * export default class App extends React.Component { + * constructor(props) { + * super(props); + * this.state = { + * checked: false + * } + * } + * + * toggle() { + * this.setState(({checked}) => { + * return { + * checked: !checked + * }; + * }); + * } + * + * render() { + * const {checked} = this.state; + * return ( + * + * Checked + * + * + * ); + * } + * } + * + * const styles = StyleSheet.create({ + * container: { + * flex: 1, + * flexDirection: 'row', + * alignItems: 'center', + * justifyContent: 'center', + * }, + * }); + * + * // skip this line if using Create React Native App + * AppRegistry.registerComponent('App', () => App); + * ``` + * * @keyword checkbox * @keyword toggle */ diff --git a/Libraries/Components/Keyboard/KeyboardAvoidingView.js b/Libraries/Components/Keyboard/KeyboardAvoidingView.js index 5b90702fefd363..1f6c4848496d5d 100644 --- a/Libraries/Components/Keyboard/KeyboardAvoidingView.js +++ b/Libraries/Components/Keyboard/KeyboardAvoidingView.js @@ -43,8 +43,8 @@ type KeyboardChangeEvent = { const viewRef = 'VIEW'; /** - * It is a component to solve the common problem of views that need to move out of the way of the virtual keyboard. - * It can automatically adjust either its position or bottom padding based on the position of the keyboard. + * This is a component to solve the common problem of views that need to move out of the way of the virtual keyboard. + * It can automatically adjust either its height, position or bottom padding based on the position of the keyboard. */ const KeyboardAvoidingView = createReactClass({ displayName: 'KeyboardAvoidingView', @@ -52,6 +52,10 @@ const KeyboardAvoidingView = createReactClass({ propTypes: { ...ViewPropTypes, + /** + * Specify how the `KeyboardAvoidingView` will react to the presence of + * the keyboard. It can adjust the height, position or bottom padding of the view + */ behavior: PropTypes.oneOf(['height', 'position', 'padding']), /** @@ -61,7 +65,7 @@ const KeyboardAvoidingView = createReactClass({ /** * This is the distance between the top of the user screen and the react native view, - * may be non-zero in some use cases. + * may be non-zero in some use cases. The default value is 0. */ keyboardVerticalOffset: PropTypes.number.isRequired, }, @@ -81,7 +85,7 @@ const KeyboardAvoidingView = createReactClass({ subscriptions: ([]: Array), frame: (null: ?ViewLayout), - relativeKeyboardHeight(keyboardFrame: ScreenRect): number { + _relativeKeyboardHeight(keyboardFrame: ScreenRect): number { const frame = this.frame; if (!frame || !keyboardFrame) { return 0; @@ -94,14 +98,14 @@ const KeyboardAvoidingView = createReactClass({ return Math.max(frame.y + frame.height - keyboardY, 0); }, - onKeyboardChange(event: ?KeyboardChangeEvent) { + _onKeyboardChange(event: ?KeyboardChangeEvent) { if (!event) { this.setState({bottom: 0}); return; } const {duration, easing, endCoordinates} = event; - const height = this.relativeKeyboardHeight(endCoordinates); + const height = this._relativeKeyboardHeight(endCoordinates); if (duration && easing) { LayoutAnimation.configureNext({ @@ -115,7 +119,7 @@ const KeyboardAvoidingView = createReactClass({ this.setState({bottom: height}); }, - onLayout(event: ViewLayoutEvent) { + _onLayout(event: ViewLayoutEvent) { this.frame = event.nativeEvent.layout; }, @@ -132,12 +136,12 @@ const KeyboardAvoidingView = createReactClass({ componentWillMount() { if (Platform.OS === 'ios') { this.subscriptions = [ - Keyboard.addListener('keyboardWillChangeFrame', this.onKeyboardChange), + Keyboard.addListener('keyboardWillChangeFrame', this._onKeyboardChange), ]; } else { this.subscriptions = [ - Keyboard.addListener('keyboardDidHide', this.onKeyboardChange), - Keyboard.addListener('keyboardDidShow', this.onKeyboardChange), + Keyboard.addListener('keyboardDidHide', this._onKeyboardChange), + Keyboard.addListener('keyboardDidShow', this._onKeyboardChange), ]; } }, @@ -161,7 +165,7 @@ const KeyboardAvoidingView = createReactClass({ heightStyle = {height: this.frame.height - this.state.bottom, flex: 0}; } return ( - + {children} ); @@ -171,7 +175,7 @@ const KeyboardAvoidingView = createReactClass({ const { contentContainerStyle } = this.props; return ( - + {children} @@ -181,14 +185,14 @@ const KeyboardAvoidingView = createReactClass({ case 'padding': const paddingStyle = {paddingBottom: this.state.bottom}; return ( - + {children} ); default: return ( - + {children} ); diff --git a/Libraries/Components/SafeAreaView/SafeAreaView.ios.js b/Libraries/Components/SafeAreaView/SafeAreaView.ios.js index 35ae985a4810f1..73336990a7a6f6 100644 --- a/Libraries/Components/SafeAreaView/SafeAreaView.ios.js +++ b/Libraries/Components/SafeAreaView/SafeAreaView.ios.js @@ -24,7 +24,7 @@ type Props = ViewProps & { /** * Renders nested content and automatically applies paddings reflect the portion of the view * that is not covered by navigation bars, tab bars, toolbars, and other ancestor views. - * Moreover, and most importantly, Safe Area's paddings feflect physical limitation of the screen, + * Moreover, and most importantly, Safe Area's paddings reflect physical limitation of the screen, * such as rounded corners or camera notches (aka sensor housing area on iPhone X). */ class SafeAreaView extends React.Component { diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index 954ecc0412ac59..f10f183c08f06f 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -28,50 +28,9 @@ import type {ViewProps} from 'ViewPropTypes'; export type Props = ViewProps; /** - * The most fundamental component for building a UI, `View` is a container that supports layout with - * [flexbox](docs/flexbox.html), [style](docs/style.html), - * [some touch handling](docs/handling-touches.html), and - * [accessibility](docs/accessibility.html) controls. `View` maps directly to the - * native view equivalent on whatever platform React Native is running on, whether that is a - * `UIView`, `
`, `android.view`, etc. + * The most fundamental component for building a UI. * - * `View` is designed to be nested inside other views and can have 0 to many children of any type. - * - * This example creates a `View` that wraps two colored boxes and a text component in a row with - * padding. - * - * ```javascript - * class ViewColoredBoxesWithText extends Component { - * render() { - * return ( - * - * - * - * Hello World! - * - * ); - * } - * } - * ``` - * - * > `View`s are designed to be used with [`StyleSheet`](docs/style.html) for clarity - * > and performance, although inline styles are also supported. - * - * ### Synthetic Touch Events - * - * For `View` responder props (e.g., `onResponderMove`), the synthetic touch event passed to them - * are of the following form: - * - * - `nativeEvent` - * - `changedTouches` - Array of all touch events that have changed since the last event. - * - `identifier` - The ID of the touch. - * - `locationX` - The X position of the touch, relative to the element. - * - `locationY` - The Y position of the touch, relative to the element. - * - `pageX` - The X position of the touch, relative to the root element. - * - `pageY` - The Y position of the touch, relative to the root element. - * - `target` - The node id of the element receiving the touch event. - * - `timestamp` - A time identifier for the touch, useful for velocity calculation. - * - `touches` - Array of all current touches on the screen. + * See http://facebook.github.io/react-native/docs/view.html */ const View = createReactClass({ displayName: 'View', diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index 30cfc2020083d9..d6510a388279ba 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -44,7 +44,7 @@ export type ViewLayoutEvent = { } } -// There's no easy way to create a different type if(Platform.isTVOS): +// There's no easy way to create a different type if (Platform.isTVOS): // so we must include TVViewProps export type ViewProps = { accessible?: bool, @@ -83,15 +83,19 @@ module.exports = { ...PlatformViewPropTypes, /** - * When `true`, indicates that the view is an accessibility element. By default, - * all the touchable elements are accessible. + * When `true`, indicates that the view is an accessibility element. + * By default, all the touchable elements are accessible. + * + * See http://facebook.github.io/react-native/docs/view.html#accessible */ accessible: PropTypes.bool, /** * Overrides the text that's read by the screen reader when the user interacts - * with the element. By default, the label is constructed by traversing all the - * children and accumulating all the `Text` nodes separated by space. + * with the element. By default, the label is constructed by traversing all + * the children and accumulating all the `Text` nodes separated by space. + * + * See http://facebook.github.io/react-native/docs/view.html#accessibilitylabel */ accessibilityLabel: PropTypes.node, @@ -99,30 +103,19 @@ module.exports = { * Indicates to accessibility services to treat UI component like a * native one. Works for Android only. * - * Possible values are one of: - * - * - `'none'` - * - `'button'` - * - `'radiobutton_checked'` - * - `'radiobutton_unchecked'` - * * @platform android + * + * See http://facebook.github.io/react-native/docs/view.html#accessibilitycomponenttype */ accessibilityComponentType: PropTypes.oneOf(AccessibilityComponentTypes), /** * Indicates to accessibility services whether the user should be notified * when this view changes. Works for Android API >= 19 only. - * Possible values: - * - * - `'none'` - Accessibility services should not announce changes to this view. - * - `'polite'`- Accessibility services should announce changes to this view. - * - `'assertive'` - Accessibility services should interrupt ongoing speech to immediately announce changes to this view. - * - * See the [Android `View` docs](http://developer.android.com/reference/android/view/View.html#attr_android:accessibilityLiveRegion) - * for reference. * * @platform android + * + * See http://facebook.github.io/react-native/docs/view.html#accessibilityliveregion */ accessibilityLiveRegion: PropTypes.oneOf([ 'none', @@ -135,19 +128,9 @@ module.exports = { * fires accessibility events and if it is reported to accessibility services * that query the screen. Works for Android only. * - * Possible values: - * - * - `'auto'` - The system determines whether the view is important for accessibility - - * default (recommended). - * - `'yes'` - The view is important for accessibility. - * - `'no'` - The view is not important for accessibility. - * - `'no-hide-descendants'` - The view is not important for accessibility, - * nor are any of its descendant views. - * - * See the [Android `importantForAccessibility` docs](http://developer.android.com/reference/android/R.attr.html#importantForAccessibility) - * for reference. - * * @platform android + * + * See http://facebook.github.io/react-native/docs/view.html#importantforaccessibility */ importantForAccessibility: PropTypes.oneOf([ 'auto', @@ -162,30 +145,9 @@ module.exports = { * * You can provide one trait or an array of many traits. * - * Possible values for `AccessibilityTraits` are: - * - * - `'none'` - The element has no traits. - * - `'button'` - The element should be treated as a button. - * - `'link'` - The element should be treated as a link. - * - `'header'` - The element is a header that divides content into sections. - * - `'search'` - The element should be treated as a search field. - * - `'image'` - The element should be treated as an image. - * - `'selected'` - The element is selected. - * - `'plays'` - The element plays sound. - * - `'key'` - The element should be treated like a keyboard key. - * - `'text'` - The element should be treated as text. - * - `'summary'` - The element provides app summary information. - * - `'disabled'` - The element is disabled. - * - `'frequentUpdates'` - The element frequently changes its value. - * - `'startsMedia'` - The element starts a media session. - * - `'adjustable'` - The element allows adjustment over a range of values. - * - `'allowsDirectInteraction'` - The element allows direct touch interaction for VoiceOver users. - * - `'pageTurn'` - Informs VoiceOver that it should scroll to the next page when it finishes reading the contents of the element. - * - * See the [Accessibility guide](docs/accessibility.html#accessibilitytraits-ios) - * for more information. - * * @platform ios + * + * See http://facebook.github.io/react-native/docs/view.html#accessibilitytraits */ accessibilityTraits: PropTypes.oneOfType([ PropTypes.oneOf(AccessibilityTraits), @@ -197,22 +159,25 @@ module.exports = { * within views that are siblings of the receiver. * Default is `false`. * - * See the [Accessibility guide](docs/accessibility.html#accessibilitytraits-ios) - * for more information. - * * @platform ios + * + * See http://facebook.github.io/react-native/docs/view.html#accessibilityviewismodal */ accessibilityViewIsModal: PropTypes.bool, /** * When `accessible` is true, the system will try to invoke this function * when the user performs accessibility tap gesture. + * + * See http://facebook.github.io/react-native/docs/view.html#onaccessibilitytap */ onAccessibilityTap: PropTypes.func, /** * When `accessible` is `true`, the system will invoke this function when the * user performs the magic tap gesture. + * + * See http://facebook.github.io/react-native/docs/view.html#onmagictap */ onMagicTap: PropTypes.func, @@ -220,6 +185,8 @@ module.exports = { * Used to locate this view in end-to-end tests. * * > This disables the 'layout-only view removal' optimization for this view! + * + * See http://facebook.github.io/react-native/docs/view.html#testid */ testID: PropTypes.string, @@ -227,6 +194,8 @@ module.exports = { * Used to locate this view from native classes. * * > This disables the 'layout-only view removal' optimization for this view! + * + * See http://facebook.github.io/react-native/docs/view.html#nativeid */ nativeID: PropTypes.string, @@ -237,90 +206,111 @@ module.exports = { */ /** - * The View is now responding for touch events. This is the time to highlight and show the user - * what is happening. + * The View is now responding for touch events. This is the time to highlight + * and show the user what is happening. * - * `View.props.onResponderGrant: (event) => {}`, where `event` is a synthetic touch event as - * described above. + * `View.props.onResponderGrant: (event) => {}`, where `event` is a synthetic + * touch event as described above. + * + * See http://facebook.github.io/react-native/docs/view.html#onrespondergrant */ onResponderGrant: PropTypes.func, /** * The user is moving their finger. * - * `View.props.onResponderMove: (event) => {}`, where `event` is a synthetic touch event as - * described above. + * `View.props.onResponderMove: (event) => {}`, where `event` is a synthetic + * touch event as described above. + * + * See http://facebook.github.io/react-native/docs/view.html#onrespondermove */ onResponderMove: PropTypes.func, /** - * Another responder is already active and will not release it to that `View` asking to be - * the responder. + * Another responder is already active and will not release it to that `View` + * asking to be the responder. * - * `View.props.onResponderReject: (event) => {}`, where `event` is a synthetic touch event as - * described above. + * `View.props.onResponderReject: (event) => {}`, where `event` is a + * synthetic touch event as described above. + * + * See http://facebook.github.io/react-native/docs/view.html#onresponderreject */ onResponderReject: PropTypes.func, /** * Fired at the end of the touch. * - * `View.props.onResponderRelease: (event) => {}`, where `event` is a synthetic touch event as - * described above. + * `View.props.onResponderRelease: (event) => {}`, where `event` is a + * synthetic touch event as described above. + * + * See http://facebook.github.io/react-native/docs/view.html#onresponderrelease */ onResponderRelease: PropTypes.func, /** - * The responder has been taken from the `View`. Might be taken by other views after a call to - * `onResponderTerminationRequest`, or might be taken by the OS without asking (e.g., happens - * with control center/ notification center on iOS) + * The responder has been taken from the `View`. Might be taken by other + * views after a call to `onResponderTerminationRequest`, or might be taken + * by the OS without asking (e.g., happens with control center/ notification + * center on iOS) * - * `View.props.onResponderTerminate: (event) => {}`, where `event` is a synthetic touch event as - * described above. + * `View.props.onResponderTerminate: (event) => {}`, where `event` is a + * synthetic touch event as described above. + * + * See http://facebook.github.io/react-native/docs/view.html#onresponderterminate */ onResponderTerminate: PropTypes.func, /** - * Some other `View` wants to become responder and is asking this `View` to release its - * responder. Returning `true` allows its release. + * Some other `View` wants to become responder and is asking this `View` to + * release its responder. Returning `true` allows its release. * - * `View.props.onResponderTerminationRequest: (event) => {}`, where `event` is a synthetic touch - * event as described above. + * `View.props.onResponderTerminationRequest: (event) => {}`, where `event` + * is a synthetic touch event as described above. + * + * See http://facebook.github.io/react-native/docs/view.html#onresponderterminationrequest */ onResponderTerminationRequest: PropTypes.func, /** * Does this view want to become responder on the start of a touch? * - * `View.props.onStartShouldSetResponder: (event) => [true | false]`, where `event` is a - * synthetic touch event as described above. + * `View.props.onStartShouldSetResponder: (event) => [true | false]`, where + * `event` is a synthetic touch event as described above. + * + * See http://facebook.github.io/react-native/docs/view.html#onstartshouldsetresponder */ onStartShouldSetResponder: PropTypes.func, /** - * If a parent `View` wants to prevent a child `View` from becoming responder on a touch start, - * it should have this handler which returns `true`. + * If a parent `View` wants to prevent a child `View` from becoming responder + * on a touch start, it should have this handler which returns `true`. * - * `View.props.onStartShouldSetResponderCapture: (event) => [true | false]`, where `event` is a - * synthetic touch event as described above. + * `View.props.onStartShouldSetResponderCapture: (event) => [true | false]`, + * where `event` is a synthetic touch event as described above. + * + * See http://facebook.github.io/react-native/docs/view.html#onstartshouldsetrespondercapture */ onStartShouldSetResponderCapture: PropTypes.func, /** - * Does this view want to "claim" touch responsiveness? This is called for every touch move on - * the `View` when it is not the responder. + * Does this view want to "claim" touch responsiveness? This is called for + * every touch move on the `View` when it is not the responder. * - * `View.props.onMoveShouldSetResponder: (event) => [true | false]`, where `event` is a - * synthetic touch event as described above. + * `View.props.onMoveShouldSetResponder: (event) => [true | false]`, where + * `event` is a synthetic touch event as described above. + * + * See http://facebook.github.io/react-native/docs/view.html#onmoveshouldsetresponder */ onMoveShouldSetResponder: PropTypes.func, /** - * If a parent `View` wants to prevent a child `View` from becoming responder on a move, - * it should have this handler which returns `true`. - * - * `View.props.onMoveShouldSetResponderCapture: (event) => [true | false]`, where `event` is a - * synthetic touch event as described above. + * If a parent `View` wants to prevent a child `View` from becoming responder + * on a move, it should have this handler which returns `true`. + * + * `View.props.onMoveShouldSetResponderCapture: (event) => [true | false]`, + * where `event` is a synthetic touch event as described above. + * + * See http://facebook.github.io/react-native/docs/view.html#onMoveShouldsetrespondercapture */ onMoveShouldSetResponderCapture: PropTypes.func, @@ -329,12 +319,11 @@ module.exports = { * Typical interface guidelines recommend touch targets that are at least * 30 - 40 points/density-independent pixels. * - * For example, if a touchable view has a height of 20 the touchable height can be extended to - * 40 with `hitSlop={{top: 10, bottom: 10, left: 0, right: 0}}` - * * > The touch area never extends past the parent view bounds and the Z-index * > of sibling views always takes precedence if a touch hits two overlapping * > views. + * + * See http://facebook.github.io/react-native/docs/view.html#hitslop */ hitSlop: EdgeInsetsPropType, @@ -346,41 +335,15 @@ module.exports = { * This event is fired immediately once the layout has been calculated, but * the new layout may not yet be reflected on the screen at the time the * event is received, especially if a layout animation is in progress. + * + * See http://facebook.github.io/react-native/docs/view.html#onlayout */ onLayout: PropTypes.func, /** * Controls whether the `View` can be the target of touch events. - * - * - `'auto'`: The View can be the target of touch events. - * - `'none'`: The View is never the target of touch events. - * - `'box-none'`: The View is never the target of touch events but it's - * subviews can be. It behaves like if the view had the following classes - * in CSS: - * ``` - * .box-none { - * pointer-events: none; - * } - * .box-none * { - * pointer-events: all; - * } - * ``` - * - `'box-only'`: The view can be the target of touch events but it's - * subviews cannot be. It behaves like if the view had the following classes - * in CSS: - * ``` - * .box-only { - * pointer-events: all; - * } - * .box-only * { - * pointer-events: none; - * } - * ``` - * > Since `pointerEvents` does not affect layout/appearance, and we are - * > already deviating from the spec by adding additional modes, we opt to not - * > include `pointerEvents` on `style`. On some platforms, we would need to - * > implement it as a `className` anyways. Using `style` or not is an - * > implementation detail of the platform. + * + * See http://facebook.github.io/react-native/docs/view.html#pointerevents */ pointerEvents: PropTypes.oneOf([ 'box-none', @@ -388,6 +351,10 @@ module.exports = { 'box-only', 'auto', ]), + + /** + * See http://facebook.github.io/react-native/docs/style.html + */ style: stylePropType, /** @@ -397,6 +364,8 @@ module.exports = { * view that contains many subviews that extend outside its bound. The * subviews must also have `overflow: hidden`, as should the containing view * (or one of its superviews). + * + * See http://facebook.github.io/react-native/docs/view.html#removeclippedsubviews */ removeClippedSubviews: PropTypes.bool, @@ -404,31 +373,18 @@ module.exports = { * Whether this `View` should render itself (and all of its children) into a * single hardware texture on the GPU. * - * On Android, this is useful for animations and interactions that only - * modify opacity, rotation, translation, and/or scale: in those cases, the - * view doesn't have to be redrawn and display lists don't need to be - * re-executed. The texture can just be re-used and re-composited with - * different parameters. The downside is that this can use up limited video - * memory, so this prop should be set back to false at the end of the - * interaction/animation. - * * @platform android + * + * See http://facebook.github.io/react-native/docs/view.html#rendertohardwaretextureandroid */ renderToHardwareTextureAndroid: PropTypes.bool, /** * Whether this `View` should be rendered as a bitmap before compositing. * - * On iOS, this is useful for animations and interactions that do not - * modify this component's dimensions nor its children; for example, when - * translating the position of a static view, rasterization allows the - * renderer to reuse a cached bitmap of a static view and quickly composite - * it during each frame. - * - * Rasterization incurs an off-screen drawing pass and the bitmap consumes - * memory. Test and measure when using this property. - * * @platform ios + * + * See http://facebook.github.io/react-native/docs/view.html#shouldrasterizeios */ shouldRasterizeIOS: PropTypes.bool, @@ -439,29 +395,18 @@ module.exports = { * ensure that this `View` exists in the native view hierarchy. * * @platform android + * + * See http://facebook.github.io/react-native/docs/view.html#collapsable */ collapsable: PropTypes.bool, /** - * Whether this `View` needs to rendered offscreen and composited with an alpha - * in order to preserve 100% correct colors and blending behavior. The default - * (`false`) falls back to drawing the component and its children with an alpha - * applied to the paint used to draw each element instead of rendering the full - * component offscreen and compositing it back with an alpha value. This default - * may be noticeable and undesired in the case where the `View` you are setting - * an opacity on has multiple overlapping elements (e.g. multiple overlapping - * `View`s, or text and a background). - * - * Rendering offscreen to preserve correct alpha behavior is extremely - * expensive and hard to debug for non-native developers, which is why it is - * not turned on by default. If you do need to enable this property for an - * animation, consider combining it with renderToHardwareTextureAndroid if the - * view **contents** are static (i.e. it doesn't need to be redrawn each frame). - * If that property is enabled, this View will be rendered off-screen once, - * saved in a hardware texture, and then composited onto the screen with an alpha - * each frame without having to switch rendering targets on the GPU. + * Whether this `View` needs to rendered offscreen and composited with an + * alpha in order to preserve 100% correct colors and blending behavior. * * @platform android + * + * See http://facebook.github.io/react-native/docs/view.html#needsoffscreenalphacompositing */ needsOffscreenAlphaCompositing: PropTypes.bool, }; diff --git a/Libraries/Core/InitializeCore.js b/Libraries/Core/InitializeCore.js index 90e9360cb90919..2e3821410e3af1 100644 --- a/Libraries/Core/InitializeCore.js +++ b/Libraries/Core/InitializeCore.js @@ -101,6 +101,7 @@ if (!global.process.env.NODE_ENV) { // Setup the Systrace profiling hooks if necessary if (global.__RCTProfileIsProfiling) { const Systrace = require('Systrace'); + Systrace.installReactHook(true); Systrace.setEnabled(true); } @@ -206,16 +207,17 @@ BatchedBridge.registerLazyCallableModule('RCTDeviceEventEmitter', () => require( BatchedBridge.registerLazyCallableModule('RCTNativeAppEventEmitter', () => require('RCTNativeAppEventEmitter')); BatchedBridge.registerLazyCallableModule('PerformanceLogger', () => require('PerformanceLogger')); -global.fetchBundle = function( - bundleId: number, +global.fetchSegment = function( + segmentId: number, callback: (?Error) => void, ) { - const {BundleFetcher} = require('NativeModules'); - if (!BundleFetcher) { - throw new Error('BundleFetcher is missing'); + const {SegmentFetcher} = require('NativeModules'); + if (!SegmentFetcher) { + throw new Error('SegmentFetcher is missing. Please ensure that it is ' + + 'included as a NativeModule.'); } - BundleFetcher.fetchBundle(bundleId, (errorObject: ?{message: string, code: string}) => { + SegmentFetcher.fetchSegment(segmentId, (errorObject: ?{message: string, code: string}) => { if (errorObject) { const error = new Error(errorObject.message); (error: any).code = errorObject.code; diff --git a/Libraries/Experimental/SwipeableRow/SwipeableListViewDataSource.js b/Libraries/Experimental/SwipeableRow/SwipeableListViewDataSource.js index 506b434160d98e..4fc44549688e2b 100644 --- a/Libraries/Experimental/SwipeableRow/SwipeableListViewDataSource.js +++ b/Libraries/Experimental/SwipeableRow/SwipeableListViewDataSource.js @@ -88,6 +88,16 @@ class SwipeableListViewDataSource { return Object.keys(this._dataBlob)[0]; } + getLastRowID(): ?string { + if (this.rowIdentities && this.rowIdentities.length) { + const lastSection = this.rowIdentities[this.rowIdentities.length - 1]; + if (lastSection && lastSection.length) { + return lastSection[lastSection.length - 1]; + } + } + return Object.keys(this._dataBlob)[this._dataBlob.length - 1]; + } + setOpenRowID(rowID: string): SwipeableListViewDataSource { this._previousOpenRowID = this._openRowID; this._openRowID = rowID; diff --git a/Libraries/Experimental/WindowedListView.js b/Libraries/Experimental/WindowedListView.js index 05e16ee7bf63c6..afbff25a42ba75 100644 --- a/Libraries/Experimental/WindowedListView.js +++ b/Libraries/Experimental/WindowedListView.js @@ -176,6 +176,11 @@ class WindowedListView extends React.Component { maxNumToRender: 30, numToRenderAhead: 10, viewablePercentThreshold: 50, + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an + * error caught by Flow 0.59 which was not caught before. Most likely, this + * error is because an exported function parameter is missing an + * annotation. Without an annotation, these parameters are uncovered by + * Flow. */ renderScrollComponent: (props) => , disableIncrementalRendering: false, recomputeRowsBatchingPeriod: 10, // This should capture most events that happen within a frame diff --git a/Libraries/Image/AssetSourceResolver.js b/Libraries/Image/AssetSourceResolver.js index 0371dbad642c8c..4b4e4117f35cba 100644 --- a/Libraries/Image/AssetSourceResolver.js +++ b/Libraries/Image/AssetSourceResolver.js @@ -50,14 +50,21 @@ function getAssetPathInDrawableFolder(asset): string { class AssetSourceResolver { serverUrl: ?string; - // where the bundle is being run from - bundleUrl: ?string; + // where the jsbundle is being run from + jsbundleUrl: ?string; + // where the embedded bundle in the app is stored + embeddedBundleUrl: ?string; // the asset to resolve asset: PackagerAsset; - constructor(serverUrl: ?string, bundleUrl: ?string, asset: PackagerAsset) { + constructor(serverUrl: ?string, + jsbundleUrl: ?string, + embeddedBundleUrl: ?string, + asset: PackagerAsset + ) { this.serverUrl = serverUrl; - this.bundleUrl = bundleUrl; + this.jsbundleUrl = jsbundleUrl; + this.embeddedBundleUrl = embeddedBundleUrl; this.asset = asset; } @@ -66,7 +73,11 @@ class AssetSourceResolver { } isLoadedFromFileSystem(): boolean { - return !!this.bundleUrl; + return !!(this.jsbundleUrl && this.jsbundleUrl.startsWith('file://')); + } + + canLoadFromEmbeddedBundledLocation(): boolean { + return !!this.embeddedBundleUrl; } defaultAsset(): ResolvedAssetSource { @@ -79,7 +90,7 @@ class AssetSourceResolver { this.drawableFolderInBundle() : this.resourceIdentifierWithoutScale(); } else { - return this.scaledAssetURLInBundle(); + return this.scaledAssetURLNearBundle(); } } @@ -107,8 +118,17 @@ class AssetSourceResolver { * Resolves to where the bundle is running from, with a scaled asset filename * E.g. 'file:///sdcard/bundle/assets/AwesomeModule/icon@2x.png' */ - scaledAssetURLInBundle(): ResolvedAssetSource { - const path = this.bundleUrl || 'file://'; + scaledAssetURLNearBundle(): ResolvedAssetSource { + const path = this.jsbundleUrl || 'file://'; + return this.fromSource(path + getScaledAssetPath(this.asset)); + } + + /** + * Resolves to the asset that was bundled with the app, with a scaled asset filename + * E.g. 'file:///sdcard/bundle/assets/AwesomeModule/icon@2x.png' + */ + scaledAssetURLInEmbeddedBundleUrl(): ResolvedAssetSource { + const path = this.embeddedBundleUrl || 'file://'; return this.fromSource(path + getScaledAssetPath(this.asset)); } @@ -129,7 +149,7 @@ class AssetSourceResolver { * E.g. 'file:///sdcard/AwesomeModule/drawable-mdpi/icon.png' */ drawableFolderInBundle(): ResolvedAssetSource { - const path = this.bundleUrl || 'file://'; + const path = this.jsbundleUrl || 'file://'; return this.fromSource( path + getAssetPathInDrawableFolder(this.asset) ); diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index b953d085515074..bdea83b20b92c8 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -274,7 +274,7 @@ var Image = createReactClass({ } if (this.props.children) { - throw new Error('The component cannot contain children. If you want to render content on top of the image, consider using aboslute positioning.'); + throw new Error('The component cannot contain children. If you want to render content on top of the image, consider using the component or absolute positioning.'); } if (source && (source.uri || Array.isArray(source))) { diff --git a/Libraries/Image/Image.ios.js b/Libraries/Image/Image.ios.js index 6a5f826027e1d7..a9c4a8f8fd9c8d 100644 --- a/Libraries/Image/Image.ios.js +++ b/Libraries/Image/Image.ios.js @@ -374,7 +374,7 @@ const Image = createReactClass({ } if (this.props.children) { - throw new Error('The component cannot contain children. If you want to render content on top of the image, consider using aboslute positioning.'); + throw new Error('The component cannot contain children. If you want to render content on top of the image, consider using the component or absolute positioning.'); } return ( diff --git a/Libraries/Image/resolveAssetSource.js b/Libraries/Image/resolveAssetSource.js index c2f4dba12ef5f4..bb46279af4df3c 100644 --- a/Libraries/Image/resolveAssetSource.js +++ b/Libraries/Image/resolveAssetSource.js @@ -19,45 +19,53 @@ const NativeModules = require('NativeModules'); import type { ResolvedAssetSource } from 'AssetSourceResolver'; -let _customSourceTransformer, _serverURL, _bundleSourceURL; +let _customSourceTransformer, _serverURL, _scriptURL, _embeddedBundleURL; function getDevServerURL(): ?string { if (_serverURL === undefined) { var scriptURL = NativeModules.SourceCode.scriptURL; var match = scriptURL && scriptURL.match(/^https?:\/\/.*?\//); if (match) { - // Bundle was loaded from network + // jsBundle was loaded from network _serverURL = match[0]; } else { - // Bundle was loaded from file + // jsBundle was loaded from file _serverURL = null; } } return _serverURL; } -function getBundleSourceURL(): ?string { - if (_bundleSourceURL === undefined) { - const scriptURL = NativeModules.SourceCode.scriptURL; - if (!scriptURL) { - // scriptURL is falsy, we have nothing to go on here - _bundleSourceURL = null; - return _bundleSourceURL; - } +function _coerceLocalScriptURL(scriptURL: ?string): ?string { + if (scriptURL) { if (scriptURL.startsWith('assets://')) { // android: running from within assets, no offline path to use - _bundleSourceURL = null; - return _bundleSourceURL; + return null; } - _bundleSourceURL = scriptURL.substring(0, scriptURL.lastIndexOf('/') + 1); - if (!scriptURL.startsWith('file://')) { + scriptURL = scriptURL.substring(0, scriptURL.lastIndexOf('/') + 1); + if (!scriptURL.includes('://')) { // Add file protocol in case we have an absolute file path and not a URL. // This shouldn't really be necessary. scriptURL should be a URL. - _bundleSourceURL = 'file://' + _bundleSourceURL; + scriptURL = 'file://' + scriptURL; } } + return scriptURL; +} + +function getScriptURL(): ?string { + if (_scriptURL === undefined) { + const scriptURL = NativeModules.SourceCode.scriptURL; + _scriptURL = _coerceLocalScriptURL(scriptURL); + } + return _scriptURL; +} - return _bundleSourceURL; +function getEmbeddedBundledURL(): ?string { + if (_embeddedBundleURL === undefined) { + const scriptURL = NativeModules.SourceCode.embeddedBundleURL; + _embeddedBundleURL = _coerceLocalScriptURL(scriptURL); + } + return _embeddedBundleURL; } function setCustomSourceTransformer( @@ -80,7 +88,12 @@ function resolveAssetSource(source: any): ?ResolvedAssetSource { return null; } - const resolver = new AssetSourceResolver(getDevServerURL(), getBundleSourceURL(), asset); + const resolver = new AssetSourceResolver( + getDevServerURL(), + getScriptURL(), + getEmbeddedBundledURL(), + asset, + ); if (_customSourceTransformer) { return _customSourceTransformer(resolver); } diff --git a/Libraries/Inspector/ElementProperties.js b/Libraries/Inspector/ElementProperties.js index 1aaaf65127e630..880dcb84d173b8 100644 --- a/Libraries/Inspector/ElementProperties.js +++ b/Libraries/Inspector/ElementProperties.js @@ -25,9 +25,11 @@ const flattenStyle = require('flattenStyle'); const mapWithSeparator = require('mapWithSeparator'); const openFileInEditor = require('openFileInEditor'); +import type {StyleObj} from 'StyleSheetTypes'; + class ElementProperties extends React.Component<{ hierarchy: Array<$FlowFixMe>, - style?: Object | Array<$FlowFixMe> | number, + style?: StyleObj, source?: { fileName?: string, lineNumber?: number, diff --git a/Libraries/Lists/ListView/__mocks__/ListViewMock.js b/Libraries/Lists/ListView/__mocks__/ListViewMock.js index 2c27303d7e7294..732dc5e1caf208 100644 --- a/Libraries/Lists/ListView/__mocks__/ListViewMock.js +++ b/Libraries/Lists/ListView/__mocks__/ListViewMock.js @@ -19,6 +19,11 @@ const StaticRenderer = require('StaticRenderer'); class ListViewMock extends React.Component<$FlowFixMeProps> { static latestRef: ?ListViewMock; static defaultProps = { + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an + * error caught by Flow 0.59 which was not caught before. Most likely, this + * error is because an exported function parameter is missing an + * annotation. Without an annotation, these parameters are uncovered by + * Flow. */ renderScrollComponent: props => , }; componentDidMount() { diff --git a/Libraries/Lists/ViewabilityHelper.js b/Libraries/Lists/ViewabilityHelper.js index 05f1a1bc79b435..858bb4d07e2d8a 100644 --- a/Libraries/Lists/ViewabilityHelper.js +++ b/Libraries/Lists/ViewabilityHelper.js @@ -74,7 +74,6 @@ export type ViewabilityConfig = {| class ViewabilityHelper { _config: ViewabilityConfig; _hasInteracted: boolean = false; - _lastUpdateTime: number = 0; _timers: Set = new Set(); _viewableIndices: Array = []; _viewableItems: Map = new Map(); @@ -170,15 +169,11 @@ class ViewabilityHelper { }) => void, renderRange?: {first: number, last: number}, // Optional optimization to reduce the scan size ): void { - const updateTime = Date.now(); - if (this._lastUpdateTime === 0 && itemCount > 0 && getFrameMetrics(0)) { - // Only count updates after the first item is rendered and has a frame. - this._lastUpdateTime = updateTime; - } - const updateElapsed = this._lastUpdateTime - ? updateTime - this._lastUpdateTime - : 0; - if (this._config.waitForInteraction && !this._hasInteracted) { + if ( + (this._config.waitForInteraction && !this._hasInteracted) || + itemCount === 0 || + !getFrameMetrics(0) + ) { return; } let viewableIndices = []; @@ -200,11 +195,7 @@ class ViewabilityHelper { return; } this._viewableIndices = viewableIndices; - this._lastUpdateTime = updateTime; - if ( - this._config.minimumViewTime && - updateElapsed < this._config.minimumViewTime - ) { + if (this._config.minimumViewTime) { const handle = setTimeout(() => { this._timers.delete(handle); this._onUpdateSync( diff --git a/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap index 7007b25c7e7551..331532e0f4c84b 100644 --- a/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap @@ -38,13 +38,13 @@ exports[`FlatList renders all the bells and whistles 1`] = ` onEndReachedThreshold={2} onLayout={[Function]} onMomentumScrollEnd={[Function]} - onRefresh={[Function]} + onRefresh={[MockFunction]} onScroll={[Function]} onScrollBeginDrag={[Function]} onScrollEndDrag={[Function]} refreshControl={ diff --git a/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap index cd0e25eeb4cba0..3b37aae1bed095 100644 --- a/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap @@ -278,14 +278,14 @@ exports[`SectionList renders all the bells and whistles 1`] = ` onEndReachedThreshold={2} onLayout={[Function]} onMomentumScrollEnd={[Function]} - onRefresh={[Function]} + onRefresh={[MockFunction]} onScroll={[Function]} onScrollBeginDrag={[Function]} onScrollEndDrag={[Function]} onViewableItemsChanged={undefined} refreshControl={ diff --git a/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap index 3c683de778bb1d..a363a2a9a42a67 100644 --- a/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap @@ -441,13 +441,13 @@ exports[`VirtualizedList renders all the bells and whistles 1`] = ` onEndReachedThreshold={2} onLayout={[Function]} onMomentumScrollEnd={[Function]} - onRefresh={[Function]} + onRefresh={[MockFunction]} onScroll={[Function]} onScrollBeginDrag={[Function]} onScrollEndDrag={[Function]} refreshControl={ diff --git a/Libraries/Network/RCTNetworking.mm b/Libraries/Network/RCTNetworking.mm index 248dfce227c3d1..402620b0f43fca 100644 --- a/Libraries/Network/RCTNetworking.mm +++ b/Libraries/Network/RCTNetworking.mm @@ -402,8 +402,14 @@ + (NSString *)decodeTextData:(NSData *)data fromResponse:(NSURLResponse *)respon if (inputCarryData) { NSUInteger encodedResponseLength = [encodedResponse dataUsingEncoding:encoding].length; - NSData *newCarryData = [currentCarryData subdataWithRange:NSMakeRange(encodedResponseLength, currentCarryData.length - encodedResponseLength)]; - [inputCarryData setData:newCarryData]; + + // Ensure a valid subrange exists within currentCarryData + if (currentCarryData.length >= encodedResponseLength) { + NSData *newCarryData = [currentCarryData subdataWithRange:NSMakeRange(encodedResponseLength, currentCarryData.length - encodedResponseLength)]; + [inputCarryData setData:newCarryData]; + } else { + [inputCarryData setLength:0]; + } } return encodedResponse; diff --git a/Libraries/Performance/Systrace.js b/Libraries/Performance/Systrace.js index 489576bb0d023f..44a156a53b65ef 100644 --- a/Libraries/Performance/Systrace.js +++ b/Libraries/Performance/Systrace.js @@ -208,7 +208,7 @@ const Systrace = { _asyncCookie++; profileName = typeof profileName === 'function' ? profileName() : profileName; - global.nativeTraceBeginAsyncSection(TRACE_TAG_REACT_APPS, profileName, cookie, 0); + global.nativeTraceBeginAsyncSection(TRACE_TAG_REACT_APPS, profileName, cookie); } return cookie; }, @@ -217,7 +217,7 @@ const Systrace = { if (_enabled) { profileName = typeof profileName === 'function' ? profileName() : profileName; - global.nativeTraceEndAsyncSection(TRACE_TAG_REACT_APPS, profileName, cookie, 0); + global.nativeTraceEndAsyncSection(TRACE_TAG_REACT_APPS, profileName, cookie); } }, diff --git a/Libraries/RCTTest/RCTTestRunner.h b/Libraries/RCTTest/RCTTestRunner.h index b1edad6a201811..9a50e94b2c9f13 100644 --- a/Libraries/RCTTest/RCTTestRunner.h +++ b/Libraries/RCTTest/RCTTestRunner.h @@ -32,10 +32,11 @@ * Use the RCTInitRunnerForApp macro for typical usage. See FBSnapshotTestCase.h for more information * on how to configure the snapshotting system. */ -#define RCTInitRunnerForApp(app__, moduleProvider__) \ +#define RCTInitRunnerForApp(app__, moduleProvider__, scriptURL__) \ [[RCTTestRunner alloc] initWithApp:(app__) \ referenceDirectory:@FB_REFERENCE_IMAGE_DIR \ - moduleProvider:(moduleProvider__)] + moduleProvider:(moduleProvider__) \ + scriptURL: scriptURL__] @protocol RCTBridgeModule; @class RCTBridge; @@ -68,7 +69,8 @@ */ - (instancetype)initWithApp:(NSString *)app referenceDirectory:(NSString *)referenceDirectory - moduleProvider:(RCTBridgeModuleListProvider)block NS_DESIGNATED_INITIALIZER; + moduleProvider:(RCTBridgeModuleListProvider)block + scriptURL:(NSURL *)scriptURL NS_DESIGNATED_INITIALIZER; /** * Simplest runTest function simply mounts the specified JS module with no diff --git a/Libraries/RCTTest/RCTTestRunner.m b/Libraries/RCTTest/RCTTestRunner.m index cb79087c321da7..836d7bb7762117 100644 --- a/Libraries/RCTTest/RCTTestRunner.m +++ b/Libraries/RCTTest/RCTTestRunner.m @@ -31,6 +31,7 @@ @implementation RCTTestRunner - (instancetype)initWithApp:(NSString *)app referenceDirectory:(NSString *)referenceDirectory moduleProvider:(RCTBridgeModuleListProvider)block + scriptURL:(NSURL *)scriptURL { RCTAssertParam(app); RCTAssertParam(referenceDirectory); @@ -46,7 +47,12 @@ - (instancetype)initWithApp:(NSString *)app _testController.referenceImagesDirectory = referenceDirectory; _moduleProvider = [block copy]; _appPath = app; - [self updateScript]; + + if (scriptURL != nil) { + _scriptURL = scriptURL; + } else { + [self updateScript]; + } } return self; } diff --git a/Libraries/ReactNative/AppRegistry.js b/Libraries/ReactNative/AppRegistry.js index e2decabdc008b6..c7d0ebe6d18d9c 100644 --- a/Libraries/ReactNative/AppRegistry.js +++ b/Libraries/ReactNative/AppRegistry.js @@ -58,30 +58,9 @@ let componentProviderInstrumentationHook: ComponentProviderInstrumentationHook = let wrapperComponentProvider: ?WrapperComponentProvider; /** - * - * - * `AppRegistry` is the JS entry point to running all React Native apps. App - * root components should register themselves with - * `AppRegistry.registerComponent`, then the native system can load the bundle - * for the app and then actually run the app when it's ready by invoking - * `AppRegistry.runApplication`. - * - * To "stop" an application when a view should be destroyed, call - * `AppRegistry.unmountApplicationComponentAtRootTag` with the tag that was - * passed into `runApplication`. These should always be used as a pair. - * - * `AppRegistry` should be `require`d early in the `require` sequence to make - * sure the JS execution environment is setup before other modules are - * `require`d. + * `AppRegistry` is the JavaScript entry point to running all React Native apps. + * + * See http://facebook.github.io/react-native/docs/appregistry.html */ const AppRegistry = { setWrapperComponentProvider(provider: WrapperComponentProvider) { @@ -108,6 +87,11 @@ const AppRegistry = { }); }, + /** + * Registers an app's root component. + * + * See http://facebook.github.io/react-native/docs/appregistry.html#registercomponent + */ registerComponent( appKey: string, componentProvider: ComponentProvider, @@ -169,6 +153,11 @@ const AppRegistry = { componentProviderInstrumentationHook = hook; }, + /** + * Loads the JavaScript bundle and runs the app. + * + * See http://facebook.github.io/react-native/docs/appregistry.html#runapplication + */ runApplication(appKey: string, appParameters: any): void { const msg = 'Running application "' + @@ -207,16 +196,19 @@ const AppRegistry = { runnables[appKey].run(appParameters); }, + /** + * Stops an application when a view should be destroyed. + * + * See http://facebook.github.io/react-native/docs/appregistry.html#unmountapplicationcomponentatroottag + */ unmountApplicationComponentAtRootTag(rootTag: number): void { ReactNative.unmountComponentAtNodeAndRemoveContainer(rootTag); }, /** * Register a headless task. A headless task is a bit of code that runs without a UI. - * @param taskKey the key associated with this task - * @param task a promise returning function that takes some data passed from the native side as - * the only argument; when the promise is resolved or rejected the native side is - * notified of this event and it may decide to destroy the JS context. + * + * See http://facebook.github.io/react-native/docs/appregistry.html#registerheadlesstask */ registerHeadlessTask(taskKey: string, task: TaskProvider): void { if (tasks.has(taskKey)) { @@ -230,9 +222,7 @@ const AppRegistry = { /** * Only called from native code. Starts a headless task. * - * @param taskId the native id for this task instance to keep track of its execution - * @param taskKey the key for the task to start - * @param data the data to pass to the task + * See http://facebook.github.io/react-native/docs/appregistry.html#startheadlesstask */ startHeadlessTask(taskId: number, taskKey: string, data: any): void { const taskProvider = tasks.get(taskKey); diff --git a/Libraries/ReactNative/renderApplication.js b/Libraries/ReactNative/renderApplication.js index a1e96f30dbb3ca..6d6783ec2b6a4e 100644 --- a/Libraries/ReactNative/renderApplication.js +++ b/Libraries/ReactNative/renderApplication.js @@ -30,12 +30,32 @@ function renderApplication( ) { invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag); - ReactNative.render( + let renderable = ( - , - rootTag, + ); + + // If the root component is async, the user probably wants the initial render + // to be async also. To do this, wrap AppContainer with an async marker. + // For more info see https://fb.me/is-component-async + if ( + RootComponent.prototype != null && + RootComponent.prototype.unstable_isAsyncReactComponent === true + ) { + // $FlowFixMe This is not yet part of the official public API + class AppContainerAsyncWrapper extends React.unstable_AsyncComponent { + render() { + return this.props.children; + } + } + + renderable = ( + {renderable} + ); + } + + ReactNative.render(renderable, rootTag); } module.exports = renderApplication; diff --git a/Libraries/ReactNative/requireNativeComponent.js b/Libraries/ReactNative/requireNativeComponent.js index 7a638afa8535f4..03fff7e0bceb45 100644 --- a/Libraries/ReactNative/requireNativeComponent.js +++ b/Libraries/ReactNative/requireNativeComponent.js @@ -55,11 +55,23 @@ function requireNativeComponent( componentInterface?: ?ComponentInterface, extraConfig?: ?{nativeOnly?: Object}, ): React$ComponentType | string { - function attachDefaultEventTypes(viewConfig) { + function attachDefaultEventTypes(viewConfig: any) { if (Platform.OS === 'android') { // This is supported on Android platform only, // as lazy view managers discovery is Android-specific. - viewConfig = merge(viewConfig, UIManager.getDefaultEventTypes()); + if (UIManager.ViewManagerNames) { + // Lazy view managers enabled. + viewConfig = merge(viewConfig, UIManager.getDefaultEventTypes()); + } else { + viewConfig.bubblingEventTypes = merge( + viewConfig.bubblingEventTypes, + UIManager.genericBubblingEventTypes, + ); + viewConfig.directEventTypes = merge( + viewConfig.directEventTypes, + UIManager.genericDirectEventTypes, + ); + } } } diff --git a/Libraries/Renderer/REVISION b/Libraries/Renderer/REVISION index 1caaa5f390ba1b..75daa905df5b11 100644 --- a/Libraries/Renderer/REVISION +++ b/Libraries/Renderer/REVISION @@ -1 +1 @@ -589c0a25dfa18c2090549cc6f5b626d69ea53c2a \ No newline at end of file +2d23a4563ef2bec7d90c4a7edff2657c890b4334 \ No newline at end of file diff --git a/Libraries/Renderer/ReactNativeFiber-dev.js b/Libraries/Renderer/ReactNativeFiber-dev.js deleted file mode 100644 index 7de81ef95f3c93..00000000000000 --- a/Libraries/Renderer/ReactNativeFiber-dev.js +++ /dev/null @@ -1,3997 +0,0 @@ -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @noflow - * @providesModule ReactNativeFiber-dev - */ -"use strict"; - -__DEV__ && function() { - var invariant = require("fbjs/lib/invariant"), require$$0 = require("fbjs/lib/warning"), ExceptionsManager = require("ExceptionsManager"), emptyObject = require("fbjs/lib/emptyObject"), react = require("react"), checkPropTypes = require("prop-types/checkPropTypes"), shallowEqual = require("fbjs/lib/shallowEqual"), deepDiffer = require("deepDiffer"), flattenStyle = require("flattenStyle"), TextInputState = require("TextInputState"), UIManager = require("UIManager"), deepFreezeAndThrowOnMutationInDev = require("deepFreezeAndThrowOnMutationInDev"); - require("InitializeCore"); - var RCTEventEmitter = require("RCTEventEmitter"), emptyFunction = require("fbjs/lib/emptyFunction"), defaultShowDialog = function(capturedError) { - return !0; - }, showDialog = defaultShowDialog; - function logCapturedError(capturedError) { - if (!1 !== showDialog(capturedError)) { - var componentName = (capturedError.error, capturedError.componentName), componentStack = capturedError.componentStack, errorBoundaryName = capturedError.errorBoundaryName, errorBoundaryFound = capturedError.errorBoundaryFound, willRetry = capturedError.willRetry, componentNameMessage = componentName ? "The above error occurred in the <" + componentName + "> component:" : "The above error occurred in one of your React components:", errorBoundaryMessage = void 0; - errorBoundaryMessage = errorBoundaryFound && errorBoundaryName ? willRetry ? "React will try to recreate this component tree from scratch " + "using the error boundary you provided, " + errorBoundaryName + "." : "This error was initially handled by the error boundary " + errorBoundaryName + ".\n" + "Recreating the tree from scratch failed so React will unmount the tree." : "Consider adding an error boundary to your tree to customize error handling behavior.\n" + "You can learn more about error boundaries at https://fb.me/react-error-boundaries."; - var combinedMessage = "" + componentNameMessage + componentStack + "\n\n" + errorBoundaryMessage; - console.error(combinedMessage); - } - } - var injection = { - injectDialog: function(fn) { - invariant(showDialog === defaultShowDialog, "The custom dialog was already injected."), - invariant("function" == typeof fn, "Injected showDialog() must be a function."), - showDialog = fn; - } - }, logCapturedError_1 = logCapturedError, ReactFiberErrorLogger = { - injection: injection, - logCapturedError: logCapturedError_1 - }, ReactErrorUtils = { - _caughtError: null, - _hasCaughtError: !1, - _rethrowError: null, - _hasRethrowError: !1, - injection: { - injectErrorUtils: function(injectedErrorUtils) { - invariant("function" == typeof injectedErrorUtils.invokeGuardedCallback, "Injected invokeGuardedCallback() must be a function."), - invokeGuardedCallback = injectedErrorUtils.invokeGuardedCallback; - } - }, - invokeGuardedCallback: function(name, func, context, a, b, c, d, e, f) { - invokeGuardedCallback.apply(ReactErrorUtils, arguments); - }, - invokeGuardedCallbackAndCatchFirstError: function(name, func, context, a, b, c, d, e, f) { - if (ReactErrorUtils.invokeGuardedCallback.apply(this, arguments), ReactErrorUtils.hasCaughtError()) { - var error = ReactErrorUtils.clearCaughtError(); - ReactErrorUtils._hasRethrowError || (ReactErrorUtils._hasRethrowError = !0, ReactErrorUtils._rethrowError = error); - } - }, - rethrowCaughtError: function() { - return rethrowCaughtError.apply(ReactErrorUtils, arguments); - }, - hasCaughtError: function() { - return ReactErrorUtils._hasCaughtError; - }, - clearCaughtError: function() { - if (ReactErrorUtils._hasCaughtError) { - var error = ReactErrorUtils._caughtError; - return ReactErrorUtils._caughtError = null, ReactErrorUtils._hasCaughtError = !1, - error; - } - invariant(!1, "clearCaughtError was called but no error was captured. This error " + "is likely caused by a bug in React. Please file an issue."); - } - }, invokeGuardedCallback = function(name, func, context, a, b, c, d, e, f) { - ReactErrorUtils._hasCaughtError = !1, ReactErrorUtils._caughtError = null; - var funcArgs = Array.prototype.slice.call(arguments, 3); - try { - func.apply(context, funcArgs); - } catch (error) { - ReactErrorUtils._caughtError = error, ReactErrorUtils._hasCaughtError = !0; - } - }; - if ("undefined" != typeof window && "function" == typeof window.dispatchEvent && "undefined" != typeof document && "function" == typeof document.createEvent) { - var fakeNode = document.createElement("react"); - invokeGuardedCallback = function(name, func, context, a, b, c, d, e, f) { - var didError = !0, funcArgs = Array.prototype.slice.call(arguments, 3); - function callCallback() { - fakeNode.removeEventListener(evtType, callCallback, !1), func.apply(context, funcArgs), - didError = !1; - } - var error = void 0, didSetError = !1, isCrossOriginError = !1; - function onError(event) { - error = event.error, didSetError = !0, null === error && 0 === event.colno && 0 === event.lineno && (isCrossOriginError = !0); - } - var evtType = "react-" + (name || "invokeguardedcallback"); - window.addEventListener("error", onError), fakeNode.addEventListener(evtType, callCallback, !1); - var evt = document.createEvent("Event"); - evt.initEvent(evtType, !1, !1), fakeNode.dispatchEvent(evt), didError ? (didSetError ? isCrossOriginError && (error = new Error("A cross-origin error was thrown. React doesn't have access to " + "the actual error object in development. " + "See https://fb.me/react-crossorigin-error for more information.")) : error = new Error("An error was thrown inside one of your components, but React " + "doesn't know what it was. This is likely due to browser " + 'flakiness. React does its best to preserve the "Pause on ' + 'exceptions" behavior of the DevTools, which requires some ' + "DEV-mode only tricks. It's possible that these don't work in " + "your browser. Try triggering the error in production mode, " + "or switching to a modern browser. If you suspect that this is " + "actually an issue with React, please file an issue."), - ReactErrorUtils._hasCaughtError = !0, ReactErrorUtils._caughtError = error) : (ReactErrorUtils._hasCaughtError = !1, - ReactErrorUtils._caughtError = null), window.removeEventListener("error", onError); - }; - } - var ComponentTree, rethrowCaughtError = function() { - if (ReactErrorUtils._hasRethrowError) { - var error = ReactErrorUtils._rethrowError; - throw ReactErrorUtils._rethrowError = null, ReactErrorUtils._hasRethrowError = !1, - error; - } - }, ReactErrorUtils_1 = ReactErrorUtils, warning = require$$0, injection$1 = { - injectComponentTree: function(Injected) { - ComponentTree = Injected, warning(Injected && Injected.getNodeFromInstance && Injected.getInstanceFromNode, "EventPluginUtils.injection.injectComponentTree(...): Injected " + "module is missing getNodeFromInstance or getInstanceFromNode."); - } - }; - function isEndish(topLevelType) { - return "topMouseUp" === topLevelType || "topTouchEnd" === topLevelType || "topTouchCancel" === topLevelType; - } - function isMoveish(topLevelType) { - return "topMouseMove" === topLevelType || "topTouchMove" === topLevelType; - } - function isStartish(topLevelType) { - return "topMouseDown" === topLevelType || "topTouchStart" === topLevelType; - } - var validateEventDispatches; - validateEventDispatches = function(event) { - var dispatchListeners = event._dispatchListeners, dispatchInstances = event._dispatchInstances, listenersIsArr = Array.isArray(dispatchListeners), listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0, instancesIsArr = Array.isArray(dispatchInstances), instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0; - warning(instancesIsArr === listenersIsArr && instancesLen === listenersLen, "EventPluginUtils: Invalid `event`."); - }; - function executeDispatch(event, simulated, listener, inst) { - var type = event.type || "unknown-event"; - event.currentTarget = EventPluginUtils.getNodeFromInstance(inst), ReactErrorUtils_1.invokeGuardedCallbackAndCatchFirstError(type, listener, void 0, event), - event.currentTarget = null; - } - function executeDispatchesInOrder(event, simulated) { - var dispatchListeners = event._dispatchListeners, dispatchInstances = event._dispatchInstances; - if (validateEventDispatches(event), Array.isArray(dispatchListeners)) for (var i = 0; i < dispatchListeners.length && !event.isPropagationStopped(); i++) executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]); else dispatchListeners && executeDispatch(event, simulated, dispatchListeners, dispatchInstances); - event._dispatchListeners = null, event._dispatchInstances = null; - } - function executeDispatchesInOrderStopAtTrueImpl(event) { - var dispatchListeners = event._dispatchListeners, dispatchInstances = event._dispatchInstances; - if (validateEventDispatches(event), Array.isArray(dispatchListeners)) { - for (var i = 0; i < dispatchListeners.length && !event.isPropagationStopped(); i++) if (dispatchListeners[i](event, dispatchInstances[i])) return dispatchInstances[i]; - } else if (dispatchListeners && dispatchListeners(event, dispatchInstances)) return dispatchInstances; - return null; - } - function executeDispatchesInOrderStopAtTrue(event) { - var ret = executeDispatchesInOrderStopAtTrueImpl(event); - return event._dispatchInstances = null, event._dispatchListeners = null, ret; - } - function executeDirectDispatch(event) { - validateEventDispatches(event); - var dispatchListener = event._dispatchListeners, dispatchInstance = event._dispatchInstances; - invariant(!Array.isArray(dispatchListener), "executeDirectDispatch(...): Invalid `event`."), - event.currentTarget = dispatchListener ? EventPluginUtils.getNodeFromInstance(dispatchInstance) : null; - var res = dispatchListener ? dispatchListener(event) : null; - return event.currentTarget = null, event._dispatchListeners = null, event._dispatchInstances = null, - res; - } - function hasDispatches(event) { - return !!event._dispatchListeners; - } - var EventPluginUtils = { - isEndish: isEndish, - isMoveish: isMoveish, - isStartish: isStartish, - executeDirectDispatch: executeDirectDispatch, - executeDispatchesInOrder: executeDispatchesInOrder, - executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue, - hasDispatches: hasDispatches, - getFiberCurrentPropsFromNode: function(node) { - return ComponentTree.getFiberCurrentPropsFromNode(node); - }, - getInstanceFromNode: function(node) { - return ComponentTree.getInstanceFromNode(node); - }, - getNodeFromInstance: function(node) { - return ComponentTree.getNodeFromInstance(node); - }, - injection: injection$1 - }, EventPluginUtils_1 = EventPluginUtils, fiberHostComponent = null, ReactControlledComponentInjection = { - injectFiberControlledHostComponent: function(hostComponentImpl) { - fiberHostComponent = hostComponentImpl; - } - }, restoreTarget = null, restoreQueue = null; - function restoreStateOfTarget(target) { - var internalInstance = EventPluginUtils_1.getInstanceFromNode(target); - if (internalInstance) { - invariant(fiberHostComponent && "function" == typeof fiberHostComponent.restoreControlledState, "Fiber needs to be injected to handle a fiber target for controlled " + "events. This error is likely caused by a bug in React. Please file an issue."); - var props = EventPluginUtils_1.getFiberCurrentPropsFromNode(internalInstance.stateNode); - fiberHostComponent.restoreControlledState(internalInstance.stateNode, internalInstance.type, props); - } - } - var ReactControlledComponent = { - injection: ReactControlledComponentInjection, - enqueueStateRestore: function(target) { - restoreTarget ? restoreQueue ? restoreQueue.push(target) : restoreQueue = [ target ] : restoreTarget = target; - }, - restoreStateIfNeeded: function() { - if (restoreTarget) { - var target = restoreTarget, queuedTargets = restoreQueue; - if (restoreTarget = null, restoreQueue = null, restoreStateOfTarget(target), queuedTargets) for (var i = 0; i < queuedTargets.length; i++) restoreStateOfTarget(queuedTargets[i]); - } - } - }, ReactControlledComponent_1 = ReactControlledComponent, fiberBatchedUpdates = function(fn, bookkeeping) { - return fn(bookkeeping); - }; - function batchedUpdates(fn, bookkeeping) { - return fiberBatchedUpdates(fn, bookkeeping); - } - var isNestingBatched = !1; - function batchedUpdatesWithControlledComponents(fn, bookkeeping) { - if (isNestingBatched) return batchedUpdates(fn, bookkeeping); - isNestingBatched = !0; - try { - return batchedUpdates(fn, bookkeeping); - } finally { - isNestingBatched = !1, ReactControlledComponent_1.restoreStateIfNeeded(); - } - } - var ReactGenericBatchingInjection = { - injectFiberBatchedUpdates: function(_batchedUpdates) { - fiberBatchedUpdates = _batchedUpdates; - } - }, ReactGenericBatching = { - batchedUpdates: batchedUpdatesWithControlledComponents, - injection: ReactGenericBatchingInjection - }, ReactGenericBatching_1 = ReactGenericBatching; - function ReactNativeFiberErrorDialog(capturedError) { - var componentStack = capturedError.componentStack, error = capturedError.error, errorToHandle = void 0; - if (error instanceof Error) { - var message = error.message, name = error.name, summary = message ? name + ": " + message : name; - errorToHandle = error; - try { - errorToHandle.message = summary + "\n\nThis error is located at:" + componentStack; - } catch (e) {} - } else errorToHandle = "string" == typeof error ? new Error(error + "\n\nThis error is located at:" + componentStack) : new Error("Unspecified error at:" + componentStack); - return ExceptionsManager.handleException(errorToHandle, !1), !1; - } - var showDialog$1 = ReactNativeFiberErrorDialog, ReactNativeFiberErrorDialog_1 = { - showDialog: showDialog$1 - }, REACT_PORTAL_TYPE = "function" == typeof Symbol && Symbol.for && Symbol.for("react.portal") || 60106, createPortal = function(children, containerInfo, implementation) { - var key = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : null; - return { - $$typeof: REACT_PORTAL_TYPE, - key: null == key ? null : "" + key, - children: children, - containerInfo: containerInfo, - implementation: implementation - }; - }, isPortal = function(object) { - return "object" == typeof object && null !== object && object.$$typeof === REACT_PORTAL_TYPE; - }, REACT_PORTAL_TYPE_1 = REACT_PORTAL_TYPE, ReactPortal = { - createPortal: createPortal, - isPortal: isPortal, - REACT_PORTAL_TYPE: REACT_PORTAL_TYPE_1 - }, instanceCache = {}, instanceProps = {}; - function precacheFiberNode(hostInst, tag) { - instanceCache[tag] = hostInst; - } - function uncacheFiberNode(tag) { - delete instanceCache[tag], delete instanceProps[tag]; - } - function getInstanceFromTag(tag) { - return instanceCache[tag] || null; - } - function getTagFromInstance(inst) { - var tag = inst.stateNode._nativeTag; - return invariant(tag, "All native instances should have a tag."), tag; - } - function getFiberCurrentPropsFromNode(stateNode) { - return instanceProps[stateNode._nativeTag] || null; - } - function updateFiberProps(tag, props) { - instanceProps[tag] = props; - } - var ReactNativeComponentTree = { - getClosestInstanceFromNode: getInstanceFromTag, - getInstanceFromNode: getInstanceFromTag, - getNodeFromInstance: getTagFromInstance, - precacheFiberNode: precacheFiberNode, - uncacheFiberNode: uncacheFiberNode, - getFiberCurrentPropsFromNode: getFiberCurrentPropsFromNode, - updateFiberProps: updateFiberProps - }, ReactNativeComponentTree_1 = ReactNativeComponentTree, commonjsGlobal = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {}, ReactFeatureFlags = { - enableAsyncSubtreeAPI: !0 - }, ReactFeatureFlags_1 = ReactFeatureFlags, ReactTypeOfSideEffect = { - NoEffect: 0, - PerformedWork: 1, - Placement: 2, - Update: 4, - PlacementAndUpdate: 6, - Deletion: 8, - ContentReset: 16, - Callback: 32, - Err: 64, - Ref: 128 - }, ReactPriorityLevel = { - NoWork: 0, - SynchronousPriority: 1, - TaskPriority: 2, - HighPriority: 3, - LowPriority: 4, - OffscreenPriority: 5 - }, ReactTypeOfWork = { - IndeterminateComponent: 0, - FunctionalComponent: 1, - ClassComponent: 2, - HostRoot: 3, - HostPortal: 4, - HostComponent: 5, - HostText: 6, - CoroutineComponent: 7, - CoroutineHandlerPhase: 8, - YieldComponent: 9, - Fragment: 10 - }, CallbackEffect = ReactTypeOfSideEffect.Callback, NoWork = ReactPriorityLevel.NoWork, SynchronousPriority = ReactPriorityLevel.SynchronousPriority, TaskPriority = ReactPriorityLevel.TaskPriority, ClassComponent = ReactTypeOfWork.ClassComponent, HostRoot = ReactTypeOfWork.HostRoot, warning$2 = require$$0, _queue1 = void 0, _queue2 = void 0; - function comparePriority(a, b) { - return a !== TaskPriority && a !== SynchronousPriority || b !== TaskPriority && b !== SynchronousPriority ? a === NoWork && b !== NoWork ? -255 : a !== NoWork && b === NoWork ? 255 : a - b : 0; - } - function createUpdateQueue() { - var queue = { - first: null, - last: null, - hasForceUpdate: !1, - callbackList: null - }; - return queue.isProcessing = !1, queue; - } - function cloneUpdate(update) { - return { - priorityLevel: update.priorityLevel, - partialState: update.partialState, - callback: update.callback, - isReplace: update.isReplace, - isForced: update.isForced, - isTopLevelUnmount: update.isTopLevelUnmount, - next: null - }; - } - function insertUpdateIntoQueue(queue, update, insertAfter, insertBefore) { - null !== insertAfter ? insertAfter.next = update : (update.next = queue.first, queue.first = update), - null !== insertBefore ? update.next = insertBefore : queue.last = update; - } - function findInsertionPosition(queue, update) { - var priorityLevel = update.priorityLevel, insertAfter = null, insertBefore = null; - if (null !== queue.last && comparePriority(queue.last.priorityLevel, priorityLevel) <= 0) insertAfter = queue.last; else for (insertBefore = queue.first; null !== insertBefore && comparePriority(insertBefore.priorityLevel, priorityLevel) <= 0; ) insertAfter = insertBefore, - insertBefore = insertBefore.next; - return insertAfter; - } - function ensureUpdateQueues(fiber) { - var alternateFiber = fiber.alternate, queue1 = fiber.updateQueue; - null === queue1 && (queue1 = fiber.updateQueue = createUpdateQueue()); - var queue2 = void 0; - null !== alternateFiber ? null === (queue2 = alternateFiber.updateQueue) && (queue2 = alternateFiber.updateQueue = createUpdateQueue()) : queue2 = null, - _queue1 = queue1, _queue2 = queue2 !== queue1 ? queue2 : null; - } - function insertUpdate(fiber, update) { - ensureUpdateQueues(fiber); - var queue1 = _queue1, queue2 = _queue2; - (queue1.isProcessing || null !== queue2 && queue2.isProcessing) && warning$2(!1, "An update (setState, replaceState, or forceUpdate) was scheduled " + "from inside an update function. Update functions should be pure, " + "with zero side-effects. Consider using componentDidUpdate or a " + "callback."); - var insertAfter1 = findInsertionPosition(queue1, update), insertBefore1 = null !== insertAfter1 ? insertAfter1.next : queue1.first; - if (null === queue2) return insertUpdateIntoQueue(queue1, update, insertAfter1, insertBefore1), - null; - var insertAfter2 = findInsertionPosition(queue2, update), insertBefore2 = null !== insertAfter2 ? insertAfter2.next : queue2.first; - if (insertUpdateIntoQueue(queue1, update, insertAfter1, insertBefore1), insertBefore1 === insertBefore2 && null !== insertBefore1 || insertAfter1 === insertAfter2 && null !== insertAfter1) return null === insertAfter2 && (queue2.first = update), - null === insertBefore2 && (queue2.last = null), null; - var update2 = cloneUpdate(update); - return insertUpdateIntoQueue(queue2, update2, insertAfter2, insertBefore2), update2; - } - function addUpdate(fiber, partialState, callback, priorityLevel) { - insertUpdate(fiber, { - priorityLevel: priorityLevel, - partialState: partialState, - callback: callback, - isReplace: !1, - isForced: !1, - isTopLevelUnmount: !1, - next: null - }); - } - var addUpdate_1 = addUpdate; - function addReplaceUpdate(fiber, state, callback, priorityLevel) { - insertUpdate(fiber, { - priorityLevel: priorityLevel, - partialState: state, - callback: callback, - isReplace: !0, - isForced: !1, - isTopLevelUnmount: !1, - next: null - }); - } - var addReplaceUpdate_1 = addReplaceUpdate; - function addForceUpdate(fiber, callback, priorityLevel) { - insertUpdate(fiber, { - priorityLevel: priorityLevel, - partialState: null, - callback: callback, - isReplace: !1, - isForced: !0, - isTopLevelUnmount: !1, - next: null - }); - } - var addForceUpdate_1 = addForceUpdate; - function getUpdatePriority(fiber) { - var updateQueue = fiber.updateQueue; - return null === updateQueue ? NoWork : fiber.tag !== ClassComponent && fiber.tag !== HostRoot ? NoWork : null !== updateQueue.first ? updateQueue.first.priorityLevel : NoWork; - } - var getUpdatePriority_1 = getUpdatePriority; - function addTopLevelUpdate$1(fiber, partialState, callback, priorityLevel) { - var isTopLevelUnmount = null === partialState.element, update = { - priorityLevel: priorityLevel, - partialState: partialState, - callback: callback, - isReplace: !1, - isForced: !1, - isTopLevelUnmount: isTopLevelUnmount, - next: null - }, update2 = insertUpdate(fiber, update); - if (isTopLevelUnmount) { - var queue1 = _queue1, queue2 = _queue2; - null !== queue1 && null !== update.next && (update.next = null, queue1.last = update), - null !== queue2 && null !== update2 && null !== update2.next && (update2.next = null, - queue2.last = update); - } - } - var addTopLevelUpdate_1 = addTopLevelUpdate$1; - function getStateFromUpdate(update, instance, prevState, props) { - var partialState = update.partialState; - if ("function" == typeof partialState) { - return partialState.call(instance, prevState, props); - } - return partialState; - } - function beginUpdateQueue(current, workInProgress, queue, instance, prevState, props, priorityLevel) { - if (null !== current && current.updateQueue === queue) { - var currentQueue = queue; - queue = workInProgress.updateQueue = { - first: currentQueue.first, - last: currentQueue.last, - callbackList: null, - hasForceUpdate: !1 - }; - } - queue.isProcessing = !0; - for (var callbackList = queue.callbackList, hasForceUpdate = queue.hasForceUpdate, state = prevState, dontMutatePrevState = !0, update = queue.first; null !== update && comparePriority(update.priorityLevel, priorityLevel) <= 0; ) { - queue.first = update.next, null === queue.first && (queue.last = null); - var _partialState = void 0; - update.isReplace ? (state = getStateFromUpdate(update, instance, state, props), - dontMutatePrevState = !0) : (_partialState = getStateFromUpdate(update, instance, state, props)) && (state = dontMutatePrevState ? Object.assign({}, state, _partialState) : Object.assign(state, _partialState), - dontMutatePrevState = !1), update.isForced && (hasForceUpdate = !0), null === update.callback || update.isTopLevelUnmount && null !== update.next || (callbackList = null !== callbackList ? callbackList : [], - callbackList.push(update.callback), workInProgress.effectTag |= CallbackEffect), - update = update.next; - } - return queue.callbackList = callbackList, queue.hasForceUpdate = hasForceUpdate, - null !== queue.first || null !== callbackList || hasForceUpdate || (workInProgress.updateQueue = null), - queue.isProcessing = !1, state; - } - var beginUpdateQueue_1 = beginUpdateQueue; - function commitCallbacks(finishedWork, queue, context) { - var callbackList = queue.callbackList; - if (null !== callbackList) { - queue.callbackList = null; - for (var i = 0; i < callbackList.length; i++) { - var _callback = callbackList[i]; - invariant("function" == typeof _callback, "Invalid argument passed as callback. Expected a function. Instead " + "received: %s", _callback), - _callback.call(context); - } - } - } - var commitCallbacks_1 = commitCallbacks, ReactFiberUpdateQueue = { - addUpdate: addUpdate_1, - addReplaceUpdate: addReplaceUpdate_1, - addForceUpdate: addForceUpdate_1, - getUpdatePriority: getUpdatePriority_1, - addTopLevelUpdate: addTopLevelUpdate_1, - beginUpdateQueue: beginUpdateQueue_1, - commitCallbacks: commitCallbacks_1 - }; - function getComponentName$1(fiber) { - var type = fiber.type; - return "string" == typeof type ? type : "function" == typeof type ? type.displayName || type.name : null; - } - var getComponentName_1 = getComponentName$1, ReactInstanceMap = { - remove: function(key) { - key._reactInternalFiber = void 0; - }, - get: function(key) { - return key._reactInternalFiber; - }, - has: function(key) { - return void 0 !== key._reactInternalFiber; - }, - set: function(key, value) { - key._reactInternalFiber = value; - } - }, ReactInstanceMap_1 = ReactInstanceMap, ReactInternals = react.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, ReactGlobalSharedState = { - ReactCurrentOwner: ReactInternals.ReactCurrentOwner - }; - Object.assign(ReactGlobalSharedState, { - ReactDebugCurrentFrame: ReactInternals.ReactDebugCurrentFrame - }); - var ReactGlobalSharedState_1 = ReactGlobalSharedState, ReactCurrentOwner = ReactGlobalSharedState_1.ReactCurrentOwner, warning$4 = require$$0, ClassComponent$2 = ReactTypeOfWork.ClassComponent, HostComponent$1 = ReactTypeOfWork.HostComponent, HostRoot$2 = ReactTypeOfWork.HostRoot, HostPortal = ReactTypeOfWork.HostPortal, HostText = ReactTypeOfWork.HostText, NoEffect = ReactTypeOfSideEffect.NoEffect, Placement = ReactTypeOfSideEffect.Placement, MOUNTING = 1, MOUNTED = 2, UNMOUNTED = 3; - function isFiberMountedImpl(fiber) { - var node = fiber; - if (fiber.alternate) for (;node.return; ) node = node.return; else { - if ((node.effectTag & Placement) !== NoEffect) return MOUNTING; - for (;node.return; ) if (node = node.return, (node.effectTag & Placement) !== NoEffect) return MOUNTING; - } - return node.tag === HostRoot$2 ? MOUNTED : UNMOUNTED; - } - var isFiberMounted$1 = function(fiber) { - return isFiberMountedImpl(fiber) === MOUNTED; - }, isMounted = function(component) { - var owner = ReactCurrentOwner.current; - if (null !== owner && owner.tag === ClassComponent$2) { - var ownerFiber = owner, instance = ownerFiber.stateNode; - warning$4(instance._warnedAboutRefsInRender, "%s is accessing isMounted inside its render() function. " + "render() should be a pure function of props and state. It should " + "never access something that requires stale data from the previous " + "render, such as refs. Move this logic to componentDidMount and " + "componentDidUpdate instead.", getComponentName_1(ownerFiber) || "A component"), - instance._warnedAboutRefsInRender = !0; - } - var fiber = ReactInstanceMap_1.get(component); - return !!fiber && isFiberMountedImpl(fiber) === MOUNTED; - }; - function assertIsMounted(fiber) { - invariant(isFiberMountedImpl(fiber) === MOUNTED, "Unable to find node on an unmounted component."); - } - function findCurrentFiberUsingSlowPath(fiber) { - var alternate = fiber.alternate; - if (!alternate) { - var state = isFiberMountedImpl(fiber); - return invariant(state !== UNMOUNTED, "Unable to find node on an unmounted component."), - state === MOUNTING ? null : fiber; - } - for (var a = fiber, b = alternate; !0; ) { - var parentA = a.return, parentB = parentA ? parentA.alternate : null; - if (!parentA || !parentB) break; - if (parentA.child === parentB.child) { - for (var child = parentA.child; child; ) { - if (child === a) return assertIsMounted(parentA), fiber; - if (child === b) return assertIsMounted(parentA), alternate; - child = child.sibling; - } - invariant(!1, "Unable to find node on an unmounted component."); - } - if (a.return !== b.return) a = parentA, b = parentB; else { - for (var didFindChild = !1, _child = parentA.child; _child; ) { - if (_child === a) { - didFindChild = !0, a = parentA, b = parentB; - break; - } - if (_child === b) { - didFindChild = !0, b = parentA, a = parentB; - break; - } - _child = _child.sibling; - } - if (!didFindChild) { - for (_child = parentB.child; _child; ) { - if (_child === a) { - didFindChild = !0, a = parentB, b = parentA; - break; - } - if (_child === b) { - didFindChild = !0, b = parentB, a = parentA; - break; - } - _child = _child.sibling; - } - invariant(didFindChild, "Child was not found in either parent set. This indicates a bug " + "in React related to the return pointer. Please file an issue."); - } - } - invariant(a.alternate === b, "Return fibers should always be each others' alternates. " + "This error is likely caused by a bug in React. Please file an issue."); - } - return invariant(a.tag === HostRoot$2, "Unable to find node on an unmounted component."), - a.stateNode.current === a ? fiber : alternate; - } - var findCurrentFiberUsingSlowPath_1 = findCurrentFiberUsingSlowPath, findCurrentHostFiber$1 = function(parent) { - var currentParent = findCurrentFiberUsingSlowPath(parent); - if (!currentParent) return null; - for (var node = currentParent; !0; ) { - if (node.tag === HostComponent$1 || node.tag === HostText) return node; - if (node.child) node.child.return = node, node = node.child; else { - if (node === currentParent) return null; - for (;!node.sibling; ) { - if (!node.return || node.return === currentParent) return null; - node = node.return; - } - node.sibling.return = node.return, node = node.sibling; - } - } - return null; - }, findCurrentHostFiberWithNoPortals$1 = function(parent) { - var currentParent = findCurrentFiberUsingSlowPath(parent); - if (!currentParent) return null; - for (var node = currentParent; !0; ) { - if (node.tag === HostComponent$1 || node.tag === HostText) return node; - if (node.child && node.tag !== HostPortal) node.child.return = node, node = node.child; else { - if (node === currentParent) return null; - for (;!node.sibling; ) { - if (!node.return || node.return === currentParent) return null; - node = node.return; - } - node.sibling.return = node.return, node = node.sibling; - } - } - return null; - }, ReactFiberTreeReflection = { - isFiberMounted: isFiberMounted$1, - isMounted: isMounted, - findCurrentFiberUsingSlowPath: findCurrentFiberUsingSlowPath_1, - findCurrentHostFiber: findCurrentHostFiber$1, - findCurrentHostFiberWithNoPortals: findCurrentHostFiberWithNoPortals$1 - }, warning$5 = require$$0, valueStack = [], fiberStack = [], index = -1, createCursor$1 = function(defaultValue) { - return { - current: defaultValue - }; - }, isEmpty = function() { - return -1 === index; - }, pop$1 = function(cursor, fiber) { - if (index < 0) return void warning$5(!1, "Unexpected pop."); - fiber !== fiberStack[index] && warning$5(!1, "Unexpected Fiber popped."), cursor.current = valueStack[index], - valueStack[index] = null, fiberStack[index] = null, index--; - }, push$1 = function(cursor, value, fiber) { - index++, valueStack[index] = cursor.current, fiberStack[index] = fiber, cursor.current = value; - }, reset = function() { - for (;index > -1; ) valueStack[index] = null, fiberStack[index] = null, index--; - }, ReactFiberStack = { - createCursor: createCursor$1, - isEmpty: isEmpty, - pop: pop$1, - push: push$1, - reset: reset - }, describeComponentFrame = function(name, source, ownerName) { - return "\n in " + (name || "Unknown") + (source ? " (at " + source.fileName.replace(/^.*[\\\/]/, "") + ":" + source.lineNumber + ")" : ownerName ? " (created by " + ownerName + ")" : ""); - }, IndeterminateComponent = ReactTypeOfWork.IndeterminateComponent, FunctionalComponent = ReactTypeOfWork.FunctionalComponent, ClassComponent$3 = ReactTypeOfWork.ClassComponent, HostComponent$2 = ReactTypeOfWork.HostComponent; - function describeFiber(fiber) { - switch (fiber.tag) { - case IndeterminateComponent: - case FunctionalComponent: - case ClassComponent$3: - case HostComponent$2: - var owner = fiber._debugOwner, source = fiber._debugSource, name = getComponentName_1(fiber), ownerName = null; - return owner && (ownerName = getComponentName_1(owner)), describeComponentFrame(name, source, ownerName); - - default: - return ""; - } - } - function getStackAddendumByWorkInProgressFiber$1(workInProgress) { - var info = "", node = workInProgress; - do { - info += describeFiber(node), node = node.return; - } while (node); - return info; - } - var ReactFiberComponentTreeHook = { - getStackAddendumByWorkInProgressFiber: getStackAddendumByWorkInProgressFiber$1 - }, ReactDebugCurrentFrame = ReactGlobalSharedState_1.ReactDebugCurrentFrame, getComponentName$3 = getComponentName_1, _require2$1 = ReactFiberComponentTreeHook, getStackAddendumByWorkInProgressFiber = _require2$1.getStackAddendumByWorkInProgressFiber; - function getCurrentFiberOwnerName() { - var fiber = ReactDebugCurrentFiber$2.current; - if (null === fiber) return null; - var owner = fiber._debugOwner; - return null !== owner && void 0 !== owner ? getComponentName$3(owner) : null; - } - function getCurrentFiberStackAddendum() { - var fiber = ReactDebugCurrentFiber$2.current; - return null === fiber ? null : getStackAddendumByWorkInProgressFiber(fiber); - } - function resetCurrentFiber() { - ReactDebugCurrentFrame.getCurrentStack = null, ReactDebugCurrentFiber$2.current = null, - ReactDebugCurrentFiber$2.phase = null; - } - function setCurrentFiber(fiber) { - ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum, ReactDebugCurrentFiber$2.current = fiber, - ReactDebugCurrentFiber$2.phase = null; - } - function setCurrentPhase(phase) { - ReactDebugCurrentFiber$2.phase = phase; - } - var ReactDebugCurrentFiber$2 = { - current: null, - phase: null, - resetCurrentFiber: resetCurrentFiber, - setCurrentFiber: setCurrentFiber, - setCurrentPhase: setCurrentPhase, - getCurrentFiberOwnerName: getCurrentFiberOwnerName, - getCurrentFiberStackAddendum: getCurrentFiberStackAddendum - }, ReactDebugCurrentFiber_1 = ReactDebugCurrentFiber$2, ReactDebugFiberPerf = null, _require$2 = ReactTypeOfWork, HostRoot$3 = _require$2.HostRoot, HostComponent$3 = _require$2.HostComponent, HostText$1 = _require$2.HostText, HostPortal$1 = _require$2.HostPortal, YieldComponent = _require$2.YieldComponent, Fragment = _require$2.Fragment, getComponentName$4 = getComponentName_1, reactEmoji = "⚛", warningEmoji = "⛔", supportsUserTiming = "undefined" != typeof performance && "function" == typeof performance.mark && "function" == typeof performance.clearMarks && "function" == typeof performance.measure && "function" == typeof performance.clearMeasures, currentFiber = null, currentPhase = null, currentPhaseFiber = null, isCommitting = !1, hasScheduledUpdateInCurrentCommit = !1, hasScheduledUpdateInCurrentPhase = !1, commitCountInCurrentWorkLoop = 0, effectCountInCurrentCommit = 0, labelsInCurrentCommit = new Set(), formatMarkName = function(markName) { - return reactEmoji + " " + markName; - }, formatLabel = function(label, warning) { - return (warning ? warningEmoji + " " : reactEmoji + " ") + label + (warning ? " Warning: " + warning : ""); - }, beginMark = function(markName) { - performance.mark(formatMarkName(markName)); - }, clearMark = function(markName) { - performance.clearMarks(formatMarkName(markName)); - }, endMark = function(label, markName, warning) { - var formattedMarkName = formatMarkName(markName), formattedLabel = formatLabel(label, warning); - try { - performance.measure(formattedLabel, formattedMarkName); - } catch (err) {} - performance.clearMarks(formattedMarkName), performance.clearMeasures(formattedLabel); - }, getFiberMarkName = function(label, debugID) { - return label + " (#" + debugID + ")"; - }, getFiberLabel = function(componentName, isMounted, phase) { - return null === phase ? componentName + " [" + (isMounted ? "update" : "mount") + "]" : componentName + "." + phase; - }, beginFiberMark = function(fiber, phase) { - var componentName = getComponentName$4(fiber) || "Unknown", debugID = fiber._debugID, isMounted = null !== fiber.alternate, label = getFiberLabel(componentName, isMounted, phase); - if (isCommitting && labelsInCurrentCommit.has(label)) return !1; - labelsInCurrentCommit.add(label); - var markName = getFiberMarkName(label, debugID); - return beginMark(markName), !0; - }, clearFiberMark = function(fiber, phase) { - var componentName = getComponentName$4(fiber) || "Unknown", debugID = fiber._debugID, isMounted = null !== fiber.alternate, label = getFiberLabel(componentName, isMounted, phase), markName = getFiberMarkName(label, debugID); - clearMark(markName); - }, endFiberMark = function(fiber, phase, warning) { - var componentName = getComponentName$4(fiber) || "Unknown", debugID = fiber._debugID, isMounted = null !== fiber.alternate, label = getFiberLabel(componentName, isMounted, phase), markName = getFiberMarkName(label, debugID); - endMark(label, markName, warning); - }, shouldIgnoreFiber = function(fiber) { - switch (fiber.tag) { - case HostRoot$3: - case HostComponent$3: - case HostText$1: - case HostPortal$1: - case YieldComponent: - case Fragment: - return !0; - - default: - return !1; - } - }, clearPendingPhaseMeasurement = function() { - null !== currentPhase && null !== currentPhaseFiber && clearFiberMark(currentPhaseFiber, currentPhase), - currentPhaseFiber = null, currentPhase = null, hasScheduledUpdateInCurrentPhase = !1; - }, pauseTimers = function() { - for (var fiber = currentFiber; fiber; ) fiber._debugIsCurrentlyTiming && endFiberMark(fiber, null, null), - fiber = fiber.return; - }, resumeTimersRecursively = function(fiber) { - null !== fiber.return && resumeTimersRecursively(fiber.return), fiber._debugIsCurrentlyTiming && beginFiberMark(fiber, null); - }, resumeTimers = function() { - null !== currentFiber && resumeTimersRecursively(currentFiber); - }; - ReactDebugFiberPerf = { - recordEffect: function() { - effectCountInCurrentCommit++; - }, - recordScheduleUpdate: function() { - isCommitting && (hasScheduledUpdateInCurrentCommit = !0), null !== currentPhase && "componentWillMount" !== currentPhase && "componentWillReceiveProps" !== currentPhase && (hasScheduledUpdateInCurrentPhase = !0); - }, - startWorkTimer: function(fiber) { - supportsUserTiming && !shouldIgnoreFiber(fiber) && (currentFiber = fiber, beginFiberMark(fiber, null) && (fiber._debugIsCurrentlyTiming = !0)); - }, - cancelWorkTimer: function(fiber) { - supportsUserTiming && !shouldIgnoreFiber(fiber) && (fiber._debugIsCurrentlyTiming = !1, - clearFiberMark(fiber, null)); - }, - stopWorkTimer: function(fiber) { - supportsUserTiming && !shouldIgnoreFiber(fiber) && (currentFiber = fiber.return, - fiber._debugIsCurrentlyTiming && (fiber._debugIsCurrentlyTiming = !1, endFiberMark(fiber, null, null))); - }, - stopFailedWorkTimer: function(fiber) { - if (supportsUserTiming && !shouldIgnoreFiber(fiber) && (currentFiber = fiber.return, - fiber._debugIsCurrentlyTiming)) { - fiber._debugIsCurrentlyTiming = !1; - endFiberMark(fiber, null, "An error was thrown inside this error boundary"); - } - }, - startPhaseTimer: function(fiber, phase) { - supportsUserTiming && (clearPendingPhaseMeasurement(), beginFiberMark(fiber, phase) && (currentPhaseFiber = fiber, - currentPhase = phase)); - }, - stopPhaseTimer: function() { - if (supportsUserTiming) { - if (null !== currentPhase && null !== currentPhaseFiber) { - endFiberMark(currentPhaseFiber, currentPhase, hasScheduledUpdateInCurrentPhase ? "Scheduled a cascading update" : null); - } - currentPhase = null, currentPhaseFiber = null; - } - }, - startWorkLoopTimer: function() { - supportsUserTiming && (commitCountInCurrentWorkLoop = 0, beginMark("(React Tree Reconciliation)"), - resumeTimers()); - }, - stopWorkLoopTimer: function() { - if (supportsUserTiming) { - var warning = commitCountInCurrentWorkLoop > 1 ? "There were cascading updates" : null; - commitCountInCurrentWorkLoop = 0, pauseTimers(), endMark("(React Tree Reconciliation)", "(React Tree Reconciliation)", warning); - } - }, - startCommitTimer: function() { - supportsUserTiming && (isCommitting = !0, hasScheduledUpdateInCurrentCommit = !1, - labelsInCurrentCommit.clear(), beginMark("(Committing Changes)")); - }, - stopCommitTimer: function() { - if (supportsUserTiming) { - var warning = null; - hasScheduledUpdateInCurrentCommit ? warning = "Lifecycle hook scheduled a cascading update" : commitCountInCurrentWorkLoop > 0 && (warning = "Caused by a cascading update in earlier commit"), - hasScheduledUpdateInCurrentCommit = !1, commitCountInCurrentWorkLoop++, isCommitting = !1, - labelsInCurrentCommit.clear(), endMark("(Committing Changes)", "(Committing Changes)", warning); - } - }, - startCommitHostEffectsTimer: function() { - supportsUserTiming && (effectCountInCurrentCommit = 0, beginMark("(Committing Host Effects)")); - }, - stopCommitHostEffectsTimer: function() { - if (supportsUserTiming) { - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0, endMark("(Committing Host Effects: " + count + " Total)", "(Committing Host Effects)", null); - } - }, - startCommitLifeCyclesTimer: function() { - supportsUserTiming && (effectCountInCurrentCommit = 0, beginMark("(Calling Lifecycle Methods)")); - }, - stopCommitLifeCyclesTimer: function() { - if (supportsUserTiming) { - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0, endMark("(Calling Lifecycle Methods: " + count + " Total)", "(Calling Lifecycle Methods)", null); - } - } - }; - var ReactDebugFiberPerf_1 = ReactDebugFiberPerf, isFiberMounted = ReactFiberTreeReflection.isFiberMounted, ClassComponent$1 = ReactTypeOfWork.ClassComponent, HostRoot$1 = ReactTypeOfWork.HostRoot, createCursor = ReactFiberStack.createCursor, pop = ReactFiberStack.pop, push = ReactFiberStack.push, warning$3 = require$$0, checkPropTypes$1 = checkPropTypes, ReactDebugCurrentFiber$1 = ReactDebugCurrentFiber_1, _require4 = ReactDebugFiberPerf_1, startPhaseTimer = _require4.startPhaseTimer, stopPhaseTimer = _require4.stopPhaseTimer, warnedAboutMissingGetChildContext = {}, contextStackCursor = createCursor(emptyObject), didPerformWorkStackCursor = createCursor(!1), previousContext = emptyObject; - function getUnmaskedContext(workInProgress) { - return isContextProvider$1(workInProgress) ? previousContext : contextStackCursor.current; - } - var getUnmaskedContext_1 = getUnmaskedContext; - function cacheContext(workInProgress, unmaskedContext, maskedContext) { - var instance = workInProgress.stateNode; - instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext, instance.__reactInternalMemoizedMaskedChildContext = maskedContext; - } - var cacheContext_1 = cacheContext, getMaskedContext = function(workInProgress, unmaskedContext) { - var type = workInProgress.type, contextTypes = type.contextTypes; - if (!contextTypes) return emptyObject; - var instance = workInProgress.stateNode; - if (instance && instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext) return instance.__reactInternalMemoizedMaskedChildContext; - var context = {}; - for (var key in contextTypes) context[key] = unmaskedContext[key]; - var name = getComponentName_1(workInProgress) || "Unknown"; - return checkPropTypes$1(contextTypes, context, "context", name, ReactDebugCurrentFiber$1.getCurrentFiberStackAddendum), - instance && cacheContext(workInProgress, unmaskedContext, context), context; - }, hasContextChanged = function() { - return didPerformWorkStackCursor.current; - }; - function isContextConsumer(fiber) { - return fiber.tag === ClassComponent$1 && null != fiber.type.contextTypes; - } - var isContextConsumer_1 = isContextConsumer; - function isContextProvider$1(fiber) { - return fiber.tag === ClassComponent$1 && null != fiber.type.childContextTypes; - } - var isContextProvider_1 = isContextProvider$1; - function popContextProvider(fiber) { - isContextProvider$1(fiber) && (pop(didPerformWorkStackCursor, fiber), pop(contextStackCursor, fiber)); - } - var popContextProvider_1 = popContextProvider, popTopLevelContextObject = function(fiber) { - pop(didPerformWorkStackCursor, fiber), pop(contextStackCursor, fiber); - }, pushTopLevelContextObject = function(fiber, context, didChange) { - invariant(null == contextStackCursor.cursor, "Unexpected context found on stack. " + "This error is likely caused by a bug in React. Please file an issue."), - push(contextStackCursor, context, fiber), push(didPerformWorkStackCursor, didChange, fiber); - }; - function processChildContext$1(fiber, parentContext) { - var instance = fiber.stateNode, childContextTypes = fiber.type.childContextTypes; - if ("function" != typeof instance.getChildContext) { - var componentName = getComponentName_1(fiber) || "Unknown"; - return warnedAboutMissingGetChildContext[componentName] || (warnedAboutMissingGetChildContext[componentName] = !0, - warning$3(!1, "%s.childContextTypes is specified but there is no getChildContext() method " + "on the instance. You can either define getChildContext() on %s or remove " + "childContextTypes from it.", componentName, componentName)), - parentContext; - } - var childContext = void 0; - ReactDebugCurrentFiber$1.setCurrentPhase("getChildContext"), startPhaseTimer(fiber, "getChildContext"), - childContext = instance.getChildContext(), stopPhaseTimer(), ReactDebugCurrentFiber$1.setCurrentPhase(null); - for (var contextKey in childContext) invariant(contextKey in childContextTypes, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', getComponentName_1(fiber) || "Unknown", contextKey); - var name = getComponentName_1(fiber) || "Unknown"; - return checkPropTypes$1(childContextTypes, childContext, "child context", name, ReactDebugCurrentFiber$1.getCurrentFiberStackAddendum), - Object.assign({}, parentContext, childContext); - } - var processChildContext_1 = processChildContext$1, pushContextProvider = function(workInProgress) { - if (!isContextProvider$1(workInProgress)) return !1; - var instance = workInProgress.stateNode, memoizedMergedChildContext = instance && instance.__reactInternalMemoizedMergedChildContext || emptyObject; - return previousContext = contextStackCursor.current, push(contextStackCursor, memoizedMergedChildContext, workInProgress), - push(didPerformWorkStackCursor, didPerformWorkStackCursor.current, workInProgress), - !0; - }, invalidateContextProvider = function(workInProgress, didChange) { - var instance = workInProgress.stateNode; - if (invariant(instance, "Expected to have an instance by this point. " + "This error is likely caused by a bug in React. Please file an issue."), - didChange) { - var mergedContext = processChildContext$1(workInProgress, previousContext); - instance.__reactInternalMemoizedMergedChildContext = mergedContext, pop(didPerformWorkStackCursor, workInProgress), - pop(contextStackCursor, workInProgress), push(contextStackCursor, mergedContext, workInProgress), - push(didPerformWorkStackCursor, didChange, workInProgress); - } else pop(didPerformWorkStackCursor, workInProgress), push(didPerformWorkStackCursor, didChange, workInProgress); - }, resetContext = function() { - previousContext = emptyObject, contextStackCursor.current = emptyObject, didPerformWorkStackCursor.current = !1; - }, findCurrentUnmaskedContext$1 = function(fiber) { - invariant(isFiberMounted(fiber) && fiber.tag === ClassComponent$1, "Expected subtree parent to be a mounted class component. " + "This error is likely caused by a bug in React. Please file an issue."); - for (var node = fiber; node.tag !== HostRoot$1; ) { - if (isContextProvider$1(node)) return node.stateNode.__reactInternalMemoizedMergedChildContext; - var parent = node.return; - invariant(parent, "Found unexpected detached subtree parent. " + "This error is likely caused by a bug in React. Please file an issue."), - node = parent; - } - return node.stateNode.context; - }, ReactFiberContext = { - getUnmaskedContext: getUnmaskedContext_1, - cacheContext: cacheContext_1, - getMaskedContext: getMaskedContext, - hasContextChanged: hasContextChanged, - isContextConsumer: isContextConsumer_1, - isContextProvider: isContextProvider_1, - popContextProvider: popContextProvider_1, - popTopLevelContextObject: popTopLevelContextObject, - pushTopLevelContextObject: pushTopLevelContextObject, - processChildContext: processChildContext_1, - pushContextProvider: pushContextProvider, - invalidateContextProvider: invalidateContextProvider, - resetContext: resetContext, - findCurrentUnmaskedContext: findCurrentUnmaskedContext$1 - }, ReactTypeOfInternalContext = { - NoContext: 0, - AsyncUpdates: 1 - }, IndeterminateComponent$1 = ReactTypeOfWork.IndeterminateComponent, ClassComponent$4 = ReactTypeOfWork.ClassComponent, HostRoot$4 = ReactTypeOfWork.HostRoot, HostComponent$4 = ReactTypeOfWork.HostComponent, HostText$2 = ReactTypeOfWork.HostText, HostPortal$2 = ReactTypeOfWork.HostPortal, CoroutineComponent = ReactTypeOfWork.CoroutineComponent, YieldComponent$1 = ReactTypeOfWork.YieldComponent, Fragment$1 = ReactTypeOfWork.Fragment, NoWork$1 = ReactPriorityLevel.NoWork, NoContext = ReactTypeOfInternalContext.NoContext, NoEffect$1 = ReactTypeOfSideEffect.NoEffect, getComponentName$5 = getComponentName_1, hasBadMapPolyfill = !1; - try { - var nonExtensibleObject = Object.preventExtensions({}); - new Map([ [ nonExtensibleObject, null ] ]), new Set([ nonExtensibleObject ]); - } catch (e) { - hasBadMapPolyfill = !0; - } - var debugCounter = 1; - function FiberNode(tag, key, internalContextTag) { - this.tag = tag, this.key = key, this.type = null, this.stateNode = null, this.return = null, - this.child = null, this.sibling = null, this.index = 0, this.ref = null, this.pendingProps = null, - this.memoizedProps = null, this.updateQueue = null, this.memoizedState = null, this.internalContextTag = internalContextTag, - this.effectTag = NoEffect$1, this.nextEffect = null, this.firstEffect = null, this.lastEffect = null, - this.pendingWorkPriority = NoWork$1, this.alternate = null, this._debugID = debugCounter++, - this._debugSource = null, this._debugOwner = null, this._debugIsCurrentlyTiming = !1, - hasBadMapPolyfill || "function" != typeof Object.preventExtensions || Object.preventExtensions(this); - } - var createFiber = function(tag, key, internalContextTag) { - return new FiberNode(tag, key, internalContextTag); - }; - function shouldConstruct(Component) { - return !(!Component.prototype || !Component.prototype.isReactComponent); - } - var createWorkInProgress = function(current, renderPriority) { - var workInProgress = current.alternate; - return null === workInProgress ? (workInProgress = createFiber(current.tag, current.key, current.internalContextTag), - workInProgress.type = current.type, workInProgress.stateNode = current.stateNode, - workInProgress._debugID = current._debugID, workInProgress._debugSource = current._debugSource, - workInProgress._debugOwner = current._debugOwner, workInProgress.alternate = current, - current.alternate = workInProgress) : (workInProgress.effectTag = NoEffect$1, workInProgress.nextEffect = null, - workInProgress.firstEffect = null, workInProgress.lastEffect = null), workInProgress.pendingWorkPriority = renderPriority, - workInProgress.child = current.child, workInProgress.memoizedProps = current.memoizedProps, - workInProgress.memoizedState = current.memoizedState, workInProgress.updateQueue = current.updateQueue, - workInProgress.sibling = current.sibling, workInProgress.index = current.index, - workInProgress.ref = current.ref, workInProgress; - }, createHostRootFiber$1 = function() { - return createFiber(HostRoot$4, null, NoContext); - }, createFiberFromElement = function(element, internalContextTag, priorityLevel) { - var owner = null; - owner = element._owner; - var fiber = createFiberFromElementType(element.type, element.key, internalContextTag, owner); - return fiber.pendingProps = element.props, fiber.pendingWorkPriority = priorityLevel, - fiber._debugSource = element._source, fiber._debugOwner = element._owner, fiber; - }, createFiberFromFragment = function(elements, internalContextTag, priorityLevel) { - var fiber = createFiber(Fragment$1, null, internalContextTag); - return fiber.pendingProps = elements, fiber.pendingWorkPriority = priorityLevel, - fiber; - }, createFiberFromText = function(content, internalContextTag, priorityLevel) { - var fiber = createFiber(HostText$2, null, internalContextTag); - return fiber.pendingProps = content, fiber.pendingWorkPriority = priorityLevel, - fiber; - }; - function createFiberFromElementType(type, key, internalContextTag, debugOwner) { - var fiber = void 0; - if ("function" == typeof type) fiber = shouldConstruct(type) ? createFiber(ClassComponent$4, key, internalContextTag) : createFiber(IndeterminateComponent$1, key, internalContextTag), - fiber.type = type; else if ("string" == typeof type) fiber = createFiber(HostComponent$4, key, internalContextTag), - fiber.type = type; else if ("object" == typeof type && null !== type && "number" == typeof type.tag) fiber = type; else { - var info = ""; - (void 0 === type || "object" == typeof type && null !== type && 0 === Object.keys(type).length) && (info += " You likely forgot to export your component from the file " + "it's defined in."); - var ownerName = debugOwner ? getComponentName$5(debugOwner) : null; - ownerName && (info += "\n\nCheck the render method of `" + ownerName + "`."), invariant(!1, "Element type is invalid: expected a string (for built-in components) " + "or a class/function (for composite components) but got: %s.%s", null == type ? type : typeof type, info); - } - return fiber; - } - var REACT_COROUTINE_TYPE$1, REACT_YIELD_TYPE$1, createFiberFromElementType_1 = createFiberFromElementType, createFiberFromHostInstanceForDeletion = function() { - var fiber = createFiber(HostComponent$4, null, NoContext); - return fiber.type = "DELETED", fiber; - }, createFiberFromCoroutine = function(coroutine, internalContextTag, priorityLevel) { - var fiber = createFiber(CoroutineComponent, coroutine.key, internalContextTag); - return fiber.type = coroutine.handler, fiber.pendingProps = coroutine, fiber.pendingWorkPriority = priorityLevel, - fiber; - }, createFiberFromYield = function(yieldNode, internalContextTag, priorityLevel) { - return createFiber(YieldComponent$1, null, internalContextTag); - }, createFiberFromPortal = function(portal, internalContextTag, priorityLevel) { - var fiber = createFiber(HostPortal$2, portal.key, internalContextTag); - return fiber.pendingProps = portal.children || [], fiber.pendingWorkPriority = priorityLevel, - fiber.stateNode = { - containerInfo: portal.containerInfo, - implementation: portal.implementation - }, fiber; - }, largerPriority = function(p1, p2) { - return p1 !== NoWork$1 && (p2 === NoWork$1 || p2 > p1) ? p1 : p2; - }, ReactFiber = { - createWorkInProgress: createWorkInProgress, - createHostRootFiber: createHostRootFiber$1, - createFiberFromElement: createFiberFromElement, - createFiberFromFragment: createFiberFromFragment, - createFiberFromText: createFiberFromText, - createFiberFromElementType: createFiberFromElementType_1, - createFiberFromHostInstanceForDeletion: createFiberFromHostInstanceForDeletion, - createFiberFromCoroutine: createFiberFromCoroutine, - createFiberFromYield: createFiberFromYield, - createFiberFromPortal: createFiberFromPortal, - largerPriority: largerPriority - }, createHostRootFiber = ReactFiber.createHostRootFiber, createFiberRoot$1 = function(containerInfo) { - var uninitializedFiber = createHostRootFiber(), root = { - current: uninitializedFiber, - containerInfo: containerInfo, - isScheduled: !1, - nextScheduledRoot: null, - context: null, - pendingContext: null - }; - return uninitializedFiber.stateNode = root, root; - }, ReactFiberRoot = { - createFiberRoot: createFiberRoot$1 - }; - "function" == typeof Symbol && Symbol.for ? (REACT_COROUTINE_TYPE$1 = Symbol.for("react.coroutine"), - REACT_YIELD_TYPE$1 = Symbol.for("react.yield")) : (REACT_COROUTINE_TYPE$1 = 60104, - REACT_YIELD_TYPE$1 = 60105); - var createCoroutine = function(children, handler, props) { - var key = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : null, coroutine = { - $$typeof: REACT_COROUTINE_TYPE$1, - key: null == key ? null : "" + key, - children: children, - handler: handler, - props: props - }; - return Object.freeze && (Object.freeze(coroutine.props), Object.freeze(coroutine)), - coroutine; - }, createYield = function(value) { - var yieldNode = { - $$typeof: REACT_YIELD_TYPE$1, - value: value - }; - return Object.freeze && Object.freeze(yieldNode), yieldNode; - }, isCoroutine = function(object) { - return "object" == typeof object && null !== object && object.$$typeof === REACT_COROUTINE_TYPE$1; - }, isYield = function(object) { - return "object" == typeof object && null !== object && object.$$typeof === REACT_YIELD_TYPE$1; - }, REACT_YIELD_TYPE_1 = REACT_YIELD_TYPE$1, REACT_COROUTINE_TYPE_1 = REACT_COROUTINE_TYPE$1, ReactCoroutine = { - createCoroutine: createCoroutine, - createYield: createYield, - isCoroutine: isCoroutine, - isYield: isYield, - REACT_YIELD_TYPE: REACT_YIELD_TYPE_1, - REACT_COROUTINE_TYPE: REACT_COROUTINE_TYPE_1 - }, REACT_COROUTINE_TYPE = ReactCoroutine.REACT_COROUTINE_TYPE, REACT_YIELD_TYPE = ReactCoroutine.REACT_YIELD_TYPE, REACT_PORTAL_TYPE$1 = ReactPortal.REACT_PORTAL_TYPE, _require3$2 = ReactDebugCurrentFiber_1, getCurrentFiberStackAddendum$1 = _require3$2.getCurrentFiberStackAddendum, warning$8 = require$$0, didWarnAboutMaps = !1, ownerHasKeyUseWarning = {}, warnForMissingKey = function(child) { - if (null !== child && "object" == typeof child && child._store && !child._store.validated && null == child.key) { - invariant("object" == typeof child._store, "React Component in warnForMissingKey should have a _store. " + "This error is likely caused by a bug in React. Please file an issue."), - child._store.validated = !0; - var currentComponentErrorInfo = "Each child in an array or iterator should have a unique " + '"key" prop. See https://fb.me/react-warning-keys for ' + "more information." + (getCurrentFiberStackAddendum$1() || ""); - ownerHasKeyUseWarning[currentComponentErrorInfo] || (ownerHasKeyUseWarning[currentComponentErrorInfo] = !0, - warning$8(!1, "Each child in an array or iterator should have a unique " + '"key" prop. See https://fb.me/react-warning-keys for ' + "more information.%s", getCurrentFiberStackAddendum$1())); - } - }, createWorkInProgress$2 = ReactFiber.createWorkInProgress, createFiberFromElement$1 = ReactFiber.createFiberFromElement, createFiberFromFragment$1 = ReactFiber.createFiberFromFragment, createFiberFromText$1 = ReactFiber.createFiberFromText, createFiberFromCoroutine$1 = ReactFiber.createFiberFromCoroutine, createFiberFromYield$1 = ReactFiber.createFiberFromYield, createFiberFromPortal$1 = ReactFiber.createFiberFromPortal, isArray = Array.isArray, FunctionalComponent$2 = ReactTypeOfWork.FunctionalComponent, ClassComponent$7 = ReactTypeOfWork.ClassComponent, HostText$4 = ReactTypeOfWork.HostText, HostPortal$5 = ReactTypeOfWork.HostPortal, CoroutineComponent$2 = ReactTypeOfWork.CoroutineComponent, YieldComponent$3 = ReactTypeOfWork.YieldComponent, Fragment$3 = ReactTypeOfWork.Fragment, NoEffect$2 = ReactTypeOfSideEffect.NoEffect, Placement$3 = ReactTypeOfSideEffect.Placement, Deletion$1 = ReactTypeOfSideEffect.Deletion, ITERATOR_SYMBOL = "function" == typeof Symbol && Symbol.iterator, REACT_ELEMENT_TYPE = "function" == typeof Symbol && Symbol.for && Symbol.for("react.element") || 60103; - function getIteratorFn(maybeIterable) { - if (null === maybeIterable || void 0 === maybeIterable) return null; - var iteratorFn = ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable["@@iterator"]; - return "function" == typeof iteratorFn ? iteratorFn : null; - } - function coerceRef(current, element) { - var mixedRef = element.ref; - if (null !== mixedRef && "function" != typeof mixedRef) { - if (element._owner) { - var owner = element._owner, inst = void 0; - if (owner) { - var ownerFiber = owner; - invariant(ownerFiber.tag === ClassComponent$7, "Stateless function components cannot have refs."), - inst = ownerFiber.stateNode; - } - invariant(inst, "Missing owner for string ref %s. This error is likely caused by a " + "bug in React. Please file an issue.", mixedRef); - var stringRef = "" + mixedRef; - if (null !== current && null !== current.ref && current.ref._stringRef === stringRef) return current.ref; - var ref = function(value) { - var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs; - null === value ? delete refs[stringRef] : refs[stringRef] = value; - }; - return ref._stringRef = stringRef, ref; - } - invariant("string" == typeof mixedRef, "Expected ref to be a function or a string."), - invariant(element._owner, "Element ref was specified as a string (%s) but no owner was " + "set. You may have multiple copies of React loaded. " + "(details: https://fb.me/react-refs-must-have-owner).", mixedRef); - } - return mixedRef; - } - function throwOnInvalidObjectType(returnFiber, newChild) { - if ("textarea" !== returnFiber.type) { - var addendum = ""; - addendum = " If you meant to render a collection of children, use an array " + "instead." + (getCurrentFiberStackAddendum$1() || ""), - invariant(!1, "Objects are not valid as a React child (found: %s).%s", "[object Object]" === Object.prototype.toString.call(newChild) ? "object with keys {" + Object.keys(newChild).join(", ") + "}" : newChild, addendum); - } - } - function warnOnFunctionType() { - warning$8(!1, "Functions are not valid as a React child. This may happen if " + "you return a Component instead of from render. " + "Or maybe you meant to call this function rather than return it.%s", getCurrentFiberStackAddendum$1() || ""); - } - function ChildReconciler(shouldClone, shouldTrackSideEffects) { - function deleteChild(returnFiber, childToDelete) { - if (shouldTrackSideEffects) { - if (!shouldClone) { - if (null === childToDelete.alternate) return; - childToDelete = childToDelete.alternate; - } - var last = returnFiber.lastEffect; - null !== last ? (last.nextEffect = childToDelete, returnFiber.lastEffect = childToDelete) : returnFiber.firstEffect = returnFiber.lastEffect = childToDelete, - childToDelete.nextEffect = null, childToDelete.effectTag = Deletion$1; - } - } - function deleteRemainingChildren(returnFiber, currentFirstChild) { - if (!shouldTrackSideEffects) return null; - for (var childToDelete = currentFirstChild; null !== childToDelete; ) deleteChild(returnFiber, childToDelete), - childToDelete = childToDelete.sibling; - return null; - } - function mapRemainingChildren(returnFiber, currentFirstChild) { - for (var existingChildren = new Map(), existingChild = currentFirstChild; null !== existingChild; ) null !== existingChild.key ? existingChildren.set(existingChild.key, existingChild) : existingChildren.set(existingChild.index, existingChild), - existingChild = existingChild.sibling; - return existingChildren; - } - function useFiber(fiber, priority) { - if (shouldClone) { - var clone = createWorkInProgress$2(fiber, priority); - return clone.index = 0, clone.sibling = null, clone; - } - return fiber.pendingWorkPriority = priority, fiber.effectTag = NoEffect$2, fiber.index = 0, - fiber.sibling = null, fiber; - } - function placeChild(newFiber, lastPlacedIndex, newIndex) { - if (newFiber.index = newIndex, !shouldTrackSideEffects) return lastPlacedIndex; - var current = newFiber.alternate; - if (null !== current) { - var oldIndex = current.index; - return oldIndex < lastPlacedIndex ? (newFiber.effectTag = Placement$3, lastPlacedIndex) : oldIndex; - } - return newFiber.effectTag = Placement$3, lastPlacedIndex; - } - function placeSingleChild(newFiber) { - return shouldTrackSideEffects && null === newFiber.alternate && (newFiber.effectTag = Placement$3), - newFiber; - } - function updateTextNode(returnFiber, current, textContent, priority) { - if (null === current || current.tag !== HostText$4) { - var created = createFiberFromText$1(textContent, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - var existing = useFiber(current, priority); - return existing.pendingProps = textContent, existing.return = returnFiber, existing; - } - function updateElement(returnFiber, current, element, priority) { - if (null === current || current.type !== element.type) { - var created = createFiberFromElement$1(element, returnFiber.internalContextTag, priority); - return created.ref = coerceRef(current, element), created.return = returnFiber, - created; - } - var existing = useFiber(current, priority); - return existing.ref = coerceRef(current, element), existing.pendingProps = element.props, - existing.return = returnFiber, existing._debugSource = element._source, existing._debugOwner = element._owner, - existing; - } - function updateCoroutine(returnFiber, current, coroutine, priority) { - if (null === current || current.tag !== CoroutineComponent$2) { - var created = createFiberFromCoroutine$1(coroutine, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - var existing = useFiber(current, priority); - return existing.pendingProps = coroutine, existing.return = returnFiber, existing; - } - function updateYield(returnFiber, current, yieldNode, priority) { - if (null === current || current.tag !== YieldComponent$3) { - var created = createFiberFromYield$1(yieldNode, returnFiber.internalContextTag, priority); - return created.type = yieldNode.value, created.return = returnFiber, created; - } - var existing = useFiber(current, priority); - return existing.type = yieldNode.value, existing.return = returnFiber, existing; - } - function updatePortal(returnFiber, current, portal, priority) { - if (null === current || current.tag !== HostPortal$5 || current.stateNode.containerInfo !== portal.containerInfo || current.stateNode.implementation !== portal.implementation) { - var created = createFiberFromPortal$1(portal, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - var existing = useFiber(current, priority); - return existing.pendingProps = portal.children || [], existing.return = returnFiber, - existing; - } - function updateFragment(returnFiber, current, fragment, priority) { - if (null === current || current.tag !== Fragment$3) { - var created = createFiberFromFragment$1(fragment, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - var existing = useFiber(current, priority); - return existing.pendingProps = fragment, existing.return = returnFiber, existing; - } - function createChild(returnFiber, newChild, priority) { - if ("string" == typeof newChild || "number" == typeof newChild) { - var created = createFiberFromText$1("" + newChild, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - if ("object" == typeof newChild && null !== newChild) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: - var _created = createFiberFromElement$1(newChild, returnFiber.internalContextTag, priority); - return _created.ref = coerceRef(null, newChild), _created.return = returnFiber, - _created; - - case REACT_COROUTINE_TYPE: - var _created2 = createFiberFromCoroutine$1(newChild, returnFiber.internalContextTag, priority); - return _created2.return = returnFiber, _created2; - - case REACT_YIELD_TYPE: - var _created3 = createFiberFromYield$1(newChild, returnFiber.internalContextTag, priority); - return _created3.type = newChild.value, _created3.return = returnFiber, _created3; - - case REACT_PORTAL_TYPE$1: - var _created4 = createFiberFromPortal$1(newChild, returnFiber.internalContextTag, priority); - return _created4.return = returnFiber, _created4; - } - if (isArray(newChild) || getIteratorFn(newChild)) { - var _created5 = createFiberFromFragment$1(newChild, returnFiber.internalContextTag, priority); - return _created5.return = returnFiber, _created5; - } - throwOnInvalidObjectType(returnFiber, newChild); - } - return "function" == typeof newChild && warnOnFunctionType(), null; - } - function updateSlot(returnFiber, oldFiber, newChild, priority) { - var key = null !== oldFiber ? oldFiber.key : null; - if ("string" == typeof newChild || "number" == typeof newChild) return null !== key ? null : updateTextNode(returnFiber, oldFiber, "" + newChild, priority); - if ("object" == typeof newChild && null !== newChild) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: - return newChild.key === key ? updateElement(returnFiber, oldFiber, newChild, priority) : null; - - case REACT_COROUTINE_TYPE: - return newChild.key === key ? updateCoroutine(returnFiber, oldFiber, newChild, priority) : null; - - case REACT_YIELD_TYPE: - return null === key ? updateYield(returnFiber, oldFiber, newChild, priority) : null; - - case REACT_PORTAL_TYPE$1: - return newChild.key === key ? updatePortal(returnFiber, oldFiber, newChild, priority) : null; - } - if (isArray(newChild) || getIteratorFn(newChild)) return null !== key ? null : updateFragment(returnFiber, oldFiber, newChild, priority); - throwOnInvalidObjectType(returnFiber, newChild); - } - return "function" == typeof newChild && warnOnFunctionType(), null; - } - function updateFromMap(existingChildren, returnFiber, newIdx, newChild, priority) { - if ("string" == typeof newChild || "number" == typeof newChild) { - return updateTextNode(returnFiber, existingChildren.get(newIdx) || null, "" + newChild, priority); - } - if ("object" == typeof newChild && null !== newChild) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: - return updateElement(returnFiber, existingChildren.get(null === newChild.key ? newIdx : newChild.key) || null, newChild, priority); - - case REACT_COROUTINE_TYPE: - return updateCoroutine(returnFiber, existingChildren.get(null === newChild.key ? newIdx : newChild.key) || null, newChild, priority); - - case REACT_YIELD_TYPE: - return updateYield(returnFiber, existingChildren.get(newIdx) || null, newChild, priority); - - case REACT_PORTAL_TYPE$1: - return updatePortal(returnFiber, existingChildren.get(null === newChild.key ? newIdx : newChild.key) || null, newChild, priority); - } - if (isArray(newChild) || getIteratorFn(newChild)) { - return updateFragment(returnFiber, existingChildren.get(newIdx) || null, newChild, priority); - } - throwOnInvalidObjectType(returnFiber, newChild); - } - return "function" == typeof newChild && warnOnFunctionType(), null; - } - function warnOnInvalidKey(child, knownKeys) { - if ("object" != typeof child || null === child) return knownKeys; - switch (child.$$typeof) { - case REACT_ELEMENT_TYPE: - case REACT_COROUTINE_TYPE: - case REACT_PORTAL_TYPE$1: - warnForMissingKey(child); - var key = child.key; - if ("string" != typeof key) break; - if (null === knownKeys) { - knownKeys = new Set(), knownKeys.add(key); - break; - } - if (!knownKeys.has(key)) { - knownKeys.add(key); - break; - } - warning$8(!1, "Encountered two children with the same key, `%s`. " + "Keys should be unique so that components maintain their identity " + "across updates. Non-unique keys may cause children to be " + "duplicated and/or omitted — the behavior is unsupported and " + "could change in a future version.%s", key, getCurrentFiberStackAddendum$1()); - } - return knownKeys; - } - function reconcileChildrenArray(returnFiber, currentFirstChild, newChildren, priority) { - for (var knownKeys = null, i = 0; i < newChildren.length; i++) { - knownKeys = warnOnInvalidKey(newChildren[i], knownKeys); - } - for (var resultingFirstChild = null, previousNewFiber = null, oldFiber = currentFirstChild, lastPlacedIndex = 0, newIdx = 0, nextOldFiber = null; null !== oldFiber && newIdx < newChildren.length; newIdx++) { - oldFiber.index > newIdx ? (nextOldFiber = oldFiber, oldFiber = null) : nextOldFiber = oldFiber.sibling; - var newFiber = updateSlot(returnFiber, oldFiber, newChildren[newIdx], priority); - if (null === newFiber) { - null === oldFiber && (oldFiber = nextOldFiber); - break; - } - shouldTrackSideEffects && oldFiber && null === newFiber.alternate && deleteChild(returnFiber, oldFiber), - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx), null === previousNewFiber ? resultingFirstChild = newFiber : previousNewFiber.sibling = newFiber, - previousNewFiber = newFiber, oldFiber = nextOldFiber; - } - if (newIdx === newChildren.length) return deleteRemainingChildren(returnFiber, oldFiber), - resultingFirstChild; - if (null === oldFiber) { - for (;newIdx < newChildren.length; newIdx++) { - var _newFiber = createChild(returnFiber, newChildren[newIdx], priority); - _newFiber && (lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx), - null === previousNewFiber ? resultingFirstChild = _newFiber : previousNewFiber.sibling = _newFiber, - previousNewFiber = _newFiber); - } - return resultingFirstChild; - } - for (var existingChildren = mapRemainingChildren(returnFiber, oldFiber); newIdx < newChildren.length; newIdx++) { - var _newFiber2 = updateFromMap(existingChildren, returnFiber, newIdx, newChildren[newIdx], priority); - _newFiber2 && (shouldTrackSideEffects && null !== _newFiber2.alternate && existingChildren.delete(null === _newFiber2.key ? newIdx : _newFiber2.key), - lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx), null === previousNewFiber ? resultingFirstChild = _newFiber2 : previousNewFiber.sibling = _newFiber2, - previousNewFiber = _newFiber2); - } - return shouldTrackSideEffects && existingChildren.forEach(function(child) { - return deleteChild(returnFiber, child); - }), resultingFirstChild; - } - function reconcileChildrenIterator(returnFiber, currentFirstChild, newChildrenIterable, priority) { - var iteratorFn = getIteratorFn(newChildrenIterable); - if (invariant("function" == typeof iteratorFn, "An object is not an iterable. This error is likely caused by a bug in " + "React. Please file an issue."), - "function" == typeof newChildrenIterable.entries) { - newChildrenIterable.entries === iteratorFn && (warning$8(didWarnAboutMaps, "Using Maps as children is unsupported and will likely yield " + "unexpected results. Convert it to a sequence/iterable of keyed " + "ReactElements instead.%s", getCurrentFiberStackAddendum$1()), - didWarnAboutMaps = !0); - } - var _newChildren = iteratorFn.call(newChildrenIterable); - if (_newChildren) for (var knownKeys = null, _step = _newChildren.next(); !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys); - } - var newChildren = iteratorFn.call(newChildrenIterable); - invariant(null != newChildren, "An iterable object provided no iterator."); - for (var resultingFirstChild = null, previousNewFiber = null, oldFiber = currentFirstChild, lastPlacedIndex = 0, newIdx = 0, nextOldFiber = null, step = newChildren.next(); null !== oldFiber && !step.done; newIdx++, - step = newChildren.next()) { - oldFiber.index > newIdx ? (nextOldFiber = oldFiber, oldFiber = null) : nextOldFiber = oldFiber.sibling; - var newFiber = updateSlot(returnFiber, oldFiber, step.value, priority); - if (null === newFiber) { - oldFiber || (oldFiber = nextOldFiber); - break; - } - shouldTrackSideEffects && oldFiber && null === newFiber.alternate && deleteChild(returnFiber, oldFiber), - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx), null === previousNewFiber ? resultingFirstChild = newFiber : previousNewFiber.sibling = newFiber, - previousNewFiber = newFiber, oldFiber = nextOldFiber; - } - if (step.done) return deleteRemainingChildren(returnFiber, oldFiber), resultingFirstChild; - if (null === oldFiber) { - for (;!step.done; newIdx++, step = newChildren.next()) { - var _newFiber3 = createChild(returnFiber, step.value, priority); - null !== _newFiber3 && (lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx), - null === previousNewFiber ? resultingFirstChild = _newFiber3 : previousNewFiber.sibling = _newFiber3, - previousNewFiber = _newFiber3); - } - return resultingFirstChild; - } - for (var existingChildren = mapRemainingChildren(returnFiber, oldFiber); !step.done; newIdx++, - step = newChildren.next()) { - var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, priority); - null !== _newFiber4 && (shouldTrackSideEffects && null !== _newFiber4.alternate && existingChildren.delete(null === _newFiber4.key ? newIdx : _newFiber4.key), - lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx), null === previousNewFiber ? resultingFirstChild = _newFiber4 : previousNewFiber.sibling = _newFiber4, - previousNewFiber = _newFiber4); - } - return shouldTrackSideEffects && existingChildren.forEach(function(child) { - return deleteChild(returnFiber, child); - }), resultingFirstChild; - } - function reconcileSingleTextNode(returnFiber, currentFirstChild, textContent, priority) { - if (null !== currentFirstChild && currentFirstChild.tag === HostText$4) { - deleteRemainingChildren(returnFiber, currentFirstChild.sibling); - var existing = useFiber(currentFirstChild, priority); - return existing.pendingProps = textContent, existing.return = returnFiber, existing; - } - deleteRemainingChildren(returnFiber, currentFirstChild); - var created = createFiberFromText$1(textContent, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - function reconcileSingleElement(returnFiber, currentFirstChild, element, priority) { - for (var key = element.key, child = currentFirstChild; null !== child; ) { - if (child.key === key) { - if (child.type === element.type) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, priority); - return existing.ref = coerceRef(child, element), existing.pendingProps = element.props, - existing.return = returnFiber, existing._debugSource = element._source, existing._debugOwner = element._owner, - existing; - } - deleteRemainingChildren(returnFiber, child); - break; - } - deleteChild(returnFiber, child), child = child.sibling; - } - var created = createFiberFromElement$1(element, returnFiber.internalContextTag, priority); - return created.ref = coerceRef(currentFirstChild, element), created.return = returnFiber, - created; - } - function reconcileSingleCoroutine(returnFiber, currentFirstChild, coroutine, priority) { - for (var key = coroutine.key, child = currentFirstChild; null !== child; ) { - if (child.key === key) { - if (child.tag === CoroutineComponent$2) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, priority); - return existing.pendingProps = coroutine, existing.return = returnFiber, existing; - } - deleteRemainingChildren(returnFiber, child); - break; - } - deleteChild(returnFiber, child), child = child.sibling; - } - var created = createFiberFromCoroutine$1(coroutine, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - function reconcileSingleYield(returnFiber, currentFirstChild, yieldNode, priority) { - var child = currentFirstChild; - if (null !== child) { - if (child.tag === YieldComponent$3) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, priority); - return existing.type = yieldNode.value, existing.return = returnFiber, existing; - } - deleteRemainingChildren(returnFiber, child); - } - var created = createFiberFromYield$1(yieldNode, returnFiber.internalContextTag, priority); - return created.type = yieldNode.value, created.return = returnFiber, created; - } - function reconcileSinglePortal(returnFiber, currentFirstChild, portal, priority) { - for (var key = portal.key, child = currentFirstChild; null !== child; ) { - if (child.key === key) { - if (child.tag === HostPortal$5 && child.stateNode.containerInfo === portal.containerInfo && child.stateNode.implementation === portal.implementation) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, priority); - return existing.pendingProps = portal.children || [], existing.return = returnFiber, - existing; - } - deleteRemainingChildren(returnFiber, child); - break; - } - deleteChild(returnFiber, child), child = child.sibling; - } - var created = createFiberFromPortal$1(portal, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - function reconcileChildFibers(returnFiber, currentFirstChild, newChild, priority) { - var isObject = "object" == typeof newChild && null !== newChild; - if (isObject) switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: - return placeSingleChild(reconcileSingleElement(returnFiber, currentFirstChild, newChild, priority)); - - case REACT_COROUTINE_TYPE: - return placeSingleChild(reconcileSingleCoroutine(returnFiber, currentFirstChild, newChild, priority)); - - case REACT_YIELD_TYPE: - return placeSingleChild(reconcileSingleYield(returnFiber, currentFirstChild, newChild, priority)); - - case REACT_PORTAL_TYPE$1: - return placeSingleChild(reconcileSinglePortal(returnFiber, currentFirstChild, newChild, priority)); - } - if ("string" == typeof newChild || "number" == typeof newChild) return placeSingleChild(reconcileSingleTextNode(returnFiber, currentFirstChild, "" + newChild, priority)); - if (isArray(newChild)) return reconcileChildrenArray(returnFiber, currentFirstChild, newChild, priority); - if (getIteratorFn(newChild)) return reconcileChildrenIterator(returnFiber, currentFirstChild, newChild, priority); - if (isObject && throwOnInvalidObjectType(returnFiber, newChild), "function" == typeof newChild && warnOnFunctionType(), - void 0 === newChild) switch (returnFiber.tag) { - case ClassComponent$7: - if (returnFiber.stateNode.render._isMockFunction) break; - - case FunctionalComponent$2: - var Component = returnFiber.type; - invariant(!1, "%s(...): Nothing was returned from render. This usually means a " + "return statement is missing. Or, to render nothing, " + "return null.", Component.displayName || Component.name || "Component"); - } - return deleteRemainingChildren(returnFiber, currentFirstChild); - } - return reconcileChildFibers; - } - var reconcileChildFibers$1 = ChildReconciler(!0, !0), reconcileChildFibersInPlace$1 = ChildReconciler(!1, !0), mountChildFibersInPlace$1 = ChildReconciler(!1, !1), cloneChildFibers$1 = function(current, workInProgress) { - if (invariant(null === current || workInProgress.child === current.child, "Resuming work not yet implemented."), - null !== workInProgress.child) { - var currentChild = workInProgress.child, newChild = createWorkInProgress$2(currentChild, currentChild.pendingWorkPriority); - for (newChild.pendingProps = currentChild.pendingProps, workInProgress.child = newChild, - newChild.return = workInProgress; null !== currentChild.sibling; ) currentChild = currentChild.sibling, - newChild = newChild.sibling = createWorkInProgress$2(currentChild, currentChild.pendingWorkPriority), - newChild.pendingProps = currentChild.pendingProps, newChild.return = workInProgress; - newChild.sibling = null; - } - }, ReactChildFiber = { - reconcileChildFibers: reconcileChildFibers$1, - reconcileChildFibersInPlace: reconcileChildFibersInPlace$1, - mountChildFibersInPlace: mountChildFibersInPlace$1, - cloneChildFibers: cloneChildFibers$1 - }, Update$1 = ReactTypeOfSideEffect.Update, AsyncUpdates$1 = ReactTypeOfInternalContext.AsyncUpdates, cacheContext$1 = ReactFiberContext.cacheContext, getMaskedContext$2 = ReactFiberContext.getMaskedContext, getUnmaskedContext$2 = ReactFiberContext.getUnmaskedContext, isContextConsumer$1 = ReactFiberContext.isContextConsumer, addUpdate$1 = ReactFiberUpdateQueue.addUpdate, addReplaceUpdate$1 = ReactFiberUpdateQueue.addReplaceUpdate, addForceUpdate$1 = ReactFiberUpdateQueue.addForceUpdate, beginUpdateQueue$2 = ReactFiberUpdateQueue.beginUpdateQueue, _require5 = ReactFiberContext, hasContextChanged$2 = _require5.hasContextChanged, isMounted$1 = ReactFiberTreeReflection.isMounted, fakeInternalInstance = {}, isArray$1 = Array.isArray, _require7$1 = ReactDebugFiberPerf_1, startPhaseTimer$1 = _require7$1.startPhaseTimer, stopPhaseTimer$1 = _require7$1.stopPhaseTimer, warning$9 = require$$0, warnOnInvalidCallback = function(callback, callerName) { - warning$9(null === callback || "function" == typeof callback, "%s(...): Expected the last optional `callback` argument to be a " + "function. Instead received: %s.", callerName, callback); - }; - Object.defineProperty(fakeInternalInstance, "_processChildContext", { - enumerable: !1, - value: function() { - invariant(!1, "_processChildContext is not available in React 16+. This likely " + "means you have multiple copies of React and are attempting to nest " + "a React 15 tree inside a React 16 tree using " + "unstable_renderSubtreeIntoContainer, which isn't supported. Try " + "to make sure you have only one copy of React (and ideally, switch " + "to ReactDOM.createPortal)."); - } - }), Object.freeze(fakeInternalInstance); - var ReactFiberClassComponent = function(scheduleUpdate, getPriorityContext, memoizeProps, memoizeState) { - var updater = { - isMounted: isMounted$1, - enqueueSetState: function(instance, partialState, callback) { - var fiber = ReactInstanceMap_1.get(instance), priorityLevel = getPriorityContext(fiber, !1); - callback = void 0 === callback ? null : callback, warnOnInvalidCallback(callback, "setState"), - addUpdate$1(fiber, partialState, callback, priorityLevel), scheduleUpdate(fiber, priorityLevel); - }, - enqueueReplaceState: function(instance, state, callback) { - var fiber = ReactInstanceMap_1.get(instance), priorityLevel = getPriorityContext(fiber, !1); - callback = void 0 === callback ? null : callback, warnOnInvalidCallback(callback, "replaceState"), - addReplaceUpdate$1(fiber, state, callback, priorityLevel), scheduleUpdate(fiber, priorityLevel); - }, - enqueueForceUpdate: function(instance, callback) { - var fiber = ReactInstanceMap_1.get(instance), priorityLevel = getPriorityContext(fiber, !1); - callback = void 0 === callback ? null : callback, warnOnInvalidCallback(callback, "forceUpdate"), - addForceUpdate$1(fiber, callback, priorityLevel), scheduleUpdate(fiber, priorityLevel); - } - }; - function checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext) { - if (null === oldProps || null !== workInProgress.updateQueue && workInProgress.updateQueue.hasForceUpdate) return !0; - var instance = workInProgress.stateNode, type = workInProgress.type; - if ("function" == typeof instance.shouldComponentUpdate) { - startPhaseTimer$1(workInProgress, "shouldComponentUpdate"); - var shouldUpdate = instance.shouldComponentUpdate(newProps, newState, newContext); - return stopPhaseTimer$1(), warning$9(void 0 !== shouldUpdate, "%s.shouldComponentUpdate(): Returned undefined instead of a " + "boolean value. Make sure to return true or false.", getComponentName_1(workInProgress) || "Unknown"), - shouldUpdate; - } - return !type.prototype || !type.prototype.isPureReactComponent || (!shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)); - } - function checkClassInstance(workInProgress) { - var instance = workInProgress.stateNode, type = workInProgress.type, name = getComponentName_1(workInProgress), renderPresent = instance.render; - warning$9(renderPresent, "%s(...): No `render` method found on the returned component " + "instance: you may have forgotten to define `render`.", name); - var noGetInitialStateOnES6 = !instance.getInitialState || instance.getInitialState.isReactClassApproved || instance.state; - warning$9(noGetInitialStateOnES6, "getInitialState was defined on %s, a plain JavaScript class. " + "This is only supported for classes created using React.createClass. " + "Did you mean to define a state property instead?", name); - var noGetDefaultPropsOnES6 = !instance.getDefaultProps || instance.getDefaultProps.isReactClassApproved; - warning$9(noGetDefaultPropsOnES6, "getDefaultProps was defined on %s, a plain JavaScript class. " + "This is only supported for classes created using React.createClass. " + "Use a static property to define defaultProps instead.", name); - var noInstancePropTypes = !instance.propTypes; - warning$9(noInstancePropTypes, "propTypes was defined as an instance property on %s. Use a static " + "property to define propTypes instead.", name); - var noInstanceContextTypes = !instance.contextTypes; - warning$9(noInstanceContextTypes, "contextTypes was defined as an instance property on %s. Use a static " + "property to define contextTypes instead.", name); - var noComponentShouldUpdate = "function" != typeof instance.componentShouldUpdate; - warning$9(noComponentShouldUpdate, "%s has a method called " + "componentShouldUpdate(). Did you mean shouldComponentUpdate()? " + "The name is phrased as a question because the function is " + "expected to return a value.", name), - type.prototype && type.prototype.isPureReactComponent && void 0 !== instance.shouldComponentUpdate && warning$9(!1, "%s has a method called shouldComponentUpdate(). " + "shouldComponentUpdate should not be used when extending React.PureComponent. " + "Please extend React.Component if shouldComponentUpdate is used.", getComponentName_1(workInProgress) || "A pure component"); - var noComponentDidUnmount = "function" != typeof instance.componentDidUnmount; - warning$9(noComponentDidUnmount, "%s has a method called " + "componentDidUnmount(). But there is no such lifecycle method. " + "Did you mean componentWillUnmount()?", name); - var noComponentWillRecieveProps = "function" != typeof instance.componentWillRecieveProps; - warning$9(noComponentWillRecieveProps, "%s has a method called " + "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", name); - var hasMutatedProps = instance.props !== workInProgress.pendingProps; - warning$9(void 0 === instance.props || !hasMutatedProps, "%s(...): When calling super() in `%s`, make sure to pass " + "up the same props that your component's constructor was passed.", name, name); - var noInstanceDefaultProps = !instance.defaultProps; - warning$9(noInstanceDefaultProps, "Setting defaultProps as an instance property on %s is not supported and will be ignored." + " Instead, define defaultProps as a static property on %s.", name, name); - var state = instance.state; - state && ("object" != typeof state || isArray$1(state)) && invariant(!1, "%s.state: must be set to an object or null", getComponentName_1(workInProgress)), - "function" == typeof instance.getChildContext && invariant("object" == typeof workInProgress.type.childContextTypes, "%s.getChildContext(): childContextTypes must be defined in order to " + "use getChildContext().", getComponentName_1(workInProgress)); - } - function resetInputPointers(workInProgress, instance) { - instance.props = workInProgress.memoizedProps, instance.state = workInProgress.memoizedState; - } - function adoptClassInstance(workInProgress, instance) { - instance.updater = updater, workInProgress.stateNode = instance, ReactInstanceMap_1.set(instance, workInProgress), - instance._reactInternalInstance = fakeInternalInstance; - } - function constructClassInstance(workInProgress, props) { - var ctor = workInProgress.type, unmaskedContext = getUnmaskedContext$2(workInProgress), needsContext = isContextConsumer$1(workInProgress), context = needsContext ? getMaskedContext$2(workInProgress, unmaskedContext) : emptyObject, instance = new ctor(props, context); - return adoptClassInstance(workInProgress, instance), needsContext && cacheContext$1(workInProgress, unmaskedContext, context), - instance; - } - function callComponentWillMount(workInProgress, instance) { - startPhaseTimer$1(workInProgress, "componentWillMount"); - var oldState = instance.state; - instance.componentWillMount(), stopPhaseTimer$1(), oldState !== instance.state && (warning$9(!1, "%s.componentWillMount(): Assigning directly to this.state is " + "deprecated (except inside a component's " + "constructor). Use setState instead.", getComponentName_1(workInProgress)), - updater.enqueueReplaceState(instance, instance.state, null)); - } - function callComponentWillReceiveProps(workInProgress, instance, newProps, newContext) { - startPhaseTimer$1(workInProgress, "componentWillReceiveProps"); - var oldState = instance.state; - instance.componentWillReceiveProps(newProps, newContext), stopPhaseTimer$1(), instance.state !== oldState && (warning$9(!1, "%s.componentWillReceiveProps(): Assigning directly to " + "this.state is deprecated (except inside a component's " + "constructor). Use setState instead.", getComponentName_1(workInProgress)), - updater.enqueueReplaceState(instance, instance.state, null)); - } - function mountClassInstance(workInProgress, priorityLevel) { - var current = workInProgress.alternate; - checkClassInstance(workInProgress); - var instance = workInProgress.stateNode, state = instance.state || null, props = workInProgress.pendingProps; - invariant(props, "There must be pending props for an initial mount. This error is " + "likely caused by a bug in React. Please file an issue."); - var unmaskedContext = getUnmaskedContext$2(workInProgress); - if (instance.props = props, instance.state = state, instance.refs = emptyObject, - instance.context = getMaskedContext$2(workInProgress, unmaskedContext), ReactFeatureFlags_1.enableAsyncSubtreeAPI && null != workInProgress.type && null != workInProgress.type.prototype && !0 === workInProgress.type.prototype.unstable_isAsyncReactComponent && (workInProgress.internalContextTag |= AsyncUpdates$1), - "function" == typeof instance.componentWillMount) { - callComponentWillMount(workInProgress, instance); - var updateQueue = workInProgress.updateQueue; - null !== updateQueue && (instance.state = beginUpdateQueue$2(current, workInProgress, updateQueue, instance, state, props, priorityLevel)); - } - "function" == typeof instance.componentDidMount && (workInProgress.effectTag |= Update$1); - } - function updateClassInstance(current, workInProgress, priorityLevel) { - var instance = workInProgress.stateNode; - resetInputPointers(workInProgress, instance); - var oldProps = workInProgress.memoizedProps, newProps = workInProgress.pendingProps; - newProps || (newProps = oldProps, invariant(null != newProps, "There should always be pending or memoized props. This error is " + "likely caused by a bug in React. Please file an issue.")); - var oldContext = instance.context, newUnmaskedContext = getUnmaskedContext$2(workInProgress), newContext = getMaskedContext$2(workInProgress, newUnmaskedContext); - "function" != typeof instance.componentWillReceiveProps || oldProps === newProps && oldContext === newContext || callComponentWillReceiveProps(workInProgress, instance, newProps, newContext); - var oldState = workInProgress.memoizedState, newState = void 0; - if (newState = null !== workInProgress.updateQueue ? beginUpdateQueue$2(current, workInProgress, workInProgress.updateQueue, instance, oldState, newProps, priorityLevel) : oldState, - !(oldProps !== newProps || oldState !== newState || hasContextChanged$2() || null !== workInProgress.updateQueue && workInProgress.updateQueue.hasForceUpdate)) return "function" == typeof instance.componentDidUpdate && (oldProps === current.memoizedProps && oldState === current.memoizedState || (workInProgress.effectTag |= Update$1)), - !1; - var shouldUpdate = checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext); - return shouldUpdate ? ("function" == typeof instance.componentWillUpdate && (startPhaseTimer$1(workInProgress, "componentWillUpdate"), - instance.componentWillUpdate(newProps, newState, newContext), stopPhaseTimer$1()), - "function" == typeof instance.componentDidUpdate && (workInProgress.effectTag |= Update$1)) : ("function" == typeof instance.componentDidUpdate && (oldProps === current.memoizedProps && oldState === current.memoizedState || (workInProgress.effectTag |= Update$1)), - memoizeProps(workInProgress, newProps), memoizeState(workInProgress, newState)), - instance.props = newProps, instance.state = newState, instance.context = newContext, - shouldUpdate; - } - return { - adoptClassInstance: adoptClassInstance, - constructClassInstance: constructClassInstance, - mountClassInstance: mountClassInstance, - updateClassInstance: updateClassInstance - }; - }, mountChildFibersInPlace = ReactChildFiber.mountChildFibersInPlace, reconcileChildFibers = ReactChildFiber.reconcileChildFibers, reconcileChildFibersInPlace = ReactChildFiber.reconcileChildFibersInPlace, cloneChildFibers = ReactChildFiber.cloneChildFibers, beginUpdateQueue$1 = ReactFiberUpdateQueue.beginUpdateQueue, getMaskedContext$1 = ReactFiberContext.getMaskedContext, getUnmaskedContext$1 = ReactFiberContext.getUnmaskedContext, hasContextChanged$1 = ReactFiberContext.hasContextChanged, pushContextProvider$1 = ReactFiberContext.pushContextProvider, pushTopLevelContextObject$1 = ReactFiberContext.pushTopLevelContextObject, invalidateContextProvider$1 = ReactFiberContext.invalidateContextProvider, IndeterminateComponent$2 = ReactTypeOfWork.IndeterminateComponent, FunctionalComponent$1 = ReactTypeOfWork.FunctionalComponent, ClassComponent$6 = ReactTypeOfWork.ClassComponent, HostRoot$6 = ReactTypeOfWork.HostRoot, HostComponent$6 = ReactTypeOfWork.HostComponent, HostText$3 = ReactTypeOfWork.HostText, HostPortal$4 = ReactTypeOfWork.HostPortal, CoroutineComponent$1 = ReactTypeOfWork.CoroutineComponent, CoroutineHandlerPhase = ReactTypeOfWork.CoroutineHandlerPhase, YieldComponent$2 = ReactTypeOfWork.YieldComponent, Fragment$2 = ReactTypeOfWork.Fragment, NoWork$3 = ReactPriorityLevel.NoWork, OffscreenPriority$1 = ReactPriorityLevel.OffscreenPriority, PerformedWork$1 = ReactTypeOfSideEffect.PerformedWork, Placement$2 = ReactTypeOfSideEffect.Placement, ContentReset$1 = ReactTypeOfSideEffect.ContentReset, Err$1 = ReactTypeOfSideEffect.Err, Ref$1 = ReactTypeOfSideEffect.Ref, ReactCurrentOwner$2 = ReactGlobalSharedState_1.ReactCurrentOwner, ReactDebugCurrentFiber$4 = ReactDebugCurrentFiber_1, _require7 = ReactDebugFiberPerf_1, cancelWorkTimer = _require7.cancelWorkTimer, warning$7 = require$$0, warnedAboutStatelessRefs = {}, ReactFiberBeginWork = function(config, hostContext, hydrationContext, scheduleUpdate, getPriorityContext) { - var shouldSetTextContent = config.shouldSetTextContent, useSyncScheduling = config.useSyncScheduling, shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree, pushHostContext = hostContext.pushHostContext, pushHostContainer = hostContext.pushHostContainer, enterHydrationState = hydrationContext.enterHydrationState, resetHydrationState = hydrationContext.resetHydrationState, tryToClaimNextHydratableInstance = hydrationContext.tryToClaimNextHydratableInstance, _ReactFiberClassCompo = ReactFiberClassComponent(scheduleUpdate, getPriorityContext, memoizeProps, memoizeState), adoptClassInstance = _ReactFiberClassCompo.adoptClassInstance, constructClassInstance = _ReactFiberClassCompo.constructClassInstance, mountClassInstance = _ReactFiberClassCompo.mountClassInstance, updateClassInstance = _ReactFiberClassCompo.updateClassInstance; - function reconcileChildren(current, workInProgress, nextChildren) { - reconcileChildrenAtPriority(current, workInProgress, nextChildren, workInProgress.pendingWorkPriority); - } - function reconcileChildrenAtPriority(current, workInProgress, nextChildren, priorityLevel) { - null === current ? workInProgress.child = mountChildFibersInPlace(workInProgress, workInProgress.child, nextChildren, priorityLevel) : current.child === workInProgress.child ? workInProgress.child = reconcileChildFibers(workInProgress, workInProgress.child, nextChildren, priorityLevel) : workInProgress.child = reconcileChildFibersInPlace(workInProgress, workInProgress.child, nextChildren, priorityLevel); - } - function updateFragment(current, workInProgress) { - var nextChildren = workInProgress.pendingProps; - if (hasContextChanged$1()) null === nextChildren && (nextChildren = workInProgress.memoizedProps); else if (null === nextChildren || workInProgress.memoizedProps === nextChildren) return bailoutOnAlreadyFinishedWork(current, workInProgress); - return reconcileChildren(current, workInProgress, nextChildren), memoizeProps(workInProgress, nextChildren), - workInProgress.child; - } - function markRef(current, workInProgress) { - var ref = workInProgress.ref; - null === ref || current && current.ref === ref || (workInProgress.effectTag |= Ref$1); - } - function updateFunctionalComponent(current, workInProgress) { - var fn = workInProgress.type, nextProps = workInProgress.pendingProps, memoizedProps = workInProgress.memoizedProps; - if (hasContextChanged$1()) null === nextProps && (nextProps = memoizedProps); else if (null === nextProps || memoizedProps === nextProps) return bailoutOnAlreadyFinishedWork(current, workInProgress); - var nextChildren, unmaskedContext = getUnmaskedContext$1(workInProgress), context = getMaskedContext$1(workInProgress, unmaskedContext); - return ReactCurrentOwner$2.current = workInProgress, ReactDebugCurrentFiber$4.setCurrentPhase("render"), - nextChildren = fn(nextProps, context), ReactDebugCurrentFiber$4.setCurrentPhase(null), - workInProgress.effectTag |= PerformedWork$1, reconcileChildren(current, workInProgress, nextChildren), - memoizeProps(workInProgress, nextProps), workInProgress.child; - } - function updateClassComponent(current, workInProgress, priorityLevel) { - var hasContext = pushContextProvider$1(workInProgress), shouldUpdate = void 0; - return null === current ? workInProgress.stateNode ? invariant(!1, "Resuming work not yet implemented.") : (constructClassInstance(workInProgress, workInProgress.pendingProps), - mountClassInstance(workInProgress, priorityLevel), shouldUpdate = !0) : shouldUpdate = updateClassInstance(current, workInProgress, priorityLevel), - finishClassComponent(current, workInProgress, shouldUpdate, hasContext); - } - function finishClassComponent(current, workInProgress, shouldUpdate, hasContext) { - if (markRef(current, workInProgress), !shouldUpdate) return hasContext && invalidateContextProvider$1(workInProgress, !1), - bailoutOnAlreadyFinishedWork(current, workInProgress); - var instance = workInProgress.stateNode; - ReactCurrentOwner$2.current = workInProgress; - var nextChildren = void 0; - return ReactDebugCurrentFiber$4.setCurrentPhase("render"), nextChildren = instance.render(), - ReactDebugCurrentFiber$4.setCurrentPhase(null), workInProgress.effectTag |= PerformedWork$1, - reconcileChildren(current, workInProgress, nextChildren), memoizeState(workInProgress, instance.state), - memoizeProps(workInProgress, instance.props), hasContext && invalidateContextProvider$1(workInProgress, !0), - workInProgress.child; - } - function pushHostRootContext(workInProgress) { - var root = workInProgress.stateNode; - root.pendingContext ? pushTopLevelContextObject$1(workInProgress, root.pendingContext, root.pendingContext !== root.context) : root.context && pushTopLevelContextObject$1(workInProgress, root.context, !1), - pushHostContainer(workInProgress, root.containerInfo); - } - function updateHostRoot(current, workInProgress, priorityLevel) { - pushHostRootContext(workInProgress); - var updateQueue = workInProgress.updateQueue; - if (null !== updateQueue) { - var prevState = workInProgress.memoizedState, state = beginUpdateQueue$1(current, workInProgress, updateQueue, null, prevState, null, priorityLevel); - if (prevState === state) return resetHydrationState(), bailoutOnAlreadyFinishedWork(current, workInProgress); - var element = state.element; - return null !== current && null !== current.child || !enterHydrationState(workInProgress) ? (resetHydrationState(), - reconcileChildren(current, workInProgress, element)) : (workInProgress.effectTag |= Placement$2, - workInProgress.child = mountChildFibersInPlace(workInProgress, workInProgress.child, element, priorityLevel)), - memoizeState(workInProgress, state), workInProgress.child; - } - return resetHydrationState(), bailoutOnAlreadyFinishedWork(current, workInProgress); - } - function updateHostComponent(current, workInProgress, renderPriority) { - pushHostContext(workInProgress), null === current && tryToClaimNextHydratableInstance(workInProgress); - var type = workInProgress.type, memoizedProps = workInProgress.memoizedProps, nextProps = workInProgress.pendingProps; - null === nextProps && (nextProps = memoizedProps, invariant(null !== nextProps, "We should always have pending or current props. This error is " + "likely caused by a bug in React. Please file an issue.")); - var prevProps = null !== current ? current.memoizedProps : null; - if (hasContextChanged$1()) ; else if (null === nextProps || memoizedProps === nextProps) return bailoutOnAlreadyFinishedWork(current, workInProgress); - var nextChildren = nextProps.children; - return shouldSetTextContent(type, nextProps) ? nextChildren = null : prevProps && shouldSetTextContent(type, prevProps) && (workInProgress.effectTag |= ContentReset$1), - markRef(current, workInProgress), renderPriority !== OffscreenPriority$1 && !useSyncScheduling && shouldDeprioritizeSubtree(type, nextProps) ? (workInProgress.pendingWorkPriority = OffscreenPriority$1, - null) : (reconcileChildren(current, workInProgress, nextChildren), memoizeProps(workInProgress, nextProps), - workInProgress.child); - } - function updateHostText(current, workInProgress) { - null === current && tryToClaimNextHydratableInstance(workInProgress); - var nextProps = workInProgress.pendingProps; - return null === nextProps && (nextProps = workInProgress.memoizedProps), memoizeProps(workInProgress, nextProps), - null; - } - function mountIndeterminateComponent(current, workInProgress, priorityLevel) { - invariant(null === current, "An indeterminate component should never have mounted. This error is " + "likely caused by a bug in React. Please file an issue."); - var value, fn = workInProgress.type, props = workInProgress.pendingProps, unmaskedContext = getUnmaskedContext$1(workInProgress), context = getMaskedContext$1(workInProgress, unmaskedContext); - if (ReactCurrentOwner$2.current = workInProgress, value = fn(props, context), workInProgress.effectTag |= PerformedWork$1, - "object" == typeof value && null !== value && "function" == typeof value.render) { - workInProgress.tag = ClassComponent$6; - var hasContext = pushContextProvider$1(workInProgress); - return adoptClassInstance(workInProgress, value), mountClassInstance(workInProgress, priorityLevel), - finishClassComponent(current, workInProgress, !0, hasContext); - } - workInProgress.tag = FunctionalComponent$1; - var Component = workInProgress.type; - if (Component && warning$7(!Component.childContextTypes, "%s(...): childContextTypes cannot be defined on a functional component.", Component.displayName || Component.name || "Component"), - null !== workInProgress.ref) { - var info = "", ownerName = ReactDebugCurrentFiber$4.getCurrentFiberOwnerName(); - ownerName && (info += "\n\nCheck the render method of `" + ownerName + "`."); - var warningKey = ownerName || workInProgress._debugID || "", debugSource = workInProgress._debugSource; - debugSource && (warningKey = debugSource.fileName + ":" + debugSource.lineNumber), - warnedAboutStatelessRefs[warningKey] || (warnedAboutStatelessRefs[warningKey] = !0, - warning$7(!1, "Stateless function components cannot be given refs. " + "Attempts to access this ref will fail.%s%s", info, ReactDebugCurrentFiber$4.getCurrentFiberStackAddendum())); - } - return reconcileChildren(current, workInProgress, value), memoizeProps(workInProgress, props), - workInProgress.child; - } - function updateCoroutineComponent(current, workInProgress) { - var nextCoroutine = workInProgress.pendingProps; - hasContextChanged$1() ? null === nextCoroutine && (nextCoroutine = current && current.memoizedProps, - invariant(null !== nextCoroutine, "We should always have pending or current props. This error is " + "likely caused by a bug in React. Please file an issue.")) : null !== nextCoroutine && workInProgress.memoizedProps !== nextCoroutine || (nextCoroutine = workInProgress.memoizedProps); - var nextChildren = nextCoroutine.children, priorityLevel = workInProgress.pendingWorkPriority; - return null === current ? workInProgress.stateNode = mountChildFibersInPlace(workInProgress, workInProgress.stateNode, nextChildren, priorityLevel) : current.child === workInProgress.child ? workInProgress.stateNode = reconcileChildFibers(workInProgress, workInProgress.stateNode, nextChildren, priorityLevel) : workInProgress.stateNode = reconcileChildFibersInPlace(workInProgress, workInProgress.stateNode, nextChildren, priorityLevel), - memoizeProps(workInProgress, nextCoroutine), workInProgress.stateNode; - } - function updatePortalComponent(current, workInProgress) { - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - var priorityLevel = workInProgress.pendingWorkPriority, nextChildren = workInProgress.pendingProps; - if (hasContextChanged$1()) null === nextChildren && (nextChildren = current && current.memoizedProps, - invariant(null != nextChildren, "We should always have pending or current props. This error is " + "likely caused by a bug in React. Please file an issue.")); else if (null === nextChildren || workInProgress.memoizedProps === nextChildren) return bailoutOnAlreadyFinishedWork(current, workInProgress); - return null === current ? (workInProgress.child = reconcileChildFibersInPlace(workInProgress, workInProgress.child, nextChildren, priorityLevel), - memoizeProps(workInProgress, nextChildren)) : (reconcileChildren(current, workInProgress, nextChildren), - memoizeProps(workInProgress, nextChildren)), workInProgress.child; - } - function bailoutOnAlreadyFinishedWork(current, workInProgress) { - return cancelWorkTimer(workInProgress), cloneChildFibers(current, workInProgress), - workInProgress.child; - } - function bailoutOnLowPriority(current, workInProgress) { - switch (cancelWorkTimer(workInProgress), workInProgress.tag) { - case HostRoot$6: - pushHostRootContext(workInProgress); - break; - - case ClassComponent$6: - pushContextProvider$1(workInProgress); - break; - - case HostPortal$4: - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - } - return null; - } - function memoizeProps(workInProgress, nextProps) { - workInProgress.memoizedProps = nextProps; - } - function memoizeState(workInProgress, nextState) { - workInProgress.memoizedState = nextState; - } - function beginWork(current, workInProgress, priorityLevel) { - if (workInProgress.pendingWorkPriority === NoWork$3 || workInProgress.pendingWorkPriority > priorityLevel) return bailoutOnLowPriority(current, workInProgress); - switch (workInProgress.tag) { - case IndeterminateComponent$2: - return mountIndeterminateComponent(current, workInProgress, priorityLevel); - - case FunctionalComponent$1: - return updateFunctionalComponent(current, workInProgress); - - case ClassComponent$6: - return updateClassComponent(current, workInProgress, priorityLevel); - - case HostRoot$6: - return updateHostRoot(current, workInProgress, priorityLevel); - - case HostComponent$6: - return updateHostComponent(current, workInProgress, priorityLevel); - - case HostText$3: - return updateHostText(current, workInProgress); - - case CoroutineHandlerPhase: - workInProgress.tag = CoroutineComponent$1; - - case CoroutineComponent$1: - return updateCoroutineComponent(current, workInProgress); - - case YieldComponent$2: - return null; - - case HostPortal$4: - return updatePortalComponent(current, workInProgress); - - case Fragment$2: - return updateFragment(current, workInProgress); - - default: - invariant(!1, "Unknown unit of work tag. This error is likely caused by a bug in " + "React. Please file an issue."); - } - } - function beginFailedWork(current, workInProgress, priorityLevel) { - switch (workInProgress.tag) { - case ClassComponent$6: - pushContextProvider$1(workInProgress); - break; - - case HostRoot$6: - pushHostRootContext(workInProgress); - break; - - default: - invariant(!1, "Invalid type of work. This error is likely caused by a bug in React. " + "Please file an issue."); - } - if (workInProgress.effectTag |= Err$1, null === current ? workInProgress.child = null : workInProgress.child !== current.child && (workInProgress.child = current.child), - workInProgress.pendingWorkPriority === NoWork$3 || workInProgress.pendingWorkPriority > priorityLevel) return bailoutOnLowPriority(current, workInProgress); - if (workInProgress.firstEffect = null, workInProgress.lastEffect = null, reconcileChildrenAtPriority(current, workInProgress, null, priorityLevel), - workInProgress.tag === ClassComponent$6) { - var instance = workInProgress.stateNode; - workInProgress.memoizedProps = instance.props, workInProgress.memoizedState = instance.state; - } - return workInProgress.child; - } - return { - beginWork: beginWork, - beginFailedWork: beginFailedWork - }; - }, reconcileChildFibers$2 = ReactChildFiber.reconcileChildFibers, popContextProvider$2 = ReactFiberContext.popContextProvider, popTopLevelContextObject$1 = ReactFiberContext.popTopLevelContextObject, IndeterminateComponent$3 = ReactTypeOfWork.IndeterminateComponent, FunctionalComponent$3 = ReactTypeOfWork.FunctionalComponent, ClassComponent$8 = ReactTypeOfWork.ClassComponent, HostRoot$7 = ReactTypeOfWork.HostRoot, HostComponent$7 = ReactTypeOfWork.HostComponent, HostText$5 = ReactTypeOfWork.HostText, HostPortal$6 = ReactTypeOfWork.HostPortal, CoroutineComponent$3 = ReactTypeOfWork.CoroutineComponent, CoroutineHandlerPhase$1 = ReactTypeOfWork.CoroutineHandlerPhase, YieldComponent$4 = ReactTypeOfWork.YieldComponent, Fragment$4 = ReactTypeOfWork.Fragment, Placement$4 = ReactTypeOfSideEffect.Placement, Ref$2 = ReactTypeOfSideEffect.Ref, Update$2 = ReactTypeOfSideEffect.Update, OffscreenPriority$2 = ReactPriorityLevel.OffscreenPriority, ReactFiberCompleteWork = function(config, hostContext, hydrationContext) { - var createInstance = config.createInstance, createTextInstance = config.createTextInstance, appendInitialChild = config.appendInitialChild, finalizeInitialChildren = config.finalizeInitialChildren, prepareUpdate = config.prepareUpdate, getRootHostContainer = hostContext.getRootHostContainer, popHostContext = hostContext.popHostContext, getHostContext = hostContext.getHostContext, popHostContainer = hostContext.popHostContainer, prepareToHydrateHostInstance = hydrationContext.prepareToHydrateHostInstance, prepareToHydrateHostTextInstance = hydrationContext.prepareToHydrateHostTextInstance, popHydrationState = hydrationContext.popHydrationState; - function markUpdate(workInProgress) { - workInProgress.effectTag |= Update$2; - } - function markRef(workInProgress) { - workInProgress.effectTag |= Ref$2; - } - function appendAllYields(yields, workInProgress) { - var node = workInProgress.stateNode; - for (node && (node.return = workInProgress); null !== node; ) { - if (node.tag === HostComponent$7 || node.tag === HostText$5 || node.tag === HostPortal$6) invariant(!1, "A coroutine cannot have host component children."); else if (node.tag === YieldComponent$4) yields.push(node.type); else if (null !== node.child) { - node.child.return = node, node = node.child; - continue; - } - for (;null === node.sibling; ) { - if (null === node.return || node.return === workInProgress) return; - node = node.return; - } - node.sibling.return = node.return, node = node.sibling; - } - } - function moveCoroutineToHandlerPhase(current, workInProgress) { - var coroutine = workInProgress.memoizedProps; - invariant(coroutine, "Should be resolved by now. This error is likely caused by a bug in " + "React. Please file an issue."), - workInProgress.tag = CoroutineHandlerPhase$1; - var yields = []; - appendAllYields(yields, workInProgress); - var fn = coroutine.handler, props = coroutine.props, nextChildren = fn(props, yields), currentFirstChild = null !== current ? current.child : null, priority = workInProgress.pendingWorkPriority; - return workInProgress.child = reconcileChildFibers$2(workInProgress, currentFirstChild, nextChildren, priority), - workInProgress.child; - } - function appendAllChildren(parent, workInProgress) { - for (var node = workInProgress.child; null !== node; ) { - if (node.tag === HostComponent$7 || node.tag === HostText$5) appendInitialChild(parent, node.stateNode); else if (node.tag === HostPortal$6) ; else if (null !== node.child) { - node = node.child; - continue; - } - if (node === workInProgress) return; - for (;null === node.sibling; ) { - if (null === node.return || node.return === workInProgress) return; - node = node.return; - } - node = node.sibling; - } - } - function completeWork(current, workInProgress, renderPriority) { - var newProps = workInProgress.pendingProps; - switch (null === newProps ? newProps = workInProgress.memoizedProps : workInProgress.pendingWorkPriority === OffscreenPriority$2 && renderPriority !== OffscreenPriority$2 || (workInProgress.pendingProps = null), - workInProgress.tag) { - case FunctionalComponent$3: - return null; - - case ClassComponent$8: - return popContextProvider$2(workInProgress), null; - - case HostRoot$7: - popHostContainer(workInProgress), popTopLevelContextObject$1(workInProgress); - var fiberRoot = workInProgress.stateNode; - return fiberRoot.pendingContext && (fiberRoot.context = fiberRoot.pendingContext, - fiberRoot.pendingContext = null), null !== current && null !== current.child || (popHydrationState(workInProgress), - workInProgress.effectTag &= ~Placement$4), null; - - case HostComponent$7: - popHostContext(workInProgress); - var rootContainerInstance = getRootHostContainer(), type = workInProgress.type; - if (null !== current && null != workInProgress.stateNode) { - var oldProps = current.memoizedProps, instance = workInProgress.stateNode, currentHostContext = getHostContext(), updatePayload = prepareUpdate(instance, type, oldProps, newProps, rootContainerInstance, currentHostContext); - workInProgress.updateQueue = updatePayload, updatePayload && markUpdate(workInProgress), - current.ref !== workInProgress.ref && markRef(workInProgress); - } else { - if (!newProps) return invariant(null !== workInProgress.stateNode, "We must have new props for new mounts. This error is likely " + "caused by a bug in React. Please file an issue."), - null; - var _currentHostContext = getHostContext(); - if (popHydrationState(workInProgress)) prepareToHydrateHostInstance(workInProgress, rootContainerInstance, _currentHostContext) && markUpdate(workInProgress); else { - var _instance = createInstance(type, newProps, rootContainerInstance, _currentHostContext, workInProgress); - appendAllChildren(_instance, workInProgress), finalizeInitialChildren(_instance, type, newProps, rootContainerInstance) && markUpdate(workInProgress), - workInProgress.stateNode = _instance; - } - null !== workInProgress.ref && markRef(workInProgress); - } - return null; - - case HostText$5: - var newText = newProps; - if (current && null != workInProgress.stateNode) { - current.memoizedProps !== newText && markUpdate(workInProgress); - } else { - if ("string" != typeof newText) return invariant(null !== workInProgress.stateNode, "We must have new props for new mounts. This error is likely " + "caused by a bug in React. Please file an issue."), - null; - var _rootContainerInstance = getRootHostContainer(), _currentHostContext2 = getHostContext(); - popHydrationState(workInProgress) ? prepareToHydrateHostTextInstance(workInProgress) && markUpdate(workInProgress) : workInProgress.stateNode = createTextInstance(newText, _rootContainerInstance, _currentHostContext2, workInProgress); - } - return null; - - case CoroutineComponent$3: - return moveCoroutineToHandlerPhase(current, workInProgress); - - case CoroutineHandlerPhase$1: - return workInProgress.tag = CoroutineComponent$3, null; - - case YieldComponent$4: - case Fragment$4: - return null; - - case HostPortal$6: - return markUpdate(workInProgress), popHostContainer(workInProgress), null; - - case IndeterminateComponent$3: - invariant(!1, "An indeterminate component should have become determinate before " + "completing. This error is likely caused by a bug in React. Please " + "file an issue."); - - default: - invariant(!1, "Unknown unit of work tag. This error is likely caused by a bug in " + "React. Please file an issue."); - } - } - return { - completeWork: completeWork - }; - }, warning$10 = require$$0, onCommitFiberRoot = null, onCommitFiberUnmount = null, hasLoggedError = !1; - function catchErrors(fn) { - return function(arg) { - try { - return fn(arg); - } catch (err) { - 0 || hasLoggedError || (hasLoggedError = !0, warning$10(!1, "React DevTools encountered an error: %s", err)); - } - }; - } - function injectInternals$1(internals) { - if ("undefined" == typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) return !1; - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - if (!hook.supportsFiber) return warning$10(!1, "The installed version of React DevTools is too old and will not work " + "with the current version of React. Please update React DevTools. " + "https://fb.me/react-devtools"), - !0; - try { - var rendererID = hook.inject(internals); - onCommitFiberRoot = catchErrors(function(root) { - return hook.onCommitFiberRoot(rendererID, root); - }), onCommitFiberUnmount = catchErrors(function(fiber) { - return hook.onCommitFiberUnmount(rendererID, fiber); - }); - } catch (err) { - warning$10(!1, "React DevTools encountered an error: %s.", err); - } - return !0; - } - function onCommitRoot$1(root) { - "function" == typeof onCommitFiberRoot && onCommitFiberRoot(root); - } - function onCommitUnmount$1(fiber) { - "function" == typeof onCommitFiberUnmount && onCommitFiberUnmount(fiber); - } - var injectInternals_1 = injectInternals$1, onCommitRoot_1 = onCommitRoot$1, onCommitUnmount_1 = onCommitUnmount$1, ReactFiberDevToolsHook = { - injectInternals: injectInternals_1, - onCommitRoot: onCommitRoot_1, - onCommitUnmount: onCommitUnmount_1 - }, ClassComponent$9 = ReactTypeOfWork.ClassComponent, HostRoot$8 = ReactTypeOfWork.HostRoot, HostComponent$8 = ReactTypeOfWork.HostComponent, HostText$6 = ReactTypeOfWork.HostText, HostPortal$7 = ReactTypeOfWork.HostPortal, CoroutineComponent$4 = ReactTypeOfWork.CoroutineComponent, commitCallbacks$1 = ReactFiberUpdateQueue.commitCallbacks, onCommitUnmount = ReactFiberDevToolsHook.onCommitUnmount, invokeGuardedCallback$2 = ReactErrorUtils_1.invokeGuardedCallback, hasCaughtError$1 = ReactErrorUtils_1.hasCaughtError, clearCaughtError$1 = ReactErrorUtils_1.clearCaughtError, Placement$5 = ReactTypeOfSideEffect.Placement, Update$3 = ReactTypeOfSideEffect.Update, Callback$1 = ReactTypeOfSideEffect.Callback, ContentReset$2 = ReactTypeOfSideEffect.ContentReset, _require5$1 = ReactDebugFiberPerf_1, startPhaseTimer$2 = _require5$1.startPhaseTimer, stopPhaseTimer$2 = _require5$1.stopPhaseTimer, ReactFiberCommitWork = function(config, captureError) { - var commitMount = config.commitMount, commitUpdate = config.commitUpdate, resetTextContent = config.resetTextContent, commitTextUpdate = config.commitTextUpdate, appendChild = config.appendChild, appendChildToContainer = config.appendChildToContainer, insertBefore = config.insertBefore, insertInContainerBefore = config.insertInContainerBefore, removeChild = config.removeChild, removeChildFromContainer = config.removeChildFromContainer, getPublicInstance = config.getPublicInstance, callComponentWillUnmountWithTimerInDev = function(current, instance) { - startPhaseTimer$2(current, "componentWillUnmount"), instance.props = current.memoizedProps, - instance.state = current.memoizedState, instance.componentWillUnmount(), stopPhaseTimer$2(); - }; - function safelyCallComponentWillUnmount(current, instance) { - if (invokeGuardedCallback$2(null, callComponentWillUnmountWithTimerInDev, null, current, instance), - hasCaughtError$1()) { - var unmountError = clearCaughtError$1(); - captureError(current, unmountError); - } - } - function safelyDetachRef(current) { - var ref = current.ref; - if (null !== ref && (invokeGuardedCallback$2(null, ref, null, null), hasCaughtError$1())) { - var refError = clearCaughtError$1(); - captureError(current, refError); - } - } - function getHostParentFiber(fiber) { - for (var parent = fiber.return; null !== parent; ) { - if (isHostParent(parent)) return parent; - parent = parent.return; - } - invariant(!1, "Expected to find a host parent. This error is likely caused by a bug " + "in React. Please file an issue."); - } - function isHostParent(fiber) { - return fiber.tag === HostComponent$8 || fiber.tag === HostRoot$8 || fiber.tag === HostPortal$7; - } - function getHostSibling(fiber) { - var node = fiber; - siblings: for (;!0; ) { - for (;null === node.sibling; ) { - if (null === node.return || isHostParent(node.return)) return null; - node = node.return; - } - for (node.sibling.return = node.return, node = node.sibling; node.tag !== HostComponent$8 && node.tag !== HostText$6; ) { - if (node.effectTag & Placement$5) continue siblings; - if (null === node.child || node.tag === HostPortal$7) continue siblings; - node.child.return = node, node = node.child; - } - if (!(node.effectTag & Placement$5)) return node.stateNode; - } - } - function commitPlacement(finishedWork) { - var parentFiber = getHostParentFiber(finishedWork), parent = void 0, isContainer = void 0; - switch (parentFiber.tag) { - case HostComponent$8: - parent = parentFiber.stateNode, isContainer = !1; - break; - - case HostRoot$8: - case HostPortal$7: - parent = parentFiber.stateNode.containerInfo, isContainer = !0; - break; - - default: - invariant(!1, "Invalid host parent fiber. This error is likely caused by a bug " + "in React. Please file an issue."); - } - parentFiber.effectTag & ContentReset$2 && (resetTextContent(parent), parentFiber.effectTag &= ~ContentReset$2); - for (var before = getHostSibling(finishedWork), node = finishedWork; !0; ) { - if (node.tag === HostComponent$8 || node.tag === HostText$6) before ? isContainer ? insertInContainerBefore(parent, node.stateNode, before) : insertBefore(parent, node.stateNode, before) : isContainer ? appendChildToContainer(parent, node.stateNode) : appendChild(parent, node.stateNode); else if (node.tag === HostPortal$7) ; else if (null !== node.child) { - node.child.return = node, node = node.child; - continue; - } - if (node === finishedWork) return; - for (;null === node.sibling; ) { - if (null === node.return || node.return === finishedWork) return; - node = node.return; - } - node.sibling.return = node.return, node = node.sibling; - } - } - function commitNestedUnmounts(root) { - for (var node = root; !0; ) if (commitUnmount(node), null === node.child || node.tag === HostPortal$7) { - if (node === root) return; - for (;null === node.sibling; ) { - if (null === node.return || node.return === root) return; - node = node.return; - } - node.sibling.return = node.return, node = node.sibling; - } else node.child.return = node, node = node.child; - } - function unmountHostComponents(current) { - for (var node = current, currentParentIsValid = !1, currentParent = void 0, currentParentIsContainer = void 0; !0; ) { - if (!currentParentIsValid) { - var parent = node.return; - findParent: for (;!0; ) { - switch (invariant(null !== parent, "Expected to find a host parent. This error is likely caused by " + "a bug in React. Please file an issue."), - parent.tag) { - case HostComponent$8: - currentParent = parent.stateNode, currentParentIsContainer = !1; - break findParent; - - case HostRoot$8: - case HostPortal$7: - currentParent = parent.stateNode.containerInfo, currentParentIsContainer = !0; - break findParent; - } - parent = parent.return; - } - currentParentIsValid = !0; - } - if (node.tag === HostComponent$8 || node.tag === HostText$6) commitNestedUnmounts(node), - currentParentIsContainer ? removeChildFromContainer(currentParent, node.stateNode) : removeChild(currentParent, node.stateNode); else if (node.tag === HostPortal$7) { - if (currentParent = node.stateNode.containerInfo, null !== node.child) { - node.child.return = node, node = node.child; - continue; - } - } else if (commitUnmount(node), null !== node.child) { - node.child.return = node, node = node.child; - continue; - } - if (node === current) return; - for (;null === node.sibling; ) { - if (null === node.return || node.return === current) return; - node = node.return, node.tag === HostPortal$7 && (currentParentIsValid = !1); - } - node.sibling.return = node.return, node = node.sibling; - } - } - function commitDeletion(current) { - unmountHostComponents(current), current.return = null, current.child = null, current.alternate && (current.alternate.child = null, - current.alternate.return = null); - } - function commitUnmount(current) { - switch ("function" == typeof onCommitUnmount && onCommitUnmount(current), current.tag) { - case ClassComponent$9: - safelyDetachRef(current); - var instance = current.stateNode; - return void ("function" == typeof instance.componentWillUnmount && safelyCallComponentWillUnmount(current, instance)); - - case HostComponent$8: - return void safelyDetachRef(current); - - case CoroutineComponent$4: - return void commitNestedUnmounts(current.stateNode); - - case HostPortal$7: - return void unmountHostComponents(current); - } - } - function commitWork(current, finishedWork) { - switch (finishedWork.tag) { - case ClassComponent$9: - return; - - case HostComponent$8: - var instance = finishedWork.stateNode; - if (null != instance) { - var newProps = finishedWork.memoizedProps, oldProps = null !== current ? current.memoizedProps : newProps, type = finishedWork.type, updatePayload = finishedWork.updateQueue; - finishedWork.updateQueue = null, null !== updatePayload && commitUpdate(instance, updatePayload, type, oldProps, newProps, finishedWork); - } - return; - - case HostText$6: - invariant(null !== finishedWork.stateNode, "This should have a text node initialized. This error is likely " + "caused by a bug in React. Please file an issue."); - var textInstance = finishedWork.stateNode, newText = finishedWork.memoizedProps, oldText = null !== current ? current.memoizedProps : newText; - return void commitTextUpdate(textInstance, oldText, newText); - - case HostRoot$8: - case HostPortal$7: - return; - - default: - invariant(!1, "This unit of work tag should not have side-effects. This error is " + "likely caused by a bug in React. Please file an issue."); - } - } - function commitLifeCycles(current, finishedWork) { - switch (finishedWork.tag) { - case ClassComponent$9: - var instance = finishedWork.stateNode; - if (finishedWork.effectTag & Update$3) if (null === current) startPhaseTimer$2(finishedWork, "componentDidMount"), - instance.props = finishedWork.memoizedProps, instance.state = finishedWork.memoizedState, - instance.componentDidMount(), stopPhaseTimer$2(); else { - var prevProps = current.memoizedProps, prevState = current.memoizedState; - startPhaseTimer$2(finishedWork, "componentDidUpdate"), instance.props = finishedWork.memoizedProps, - instance.state = finishedWork.memoizedState, instance.componentDidUpdate(prevProps, prevState), - stopPhaseTimer$2(); - } - return void (finishedWork.effectTag & Callback$1 && null !== finishedWork.updateQueue && commitCallbacks$1(finishedWork, finishedWork.updateQueue, instance)); - - case HostRoot$8: - var updateQueue = finishedWork.updateQueue; - if (null !== updateQueue) { - var _instance = finishedWork.child && finishedWork.child.stateNode; - commitCallbacks$1(finishedWork, updateQueue, _instance); - } - return; - - case HostComponent$8: - var _instance2 = finishedWork.stateNode; - if (null === current && finishedWork.effectTag & Update$3) { - var type = finishedWork.type, props = finishedWork.memoizedProps; - commitMount(_instance2, type, props, finishedWork); - } - return; - - case HostText$6: - case HostPortal$7: - return; - - default: - invariant(!1, "This unit of work tag should not have side-effects. This error is " + "likely caused by a bug in React. Please file an issue."); - } - } - function commitAttachRef(finishedWork) { - var ref = finishedWork.ref; - if (null !== ref) { - var instance = finishedWork.stateNode; - switch (finishedWork.tag) { - case HostComponent$8: - ref(getPublicInstance(instance)); - break; - - default: - ref(instance); - } - } - } - function commitDetachRef(current) { - var currentRef = current.ref; - null !== currentRef && currentRef(null); - } - return { - commitPlacement: commitPlacement, - commitDeletion: commitDeletion, - commitWork: commitWork, - commitLifeCycles: commitLifeCycles, - commitAttachRef: commitAttachRef, - commitDetachRef: commitDetachRef - }; - }, createCursor$2 = ReactFiberStack.createCursor, pop$2 = ReactFiberStack.pop, push$2 = ReactFiberStack.push, NO_CONTEXT = {}, ReactFiberHostContext = function(config) { - var getChildHostContext = config.getChildHostContext, getRootHostContext = config.getRootHostContext, contextStackCursor = createCursor$2(NO_CONTEXT), contextFiberStackCursor = createCursor$2(NO_CONTEXT), rootInstanceStackCursor = createCursor$2(NO_CONTEXT); - function requiredContext(c) { - return invariant(c !== NO_CONTEXT, "Expected host context to exist. This error is likely caused by a bug " + "in React. Please file an issue."), - c; - } - function getRootHostContainer() { - return requiredContext(rootInstanceStackCursor.current); - } - function pushHostContainer(fiber, nextRootInstance) { - push$2(rootInstanceStackCursor, nextRootInstance, fiber); - var nextRootContext = getRootHostContext(nextRootInstance); - push$2(contextFiberStackCursor, fiber, fiber), push$2(contextStackCursor, nextRootContext, fiber); - } - function popHostContainer(fiber) { - pop$2(contextStackCursor, fiber), pop$2(contextFiberStackCursor, fiber), pop$2(rootInstanceStackCursor, fiber); - } - function getHostContext() { - return requiredContext(contextStackCursor.current); - } - function pushHostContext(fiber) { - var rootInstance = requiredContext(rootInstanceStackCursor.current), context = requiredContext(contextStackCursor.current), nextContext = getChildHostContext(context, fiber.type, rootInstance); - context !== nextContext && (push$2(contextFiberStackCursor, fiber, fiber), push$2(contextStackCursor, nextContext, fiber)); - } - function popHostContext(fiber) { - contextFiberStackCursor.current === fiber && (pop$2(contextStackCursor, fiber), - pop$2(contextFiberStackCursor, fiber)); - } - function resetHostContainer() { - contextStackCursor.current = NO_CONTEXT, rootInstanceStackCursor.current = NO_CONTEXT; - } - return { - getHostContext: getHostContext, - getRootHostContainer: getRootHostContainer, - popHostContainer: popHostContainer, - popHostContext: popHostContext, - pushHostContainer: pushHostContainer, - pushHostContext: pushHostContext, - resetHostContainer: resetHostContainer - }; - }, HostComponent$9 = ReactTypeOfWork.HostComponent, HostText$7 = ReactTypeOfWork.HostText, HostRoot$9 = ReactTypeOfWork.HostRoot, Deletion$2 = ReactTypeOfSideEffect.Deletion, Placement$6 = ReactTypeOfSideEffect.Placement, createFiberFromHostInstanceForDeletion$1 = ReactFiber.createFiberFromHostInstanceForDeletion, ReactFiberHydrationContext = function(config) { - var shouldSetTextContent = config.shouldSetTextContent, canHydrateInstance = config.canHydrateInstance, canHydrateTextInstance = config.canHydrateTextInstance, getNextHydratableSibling = config.getNextHydratableSibling, getFirstHydratableChild = config.getFirstHydratableChild, hydrateInstance = config.hydrateInstance, hydrateTextInstance = config.hydrateTextInstance, didNotHydrateInstance = config.didNotHydrateInstance, didNotFindHydratableInstance = config.didNotFindHydratableInstance, didNotFindHydratableTextInstance = config.didNotFindHydratableTextInstance; - if (!(canHydrateInstance && canHydrateTextInstance && getNextHydratableSibling && getFirstHydratableChild && hydrateInstance && hydrateTextInstance && didNotHydrateInstance && didNotFindHydratableInstance && didNotFindHydratableTextInstance)) return { - enterHydrationState: function() { - return !1; - }, - resetHydrationState: function() {}, - tryToClaimNextHydratableInstance: function() {}, - prepareToHydrateHostInstance: function() { - invariant(!1, "Expected prepareToHydrateHostInstance() to never be called. " + "This error is likely caused by a bug in React. Please file an issue."); - }, - prepareToHydrateHostTextInstance: function() { - invariant(!1, "Expected prepareToHydrateHostTextInstance() to never be called. " + "This error is likely caused by a bug in React. Please file an issue."); - }, - popHydrationState: function(fiber) { - return !1; - } - }; - var hydrationParentFiber = null, nextHydratableInstance = null, isHydrating = !1; - function enterHydrationState(fiber) { - var parentInstance = fiber.stateNode.containerInfo; - return nextHydratableInstance = getFirstHydratableChild(parentInstance), hydrationParentFiber = fiber, - isHydrating = !0, !0; - } - function deleteHydratableInstance(returnFiber, instance) { - switch (returnFiber.tag) { - case HostRoot$9: - didNotHydrateInstance(returnFiber.stateNode.containerInfo, instance); - break; - - case HostComponent$9: - didNotHydrateInstance(returnFiber.stateNode, instance); - } - var childToDelete = createFiberFromHostInstanceForDeletion$1(); - childToDelete.stateNode = instance, childToDelete.return = returnFiber, childToDelete.effectTag = Deletion$2, - null !== returnFiber.lastEffect ? (returnFiber.lastEffect.nextEffect = childToDelete, - returnFiber.lastEffect = childToDelete) : returnFiber.firstEffect = returnFiber.lastEffect = childToDelete; - } - function insertNonHydratedInstance(returnFiber, fiber) { - fiber.effectTag |= Placement$6; - var parentInstance; - switch (returnFiber.tag) { - case HostComponent$9: - parentInstance = returnFiber.stateNode; - break; - - default: - return; - } - switch (fiber.tag) { - case HostComponent$9: - var type = fiber.type, props = fiber.pendingProps; - didNotFindHydratableInstance(parentInstance, type, props); - break; - - case HostText$7: - var text = fiber.pendingProps; - didNotFindHydratableTextInstance(parentInstance, text); - } - } - function canHydrate(fiber, nextInstance) { - switch (fiber.tag) { - case HostComponent$9: - var type = fiber.type, props = fiber.pendingProps; - return canHydrateInstance(nextInstance, type, props); - - case HostText$7: - var text = fiber.pendingProps; - return canHydrateTextInstance(nextInstance, text); - - default: - return !1; - } - } - function tryToClaimNextHydratableInstance(fiber) { - if (isHydrating) { - var nextInstance = nextHydratableInstance; - if (!nextInstance) return insertNonHydratedInstance(hydrationParentFiber, fiber), - isHydrating = !1, void (hydrationParentFiber = fiber); - if (!canHydrate(fiber, nextInstance)) { - if (!(nextInstance = getNextHydratableSibling(nextInstance)) || !canHydrate(fiber, nextInstance)) return insertNonHydratedInstance(hydrationParentFiber, fiber), - isHydrating = !1, void (hydrationParentFiber = fiber); - deleteHydratableInstance(hydrationParentFiber, nextHydratableInstance); - } - fiber.stateNode = nextInstance, hydrationParentFiber = fiber, nextHydratableInstance = getFirstHydratableChild(nextInstance); - } - } - function prepareToHydrateHostInstance(fiber, rootContainerInstance, hostContext) { - var instance = fiber.stateNode, updatePayload = hydrateInstance(instance, fiber.type, fiber.memoizedProps, rootContainerInstance, hostContext, fiber); - return fiber.updateQueue = updatePayload, null !== updatePayload; - } - function prepareToHydrateHostTextInstance(fiber) { - var textInstance = fiber.stateNode; - return hydrateTextInstance(textInstance, fiber.memoizedProps, fiber); - } - function popToNextHostParent(fiber) { - for (var parent = fiber.return; null !== parent && parent.tag !== HostComponent$9 && parent.tag !== HostRoot$9; ) parent = parent.return; - hydrationParentFiber = parent; - } - function popHydrationState(fiber) { - if (fiber !== hydrationParentFiber) return !1; - if (!isHydrating) return popToNextHostParent(fiber), isHydrating = !0, !1; - var type = fiber.type; - if (fiber.tag !== HostComponent$9 || "head" !== type && "body" !== type && !shouldSetTextContent(type, fiber.memoizedProps)) for (var nextInstance = nextHydratableInstance; nextInstance; ) deleteHydratableInstance(fiber, nextInstance), - nextInstance = getNextHydratableSibling(nextInstance); - return popToNextHostParent(fiber), nextHydratableInstance = hydrationParentFiber ? getNextHydratableSibling(fiber.stateNode) : null, - !0; - } - function resetHydrationState() { - hydrationParentFiber = null, nextHydratableInstance = null, isHydrating = !1; - } - return { - enterHydrationState: enterHydrationState, - resetHydrationState: resetHydrationState, - tryToClaimNextHydratableInstance: tryToClaimNextHydratableInstance, - prepareToHydrateHostInstance: prepareToHydrateHostInstance, - prepareToHydrateHostTextInstance: prepareToHydrateHostTextInstance, - popHydrationState: popHydrationState - }; - }, ReactFiberInstrumentation$2 = { - debugTool: null - }, ReactFiberInstrumentation_1 = ReactFiberInstrumentation$2, popContextProvider$1 = ReactFiberContext.popContextProvider, reset$1 = ReactFiberStack.reset, getStackAddendumByWorkInProgressFiber$2 = ReactFiberComponentTreeHook.getStackAddendumByWorkInProgressFiber, logCapturedError$1 = ReactFiberErrorLogger.logCapturedError, invokeGuardedCallback$1 = ReactErrorUtils_1.invokeGuardedCallback, hasCaughtError = ReactErrorUtils_1.hasCaughtError, clearCaughtError = ReactErrorUtils_1.clearCaughtError, ReactCurrentOwner$1 = ReactGlobalSharedState_1.ReactCurrentOwner, createWorkInProgress$1 = ReactFiber.createWorkInProgress, largerPriority$1 = ReactFiber.largerPriority, onCommitRoot = ReactFiberDevToolsHook.onCommitRoot, NoWork$2 = ReactPriorityLevel.NoWork, SynchronousPriority$1 = ReactPriorityLevel.SynchronousPriority, TaskPriority$1 = ReactPriorityLevel.TaskPriority, HighPriority = ReactPriorityLevel.HighPriority, LowPriority = ReactPriorityLevel.LowPriority, OffscreenPriority = ReactPriorityLevel.OffscreenPriority, AsyncUpdates = ReactTypeOfInternalContext.AsyncUpdates, PerformedWork = ReactTypeOfSideEffect.PerformedWork, Placement$1 = ReactTypeOfSideEffect.Placement, Update = ReactTypeOfSideEffect.Update, PlacementAndUpdate = ReactTypeOfSideEffect.PlacementAndUpdate, Deletion = ReactTypeOfSideEffect.Deletion, ContentReset = ReactTypeOfSideEffect.ContentReset, Callback = ReactTypeOfSideEffect.Callback, Err = ReactTypeOfSideEffect.Err, Ref = ReactTypeOfSideEffect.Ref, HostRoot$5 = ReactTypeOfWork.HostRoot, HostComponent$5 = ReactTypeOfWork.HostComponent, HostPortal$3 = ReactTypeOfWork.HostPortal, ClassComponent$5 = ReactTypeOfWork.ClassComponent, getUpdatePriority$1 = ReactFiberUpdateQueue.getUpdatePriority, _require14 = ReactFiberContext, resetContext$1 = _require14.resetContext, warning$6 = require$$0, ReactFiberInstrumentation$1 = ReactFiberInstrumentation_1, ReactDebugCurrentFiber$3 = ReactDebugCurrentFiber_1, _require15 = ReactDebugFiberPerf_1, recordEffect = _require15.recordEffect, recordScheduleUpdate = _require15.recordScheduleUpdate, startWorkTimer = _require15.startWorkTimer, stopWorkTimer = _require15.stopWorkTimer, stopFailedWorkTimer = _require15.stopFailedWorkTimer, startWorkLoopTimer = _require15.startWorkLoopTimer, stopWorkLoopTimer = _require15.stopWorkLoopTimer, startCommitTimer = _require15.startCommitTimer, stopCommitTimer = _require15.stopCommitTimer, startCommitHostEffectsTimer = _require15.startCommitHostEffectsTimer, stopCommitHostEffectsTimer = _require15.stopCommitHostEffectsTimer, startCommitLifeCyclesTimer = _require15.startCommitLifeCyclesTimer, stopCommitLifeCyclesTimer = _require15.stopCommitLifeCyclesTimer, warnAboutUpdateOnUnmounted = function(instance) { - var ctor = instance.constructor; - warning$6(!1, "Can only update a mounted or mounting component. This usually means " + "you called setState, replaceState, or forceUpdate on an unmounted " + "component. This is a no-op.\n\nPlease check the code for the " + "%s component.", ctor && (ctor.displayName || ctor.name) || "ReactClass"); - }, warnAboutInvalidUpdates = function(instance) { - switch (ReactDebugCurrentFiber$3.phase) { - case "getChildContext": - warning$6(!1, "setState(...): Cannot call setState() inside getChildContext()"); - break; - - case "render": - warning$6(!1, "Cannot update during an existing state transition (such as within " + "`render` or another component's constructor). Render methods should " + "be a pure function of props and state; constructor side-effects are " + "an anti-pattern, but can be moved to `componentWillMount`."); - } - }, timeHeuristicForUnitOfWork = 1, ReactFiberScheduler = function(config) { - var hostContext = ReactFiberHostContext(config), hydrationContext = ReactFiberHydrationContext(config), popHostContainer = hostContext.popHostContainer, popHostContext = hostContext.popHostContext, resetHostContainer = hostContext.resetHostContainer, _ReactFiberBeginWork = ReactFiberBeginWork(config, hostContext, hydrationContext, scheduleUpdate, getPriorityContext), beginWork = _ReactFiberBeginWork.beginWork, beginFailedWork = _ReactFiberBeginWork.beginFailedWork, _ReactFiberCompleteWo = ReactFiberCompleteWork(config, hostContext, hydrationContext), completeWork = _ReactFiberCompleteWo.completeWork, _ReactFiberCommitWork = ReactFiberCommitWork(config, captureError), commitPlacement = _ReactFiberCommitWork.commitPlacement, commitDeletion = _ReactFiberCommitWork.commitDeletion, commitWork = _ReactFiberCommitWork.commitWork, commitLifeCycles = _ReactFiberCommitWork.commitLifeCycles, commitAttachRef = _ReactFiberCommitWork.commitAttachRef, commitDetachRef = _ReactFiberCommitWork.commitDetachRef, scheduleDeferredCallback = config.scheduleDeferredCallback, useSyncScheduling = config.useSyncScheduling, prepareForCommit = config.prepareForCommit, resetAfterCommit = config.resetAfterCommit, priorityContext = NoWork$2, isPerformingWork = !1, deadlineHasExpired = !1, isBatchingUpdates = !1, isUnbatchingUpdates = !1, nextUnitOfWork = null, nextPriorityLevel = NoWork$2, nextEffect = null, pendingCommit = null, nextScheduledRoot = null, lastScheduledRoot = null, isCallbackScheduled = !1, capturedErrors = null, failedBoundaries = null, commitPhaseBoundaries = null, firstUncaughtError = null, didFatal = !1, isCommitting = !1, isUnmounting = !1, NESTED_UPDATE_LIMIT = 1e3, nestedUpdateCount = 0, nextRenderedTree = null; - function resetContextStack() { - reset$1(), resetContext$1(), resetHostContainer(); - } - function resetNextUnitOfWork() { - for (;null !== nextScheduledRoot && nextScheduledRoot.current.pendingWorkPriority === NoWork$2; ) { - nextScheduledRoot.isScheduled = !1; - var next = nextScheduledRoot.nextScheduledRoot; - if (nextScheduledRoot.nextScheduledRoot = null, nextScheduledRoot === lastScheduledRoot) return nextScheduledRoot = null, - lastScheduledRoot = null, nextPriorityLevel = NoWork$2, null; - nextScheduledRoot = next; - } - for (var root = nextScheduledRoot, highestPriorityRoot = null, highestPriorityLevel = NoWork$2; null !== root; ) root.current.pendingWorkPriority !== NoWork$2 && (highestPriorityLevel === NoWork$2 || highestPriorityLevel > root.current.pendingWorkPriority) && (highestPriorityLevel = root.current.pendingWorkPriority, - highestPriorityRoot = root), root = root.nextScheduledRoot; - if (null !== highestPriorityRoot) return nextPriorityLevel = highestPriorityLevel, - resetContextStack(), nextUnitOfWork = createWorkInProgress$1(highestPriorityRoot.current, highestPriorityLevel), - void (highestPriorityRoot !== nextRenderedTree && (nestedUpdateCount = 0, nextRenderedTree = highestPriorityRoot)); - nextPriorityLevel = NoWork$2, nextUnitOfWork = null, nextRenderedTree = null; - } - function commitAllHostEffects() { - for (;null !== nextEffect; ) { - ReactDebugCurrentFiber$3.setCurrentFiber(nextEffect), recordEffect(); - var effectTag = nextEffect.effectTag; - if (effectTag & ContentReset && config.resetTextContent(nextEffect.stateNode), effectTag & Ref) { - var current = nextEffect.alternate; - null !== current && commitDetachRef(current); - } - switch (effectTag & ~(Callback | Err | ContentReset | Ref | PerformedWork)) { - case Placement$1: - commitPlacement(nextEffect), nextEffect.effectTag &= ~Placement$1; - break; - - case PlacementAndUpdate: - commitPlacement(nextEffect), nextEffect.effectTag &= ~Placement$1; - var _current = nextEffect.alternate; - commitWork(_current, nextEffect); - break; - - case Update: - var _current2 = nextEffect.alternate; - commitWork(_current2, nextEffect); - break; - - case Deletion: - isUnmounting = !0, commitDeletion(nextEffect), isUnmounting = !1; - } - nextEffect = nextEffect.nextEffect; - } - ReactDebugCurrentFiber$3.resetCurrentFiber(); - } - function commitAllLifeCycles() { - for (;null !== nextEffect; ) { - var effectTag = nextEffect.effectTag; - if (effectTag & (Update | Callback)) { - recordEffect(); - var current = nextEffect.alternate; - commitLifeCycles(current, nextEffect); - } - effectTag & Ref && (recordEffect(), commitAttachRef(nextEffect)), effectTag & Err && (recordEffect(), - commitErrorHandling(nextEffect)); - var next = nextEffect.nextEffect; - nextEffect.nextEffect = null, nextEffect = next; - } - } - function commitAllWork(finishedWork) { - isCommitting = !0, startCommitTimer(), pendingCommit = null; - var root = finishedWork.stateNode; - invariant(root.current !== finishedWork, "Cannot commit the same tree as before. This is probably a bug " + "related to the return field. This error is likely caused by a bug " + "in React. Please file an issue."), - nextPriorityLevel !== SynchronousPriority$1 && nextPriorityLevel !== TaskPriority$1 || nestedUpdateCount++, - ReactCurrentOwner$1.current = null; - var firstEffect = void 0; - for (finishedWork.effectTag > PerformedWork ? null !== finishedWork.lastEffect ? (finishedWork.lastEffect.nextEffect = finishedWork, - firstEffect = finishedWork.firstEffect) : firstEffect = finishedWork : firstEffect = finishedWork.firstEffect, - prepareForCommit(), nextEffect = firstEffect, startCommitHostEffectsTimer(); null !== nextEffect; ) { - var didError = !1, _error = void 0; - invokeGuardedCallback$1(null, commitAllHostEffects, null), hasCaughtError() && (didError = !0, - _error = clearCaughtError()), didError && (invariant(null !== nextEffect, "Should have next effect. This error is likely caused by a bug " + "in React. Please file an issue."), - captureError(nextEffect, _error), null !== nextEffect && (nextEffect = nextEffect.nextEffect)); - } - for (stopCommitHostEffectsTimer(), resetAfterCommit(), root.current = finishedWork, - nextEffect = firstEffect, startCommitLifeCyclesTimer(); null !== nextEffect; ) { - var _didError = !1, _error2 = void 0; - invokeGuardedCallback$1(null, commitAllLifeCycles, null), hasCaughtError() && (_didError = !0, - _error2 = clearCaughtError()), _didError && (invariant(null !== nextEffect, "Should have next effect. This error is likely caused by a bug " + "in React. Please file an issue."), - captureError(nextEffect, _error2), null !== nextEffect && (nextEffect = nextEffect.nextEffect)); - } - isCommitting = !1, stopCommitLifeCyclesTimer(), stopCommitTimer(), "function" == typeof onCommitRoot && onCommitRoot(finishedWork.stateNode), - !0 && ReactFiberInstrumentation$1.debugTool && ReactFiberInstrumentation$1.debugTool.onCommitWork(finishedWork), - commitPhaseBoundaries && (commitPhaseBoundaries.forEach(scheduleErrorRecovery), - commitPhaseBoundaries = null), resetNextUnitOfWork(); - } - function resetWorkPriority(workInProgress, renderPriority) { - if (!(workInProgress.pendingWorkPriority !== NoWork$2 && workInProgress.pendingWorkPriority > renderPriority)) { - for (var newPriority = getUpdatePriority$1(workInProgress), child = workInProgress.child; null !== child; ) newPriority = largerPriority$1(newPriority, child.pendingWorkPriority), - child = child.sibling; - workInProgress.pendingWorkPriority = newPriority; - } - } - function completeUnitOfWork(workInProgress) { - for (;!0; ) { - var current = workInProgress.alternate; - ReactDebugCurrentFiber$3.setCurrentFiber(workInProgress); - var next = completeWork(current, workInProgress, nextPriorityLevel); - ReactDebugCurrentFiber$3.resetCurrentFiber(); - var returnFiber = workInProgress.return, siblingFiber = workInProgress.sibling; - if (resetWorkPriority(workInProgress, nextPriorityLevel), null !== next) return stopWorkTimer(workInProgress), - !0 && ReactFiberInstrumentation$1.debugTool && ReactFiberInstrumentation$1.debugTool.onCompleteWork(workInProgress), - next; - if (null !== returnFiber) { - null === returnFiber.firstEffect && (returnFiber.firstEffect = workInProgress.firstEffect), - null !== workInProgress.lastEffect && (null !== returnFiber.lastEffect && (returnFiber.lastEffect.nextEffect = workInProgress.firstEffect), - returnFiber.lastEffect = workInProgress.lastEffect); - workInProgress.effectTag > PerformedWork && (null !== returnFiber.lastEffect ? returnFiber.lastEffect.nextEffect = workInProgress : returnFiber.firstEffect = workInProgress, - returnFiber.lastEffect = workInProgress); - } - if (stopWorkTimer(workInProgress), !0 && ReactFiberInstrumentation$1.debugTool && ReactFiberInstrumentation$1.debugTool.onCompleteWork(workInProgress), - null !== siblingFiber) return siblingFiber; - if (null === returnFiber) return pendingCommit = workInProgress, null; - workInProgress = returnFiber; - } - return null; - } - function performUnitOfWork(workInProgress) { - var current = workInProgress.alternate; - startWorkTimer(workInProgress), ReactDebugCurrentFiber$3.setCurrentFiber(workInProgress); - var next = beginWork(current, workInProgress, nextPriorityLevel); - return ReactDebugCurrentFiber$3.resetCurrentFiber(), !0 && ReactFiberInstrumentation$1.debugTool && ReactFiberInstrumentation$1.debugTool.onBeginWork(workInProgress), - null === next && (next = completeUnitOfWork(workInProgress)), ReactCurrentOwner$1.current = null, - next; - } - function performFailedUnitOfWork(workInProgress) { - var current = workInProgress.alternate; - startWorkTimer(workInProgress), ReactDebugCurrentFiber$3.setCurrentFiber(workInProgress); - var next = beginFailedWork(current, workInProgress, nextPriorityLevel); - return ReactDebugCurrentFiber$3.resetCurrentFiber(), !0 && ReactFiberInstrumentation$1.debugTool && ReactFiberInstrumentation$1.debugTool.onBeginWork(workInProgress), - null === next && (next = completeUnitOfWork(workInProgress)), ReactCurrentOwner$1.current = null, - next; - } - function performDeferredWork(deadline) { - performWork(OffscreenPriority, deadline); - } - function handleCommitPhaseErrors() { - if (null !== capturedErrors && capturedErrors.size > 0 && nextPriorityLevel === TaskPriority$1) for (;null !== nextUnitOfWork && (null !== (nextUnitOfWork = hasCapturedError(nextUnitOfWork) ? performFailedUnitOfWork(nextUnitOfWork) : performUnitOfWork(nextUnitOfWork)) || (invariant(null !== pendingCommit, "Should have a pending commit. This error is likely caused by " + "a bug in React. Please file an issue."), - priorityContext = TaskPriority$1, commitAllWork(pendingCommit), priorityContext = nextPriorityLevel, - null !== capturedErrors && 0 !== capturedErrors.size && nextPriorityLevel === TaskPriority$1)); ) ; - } - function workLoop(minPriorityLevel, deadline) { - if (null !== pendingCommit ? (priorityContext = TaskPriority$1, commitAllWork(pendingCommit), - handleCommitPhaseErrors()) : null === nextUnitOfWork && resetNextUnitOfWork(), !(nextPriorityLevel === NoWork$2 || nextPriorityLevel > minPriorityLevel)) { - priorityContext = nextPriorityLevel; - loop: do { - if (nextPriorityLevel <= TaskPriority$1) for (;null !== nextUnitOfWork && !(null === (nextUnitOfWork = performUnitOfWork(nextUnitOfWork)) && (invariant(null !== pendingCommit, "Should have a pending commit. This error is likely caused by " + "a bug in React. Please file an issue."), - priorityContext = TaskPriority$1, commitAllWork(pendingCommit), priorityContext = nextPriorityLevel, - handleCommitPhaseErrors(), nextPriorityLevel === NoWork$2 || nextPriorityLevel > minPriorityLevel || nextPriorityLevel > TaskPriority$1)); ) ; else if (null !== deadline) for (;null !== nextUnitOfWork && !deadlineHasExpired; ) if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) { - if (null === (nextUnitOfWork = performUnitOfWork(nextUnitOfWork))) if (invariant(null !== pendingCommit, "Should have a pending commit. This error is likely caused by " + "a bug in React. Please file an issue."), - deadline.timeRemaining() > timeHeuristicForUnitOfWork) { - if (priorityContext = TaskPriority$1, commitAllWork(pendingCommit), priorityContext = nextPriorityLevel, - handleCommitPhaseErrors(), nextPriorityLevel === NoWork$2 || nextPriorityLevel > minPriorityLevel || nextPriorityLevel < HighPriority) break; - } else deadlineHasExpired = !0; - } else deadlineHasExpired = !0; - switch (nextPriorityLevel) { - case SynchronousPriority$1: - case TaskPriority$1: - if (nextPriorityLevel <= minPriorityLevel) continue loop; - break loop; - - case HighPriority: - case LowPriority: - case OffscreenPriority: - if (null === deadline) break loop; - if (!deadlineHasExpired && nextPriorityLevel <= minPriorityLevel) continue loop; - break loop; - - case NoWork$2: - break loop; - - default: - invariant(!1, "Switch statement should be exhuastive. " + "This error is likely caused by a bug in React. Please file an issue."); - } - } while (!0); - } - } - function performWorkCatchBlock(failedWork, boundary, minPriorityLevel, deadline) { - unwindContexts(failedWork, boundary), nextUnitOfWork = performFailedUnitOfWork(boundary), - workLoop(minPriorityLevel, deadline); - } - function performWork(minPriorityLevel, deadline) { - startWorkLoopTimer(), invariant(!isPerformingWork, "performWork was called recursively. This error is likely caused " + "by a bug in React. Please file an issue."), - isPerformingWork = !0; - var previousPriorityContext = priorityContext, didError = !1, error = null; - for (invokeGuardedCallback$1(null, workLoop, null, minPriorityLevel, deadline), - hasCaughtError() && (didError = !0, error = clearCaughtError()); didError; ) { - if (didFatal) { - firstUncaughtError = error; - break; - } - var failedWork = nextUnitOfWork; - if (null !== failedWork) { - var boundary = captureError(failedWork, error); - if (invariant(null !== boundary, "Should have found an error boundary. This error is likely " + "caused by a bug in React. Please file an issue."), - !didFatal) { - if (didError = !1, error = null, invokeGuardedCallback$1(null, performWorkCatchBlock, null, failedWork, boundary, minPriorityLevel, deadline), - !hasCaughtError()) break; - didError = !0, error = clearCaughtError(); - } - } else didFatal = !0; - } - priorityContext = previousPriorityContext, null !== deadline && (isCallbackScheduled = !1), - nextPriorityLevel > TaskPriority$1 && !isCallbackScheduled && (scheduleDeferredCallback(performDeferredWork), - isCallbackScheduled = !0); - var errorToThrow = firstUncaughtError; - if (isPerformingWork = !1, deadlineHasExpired = !1, didFatal = !1, firstUncaughtError = null, - capturedErrors = null, failedBoundaries = null, nextRenderedTree = null, nestedUpdateCount = 0, - stopWorkLoopTimer(), null !== errorToThrow) throw errorToThrow; - } - function captureError(failedWork, error) { - ReactCurrentOwner$1.current = null, ReactDebugCurrentFiber$3.resetCurrentFiber(); - var boundary = null, errorBoundaryFound = !1, willRetry = !1, errorBoundaryName = null; - if (failedWork.tag === HostRoot$5) boundary = failedWork, isFailedBoundary(failedWork) && (didFatal = !0); else for (var node = failedWork.return; null !== node && null === boundary; ) { - if (node.tag === ClassComponent$5) { - var instance = node.stateNode; - "function" == typeof instance.componentDidCatch && (errorBoundaryFound = !0, errorBoundaryName = getComponentName_1(node), - boundary = node, willRetry = !0); - } else node.tag === HostRoot$5 && (boundary = node); - if (isFailedBoundary(node)) { - if (isUnmounting) return null; - if (null !== commitPhaseBoundaries && (commitPhaseBoundaries.has(node) || null !== node.alternate && commitPhaseBoundaries.has(node.alternate))) return null; - boundary = null, willRetry = !1; - } - node = node.return; - } - if (null !== boundary) { - null === failedBoundaries && (failedBoundaries = new Set()), failedBoundaries.add(boundary); - var _componentStack = getStackAddendumByWorkInProgressFiber$2(failedWork), _componentName = getComponentName_1(failedWork); - null === capturedErrors && (capturedErrors = new Map()); - var capturedError = { - componentName: _componentName, - componentStack: _componentStack, - error: error, - errorBoundary: errorBoundaryFound ? boundary.stateNode : null, - errorBoundaryFound: errorBoundaryFound, - errorBoundaryName: errorBoundaryName, - willRetry: willRetry - }; - capturedErrors.set(boundary, capturedError); - try { - logCapturedError$1(capturedError); - } catch (e) { - console.error(e); - } - return isCommitting ? (null === commitPhaseBoundaries && (commitPhaseBoundaries = new Set()), - commitPhaseBoundaries.add(boundary)) : scheduleErrorRecovery(boundary), boundary; - } - return null === firstUncaughtError && (firstUncaughtError = error), null; - } - function hasCapturedError(fiber) { - return null !== capturedErrors && (capturedErrors.has(fiber) || null !== fiber.alternate && capturedErrors.has(fiber.alternate)); - } - function isFailedBoundary(fiber) { - return null !== failedBoundaries && (failedBoundaries.has(fiber) || null !== fiber.alternate && failedBoundaries.has(fiber.alternate)); - } - function commitErrorHandling(effectfulFiber) { - var capturedError = void 0; - switch (null !== capturedErrors && (capturedError = capturedErrors.get(effectfulFiber), - capturedErrors.delete(effectfulFiber), null == capturedError && null !== effectfulFiber.alternate && (effectfulFiber = effectfulFiber.alternate, - capturedError = capturedErrors.get(effectfulFiber), capturedErrors.delete(effectfulFiber))), - invariant(null != capturedError, "No error for given unit of work. This error is likely caused by a " + "bug in React. Please file an issue."), - effectfulFiber.tag) { - case ClassComponent$5: - var instance = effectfulFiber.stateNode, info = { - componentStack: capturedError.componentStack - }; - return void instance.componentDidCatch(capturedError.error, info); - - case HostRoot$5: - return void (null === firstUncaughtError && (firstUncaughtError = capturedError.error)); - - default: - invariant(!1, "Invalid type of work. This error is likely caused by a bug in " + "React. Please file an issue."); - } - } - function unwindContexts(from, to) { - for (var node = from; null !== node; ) { - switch (node.tag) { - case ClassComponent$5: - popContextProvider$1(node); - break; - - case HostComponent$5: - popHostContext(node); - break; - - case HostRoot$5: - case HostPortal$3: - popHostContainer(node); - } - if (node === to || node.alternate === to) { - stopFailedWorkTimer(node); - break; - } - stopWorkTimer(node), node = node.return; - } - } - function scheduleRoot(root, priorityLevel) { - priorityLevel !== NoWork$2 && (root.isScheduled || (root.isScheduled = !0, lastScheduledRoot ? (lastScheduledRoot.nextScheduledRoot = root, - lastScheduledRoot = root) : (nextScheduledRoot = root, lastScheduledRoot = root))); - } - function scheduleUpdate(fiber, priorityLevel) { - return scheduleUpdateImpl(fiber, priorityLevel, !1); - } - function scheduleUpdateImpl(fiber, priorityLevel, isErrorRecovery) { - if (recordScheduleUpdate(), nestedUpdateCount > NESTED_UPDATE_LIMIT && (didFatal = !0, - invariant(!1, "Maximum update depth exceeded. This can happen when a " + "component repeatedly calls setState inside componentWillUpdate or " + "componentDidUpdate. React limits the number of nested updates to " + "prevent infinite loops.")), - !isPerformingWork && priorityLevel <= nextPriorityLevel && (nextUnitOfWork = null), - !isErrorRecovery && fiber.tag === ClassComponent$5) { - var instance = fiber.stateNode; - warnAboutInvalidUpdates(instance); - } - for (var node = fiber, shouldContinue = !0; null !== node && shouldContinue; ) { - if (shouldContinue = !1, (node.pendingWorkPriority === NoWork$2 || node.pendingWorkPriority > priorityLevel) && (shouldContinue = !0, - node.pendingWorkPriority = priorityLevel), null !== node.alternate && (node.alternate.pendingWorkPriority === NoWork$2 || node.alternate.pendingWorkPriority > priorityLevel) && (shouldContinue = !0, - node.alternate.pendingWorkPriority = priorityLevel), null === node.return) { - if (node.tag !== HostRoot$5) return void (isErrorRecovery || fiber.tag !== ClassComponent$5 || warnAboutUpdateOnUnmounted(fiber.stateNode)); - if (scheduleRoot(node.stateNode, priorityLevel), !isPerformingWork) switch (priorityLevel) { - case SynchronousPriority$1: - isUnbatchingUpdates ? performWork(SynchronousPriority$1, null) : performWork(TaskPriority$1, null); - break; - - case TaskPriority$1: - invariant(isBatchingUpdates, "Task updates can only be scheduled as a nested update or " + "inside batchedUpdates."); - break; - - default: - isCallbackScheduled || (scheduleDeferredCallback(performDeferredWork), isCallbackScheduled = !0); - } - } - node = node.return; - } - } - function getPriorityContext(fiber, forceAsync) { - var priorityLevel = priorityContext; - return priorityLevel === NoWork$2 && (priorityLevel = !useSyncScheduling || fiber.internalContextTag & AsyncUpdates || forceAsync ? LowPriority : SynchronousPriority$1), - priorityLevel === SynchronousPriority$1 && (isPerformingWork || isBatchingUpdates) ? TaskPriority$1 : priorityLevel; - } - function scheduleErrorRecovery(fiber) { - scheduleUpdateImpl(fiber, TaskPriority$1, !0); - } - function batchedUpdates(fn, a) { - var previousIsBatchingUpdates = isBatchingUpdates; - isBatchingUpdates = !0; - try { - return fn(a); - } finally { - isBatchingUpdates = previousIsBatchingUpdates, isPerformingWork || isBatchingUpdates || performWork(TaskPriority$1, null); - } - } - function unbatchedUpdates(fn) { - var previousIsUnbatchingUpdates = isUnbatchingUpdates, previousIsBatchingUpdates = isBatchingUpdates; - isUnbatchingUpdates = isBatchingUpdates, isBatchingUpdates = !1; - try { - return fn(); - } finally { - isBatchingUpdates = previousIsBatchingUpdates, isUnbatchingUpdates = previousIsUnbatchingUpdates; - } - } - function flushSync(batch) { - var previousIsBatchingUpdates = isBatchingUpdates, previousPriorityContext = priorityContext; - isBatchingUpdates = !0, priorityContext = SynchronousPriority$1; - try { - return batch(); - } finally { - isBatchingUpdates = previousIsBatchingUpdates, priorityContext = previousPriorityContext, - invariant(!isPerformingWork, "flushSync was called from inside a lifecycle method. It cannot be " + "called when React is already rendering."), - performWork(TaskPriority$1, null); - } - } - function deferredUpdates(fn) { - var previousPriorityContext = priorityContext; - priorityContext = LowPriority; - try { - return fn(); - } finally { - priorityContext = previousPriorityContext; - } - } - return { - scheduleUpdate: scheduleUpdate, - getPriorityContext: getPriorityContext, - batchedUpdates: batchedUpdates, - unbatchedUpdates: unbatchedUpdates, - flushSync: flushSync, - deferredUpdates: deferredUpdates - }; - }, addTopLevelUpdate = ReactFiberUpdateQueue.addTopLevelUpdate, findCurrentUnmaskedContext = ReactFiberContext.findCurrentUnmaskedContext, isContextProvider = ReactFiberContext.isContextProvider, processChildContext = ReactFiberContext.processChildContext, createFiberRoot = ReactFiberRoot.createFiberRoot, HostComponent = ReactTypeOfWork.HostComponent, warning$1 = require$$0, ReactFiberInstrumentation = ReactFiberInstrumentation_1, ReactDebugCurrentFiber = ReactDebugCurrentFiber_1, getComponentName = getComponentName_1, findCurrentHostFiber = ReactFiberTreeReflection.findCurrentHostFiber, findCurrentHostFiberWithNoPortals = ReactFiberTreeReflection.findCurrentHostFiberWithNoPortals; - function getContextForSubtree(parentComponent) { - if (!parentComponent) return emptyObject; - var fiber = ReactInstanceMap_1.get(parentComponent), parentContext = findCurrentUnmaskedContext(fiber); - return isContextProvider(fiber) ? processChildContext(fiber, parentContext) : parentContext; - } - function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function"); - } - var objects = {}, uniqueID = 1, emptyObject$3 = {}, ReactNativePropRegistry = function() { - function ReactNativePropRegistry() { - _classCallCheck(this, ReactNativePropRegistry); - } - return ReactNativePropRegistry.register = function(object) { - var id = ++uniqueID; - return Object.freeze(object), objects[id] = object, id; - }, ReactNativePropRegistry.getByID = function(id) { - if (!id) return emptyObject$3; - var object = objects[id]; - return object || (console.warn("Invalid style with id `" + id + "`. Skipping ..."), - emptyObject$3); - }, ReactNativePropRegistry; - }(), ReactNativePropRegistry_1 = ReactNativePropRegistry, emptyObject$2 = {}, removedKeys = null, removedKeyCount = 0; - function defaultDiffer(prevProp, nextProp) { - return "object" != typeof nextProp || null === nextProp || deepDiffer(prevProp, nextProp); - } - function resolveObject(idOrObject) { - return "number" == typeof idOrObject ? ReactNativePropRegistry_1.getByID(idOrObject) : idOrObject; - } - function restoreDeletedValuesInNestedArray(updatePayload, node, validAttributes) { - if (Array.isArray(node)) for (var i = node.length; i-- && removedKeyCount > 0; ) restoreDeletedValuesInNestedArray(updatePayload, node[i], validAttributes); else if (node && removedKeyCount > 0) { - var obj = resolveObject(node); - for (var propKey in removedKeys) if (removedKeys[propKey]) { - var nextProp = obj[propKey]; - if (void 0 !== nextProp) { - var attributeConfig = validAttributes[propKey]; - if (attributeConfig) { - if ("function" == typeof nextProp && (nextProp = !0), void 0 === nextProp && (nextProp = null), - "object" != typeof attributeConfig) updatePayload[propKey] = nextProp; else if ("function" == typeof attributeConfig.diff || "function" == typeof attributeConfig.process) { - var nextValue = "function" == typeof attributeConfig.process ? attributeConfig.process(nextProp) : nextProp; - updatePayload[propKey] = nextValue; - } - removedKeys[propKey] = !1, removedKeyCount--; - } - } - } - } - } - function diffNestedArrayProperty(updatePayload, prevArray, nextArray, validAttributes) { - var i, minLength = prevArray.length < nextArray.length ? prevArray.length : nextArray.length; - for (i = 0; i < minLength; i++) updatePayload = diffNestedProperty(updatePayload, prevArray[i], nextArray[i], validAttributes); - for (;i < prevArray.length; i++) updatePayload = clearNestedProperty(updatePayload, prevArray[i], validAttributes); - for (;i < nextArray.length; i++) updatePayload = addNestedProperty(updatePayload, nextArray[i], validAttributes); - return updatePayload; - } - function diffNestedProperty(updatePayload, prevProp, nextProp, validAttributes) { - return updatePayload || prevProp !== nextProp ? prevProp && nextProp ? Array.isArray(prevProp) || Array.isArray(nextProp) ? Array.isArray(prevProp) && Array.isArray(nextProp) ? diffNestedArrayProperty(updatePayload, prevProp, nextProp, validAttributes) : Array.isArray(prevProp) ? diffProperties(updatePayload, flattenStyle(prevProp), resolveObject(nextProp), validAttributes) : diffProperties(updatePayload, resolveObject(prevProp), flattenStyle(nextProp), validAttributes) : diffProperties(updatePayload, resolveObject(prevProp), resolveObject(nextProp), validAttributes) : nextProp ? addNestedProperty(updatePayload, nextProp, validAttributes) : prevProp ? clearNestedProperty(updatePayload, prevProp, validAttributes) : updatePayload : updatePayload; - } - function addNestedProperty(updatePayload, nextProp, validAttributes) { - if (!nextProp) return updatePayload; - if (!Array.isArray(nextProp)) return addProperties(updatePayload, resolveObject(nextProp), validAttributes); - for (var i = 0; i < nextProp.length; i++) updatePayload = addNestedProperty(updatePayload, nextProp[i], validAttributes); - return updatePayload; - } - function clearNestedProperty(updatePayload, prevProp, validAttributes) { - if (!prevProp) return updatePayload; - if (!Array.isArray(prevProp)) return clearProperties(updatePayload, resolveObject(prevProp), validAttributes); - for (var i = 0; i < prevProp.length; i++) updatePayload = clearNestedProperty(updatePayload, prevProp[i], validAttributes); - return updatePayload; - } - function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { - var attributeConfig, nextProp, prevProp; - for (var propKey in nextProps) if (attributeConfig = validAttributes[propKey]) if (prevProp = prevProps[propKey], - nextProp = nextProps[propKey], "function" == typeof nextProp && (nextProp = !0, - "function" == typeof prevProp && (prevProp = !0)), void 0 === nextProp && (nextProp = null, - void 0 === prevProp && (prevProp = null)), removedKeys && (removedKeys[propKey] = !1), - updatePayload && void 0 !== updatePayload[propKey]) { - if ("object" != typeof attributeConfig) updatePayload[propKey] = nextProp; else if ("function" == typeof attributeConfig.diff || "function" == typeof attributeConfig.process) { - var nextValue = "function" == typeof attributeConfig.process ? attributeConfig.process(nextProp) : nextProp; - updatePayload[propKey] = nextValue; - } - } else if (prevProp !== nextProp) if ("object" != typeof attributeConfig) defaultDiffer(prevProp, nextProp) && ((updatePayload || (updatePayload = {}))[propKey] = nextProp); else if ("function" == typeof attributeConfig.diff || "function" == typeof attributeConfig.process) { - var shouldUpdate = void 0 === prevProp || ("function" == typeof attributeConfig.diff ? attributeConfig.diff(prevProp, nextProp) : defaultDiffer(prevProp, nextProp)); - shouldUpdate && (nextValue = "function" == typeof attributeConfig.process ? attributeConfig.process(nextProp) : nextProp, - (updatePayload || (updatePayload = {}))[propKey] = nextValue); - } else removedKeys = null, removedKeyCount = 0, updatePayload = diffNestedProperty(updatePayload, prevProp, nextProp, attributeConfig), - removedKeyCount > 0 && updatePayload && (restoreDeletedValuesInNestedArray(updatePayload, nextProp, attributeConfig), - removedKeys = null); - for (propKey in prevProps) void 0 === nextProps[propKey] && (attributeConfig = validAttributes[propKey]) && (updatePayload && void 0 !== updatePayload[propKey] || void 0 !== (prevProp = prevProps[propKey]) && ("object" != typeof attributeConfig || "function" == typeof attributeConfig.diff || "function" == typeof attributeConfig.process ? ((updatePayload || (updatePayload = {}))[propKey] = null, - removedKeys || (removedKeys = {}), removedKeys[propKey] || (removedKeys[propKey] = !0, - removedKeyCount++)) : updatePayload = clearNestedProperty(updatePayload, prevProp, attributeConfig))); - return updatePayload; - } - function addProperties(updatePayload, props, validAttributes) { - return diffProperties(updatePayload, emptyObject$2, props, validAttributes); - } - function clearProperties(updatePayload, prevProps, validAttributes) { - return diffProperties(updatePayload, prevProps, emptyObject$2, validAttributes); - } - var ReactNativeAttributePayload = { - create: function(props, validAttributes) { - return addProperties(null, props, validAttributes); - }, - diff: function(prevProps, nextProps, validAttributes) { - return diffProperties(null, prevProps, nextProps, validAttributes); - } - }, ReactNativeAttributePayload_1 = ReactNativeAttributePayload; - function mountSafeCallback$1(context, callback) { - return function() { - if (callback) { - if ("boolean" == typeof context.__isMounted) { - if (!context.__isMounted) return; - } else if ("function" == typeof context.isMounted && !context.isMounted()) return; - return callback.apply(context, arguments); - } - }; - } - function throwOnStylesProp(component, props) { - if (void 0 !== props.styles) { - var owner = component._owner || null, name = component.constructor.displayName, msg = "`styles` is not a supported property of `" + name + "`, did " + "you mean `style` (singular)?"; - throw owner && owner.constructor && owner.constructor.displayName && (msg += "\n\nCheck the `" + owner.constructor.displayName + "` parent " + " component."), - new Error(msg); - } - } - function warnForStyleProps$1(props, validAttributes) { - for (var key in validAttributes.style) validAttributes[key] || void 0 === props[key] || console.error("You are setting the style `{ " + key + ": ... }` as a prop. You " + "should nest it in a style object. " + "E.g. `{ style: { " + key + ": ... } }`"); - } - var NativeMethodsMixinUtils = { - mountSafeCallback: mountSafeCallback$1, - throwOnStylesProp: throwOnStylesProp, - warnForStyleProps: warnForStyleProps$1 - }; - function _classCallCheck$1(instance, Constructor) { - if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function"); - } - var mountSafeCallback = NativeMethodsMixinUtils.mountSafeCallback, warnForStyleProps = NativeMethodsMixinUtils.warnForStyleProps, ReactNativeFiberHostComponent = function() { - function ReactNativeFiberHostComponent(tag, viewConfig) { - _classCallCheck$1(this, ReactNativeFiberHostComponent), this._nativeTag = tag, this._children = [], - this.viewConfig = viewConfig; - } - return ReactNativeFiberHostComponent.prototype.blur = function() { - TextInputState.blurTextInput(this._nativeTag); - }, ReactNativeFiberHostComponent.prototype.focus = function() { - TextInputState.focusTextInput(this._nativeTag); - }, ReactNativeFiberHostComponent.prototype.measure = function(callback) { - UIManager.measure(this._nativeTag, mountSafeCallback(this, callback)); - }, ReactNativeFiberHostComponent.prototype.measureInWindow = function(callback) { - UIManager.measureInWindow(this._nativeTag, mountSafeCallback(this, callback)); - }, ReactNativeFiberHostComponent.prototype.measureLayout = function(relativeToNativeNode, onSuccess, onFail) { - UIManager.measureLayout(this._nativeTag, relativeToNativeNode, mountSafeCallback(this, onFail), mountSafeCallback(this, onSuccess)); - }, ReactNativeFiberHostComponent.prototype.setNativeProps = function(nativeProps) { - warnForStyleProps(nativeProps, this.viewConfig.validAttributes); - var updatePayload = ReactNativeAttributePayload_1.create(nativeProps, this.viewConfig.validAttributes); - null != updatePayload && UIManager.updateView(this._nativeTag, this.viewConfig.uiViewClassName, updatePayload); - }, ReactNativeFiberHostComponent; - }(), ReactNativeFiberHostComponent_1 = ReactNativeFiberHostComponent, INITIAL_TAG_COUNT = 1, ReactNativeTagHandles = { - tagsStartAt: INITIAL_TAG_COUNT, - tagCount: INITIAL_TAG_COUNT, - allocateTag: function() { - for (;this.reactTagIsNativeTopRootID(ReactNativeTagHandles.tagCount); ) ReactNativeTagHandles.tagCount++; - var tag = ReactNativeTagHandles.tagCount; - return ReactNativeTagHandles.tagCount++, tag; - }, - assertRootTag: function(tag) { - invariant(this.reactTagIsNativeTopRootID(tag), "Expect a native root tag, instead got %s", tag); - }, - reactTagIsNativeTopRootID: function(reactTag) { - return reactTag % 10 == 1; - } - }, ReactNativeTagHandles_1 = ReactNativeTagHandles, viewConfigCallbacks = new Map(), viewConfigs = new Map(), ReactNativeViewConfigRegistry = { - register: function(name, callback) { - return invariant(!viewConfigCallbacks.has(name), "Tried to register two views with the same name %s", name), - viewConfigCallbacks.set(name, callback), name; - }, - get: function(name) { - var viewConfig = void 0; - if (viewConfigs.has(name)) viewConfig = viewConfigs.get(name); else { - var callback = viewConfigCallbacks.get(name); - invariant("function" == typeof callback, "View config not found for name %s", name), - viewConfigCallbacks.set(name, null), viewConfig = callback(), viewConfigs.set(name, viewConfig); - } - return invariant(viewConfig, "View config not found for name %s", name), viewConfig; - } - }, ReactNativeViewConfigRegistry_1 = ReactNativeViewConfigRegistry, precacheFiberNode$1 = ReactNativeComponentTree_1.precacheFiberNode, uncacheFiberNode$1 = ReactNativeComponentTree_1.uncacheFiberNode, updateFiberProps$1 = ReactNativeComponentTree_1.updateFiberProps; - function recursivelyUncacheFiberNode(node) { - "number" == typeof node ? uncacheFiberNode$1(node) : (uncacheFiberNode$1(node._nativeTag), - node._children.forEach(recursivelyUncacheFiberNode)); - } - var NativeRenderer = function(config) { - var getPublicInstance = config.getPublicInstance, _ReactFiberScheduler = ReactFiberScheduler(config), scheduleUpdate = _ReactFiberScheduler.scheduleUpdate, getPriorityContext = _ReactFiberScheduler.getPriorityContext, batchedUpdates = _ReactFiberScheduler.batchedUpdates, unbatchedUpdates = _ReactFiberScheduler.unbatchedUpdates, flushSync = _ReactFiberScheduler.flushSync, deferredUpdates = _ReactFiberScheduler.deferredUpdates; - function scheduleTopLevelUpdate(current, element, callback) { - "render" === ReactDebugCurrentFiber.phase && null !== ReactDebugCurrentFiber.current && warning$1(!1, "Render methods should be a pure function of props and state; " + "triggering nested component updates from render is not allowed. " + "If necessary, trigger nested updates in componentDidUpdate.\n\n" + "Check the render method of %s.", getComponentName(ReactDebugCurrentFiber.current) || "Unknown"); - var forceAsync = ReactFeatureFlags_1.enableAsyncSubtreeAPI && null != element && null != element.type && null != element.type.prototype && !0 === element.type.prototype.unstable_isAsyncReactComponent, priorityLevel = getPriorityContext(current, forceAsync), nextState = { - element: element - }; - callback = void 0 === callback ? null : callback, warning$1(null === callback || "function" == typeof callback, "render(...): Expected the last optional `callback` argument to be a " + "function. Instead received: %s.", callback), - addTopLevelUpdate(current, nextState, callback, priorityLevel), scheduleUpdate(current, priorityLevel); - } - return { - createContainer: function(containerInfo) { - return createFiberRoot(containerInfo); - }, - updateContainer: function(element, container, parentComponent, callback) { - var current = container.current; - ReactFiberInstrumentation.debugTool && (null === current.alternate ? ReactFiberInstrumentation.debugTool.onMountContainer(container) : null === element ? ReactFiberInstrumentation.debugTool.onUnmountContainer(container) : ReactFiberInstrumentation.debugTool.onUpdateContainer(container)); - var context = getContextForSubtree(parentComponent); - null === container.context ? container.context = context : container.pendingContext = context, - scheduleTopLevelUpdate(current, element, callback); - }, - batchedUpdates: batchedUpdates, - unbatchedUpdates: unbatchedUpdates, - deferredUpdates: deferredUpdates, - flushSync: flushSync, - getPublicRootInstance: function(container) { - var containerFiber = container.current; - if (!containerFiber.child) return null; - switch (containerFiber.child.tag) { - case HostComponent: - return getPublicInstance(containerFiber.child.stateNode); - - default: - return containerFiber.child.stateNode; - } - }, - findHostInstance: function(fiber) { - var hostFiber = findCurrentHostFiber(fiber); - return null === hostFiber ? null : hostFiber.stateNode; - }, - findHostInstanceWithNoPortals: function(fiber) { - var hostFiber = findCurrentHostFiberWithNoPortals(fiber); - return null === hostFiber ? null : hostFiber.stateNode; - } - }; - }({ - appendChild: function(parentInstance, child) { - var childTag = "number" == typeof child ? child : child._nativeTag, children = parentInstance._children, index = children.indexOf(child); - index >= 0 ? (children.splice(index, 1), children.push(child), UIManager.manageChildren(parentInstance._nativeTag, [ index ], [ children.length - 1 ], [], [], [])) : (children.push(child), - UIManager.manageChildren(parentInstance._nativeTag, [], [], [ childTag ], [ children.length - 1 ], [])); - }, - appendChildToContainer: function(parentInstance, child) { - var childTag = "number" == typeof child ? child : child._nativeTag; - UIManager.setChildren(parentInstance, [ childTag ]); - }, - appendInitialChild: function(parentInstance, child) { - parentInstance._children.push(child); - }, - commitTextUpdate: function(textInstance, oldText, newText) { - UIManager.updateView(textInstance, "RCTRawText", { - text: newText - }); - }, - commitMount: function(instance, type, newProps, internalInstanceHandle) {}, - commitUpdate: function(instance, updatePayloadTODO, type, oldProps, newProps, internalInstanceHandle) { - var viewConfig = instance.viewConfig; - updateFiberProps$1(instance._nativeTag, newProps); - var updatePayload = ReactNativeAttributePayload_1.diff(oldProps, newProps, viewConfig.validAttributes); - null != updatePayload && UIManager.updateView(instance._nativeTag, viewConfig.uiViewClassName, updatePayload); - }, - createInstance: function(type, props, rootContainerInstance, hostContext, internalInstanceHandle) { - var tag = ReactNativeTagHandles_1.allocateTag(), viewConfig = ReactNativeViewConfigRegistry_1.get(type); - for (var key in viewConfig.validAttributes) props.hasOwnProperty(key) && deepFreezeAndThrowOnMutationInDev(props[key]); - var updatePayload = ReactNativeAttributePayload_1.create(props, viewConfig.validAttributes); - UIManager.createView(tag, viewConfig.uiViewClassName, rootContainerInstance, updatePayload); - var component = new ReactNativeFiberHostComponent_1(tag, viewConfig); - return precacheFiberNode$1(internalInstanceHandle, tag), updateFiberProps$1(tag, props), - component; - }, - createTextInstance: function(text, rootContainerInstance, hostContext, internalInstanceHandle) { - var tag = ReactNativeTagHandles_1.allocateTag(); - return UIManager.createView(tag, "RCTRawText", rootContainerInstance, { - text: text - }), precacheFiberNode$1(internalInstanceHandle, tag), tag; - }, - finalizeInitialChildren: function(parentInstance, type, props, rootContainerInstance) { - if (0 === parentInstance._children.length) return !1; - var nativeTags = parentInstance._children.map(function(child) { - return "number" == typeof child ? child : child._nativeTag; - }); - return UIManager.setChildren(parentInstance._nativeTag, nativeTags), !1; - }, - getRootHostContext: function() { - return emptyObject; - }, - getChildHostContext: function() { - return emptyObject; - }, - getPublicInstance: function(instance) { - return instance; - }, - insertBefore: function(parentInstance, child, beforeChild) { - var children = parentInstance._children, index = children.indexOf(child); - if (index >= 0) { - children.splice(index, 1); - var beforeChildIndex = children.indexOf(beforeChild); - children.splice(beforeChildIndex, 0, child), UIManager.manageChildren(parentInstance._nativeTag, [ index ], [ beforeChildIndex ], [], [], []); - } else { - var _beforeChildIndex = children.indexOf(beforeChild); - children.splice(_beforeChildIndex, 0, child); - var childTag = "number" == typeof child ? child : child._nativeTag; - UIManager.manageChildren(parentInstance._nativeTag, [], [], [ childTag ], [ _beforeChildIndex ], []); - } - }, - insertInContainerBefore: function(parentInstance, child, beforeChild) { - invariant("number" != typeof parentInstance, "Container does not support insertBefore operation"); - }, - prepareForCommit: function() {}, - prepareUpdate: function(instance, type, oldProps, newProps, rootContainerInstance, hostContext) { - return emptyObject; - }, - removeChild: function(parentInstance, child) { - recursivelyUncacheFiberNode(child); - var children = parentInstance._children, index = children.indexOf(child); - children.splice(index, 1), UIManager.manageChildren(parentInstance._nativeTag, [], [], [], [], [ index ]); - }, - removeChildFromContainer: function(parentInstance, child) { - recursivelyUncacheFiberNode(child), UIManager.manageChildren(parentInstance, [], [], [], [], [ 0 ]); - }, - resetAfterCommit: function() {}, - resetTextContent: function(instance) {}, - shouldDeprioritizeSubtree: function(type, props) { - return !1; - }, - scheduleDeferredCallback: commonjsGlobal.requestIdleCallback, - shouldSetTextContent: function(type, props) { - return !1; - }, - useSyncScheduling: !0 - }), ReactNativeFiberRenderer = NativeRenderer, getClosestInstanceFromNode = ReactNativeComponentTree_1.getClosestInstanceFromNode, findCurrentFiberUsingSlowPath$1 = ReactFiberTreeReflection.findCurrentFiberUsingSlowPath, HostComponent$10 = ReactTypeOfWork.HostComponent, getInspectorDataForViewTag = void 0, traverseOwnerTreeUp = function(hierarchy, instance) { - instance && (hierarchy.unshift(instance), traverseOwnerTreeUp(hierarchy, instance._debugOwner)); - }, getOwnerHierarchy = function(instance) { - var hierarchy = []; - return traverseOwnerTreeUp(hierarchy, instance), hierarchy; - }, lastNonHostInstance = function(hierarchy) { - for (var i = hierarchy.length - 1; i > 1; i--) { - var instance = hierarchy[i]; - if (instance.tag !== HostComponent$10) return instance; - } - return hierarchy[0]; - }, getHostProps = function(fiber) { - var host = ReactFiberTreeReflection.findCurrentHostFiber(fiber); - return host ? host.memoizedProps || emptyObject : emptyObject; - }, getHostNode = function(fiber, findNodeHandle) { - for (var hostNode = void 0; fiber; ) { - if (null !== fiber.stateNode && fiber.tag === HostComponent$10 && (hostNode = findNodeHandle(fiber.stateNode)), - hostNode) return hostNode; - fiber = fiber.child; - } - return null; - }, createHierarchy = function(fiberHierarchy) { - return fiberHierarchy.map(function(fiber) { - return { - name: getComponentName_1(fiber), - getInspectorData: function(findNodeHandle) { - return { - measure: function(callback) { - return UIManager.measure(getHostNode(fiber, findNodeHandle), callback); - }, - props: getHostProps(fiber), - source: fiber._debugSource - }; - } - }; - }); - }; - getInspectorDataForViewTag = function(viewTag) { - var closestInstance = getClosestInstanceFromNode(viewTag); - if (!closestInstance) return { - hierarchy: [], - props: emptyObject, - selection: null, - source: null - }; - var fiber = findCurrentFiberUsingSlowPath$1(closestInstance), fiberHierarchy = getOwnerHierarchy(fiber), instance = lastNonHostInstance(fiberHierarchy), hierarchy = createHierarchy(fiberHierarchy), props = getHostProps(instance), source = instance._debugSource; - return { - hierarchy: hierarchy, - props: props, - selection: fiberHierarchy.indexOf(instance), - source: source - }; - }; - var ReactNativeFiberInspector = { - getInspectorDataForViewTag: getInspectorDataForViewTag - }, ReactVersion = "16.0.0", ReactCurrentOwner$3 = ReactGlobalSharedState_1.ReactCurrentOwner, warning$11 = require$$0; - function findNodeHandle(componentOrHandle) { - var owner = ReactCurrentOwner$3.current; - if (null !== owner && null !== owner.stateNode && (warning$11(owner.stateNode._warnedAboutRefsInRender, "%s is accessing findNodeHandle inside its render(). " + "render() should be a pure function of props and state. It should " + "never access something that requires stale data from the previous " + "render, such as refs. Move this logic to componentDidMount and " + "componentDidUpdate instead.", getComponentName_1(owner) || "A component"), - owner.stateNode._warnedAboutRefsInRender = !0), null == componentOrHandle) return null; - if ("number" == typeof componentOrHandle) return componentOrHandle; - var component = componentOrHandle, internalInstance = ReactInstanceMap_1.get(component); - return internalInstance ? ReactNativeFiberRenderer.findHostInstance(internalInstance) : component || (invariant("object" == typeof component && "_nativeTag" in component || null != component.render && "function" == typeof component.render, "findNodeHandle(...): Argument is not a component " + "(type: %s, keys: %s)", typeof component, Object.keys(component)), - void invariant(!1, "findNodeHandle(...): Unable to find node handle for unmounted " + "component.")); - } - var findNodeHandle_1 = findNodeHandle, findNumericNodeHandle = function(componentOrHandle) { - var instance = findNodeHandle_1(componentOrHandle); - return null == instance || "number" == typeof instance ? instance : instance._nativeTag; - }, eventPluginOrder = null, namesToPlugins = {}; - function recomputePluginOrdering() { - if (eventPluginOrder) for (var pluginName in namesToPlugins) { - var pluginModule = namesToPlugins[pluginName], pluginIndex = eventPluginOrder.indexOf(pluginName); - if (invariant(pluginIndex > -1, "EventPluginRegistry: Cannot inject event plugins that do not exist in " + "the plugin ordering, `%s`.", pluginName), - !EventPluginRegistry.plugins[pluginIndex]) { - invariant(pluginModule.extractEvents, "EventPluginRegistry: Event plugins must implement an `extractEvents` " + "method, but `%s` does not.", pluginName), - EventPluginRegistry.plugins[pluginIndex] = pluginModule; - var publishedEvents = pluginModule.eventTypes; - for (var eventName in publishedEvents) invariant(publishEventForPlugin(publishedEvents[eventName], pluginModule, eventName), "EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.", eventName, pluginName); - } - } - } - function publishEventForPlugin(dispatchConfig, pluginModule, eventName) { - invariant(!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName), "EventPluginHub: More than one plugin attempted to publish the same " + "event name, `%s`.", eventName), - EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig; - var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; - if (phasedRegistrationNames) { - for (var phaseName in phasedRegistrationNames) if (phasedRegistrationNames.hasOwnProperty(phaseName)) { - var phasedRegistrationName = phasedRegistrationNames[phaseName]; - publishRegistrationName(phasedRegistrationName, pluginModule, eventName); - } - return !0; - } - return !!dispatchConfig.registrationName && (publishRegistrationName(dispatchConfig.registrationName, pluginModule, eventName), - !0); - } - function publishRegistrationName(registrationName, pluginModule, eventName) { - invariant(!EventPluginRegistry.registrationNameModules[registrationName], "EventPluginHub: More than one plugin attempted to publish the same " + "registration name, `%s`.", registrationName), - EventPluginRegistry.registrationNameModules[registrationName] = pluginModule, EventPluginRegistry.registrationNameDependencies[registrationName] = pluginModule.eventTypes[eventName].dependencies; - var lowerCasedName = registrationName.toLowerCase(); - EventPluginRegistry.possibleRegistrationNames[lowerCasedName] = registrationName, - "onDoubleClick" === registrationName && (EventPluginRegistry.possibleRegistrationNames.ondblclick = registrationName); - } - var EventPluginRegistry = { - plugins: [], - eventNameDispatchConfigs: {}, - registrationNameModules: {}, - registrationNameDependencies: {}, - possibleRegistrationNames: {}, - injectEventPluginOrder: function(injectedEventPluginOrder) { - invariant(!eventPluginOrder, "EventPluginRegistry: Cannot inject event plugin ordering more than " + "once. You are likely trying to load more than one copy of React."), - eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder), recomputePluginOrdering(); - }, - injectEventPluginsByName: function(injectedNamesToPlugins) { - var isOrderingDirty = !1; - for (var pluginName in injectedNamesToPlugins) if (injectedNamesToPlugins.hasOwnProperty(pluginName)) { - var pluginModule = injectedNamesToPlugins[pluginName]; - namesToPlugins.hasOwnProperty(pluginName) && namesToPlugins[pluginName] === pluginModule || (invariant(!namesToPlugins[pluginName], "EventPluginRegistry: Cannot inject two different event plugins " + "using the same name, `%s`.", pluginName), - namesToPlugins[pluginName] = pluginModule, isOrderingDirty = !0); - } - isOrderingDirty && recomputePluginOrdering(); - } - }, EventPluginRegistry_1 = EventPluginRegistry; - function accumulateInto(current, next) { - return invariant(null != next, "accumulateInto(...): Accumulated items must not be null or undefined."), - null == current ? next : Array.isArray(current) ? Array.isArray(next) ? (current.push.apply(current, next), - current) : (current.push(next), current) : Array.isArray(next) ? [ current ].concat(next) : [ current, next ]; - } - var accumulateInto_1 = accumulateInto; - function forEachAccumulated(arr, cb, scope) { - Array.isArray(arr) ? arr.forEach(cb, scope) : arr && cb.call(scope, arr); - } - var forEachAccumulated_1 = forEachAccumulated, eventQueue = null, executeDispatchesAndRelease = function(event, simulated) { - event && (EventPluginUtils_1.executeDispatchesInOrder(event, simulated), event.isPersistent() || event.constructor.release(event)); - }, executeDispatchesAndReleaseSimulated = function(e) { - return executeDispatchesAndRelease(e, !0); - }, executeDispatchesAndReleaseTopLevel = function(e) { - return executeDispatchesAndRelease(e, !1); - }; - function isInteractive(tag) { - return "button" === tag || "input" === tag || "select" === tag || "textarea" === tag; - } - function shouldPreventMouseEvent(name, type, props) { - switch (name) { - case "onClick": - case "onClickCapture": - case "onDoubleClick": - case "onDoubleClickCapture": - case "onMouseDown": - case "onMouseDownCapture": - case "onMouseMove": - case "onMouseMoveCapture": - case "onMouseUp": - case "onMouseUpCapture": - return !(!props.disabled || !isInteractive(type)); - - default: - return !1; - } - } - var EventPluginHub = { - injection: { - injectEventPluginOrder: EventPluginRegistry_1.injectEventPluginOrder, - injectEventPluginsByName: EventPluginRegistry_1.injectEventPluginsByName - }, - getListener: function(inst, registrationName) { - var listener, stateNode = inst.stateNode; - if (!stateNode) return null; - var props = EventPluginUtils_1.getFiberCurrentPropsFromNode(stateNode); - return props ? (listener = props[registrationName], shouldPreventMouseEvent(registrationName, inst.type, props) ? null : (invariant(!listener || "function" == typeof listener, "Expected `%s` listener to be a function, instead got a value of `%s` type.", registrationName, typeof listener), - listener)) : null; - }, - extractEvents: function(topLevelType, targetInst, nativeEvent, nativeEventTarget) { - for (var events, plugins = EventPluginRegistry_1.plugins, i = 0; i < plugins.length; i++) { - var possiblePlugin = plugins[i]; - if (possiblePlugin) { - var extractedEvents = possiblePlugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget); - extractedEvents && (events = accumulateInto_1(events, extractedEvents)); - } - } - return events; - }, - enqueueEvents: function(events) { - events && (eventQueue = accumulateInto_1(eventQueue, events)); - }, - processEventQueue: function(simulated) { - var processingEventQueue = eventQueue; - eventQueue = null, simulated ? forEachAccumulated_1(processingEventQueue, executeDispatchesAndReleaseSimulated) : forEachAccumulated_1(processingEventQueue, executeDispatchesAndReleaseTopLevel), - invariant(!eventQueue, "processEventQueue(): Additional events were enqueued while processing " + "an event queue. Support for this has not yet been implemented."), - ReactErrorUtils_1.rethrowCaughtError(); - } - }, EventPluginHub_1 = EventPluginHub, HostComponent$11 = ReactTypeOfWork.HostComponent; - function getParent(inst) { - do { - inst = inst.return; - } while (inst && inst.tag !== HostComponent$11); - return inst || null; - } - function getLowestCommonAncestor(instA, instB) { - for (var depthA = 0, tempA = instA; tempA; tempA = getParent(tempA)) depthA++; - for (var depthB = 0, tempB = instB; tempB; tempB = getParent(tempB)) depthB++; - for (;depthA - depthB > 0; ) instA = getParent(instA), depthA--; - for (;depthB - depthA > 0; ) instB = getParent(instB), depthB--; - for (var depth = depthA; depth--; ) { - if (instA === instB || instA === instB.alternate) return instA; - instA = getParent(instA), instB = getParent(instB); - } - return null; - } - function isAncestor(instA, instB) { - for (;instB; ) { - if (instA === instB || instA === instB.alternate) return !0; - instB = getParent(instB); - } - return !1; - } - function getParentInstance(inst) { - return getParent(inst); - } - function traverseTwoPhase(inst, fn, arg) { - for (var path = []; inst; ) path.push(inst), inst = getParent(inst); - var i; - for (i = path.length; i-- > 0; ) fn(path[i], "captured", arg); - for (i = 0; i < path.length; i++) fn(path[i], "bubbled", arg); - } - function traverseEnterLeave(from, to, fn, argFrom, argTo) { - for (var common = from && to ? getLowestCommonAncestor(from, to) : null, pathFrom = []; from && from !== common; ) pathFrom.push(from), - from = getParent(from); - for (var pathTo = []; to && to !== common; ) pathTo.push(to), to = getParent(to); - var i; - for (i = 0; i < pathFrom.length; i++) fn(pathFrom[i], "bubbled", argFrom); - for (i = pathTo.length; i-- > 0; ) fn(pathTo[i], "captured", argTo); - } - var ReactTreeTraversal = { - isAncestor: isAncestor, - getLowestCommonAncestor: getLowestCommonAncestor, - getParentInstance: getParentInstance, - traverseTwoPhase: traverseTwoPhase, - traverseEnterLeave: traverseEnterLeave - }, getListener = EventPluginHub_1.getListener, warning$12 = require$$0; - function listenerAtPhase(inst, event, propagationPhase) { - var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase]; - return getListener(inst, registrationName); - } - function accumulateDirectionalDispatches(inst, phase, event) { - warning$12(inst, "Dispatching inst must not be null"); - var listener = listenerAtPhase(inst, event, phase); - listener && (event._dispatchListeners = accumulateInto_1(event._dispatchListeners, listener), - event._dispatchInstances = accumulateInto_1(event._dispatchInstances, inst)); - } - function accumulateTwoPhaseDispatchesSingle(event) { - event && event.dispatchConfig.phasedRegistrationNames && ReactTreeTraversal.traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); - } - function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - var targetInst = event._targetInst, parentInst = targetInst ? ReactTreeTraversal.getParentInstance(targetInst) : null; - ReactTreeTraversal.traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event); - } - } - function accumulateDispatches(inst, ignoredDirection, event) { - if (inst && event && event.dispatchConfig.registrationName) { - var registrationName = event.dispatchConfig.registrationName, listener = getListener(inst, registrationName); - listener && (event._dispatchListeners = accumulateInto_1(event._dispatchListeners, listener), - event._dispatchInstances = accumulateInto_1(event._dispatchInstances, inst)); - } - } - function accumulateDirectDispatchesSingle(event) { - event && event.dispatchConfig.registrationName && accumulateDispatches(event._targetInst, null, event); - } - function accumulateTwoPhaseDispatches(events) { - forEachAccumulated_1(events, accumulateTwoPhaseDispatchesSingle); - } - function accumulateTwoPhaseDispatchesSkipTarget(events) { - forEachAccumulated_1(events, accumulateTwoPhaseDispatchesSingleSkipTarget); - } - function accumulateEnterLeaveDispatches(leave, enter, from, to) { - ReactTreeTraversal.traverseEnterLeave(from, to, accumulateDispatches, leave, enter); - } - function accumulateDirectDispatches(events) { - forEachAccumulated_1(events, accumulateDirectDispatchesSingle); - } - var EventPropagators = { - accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches, - accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget, - accumulateDirectDispatches: accumulateDirectDispatches, - accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches - }, EventPropagators_1 = EventPropagators, didWarnForAddedNewProperty = !1, isProxySupported = "function" == typeof Proxy, EVENT_POOL_SIZE = 10, warning$13 = require$$0, shouldBeReleasedProperties = [ "dispatchConfig", "_targetInst", "nativeEvent", "isDefaultPrevented", "isPropagationStopped", "_dispatchListeners", "_dispatchInstances" ], EventInterface = { - type: null, - target: null, - currentTarget: emptyFunction.thatReturnsNull, - eventPhase: null, - bubbles: null, - cancelable: null, - timeStamp: function(event) { - return event.timeStamp || Date.now(); - }, - defaultPrevented: null, - isTrusted: null - }; - function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) { - delete this.nativeEvent, delete this.preventDefault, delete this.stopPropagation, - this.dispatchConfig = dispatchConfig, this._targetInst = targetInst, this.nativeEvent = nativeEvent; - var Interface = this.constructor.Interface; - for (var propName in Interface) if (Interface.hasOwnProperty(propName)) { - delete this[propName]; - var normalize = Interface[propName]; - normalize ? this[propName] = normalize(nativeEvent) : "target" === propName ? this.target = nativeEventTarget : this[propName] = nativeEvent[propName]; - } - var defaultPrevented = null != nativeEvent.defaultPrevented ? nativeEvent.defaultPrevented : !1 === nativeEvent.returnValue; - return this.isDefaultPrevented = defaultPrevented ? emptyFunction.thatReturnsTrue : emptyFunction.thatReturnsFalse, - this.isPropagationStopped = emptyFunction.thatReturnsFalse, this; - } - Object.assign(SyntheticEvent.prototype, { - preventDefault: function() { - this.defaultPrevented = !0; - var event = this.nativeEvent; - event && (event.preventDefault ? event.preventDefault() : "unknown" != typeof event.returnValue && (event.returnValue = !1), - this.isDefaultPrevented = emptyFunction.thatReturnsTrue); - }, - stopPropagation: function() { - var event = this.nativeEvent; - event && (event.stopPropagation ? event.stopPropagation() : "unknown" != typeof event.cancelBubble && (event.cancelBubble = !0), - this.isPropagationStopped = emptyFunction.thatReturnsTrue); - }, - persist: function() { - this.isPersistent = emptyFunction.thatReturnsTrue; - }, - isPersistent: emptyFunction.thatReturnsFalse, - destructor: function() { - var Interface = this.constructor.Interface; - for (var propName in Interface) Object.defineProperty(this, propName, getPooledWarningPropertyDefinition(propName, Interface[propName])); - for (var i = 0; i < shouldBeReleasedProperties.length; i++) this[shouldBeReleasedProperties[i]] = null; - Object.defineProperty(this, "nativeEvent", getPooledWarningPropertyDefinition("nativeEvent", null)), - Object.defineProperty(this, "preventDefault", getPooledWarningPropertyDefinition("preventDefault", emptyFunction)), - Object.defineProperty(this, "stopPropagation", getPooledWarningPropertyDefinition("stopPropagation", emptyFunction)); - } - }), SyntheticEvent.Interface = EventInterface, SyntheticEvent.augmentClass = function(Class, Interface) { - var Super = this, E = function() {}; - E.prototype = Super.prototype; - var prototype = new E(); - Object.assign(prototype, Class.prototype), Class.prototype = prototype, Class.prototype.constructor = Class, - Class.Interface = Object.assign({}, Super.Interface, Interface), Class.augmentClass = Super.augmentClass, - addEventPoolingTo(Class); - }, isProxySupported && (SyntheticEvent = new Proxy(SyntheticEvent, { - construct: function(target, args) { - return this.apply(target, Object.create(target.prototype), args); - }, - apply: function(constructor, that, args) { - return new Proxy(constructor.apply(that, args), { - set: function(target, prop, value) { - return "isPersistent" === prop || target.constructor.Interface.hasOwnProperty(prop) || -1 !== shouldBeReleasedProperties.indexOf(prop) || (warning$13(didWarnForAddedNewProperty || target.isPersistent(), "This synthetic event is reused for performance reasons. If you're " + "seeing this, you're adding a new property in the synthetic event object. " + "The property is never released. See " + "https://fb.me/react-event-pooling for more information."), - didWarnForAddedNewProperty = !0), target[prop] = value, !0; - } - }); - } - })), addEventPoolingTo(SyntheticEvent); - var SyntheticEvent_1 = SyntheticEvent; - function getPooledWarningPropertyDefinition(propName, getVal) { - var isFunction = "function" == typeof getVal; - return { - configurable: !0, - set: set, - get: get - }; - function set(val) { - return warn(isFunction ? "setting the method" : "setting the property", "This is effectively a no-op"), - val; - } - function get() { - return warn(isFunction ? "accessing the method" : "accessing the property", isFunction ? "This is a no-op function" : "This is set to null"), - getVal; - } - function warn(action, result) { - warning$13(!1, "This synthetic event is reused for performance reasons. If you're seeing this, " + "you're %s `%s` on a released/nullified synthetic event. %s. " + "If you must keep the original synthetic event around, use event.persist(). " + "See https://fb.me/react-event-pooling for more information.", action, propName, result); - } - } - function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) { - var EventConstructor = this; - if (EventConstructor.eventPool.length) { - var instance = EventConstructor.eventPool.pop(); - return EventConstructor.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst), - instance; - } - return new EventConstructor(dispatchConfig, targetInst, nativeEvent, nativeInst); - } - function releasePooledEvent(event) { - var EventConstructor = this; - invariant(event instanceof EventConstructor, "Trying to release an event instance into a pool of a different type."), - event.destructor(), EventConstructor.eventPool.length < EVENT_POOL_SIZE && EventConstructor.eventPool.push(event); - } - function addEventPoolingTo(EventConstructor) { - EventConstructor.eventPool = [], EventConstructor.getPooled = getPooledEvent, EventConstructor.release = releasePooledEvent; - } - var customBubblingEventTypes = {}, customDirectEventTypes = {}, ReactNativeBridgeEventPlugin = { - eventTypes: {}, - extractEvents: function(topLevelType, targetInst, nativeEvent, nativeEventTarget) { - var bubbleDispatchConfig = customBubblingEventTypes[topLevelType], directDispatchConfig = customDirectEventTypes[topLevelType]; - invariant(bubbleDispatchConfig || directDispatchConfig, 'Unsupported top level event type "%s" dispatched', topLevelType); - var event = SyntheticEvent_1.getPooled(bubbleDispatchConfig || directDispatchConfig, targetInst, nativeEvent, nativeEventTarget); - if (bubbleDispatchConfig) EventPropagators_1.accumulateTwoPhaseDispatches(event); else { - if (!directDispatchConfig) return null; - EventPropagators_1.accumulateDirectDispatches(event); - } - return event; - }, - processEventTypes: function(viewConfig) { - var bubblingEventTypes = viewConfig.bubblingEventTypes, directEventTypes = viewConfig.directEventTypes; - if (null != bubblingEventTypes && null != directEventTypes) for (var topLevelType in directEventTypes) invariant(null == bubblingEventTypes[topLevelType], "Event cannot be both direct and bubbling: %s", topLevelType); - if (null != bubblingEventTypes) for (var _topLevelType in bubblingEventTypes) null == customBubblingEventTypes[_topLevelType] && (ReactNativeBridgeEventPlugin.eventTypes[_topLevelType] = customBubblingEventTypes[_topLevelType] = bubblingEventTypes[_topLevelType]); - if (null != directEventTypes) for (var _topLevelType2 in directEventTypes) null == customDirectEventTypes[_topLevelType2] && (ReactNativeBridgeEventPlugin.eventTypes[_topLevelType2] = customDirectEventTypes[_topLevelType2] = directEventTypes[_topLevelType2]); - } - }, ReactNativeBridgeEventPlugin_1 = ReactNativeBridgeEventPlugin; - function runEventQueueInBatch(events) { - EventPluginHub_1.enqueueEvents(events), EventPluginHub_1.processEventQueue(!1); - } - var ReactEventEmitterMixin = { - handleTopLevel: function(topLevelType, targetInst, nativeEvent, nativeEventTarget) { - runEventQueueInBatch(EventPluginHub_1.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget)); - } - }, ReactEventEmitterMixin_1 = ReactEventEmitterMixin, warning$14 = require$$0, EMPTY_NATIVE_EVENT = {}, touchSubsequence = function(touches, indices) { - for (var ret = [], i = 0; i < indices.length; i++) ret.push(touches[indices[i]]); - return ret; - }, removeTouchesAtIndices = function(touches, indices) { - for (var rippedOut = [], temp = touches, i = 0; i < indices.length; i++) { - var index = indices[i]; - rippedOut.push(touches[index]), temp[index] = null; - } - for (var fillAt = 0, j = 0; j < temp.length; j++) { - var cur = temp[j]; - null !== cur && (temp[fillAt++] = cur); - } - return temp.length = fillAt, rippedOut; - }, ReactNativeEventEmitter = Object.assign({}, ReactEventEmitterMixin_1, { - registrationNames: EventPluginRegistry_1.registrationNameModules, - getListener: EventPluginHub_1.getListener, - _receiveRootNodeIDEvent: function(rootNodeID, topLevelType, nativeEventParam) { - var nativeEvent = nativeEventParam || EMPTY_NATIVE_EVENT, inst = ReactNativeComponentTree_1.getInstanceFromNode(rootNodeID); - ReactGenericBatching_1.batchedUpdates(function() { - ReactNativeEventEmitter.handleTopLevel(topLevelType, inst, nativeEvent, nativeEvent.target); - }); - }, - receiveEvent: function(rootNodeID, topLevelType, nativeEventParam) { - ReactNativeEventEmitter._receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam); - }, - receiveTouches: function(eventTopLevelType, touches, changedIndices) { - for (var changedTouches = "topTouchEnd" === eventTopLevelType || "topTouchCancel" === eventTopLevelType ? removeTouchesAtIndices(touches, changedIndices) : touchSubsequence(touches, changedIndices), jj = 0; jj < changedTouches.length; jj++) { - var touch = changedTouches[jj]; - touch.changedTouches = changedTouches, touch.touches = touches; - var nativeEvent = touch, rootNodeID = null, target = nativeEvent.target; - null !== target && void 0 !== target && (target < ReactNativeTagHandles_1.tagsStartAt ? warning$14(!1, "A view is reporting that a touch occurred on tag zero.") : rootNodeID = target), - ReactNativeEventEmitter._receiveRootNodeIDEvent(rootNodeID, eventTopLevelType, nativeEvent); - } - } - }), ReactNativeEventEmitter_1 = ReactNativeEventEmitter, ReactNativeEventPluginOrder = [ "ResponderEventPlugin", "ReactNativeBridgeEventPlugin" ], ReactNativeEventPluginOrder_1 = ReactNativeEventPluginOrder, ReactNativeGlobalResponderHandler = { - onChange: function(from, to, blockNativeResponder) { - if (null !== to) { - var tag = to.stateNode._nativeTag; - UIManager.setJSResponder(tag, blockNativeResponder); - } else UIManager.clearJSResponder(); - } - }, ReactNativeGlobalResponderHandler_1 = ReactNativeGlobalResponderHandler, ResponderEventInterface = { - touchHistory: function(nativeEvent) { - return null; - } - }; - function ResponderSyntheticEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { - return SyntheticEvent_1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); - } - SyntheticEvent_1.augmentClass(ResponderSyntheticEvent, ResponderEventInterface); - var ResponderSyntheticEvent_1 = ResponderSyntheticEvent, isEndish$2 = EventPluginUtils_1.isEndish, isMoveish$2 = EventPluginUtils_1.isMoveish, isStartish$2 = EventPluginUtils_1.isStartish, warning$15 = require$$0, MAX_TOUCH_BANK = 20, touchBank = [], touchHistory = { - touchBank: touchBank, - numberActiveTouches: 0, - indexOfSingleActiveTouch: -1, - mostRecentTimeStamp: 0 - }; - function timestampForTouch(touch) { - return touch.timeStamp || touch.timestamp; - } - function createTouchRecord(touch) { - return { - touchActive: !0, - startPageX: touch.pageX, - startPageY: touch.pageY, - startTimeStamp: timestampForTouch(touch), - currentPageX: touch.pageX, - currentPageY: touch.pageY, - currentTimeStamp: timestampForTouch(touch), - previousPageX: touch.pageX, - previousPageY: touch.pageY, - previousTimeStamp: timestampForTouch(touch) - }; - } - function resetTouchRecord(touchRecord, touch) { - touchRecord.touchActive = !0, touchRecord.startPageX = touch.pageX, touchRecord.startPageY = touch.pageY, - touchRecord.startTimeStamp = timestampForTouch(touch), touchRecord.currentPageX = touch.pageX, - touchRecord.currentPageY = touch.pageY, touchRecord.currentTimeStamp = timestampForTouch(touch), - touchRecord.previousPageX = touch.pageX, touchRecord.previousPageY = touch.pageY, - touchRecord.previousTimeStamp = timestampForTouch(touch); - } - function getTouchIdentifier(_ref) { - var identifier = _ref.identifier; - return invariant(null != identifier, "Touch object is missing identifier."), warning$15(identifier <= MAX_TOUCH_BANK, "Touch identifier %s is greater than maximum supported %s which causes " + "performance issues backfilling array locations for all of the indices.", identifier, MAX_TOUCH_BANK), - identifier; - } - function recordTouchStart(touch) { - var identifier = getTouchIdentifier(touch), touchRecord = touchBank[identifier]; - touchRecord ? resetTouchRecord(touchRecord, touch) : touchBank[identifier] = createTouchRecord(touch), - touchHistory.mostRecentTimeStamp = timestampForTouch(touch); - } - function recordTouchMove(touch) { - var touchRecord = touchBank[getTouchIdentifier(touch)]; - touchRecord ? (touchRecord.touchActive = !0, touchRecord.previousPageX = touchRecord.currentPageX, - touchRecord.previousPageY = touchRecord.currentPageY, touchRecord.previousTimeStamp = touchRecord.currentTimeStamp, - touchRecord.currentPageX = touch.pageX, touchRecord.currentPageY = touch.pageY, - touchRecord.currentTimeStamp = timestampForTouch(touch), touchHistory.mostRecentTimeStamp = timestampForTouch(touch)) : console.error("Cannot record touch move without a touch start.\n" + "Touch Move: %s\n", "Touch Bank: %s", printTouch(touch), printTouchBank()); - } - function recordTouchEnd(touch) { - var touchRecord = touchBank[getTouchIdentifier(touch)]; - touchRecord ? (touchRecord.touchActive = !1, touchRecord.previousPageX = touchRecord.currentPageX, - touchRecord.previousPageY = touchRecord.currentPageY, touchRecord.previousTimeStamp = touchRecord.currentTimeStamp, - touchRecord.currentPageX = touch.pageX, touchRecord.currentPageY = touch.pageY, - touchRecord.currentTimeStamp = timestampForTouch(touch), touchHistory.mostRecentTimeStamp = timestampForTouch(touch)) : console.error("Cannot record touch end without a touch start.\n" + "Touch End: %s\n", "Touch Bank: %s", printTouch(touch), printTouchBank()); - } - function printTouch(touch) { - return JSON.stringify({ - identifier: touch.identifier, - pageX: touch.pageX, - pageY: touch.pageY, - timestamp: timestampForTouch(touch) - }); - } - function printTouchBank() { - var printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK)); - return touchBank.length > MAX_TOUCH_BANK && (printed += " (original size: " + touchBank.length + ")"), - printed; - } - var ResponderTouchHistoryStore = { - recordTouchTrack: function(topLevelType, nativeEvent) { - if (isMoveish$2(topLevelType)) nativeEvent.changedTouches.forEach(recordTouchMove); else if (isStartish$2(topLevelType)) nativeEvent.changedTouches.forEach(recordTouchStart), - touchHistory.numberActiveTouches = nativeEvent.touches.length, 1 === touchHistory.numberActiveTouches && (touchHistory.indexOfSingleActiveTouch = nativeEvent.touches[0].identifier); else if (isEndish$2(topLevelType) && (nativeEvent.changedTouches.forEach(recordTouchEnd), - touchHistory.numberActiveTouches = nativeEvent.touches.length, 1 === touchHistory.numberActiveTouches)) { - for (var i = 0; i < touchBank.length; i++) { - var touchTrackToCheck = touchBank[i]; - if (null != touchTrackToCheck && touchTrackToCheck.touchActive) { - touchHistory.indexOfSingleActiveTouch = i; - break; - } - } - var activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch]; - warning$15(null != activeRecord && activeRecord.touchActive, "Cannot find single active touch."); - } - }, - touchHistory: touchHistory - }, ResponderTouchHistoryStore_1 = ResponderTouchHistoryStore; - function accumulate(current, next) { - return invariant(null != next, "accumulate(...): Accumulated items must be not be null or undefined."), - null == current ? next : Array.isArray(current) ? current.concat(next) : Array.isArray(next) ? [ current ].concat(next) : [ current, next ]; - } - var accumulate_1 = accumulate, isStartish$1 = EventPluginUtils_1.isStartish, isMoveish$1 = EventPluginUtils_1.isMoveish, isEndish$1 = EventPluginUtils_1.isEndish, executeDirectDispatch$1 = EventPluginUtils_1.executeDirectDispatch, hasDispatches$1 = EventPluginUtils_1.hasDispatches, executeDispatchesInOrderStopAtTrue$1 = EventPluginUtils_1.executeDispatchesInOrderStopAtTrue, responderInst = null, trackedTouchCount = 0, previousActiveTouches = 0, changeResponder = function(nextResponderInst, blockHostResponder) { - var oldResponderInst = responderInst; - responderInst = nextResponderInst, null !== ResponderEventPlugin.GlobalResponderHandler && ResponderEventPlugin.GlobalResponderHandler.onChange(oldResponderInst, nextResponderInst, blockHostResponder); - }, eventTypes = { - startShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onStartShouldSetResponder", - captured: "onStartShouldSetResponderCapture" - } - }, - scrollShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onScrollShouldSetResponder", - captured: "onScrollShouldSetResponderCapture" - } - }, - selectionChangeShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onSelectionChangeShouldSetResponder", - captured: "onSelectionChangeShouldSetResponderCapture" - } - }, - moveShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onMoveShouldSetResponder", - captured: "onMoveShouldSetResponderCapture" - } - }, - responderStart: { - registrationName: "onResponderStart" - }, - responderMove: { - registrationName: "onResponderMove" - }, - responderEnd: { - registrationName: "onResponderEnd" - }, - responderRelease: { - registrationName: "onResponderRelease" - }, - responderTerminationRequest: { - registrationName: "onResponderTerminationRequest" - }, - responderGrant: { - registrationName: "onResponderGrant" - }, - responderReject: { - registrationName: "onResponderReject" - }, - responderTerminate: { - registrationName: "onResponderTerminate" - } - }; - function setResponderAndExtractTransfer(topLevelType, targetInst, nativeEvent, nativeEventTarget) { - var shouldSetEventType = isStartish$1(topLevelType) ? eventTypes.startShouldSetResponder : isMoveish$1(topLevelType) ? eventTypes.moveShouldSetResponder : "topSelectionChange" === topLevelType ? eventTypes.selectionChangeShouldSetResponder : eventTypes.scrollShouldSetResponder, bubbleShouldSetFrom = responderInst ? ReactTreeTraversal.getLowestCommonAncestor(responderInst, targetInst) : targetInst, skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst, shouldSetEvent = ResponderSyntheticEvent_1.getPooled(shouldSetEventType, bubbleShouldSetFrom, nativeEvent, nativeEventTarget); - shouldSetEvent.touchHistory = ResponderTouchHistoryStore_1.touchHistory, skipOverBubbleShouldSetFrom ? EventPropagators_1.accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent) : EventPropagators_1.accumulateTwoPhaseDispatches(shouldSetEvent); - var wantsResponderInst = executeDispatchesInOrderStopAtTrue$1(shouldSetEvent); - if (shouldSetEvent.isPersistent() || shouldSetEvent.constructor.release(shouldSetEvent), - !wantsResponderInst || wantsResponderInst === responderInst) return null; - var extracted, grantEvent = ResponderSyntheticEvent_1.getPooled(eventTypes.responderGrant, wantsResponderInst, nativeEvent, nativeEventTarget); - grantEvent.touchHistory = ResponderTouchHistoryStore_1.touchHistory, EventPropagators_1.accumulateDirectDispatches(grantEvent); - var blockHostResponder = !0 === executeDirectDispatch$1(grantEvent); - if (responderInst) { - var terminationRequestEvent = ResponderSyntheticEvent_1.getPooled(eventTypes.responderTerminationRequest, responderInst, nativeEvent, nativeEventTarget); - terminationRequestEvent.touchHistory = ResponderTouchHistoryStore_1.touchHistory, - EventPropagators_1.accumulateDirectDispatches(terminationRequestEvent); - var shouldSwitch = !hasDispatches$1(terminationRequestEvent) || executeDirectDispatch$1(terminationRequestEvent); - if (terminationRequestEvent.isPersistent() || terminationRequestEvent.constructor.release(terminationRequestEvent), - shouldSwitch) { - var terminateEvent = ResponderSyntheticEvent_1.getPooled(eventTypes.responderTerminate, responderInst, nativeEvent, nativeEventTarget); - terminateEvent.touchHistory = ResponderTouchHistoryStore_1.touchHistory, EventPropagators_1.accumulateDirectDispatches(terminateEvent), - extracted = accumulate_1(extracted, [ grantEvent, terminateEvent ]), changeResponder(wantsResponderInst, blockHostResponder); - } else { - var rejectEvent = ResponderSyntheticEvent_1.getPooled(eventTypes.responderReject, wantsResponderInst, nativeEvent, nativeEventTarget); - rejectEvent.touchHistory = ResponderTouchHistoryStore_1.touchHistory, EventPropagators_1.accumulateDirectDispatches(rejectEvent), - extracted = accumulate_1(extracted, rejectEvent); - } - } else extracted = accumulate_1(extracted, grantEvent), changeResponder(wantsResponderInst, blockHostResponder); - return extracted; - } - function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) { - return topLevelInst && ("topScroll" === topLevelType && !nativeEvent.responderIgnoreScroll || trackedTouchCount > 0 && "topSelectionChange" === topLevelType || isStartish$1(topLevelType) || isMoveish$1(topLevelType)); - } - function noResponderTouches(nativeEvent) { - var touches = nativeEvent.touches; - if (!touches || 0 === touches.length) return !0; - for (var i = 0; i < touches.length; i++) { - var activeTouch = touches[i], target = activeTouch.target; - if (null !== target && void 0 !== target && 0 !== target) { - var targetInst = EventPluginUtils_1.getInstanceFromNode(target); - if (ReactTreeTraversal.isAncestor(responderInst, targetInst)) return !1; - } - } - return !0; - } - var ResponderEventPlugin = { - _getResponder: function() { - return responderInst; - }, - eventTypes: eventTypes, - extractEvents: function(topLevelType, targetInst, nativeEvent, nativeEventTarget) { - if (isStartish$1(topLevelType)) trackedTouchCount += 1; else if (isEndish$1(topLevelType)) { - if (!(trackedTouchCount >= 0)) return console.error("Ended a touch event which was not counted in `trackedTouchCount`."), - null; - trackedTouchCount -= 1; - } - ResponderTouchHistoryStore_1.recordTouchTrack(topLevelType, nativeEvent); - var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent) ? setResponderAndExtractTransfer(topLevelType, targetInst, nativeEvent, nativeEventTarget) : null, isResponderTouchStart = responderInst && isStartish$1(topLevelType), isResponderTouchMove = responderInst && isMoveish$1(topLevelType), isResponderTouchEnd = responderInst && isEndish$1(topLevelType), incrementalTouch = isResponderTouchStart ? eventTypes.responderStart : isResponderTouchMove ? eventTypes.responderMove : isResponderTouchEnd ? eventTypes.responderEnd : null; - if (incrementalTouch) { - var gesture = ResponderSyntheticEvent_1.getPooled(incrementalTouch, responderInst, nativeEvent, nativeEventTarget); - gesture.touchHistory = ResponderTouchHistoryStore_1.touchHistory, EventPropagators_1.accumulateDirectDispatches(gesture), - extracted = accumulate_1(extracted, gesture); - } - var isResponderTerminate = responderInst && "topTouchCancel" === topLevelType, isResponderRelease = responderInst && !isResponderTerminate && isEndish$1(topLevelType) && noResponderTouches(nativeEvent), finalTouch = isResponderTerminate ? eventTypes.responderTerminate : isResponderRelease ? eventTypes.responderRelease : null; - if (finalTouch) { - var finalEvent = ResponderSyntheticEvent_1.getPooled(finalTouch, responderInst, nativeEvent, nativeEventTarget); - finalEvent.touchHistory = ResponderTouchHistoryStore_1.touchHistory, EventPropagators_1.accumulateDirectDispatches(finalEvent), - extracted = accumulate_1(extracted, finalEvent), changeResponder(null); - } - var numberActiveTouches = ResponderTouchHistoryStore_1.touchHistory.numberActiveTouches; - return ResponderEventPlugin.GlobalInteractionHandler && numberActiveTouches !== previousActiveTouches && ResponderEventPlugin.GlobalInteractionHandler.onChange(numberActiveTouches), - previousActiveTouches = numberActiveTouches, extracted; - }, - GlobalResponderHandler: null, - GlobalInteractionHandler: null, - injection: { - injectGlobalResponderHandler: function(GlobalResponderHandler) { - ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; - }, - injectGlobalInteractionHandler: function(GlobalInteractionHandler) { - ResponderEventPlugin.GlobalInteractionHandler = GlobalInteractionHandler; - } - } - }, ResponderEventPlugin_1 = ResponderEventPlugin; - RCTEventEmitter.register(ReactNativeEventEmitter_1), EventPluginHub_1.injection.injectEventPluginOrder(ReactNativeEventPluginOrder_1), - EventPluginUtils_1.injection.injectComponentTree(ReactNativeComponentTree_1), ResponderEventPlugin_1.injection.injectGlobalResponderHandler(ReactNativeGlobalResponderHandler_1), - EventPluginHub_1.injection.injectEventPluginsByName({ - ResponderEventPlugin: ResponderEventPlugin_1, - ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin_1 - }); - function _classCallCheck$2(instance, Constructor) { - if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function"); - } - function _possibleConstructorReturn(self, call) { - if (!self) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - return !call || "object" != typeof call && "function" != typeof call ? self : call; - } - function _inherits(subClass, superClass) { - if ("function" != typeof superClass && null !== superClass) throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: !1, - writable: !0, - configurable: !0 - } - }), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass); - } - var mountSafeCallback$2 = NativeMethodsMixinUtils.mountSafeCallback, ReactNativeComponent = function(_React$Component) { - _inherits(ReactNativeComponent, _React$Component); - function ReactNativeComponent() { - return _classCallCheck$2(this, ReactNativeComponent), _possibleConstructorReturn(this, _React$Component.apply(this, arguments)); - } - return ReactNativeComponent.prototype.blur = function() { - TextInputState.blurTextInput(findNumericNodeHandle(this)); - }, ReactNativeComponent.prototype.focus = function() { - TextInputState.focusTextInput(findNumericNodeHandle(this)); - }, ReactNativeComponent.prototype.measure = function(callback) { - UIManager.measure(findNumericNodeHandle(this), mountSafeCallback$2(this, callback)); - }, ReactNativeComponent.prototype.measureInWindow = function(callback) { - UIManager.measureInWindow(findNumericNodeHandle(this), mountSafeCallback$2(this, callback)); - }, ReactNativeComponent.prototype.measureLayout = function(relativeToNativeNode, onSuccess, onFail) { - UIManager.measureLayout(findNumericNodeHandle(this), relativeToNativeNode, mountSafeCallback$2(this, onFail), mountSafeCallback$2(this, onSuccess)); - }, ReactNativeComponent.prototype.setNativeProps = function(nativeProps) { - var maybeInstance = void 0; - try { - maybeInstance = findNodeHandle_1(this); - } catch (error) {} - if (null != maybeInstance) { - var viewConfig = maybeInstance.viewConfig, updatePayload = ReactNativeAttributePayload_1.create(nativeProps, viewConfig.validAttributes); - null != updatePayload && UIManager.updateView(maybeInstance._nativeTag, viewConfig.uiViewClassName, updatePayload); - } - }, ReactNativeComponent; - }(react.Component), ReactNativeComponent_1 = ReactNativeComponent, mountSafeCallback$3 = NativeMethodsMixinUtils.mountSafeCallback, throwOnStylesProp$1 = NativeMethodsMixinUtils.throwOnStylesProp, warnForStyleProps$2 = NativeMethodsMixinUtils.warnForStyleProps, NativeMethodsMixin = { - measure: function(callback) { - UIManager.measure(findNumericNodeHandle(this), mountSafeCallback$3(this, callback)); - }, - measureInWindow: function(callback) { - UIManager.measureInWindow(findNumericNodeHandle(this), mountSafeCallback$3(this, callback)); - }, - measureLayout: function(relativeToNativeNode, onSuccess, onFail) { - UIManager.measureLayout(findNumericNodeHandle(this), relativeToNativeNode, mountSafeCallback$3(this, onFail), mountSafeCallback$3(this, onSuccess)); - }, - setNativeProps: function(nativeProps) { - var maybeInstance = void 0; - try { - maybeInstance = findNodeHandle_1(this); - } catch (error) {} - if (null != maybeInstance) { - var viewConfig = maybeInstance.viewConfig; - warnForStyleProps$2(nativeProps, viewConfig.validAttributes); - var updatePayload = ReactNativeAttributePayload_1.create(nativeProps, viewConfig.validAttributes); - null != updatePayload && UIManager.updateView(maybeInstance._nativeTag, viewConfig.uiViewClassName, updatePayload); - } - }, - focus: function() { - TextInputState.focusTextInput(findNumericNodeHandle(this)); - }, - blur: function() { - TextInputState.blurTextInput(findNumericNodeHandle(this)); - } - }, NativeMethodsMixin_DEV = NativeMethodsMixin; - invariant(!NativeMethodsMixin_DEV.componentWillMount && !NativeMethodsMixin_DEV.componentWillReceiveProps, "Do not override existing functions."), - NativeMethodsMixin_DEV.componentWillMount = function() { - throwOnStylesProp$1(this, this.props); - }, NativeMethodsMixin_DEV.componentWillReceiveProps = function(newProps) { - throwOnStylesProp$1(this, newProps); - }; - var NativeMethodsMixin_1 = NativeMethodsMixin, TouchHistoryMath = { - centroidDimension: function(touchHistory, touchesChangedAfter, isXAxis, ofCurrent) { - var touchBank = touchHistory.touchBank, total = 0, count = 0, oneTouchData = 1 === touchHistory.numberActiveTouches ? touchHistory.touchBank[touchHistory.indexOfSingleActiveTouch] : null; - if (null !== oneTouchData) oneTouchData.touchActive && oneTouchData.currentTimeStamp > touchesChangedAfter && (total += ofCurrent && isXAxis ? oneTouchData.currentPageX : ofCurrent && !isXAxis ? oneTouchData.currentPageY : !ofCurrent && isXAxis ? oneTouchData.previousPageX : oneTouchData.previousPageY, - count = 1); else for (var i = 0; i < touchBank.length; i++) { - var touchTrack = touchBank[i]; - if (null !== touchTrack && void 0 !== touchTrack && touchTrack.touchActive && touchTrack.currentTimeStamp >= touchesChangedAfter) { - var toAdd; - toAdd = ofCurrent && isXAxis ? touchTrack.currentPageX : ofCurrent && !isXAxis ? touchTrack.currentPageY : !ofCurrent && isXAxis ? touchTrack.previousPageX : touchTrack.previousPageY, - total += toAdd, count++; - } - } - return count > 0 ? total / count : TouchHistoryMath.noCentroid; - }, - currentCentroidXOfTouchesChangedAfter: function(touchHistory, touchesChangedAfter) { - return TouchHistoryMath.centroidDimension(touchHistory, touchesChangedAfter, !0, !0); - }, - currentCentroidYOfTouchesChangedAfter: function(touchHistory, touchesChangedAfter) { - return TouchHistoryMath.centroidDimension(touchHistory, touchesChangedAfter, !1, !0); - }, - previousCentroidXOfTouchesChangedAfter: function(touchHistory, touchesChangedAfter) { - return TouchHistoryMath.centroidDimension(touchHistory, touchesChangedAfter, !0, !1); - }, - previousCentroidYOfTouchesChangedAfter: function(touchHistory, touchesChangedAfter) { - return TouchHistoryMath.centroidDimension(touchHistory, touchesChangedAfter, !1, !1); - }, - currentCentroidX: function(touchHistory) { - return TouchHistoryMath.centroidDimension(touchHistory, 0, !0, !0); - }, - currentCentroidY: function(touchHistory) { - return TouchHistoryMath.centroidDimension(touchHistory, 0, !1, !0); - }, - noCentroid: -1 - }, TouchHistoryMath_1 = TouchHistoryMath, createReactNativeComponentClass = function(name, callback) { - return ReactNativeViewConfigRegistry_1.register(name, callback); - }, createReactNativeComponentClass_1 = createReactNativeComponentClass; - function takeSnapshot(view, options) { - return "number" != typeof view && "window" !== view && (view = findNumericNodeHandle(view) || "window"), - UIManager.__takeSnapshot(view, options); - } - var takeSnapshot_1 = takeSnapshot, injectInternals = ReactFiberDevToolsHook.injectInternals; - ReactGenericBatching_1.injection.injectFiberBatchedUpdates(ReactNativeFiberRenderer.batchedUpdates); - var roots = new Map(); - ReactFiberErrorLogger.injection.injectDialog(ReactNativeFiberErrorDialog_1.showDialog); - var ReactNativeFiber = { - NativeComponent: ReactNativeComponent_1, - findNodeHandle: findNumericNodeHandle, - render: function(element, containerTag, callback) { - var root = roots.get(containerTag); - return root || (root = ReactNativeFiberRenderer.createContainer(containerTag), roots.set(containerTag, root)), - ReactNativeFiberRenderer.updateContainer(element, root, null, callback), ReactNativeFiberRenderer.getPublicRootInstance(root); - }, - unmountComponentAtNode: function(containerTag) { - var root = roots.get(containerTag); - root && ReactNativeFiberRenderer.updateContainer(null, root, null, function() { - roots.delete(containerTag); - }); - }, - unmountComponentAtNodeAndRemoveContainer: function(containerTag) { - ReactNativeFiber.unmountComponentAtNode(containerTag), UIManager.removeRootView(containerTag); - }, - createPortal: function(children, containerTag) { - var key = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : null; - return ReactPortal.createPortal(children, containerTag, null, key); - }, - unstable_batchedUpdates: ReactGenericBatching_1.batchedUpdates, - flushSync: ReactNativeFiberRenderer.flushSync, - __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: { - NativeMethodsMixin: NativeMethodsMixin_1, - ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin_1, - ReactGlobalSharedState: ReactGlobalSharedState_1, - ReactNativeComponentTree: ReactNativeComponentTree_1, - ReactNativePropRegistry: ReactNativePropRegistry_1, - TouchHistoryMath: TouchHistoryMath_1, - createReactNativeComponentClass: createReactNativeComponentClass_1, - takeSnapshot: takeSnapshot_1 - } - }; - Object.assign(ReactNativeFiber.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, { - ReactDebugTool: { - addHook: function() {}, - removeHook: function() {} - }, - ReactPerf: { - start: function() {}, - stop: function() {}, - printInclusive: function() {}, - printWasted: function() {} - } - }), injectInternals({ - findFiberByHostInstance: ReactNativeComponentTree_1.getClosestInstanceFromNode, - findHostInstanceByFiber: ReactNativeFiberRenderer.findHostInstance, - getInspectorDataForViewTag: ReactNativeFiberInspector.getInspectorDataForViewTag, - bundleType: 1, - version: ReactVersion, - rendererPackageName: "react-native" - }); - var ReactNativeFiberEntry = ReactNativeFiber; - module.exports = ReactNativeFiberEntry; -}(); diff --git a/Libraries/Renderer/ReactNativeFiber-prod.js b/Libraries/Renderer/ReactNativeFiber-prod.js deleted file mode 100644 index 12e7faa7d5419b..00000000000000 --- a/Libraries/Renderer/ReactNativeFiber-prod.js +++ /dev/null @@ -1,3666 +0,0 @@ -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @noflow - * @providesModule ReactNativeFiber-prod - */ -"use strict"; - -var invariant = require("fbjs/lib/invariant"), ExceptionsManager = require("ExceptionsManager"), emptyObject = require("fbjs/lib/emptyObject"), react = require("react"), shallowEqual = require("fbjs/lib/shallowEqual"), deepDiffer = require("deepDiffer"), flattenStyle = require("flattenStyle"), TextInputState = require("TextInputState"), UIManager = require("UIManager"); - -require("deepFreezeAndThrowOnMutationInDev"), require("InitializeCore"); - -var RCTEventEmitter = require("RCTEventEmitter"), emptyFunction = require("fbjs/lib/emptyFunction"), defaultShowDialog = function(capturedError) { - return !0; -}, showDialog = defaultShowDialog; - -function logCapturedError(capturedError) { - if (!1 !== showDialog(capturedError)) { - var error = capturedError.error; - console.error(error); - } -} - -var injection = { - injectDialog: function(fn) { - invariant(showDialog === defaultShowDialog, "The custom dialog was already injected."), - invariant("function" == typeof fn, "Injected showDialog() must be a function."), - showDialog = fn; - } -}, logCapturedError_1 = logCapturedError, ReactFiberErrorLogger = { - injection: injection, - logCapturedError: logCapturedError_1 -}, ReactErrorUtils = { - _caughtError: null, - _hasCaughtError: !1, - _rethrowError: null, - _hasRethrowError: !1, - injection: { - injectErrorUtils: function(injectedErrorUtils) { - invariant("function" == typeof injectedErrorUtils.invokeGuardedCallback, "Injected invokeGuardedCallback() must be a function."), - invokeGuardedCallback = injectedErrorUtils.invokeGuardedCallback; - } - }, - invokeGuardedCallback: function(name, func, context, a, b, c, d, e, f) { - invokeGuardedCallback.apply(ReactErrorUtils, arguments); - }, - invokeGuardedCallbackAndCatchFirstError: function(name, func, context, a, b, c, d, e, f) { - if (ReactErrorUtils.invokeGuardedCallback.apply(this, arguments), ReactErrorUtils.hasCaughtError()) { - var error = ReactErrorUtils.clearCaughtError(); - ReactErrorUtils._hasRethrowError || (ReactErrorUtils._hasRethrowError = !0, ReactErrorUtils._rethrowError = error); - } - }, - rethrowCaughtError: function() { - return rethrowCaughtError.apply(ReactErrorUtils, arguments); - }, - hasCaughtError: function() { - return ReactErrorUtils._hasCaughtError; - }, - clearCaughtError: function() { - if (ReactErrorUtils._hasCaughtError) { - var error = ReactErrorUtils._caughtError; - return ReactErrorUtils._caughtError = null, ReactErrorUtils._hasCaughtError = !1, - error; - } - invariant(!1, "clearCaughtError was called but no error was captured. This error " + "is likely caused by a bug in React. Please file an issue."); - } -}, invokeGuardedCallback = function(name, func, context, a, b, c, d, e, f) { - ReactErrorUtils._hasCaughtError = !1, ReactErrorUtils._caughtError = null; - var funcArgs = Array.prototype.slice.call(arguments, 3); - try { - func.apply(context, funcArgs); - } catch (error) { - ReactErrorUtils._caughtError = error, ReactErrorUtils._hasCaughtError = !0; - } -}, rethrowCaughtError = function() { - if (ReactErrorUtils._hasRethrowError) { - var error = ReactErrorUtils._rethrowError; - throw ReactErrorUtils._rethrowError = null, ReactErrorUtils._hasRethrowError = !1, - error; - } -}, ReactErrorUtils_1 = ReactErrorUtils, ComponentTree, injection$1 = { - injectComponentTree: function(Injected) { - ComponentTree = Injected; - } -}; - -function isEndish(topLevelType) { - return "topMouseUp" === topLevelType || "topTouchEnd" === topLevelType || "topTouchCancel" === topLevelType; -} - -function isMoveish(topLevelType) { - return "topMouseMove" === topLevelType || "topTouchMove" === topLevelType; -} - -function isStartish(topLevelType) { - return "topMouseDown" === topLevelType || "topTouchStart" === topLevelType; -} - -function executeDispatch(event, simulated, listener, inst) { - var type = event.type || "unknown-event"; - event.currentTarget = EventPluginUtils.getNodeFromInstance(inst), ReactErrorUtils_1.invokeGuardedCallbackAndCatchFirstError(type, listener, void 0, event), - event.currentTarget = null; -} - -function executeDispatchesInOrder(event, simulated) { - var dispatchListeners = event._dispatchListeners, dispatchInstances = event._dispatchInstances; - if (Array.isArray(dispatchListeners)) for (var i = 0; i < dispatchListeners.length && !event.isPropagationStopped(); i++) executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]); else dispatchListeners && executeDispatch(event, simulated, dispatchListeners, dispatchInstances); - event._dispatchListeners = null, event._dispatchInstances = null; -} - -function executeDispatchesInOrderStopAtTrueImpl(event) { - var dispatchListeners = event._dispatchListeners, dispatchInstances = event._dispatchInstances; - if (Array.isArray(dispatchListeners)) { - for (var i = 0; i < dispatchListeners.length && !event.isPropagationStopped(); i++) if (dispatchListeners[i](event, dispatchInstances[i])) return dispatchInstances[i]; - } else if (dispatchListeners && dispatchListeners(event, dispatchInstances)) return dispatchInstances; - return null; -} - -function executeDispatchesInOrderStopAtTrue(event) { - var ret = executeDispatchesInOrderStopAtTrueImpl(event); - return event._dispatchInstances = null, event._dispatchListeners = null, ret; -} - -function executeDirectDispatch(event) { - var dispatchListener = event._dispatchListeners, dispatchInstance = event._dispatchInstances; - invariant(!Array.isArray(dispatchListener), "executeDirectDispatch(...): Invalid `event`."), - event.currentTarget = dispatchListener ? EventPluginUtils.getNodeFromInstance(dispatchInstance) : null; - var res = dispatchListener ? dispatchListener(event) : null; - return event.currentTarget = null, event._dispatchListeners = null, event._dispatchInstances = null, - res; -} - -function hasDispatches(event) { - return !!event._dispatchListeners; -} - -var EventPluginUtils = { - isEndish: isEndish, - isMoveish: isMoveish, - isStartish: isStartish, - executeDirectDispatch: executeDirectDispatch, - executeDispatchesInOrder: executeDispatchesInOrder, - executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue, - hasDispatches: hasDispatches, - getFiberCurrentPropsFromNode: function(node) { - return ComponentTree.getFiberCurrentPropsFromNode(node); - }, - getInstanceFromNode: function(node) { - return ComponentTree.getInstanceFromNode(node); - }, - getNodeFromInstance: function(node) { - return ComponentTree.getNodeFromInstance(node); - }, - injection: injection$1 -}, EventPluginUtils_1 = EventPluginUtils, fiberHostComponent = null, ReactControlledComponentInjection = { - injectFiberControlledHostComponent: function(hostComponentImpl) { - fiberHostComponent = hostComponentImpl; - } -}, restoreTarget = null, restoreQueue = null; - -function restoreStateOfTarget(target) { - var internalInstance = EventPluginUtils_1.getInstanceFromNode(target); - if (internalInstance) { - invariant(fiberHostComponent && "function" == typeof fiberHostComponent.restoreControlledState, "Fiber needs to be injected to handle a fiber target for controlled " + "events. This error is likely caused by a bug in React. Please file an issue."); - var props = EventPluginUtils_1.getFiberCurrentPropsFromNode(internalInstance.stateNode); - fiberHostComponent.restoreControlledState(internalInstance.stateNode, internalInstance.type, props); - } -} - -var ReactControlledComponent = { - injection: ReactControlledComponentInjection, - enqueueStateRestore: function(target) { - restoreTarget ? restoreQueue ? restoreQueue.push(target) : restoreQueue = [ target ] : restoreTarget = target; - }, - restoreStateIfNeeded: function() { - if (restoreTarget) { - var target = restoreTarget, queuedTargets = restoreQueue; - if (restoreTarget = null, restoreQueue = null, restoreStateOfTarget(target), queuedTargets) for (var i = 0; i < queuedTargets.length; i++) restoreStateOfTarget(queuedTargets[i]); - } - } -}, ReactControlledComponent_1 = ReactControlledComponent, fiberBatchedUpdates = function(fn, bookkeeping) { - return fn(bookkeeping); -}; - -function batchedUpdates(fn, bookkeeping) { - return fiberBatchedUpdates(fn, bookkeeping); -} - -var isNestingBatched = !1; - -function batchedUpdatesWithControlledComponents(fn, bookkeeping) { - if (isNestingBatched) return batchedUpdates(fn, bookkeeping); - isNestingBatched = !0; - try { - return batchedUpdates(fn, bookkeeping); - } finally { - isNestingBatched = !1, ReactControlledComponent_1.restoreStateIfNeeded(); - } -} - -var ReactGenericBatchingInjection = { - injectFiberBatchedUpdates: function(_batchedUpdates) { - fiberBatchedUpdates = _batchedUpdates; - } -}, ReactGenericBatching = { - batchedUpdates: batchedUpdatesWithControlledComponents, - injection: ReactGenericBatchingInjection -}, ReactGenericBatching_1 = ReactGenericBatching; - -function ReactNativeFiberErrorDialog(capturedError) { - var componentStack = capturedError.componentStack, error = capturedError.error, errorToHandle = void 0; - if (error instanceof Error) { - var message = error.message, name = error.name, summary = message ? name + ": " + message : name; - errorToHandle = error; - try { - errorToHandle.message = summary + "\n\nThis error is located at:" + componentStack; - } catch (e) {} - } else errorToHandle = "string" == typeof error ? new Error(error + "\n\nThis error is located at:" + componentStack) : new Error("Unspecified error at:" + componentStack); - return ExceptionsManager.handleException(errorToHandle, !1), !1; -} - -var showDialog$1 = ReactNativeFiberErrorDialog, ReactNativeFiberErrorDialog_1 = { - showDialog: showDialog$1 -}, REACT_PORTAL_TYPE = "function" == typeof Symbol && Symbol.for && Symbol.for("react.portal") || 60106, createPortal = function(children, containerInfo, implementation) { - var key = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : null; - return { - $$typeof: REACT_PORTAL_TYPE, - key: null == key ? null : "" + key, - children: children, - containerInfo: containerInfo, - implementation: implementation - }; -}, isPortal = function(object) { - return "object" == typeof object && null !== object && object.$$typeof === REACT_PORTAL_TYPE; -}, REACT_PORTAL_TYPE_1 = REACT_PORTAL_TYPE, ReactPortal = { - createPortal: createPortal, - isPortal: isPortal, - REACT_PORTAL_TYPE: REACT_PORTAL_TYPE_1 -}, instanceCache = {}, instanceProps = {}; - -function precacheFiberNode(hostInst, tag) { - instanceCache[tag] = hostInst; -} - -function uncacheFiberNode(tag) { - delete instanceCache[tag], delete instanceProps[tag]; -} - -function getInstanceFromTag(tag) { - return instanceCache[tag] || null; -} - -function getTagFromInstance(inst) { - var tag = inst.stateNode._nativeTag; - return invariant(tag, "All native instances should have a tag."), tag; -} - -function getFiberCurrentPropsFromNode(stateNode) { - return instanceProps[stateNode._nativeTag] || null; -} - -function updateFiberProps(tag, props) { - instanceProps[tag] = props; -} - -var ReactNativeComponentTree = { - getClosestInstanceFromNode: getInstanceFromTag, - getInstanceFromNode: getInstanceFromTag, - getNodeFromInstance: getTagFromInstance, - precacheFiberNode: precacheFiberNode, - uncacheFiberNode: uncacheFiberNode, - getFiberCurrentPropsFromNode: getFiberCurrentPropsFromNode, - updateFiberProps: updateFiberProps -}, ReactNativeComponentTree_1 = ReactNativeComponentTree, commonjsGlobal = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {}, ReactFeatureFlags = { - enableAsyncSubtreeAPI: !0 -}, ReactFeatureFlags_1 = ReactFeatureFlags, ReactTypeOfSideEffect = { - NoEffect: 0, - PerformedWork: 1, - Placement: 2, - Update: 4, - PlacementAndUpdate: 6, - Deletion: 8, - ContentReset: 16, - Callback: 32, - Err: 64, - Ref: 128 -}, ReactPriorityLevel = { - NoWork: 0, - SynchronousPriority: 1, - TaskPriority: 2, - HighPriority: 3, - LowPriority: 4, - OffscreenPriority: 5 -}, ReactTypeOfWork = { - IndeterminateComponent: 0, - FunctionalComponent: 1, - ClassComponent: 2, - HostRoot: 3, - HostPortal: 4, - HostComponent: 5, - HostText: 6, - CoroutineComponent: 7, - CoroutineHandlerPhase: 8, - YieldComponent: 9, - Fragment: 10 -}, CallbackEffect = ReactTypeOfSideEffect.Callback, NoWork = ReactPriorityLevel.NoWork, SynchronousPriority = ReactPriorityLevel.SynchronousPriority, TaskPriority = ReactPriorityLevel.TaskPriority, ClassComponent = ReactTypeOfWork.ClassComponent, HostRoot = ReactTypeOfWork.HostRoot, _queue1 = void 0, _queue2 = void 0; - -function comparePriority(a, b) { - return a !== TaskPriority && a !== SynchronousPriority || b !== TaskPriority && b !== SynchronousPriority ? a === NoWork && b !== NoWork ? -255 : a !== NoWork && b === NoWork ? 255 : a - b : 0; -} - -function createUpdateQueue() { - return { - first: null, - last: null, - hasForceUpdate: !1, - callbackList: null - }; -} - -function cloneUpdate(update) { - return { - priorityLevel: update.priorityLevel, - partialState: update.partialState, - callback: update.callback, - isReplace: update.isReplace, - isForced: update.isForced, - isTopLevelUnmount: update.isTopLevelUnmount, - next: null - }; -} - -function insertUpdateIntoQueue(queue, update, insertAfter, insertBefore) { - null !== insertAfter ? insertAfter.next = update : (update.next = queue.first, queue.first = update), - null !== insertBefore ? update.next = insertBefore : queue.last = update; -} - -function findInsertionPosition(queue, update) { - var priorityLevel = update.priorityLevel, insertAfter = null, insertBefore = null; - if (null !== queue.last && comparePriority(queue.last.priorityLevel, priorityLevel) <= 0) insertAfter = queue.last; else for (insertBefore = queue.first; null !== insertBefore && comparePriority(insertBefore.priorityLevel, priorityLevel) <= 0; ) insertAfter = insertBefore, - insertBefore = insertBefore.next; - return insertAfter; -} - -function ensureUpdateQueues(fiber) { - var alternateFiber = fiber.alternate, queue1 = fiber.updateQueue; - null === queue1 && (queue1 = fiber.updateQueue = createUpdateQueue()); - var queue2 = void 0; - null !== alternateFiber ? null === (queue2 = alternateFiber.updateQueue) && (queue2 = alternateFiber.updateQueue = createUpdateQueue()) : queue2 = null, - _queue1 = queue1, _queue2 = queue2 !== queue1 ? queue2 : null; -} - -function insertUpdate(fiber, update) { - ensureUpdateQueues(fiber); - var queue1 = _queue1, queue2 = _queue2, insertAfter1 = findInsertionPosition(queue1, update), insertBefore1 = null !== insertAfter1 ? insertAfter1.next : queue1.first; - if (null === queue2) return insertUpdateIntoQueue(queue1, update, insertAfter1, insertBefore1), - null; - var insertAfter2 = findInsertionPosition(queue2, update), insertBefore2 = null !== insertAfter2 ? insertAfter2.next : queue2.first; - if (insertUpdateIntoQueue(queue1, update, insertAfter1, insertBefore1), insertBefore1 === insertBefore2 && null !== insertBefore1 || insertAfter1 === insertAfter2 && null !== insertAfter1) return null === insertAfter2 && (queue2.first = update), - null === insertBefore2 && (queue2.last = null), null; - var update2 = cloneUpdate(update); - return insertUpdateIntoQueue(queue2, update2, insertAfter2, insertBefore2), update2; -} - -function addUpdate(fiber, partialState, callback, priorityLevel) { - insertUpdate(fiber, { - priorityLevel: priorityLevel, - partialState: partialState, - callback: callback, - isReplace: !1, - isForced: !1, - isTopLevelUnmount: !1, - next: null - }); -} - -var addUpdate_1 = addUpdate; - -function addReplaceUpdate(fiber, state, callback, priorityLevel) { - insertUpdate(fiber, { - priorityLevel: priorityLevel, - partialState: state, - callback: callback, - isReplace: !0, - isForced: !1, - isTopLevelUnmount: !1, - next: null - }); -} - -var addReplaceUpdate_1 = addReplaceUpdate; - -function addForceUpdate(fiber, callback, priorityLevel) { - insertUpdate(fiber, { - priorityLevel: priorityLevel, - partialState: null, - callback: callback, - isReplace: !1, - isForced: !0, - isTopLevelUnmount: !1, - next: null - }); -} - -var addForceUpdate_1 = addForceUpdate; - -function getUpdatePriority(fiber) { - var updateQueue = fiber.updateQueue; - return null === updateQueue ? NoWork : fiber.tag !== ClassComponent && fiber.tag !== HostRoot ? NoWork : null !== updateQueue.first ? updateQueue.first.priorityLevel : NoWork; -} - -var getUpdatePriority_1 = getUpdatePriority; - -function addTopLevelUpdate$1(fiber, partialState, callback, priorityLevel) { - var isTopLevelUnmount = null === partialState.element, update = { - priorityLevel: priorityLevel, - partialState: partialState, - callback: callback, - isReplace: !1, - isForced: !1, - isTopLevelUnmount: isTopLevelUnmount, - next: null - }, update2 = insertUpdate(fiber, update); - if (isTopLevelUnmount) { - var queue1 = _queue1, queue2 = _queue2; - null !== queue1 && null !== update.next && (update.next = null, queue1.last = update), - null !== queue2 && null !== update2 && null !== update2.next && (update2.next = null, - queue2.last = update); - } -} - -var addTopLevelUpdate_1 = addTopLevelUpdate$1; - -function getStateFromUpdate(update, instance, prevState, props) { - var partialState = update.partialState; - if ("function" == typeof partialState) { - return partialState.call(instance, prevState, props); - } - return partialState; -} - -function beginUpdateQueue(current, workInProgress, queue, instance, prevState, props, priorityLevel) { - if (null !== current && current.updateQueue === queue) { - var currentQueue = queue; - queue = workInProgress.updateQueue = { - first: currentQueue.first, - last: currentQueue.last, - callbackList: null, - hasForceUpdate: !1 - }; - } - for (var callbackList = queue.callbackList, hasForceUpdate = queue.hasForceUpdate, state = prevState, dontMutatePrevState = !0, update = queue.first; null !== update && comparePriority(update.priorityLevel, priorityLevel) <= 0; ) { - queue.first = update.next, null === queue.first && (queue.last = null); - var _partialState = void 0; - update.isReplace ? (state = getStateFromUpdate(update, instance, state, props), - dontMutatePrevState = !0) : (_partialState = getStateFromUpdate(update, instance, state, props)) && (state = dontMutatePrevState ? Object.assign({}, state, _partialState) : Object.assign(state, _partialState), - dontMutatePrevState = !1), update.isForced && (hasForceUpdate = !0), null === update.callback || update.isTopLevelUnmount && null !== update.next || (callbackList = null !== callbackList ? callbackList : [], - callbackList.push(update.callback), workInProgress.effectTag |= CallbackEffect), - update = update.next; - } - return queue.callbackList = callbackList, queue.hasForceUpdate = hasForceUpdate, - null !== queue.first || null !== callbackList || hasForceUpdate || (workInProgress.updateQueue = null), - state; -} - -var beginUpdateQueue_1 = beginUpdateQueue; - -function commitCallbacks(finishedWork, queue, context) { - var callbackList = queue.callbackList; - if (null !== callbackList) { - queue.callbackList = null; - for (var i = 0; i < callbackList.length; i++) { - var _callback = callbackList[i]; - invariant("function" == typeof _callback, "Invalid argument passed as callback. Expected a function. Instead " + "received: %s", _callback), - _callback.call(context); - } - } -} - -var commitCallbacks_1 = commitCallbacks, ReactFiberUpdateQueue = { - addUpdate: addUpdate_1, - addReplaceUpdate: addReplaceUpdate_1, - addForceUpdate: addForceUpdate_1, - getUpdatePriority: getUpdatePriority_1, - addTopLevelUpdate: addTopLevelUpdate_1, - beginUpdateQueue: beginUpdateQueue_1, - commitCallbacks: commitCallbacks_1 -}; - -function getComponentName$1(fiber) { - var type = fiber.type; - return "string" == typeof type ? type : "function" == typeof type ? type.displayName || type.name : null; -} - -var getComponentName_1 = getComponentName$1, ReactInstanceMap = { - remove: function(key) { - key._reactInternalFiber = void 0; - }, - get: function(key) { - return key._reactInternalFiber; - }, - has: function(key) { - return void 0 !== key._reactInternalFiber; - }, - set: function(key, value) { - key._reactInternalFiber = value; - } -}, ReactInstanceMap_1 = ReactInstanceMap, ReactInternals = react.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, ReactGlobalSharedState = { - ReactCurrentOwner: ReactInternals.ReactCurrentOwner -}, ReactGlobalSharedState_1 = ReactGlobalSharedState, HostComponent$1 = ReactTypeOfWork.HostComponent, HostRoot$2 = ReactTypeOfWork.HostRoot, HostPortal = ReactTypeOfWork.HostPortal, HostText = ReactTypeOfWork.HostText, NoEffect = ReactTypeOfSideEffect.NoEffect, Placement = ReactTypeOfSideEffect.Placement, MOUNTING = 1, MOUNTED = 2, UNMOUNTED = 3; - -function isFiberMountedImpl(fiber) { - var node = fiber; - if (fiber.alternate) for (;node.return; ) node = node.return; else { - if ((node.effectTag & Placement) !== NoEffect) return MOUNTING; - for (;node.return; ) if (node = node.return, (node.effectTag & Placement) !== NoEffect) return MOUNTING; - } - return node.tag === HostRoot$2 ? MOUNTED : UNMOUNTED; -} - -var isFiberMounted$1 = function(fiber) { - return isFiberMountedImpl(fiber) === MOUNTED; -}, isMounted = function(component) { - var fiber = ReactInstanceMap_1.get(component); - return !!fiber && isFiberMountedImpl(fiber) === MOUNTED; -}; - -function assertIsMounted(fiber) { - invariant(isFiberMountedImpl(fiber) === MOUNTED, "Unable to find node on an unmounted component."); -} - -function findCurrentFiberUsingSlowPath(fiber) { - var alternate = fiber.alternate; - if (!alternate) { - var state = isFiberMountedImpl(fiber); - return invariant(state !== UNMOUNTED, "Unable to find node on an unmounted component."), - state === MOUNTING ? null : fiber; - } - for (var a = fiber, b = alternate; !0; ) { - var parentA = a.return, parentB = parentA ? parentA.alternate : null; - if (!parentA || !parentB) break; - if (parentA.child === parentB.child) { - for (var child = parentA.child; child; ) { - if (child === a) return assertIsMounted(parentA), fiber; - if (child === b) return assertIsMounted(parentA), alternate; - child = child.sibling; - } - invariant(!1, "Unable to find node on an unmounted component."); - } - if (a.return !== b.return) a = parentA, b = parentB; else { - for (var didFindChild = !1, _child = parentA.child; _child; ) { - if (_child === a) { - didFindChild = !0, a = parentA, b = parentB; - break; - } - if (_child === b) { - didFindChild = !0, b = parentA, a = parentB; - break; - } - _child = _child.sibling; - } - if (!didFindChild) { - for (_child = parentB.child; _child; ) { - if (_child === a) { - didFindChild = !0, a = parentB, b = parentA; - break; - } - if (_child === b) { - didFindChild = !0, b = parentB, a = parentA; - break; - } - _child = _child.sibling; - } - invariant(didFindChild, "Child was not found in either parent set. This indicates a bug " + "in React related to the return pointer. Please file an issue."); - } - } - invariant(a.alternate === b, "Return fibers should always be each others' alternates. " + "This error is likely caused by a bug in React. Please file an issue."); - } - return invariant(a.tag === HostRoot$2, "Unable to find node on an unmounted component."), - a.stateNode.current === a ? fiber : alternate; -} - -var findCurrentFiberUsingSlowPath_1 = findCurrentFiberUsingSlowPath, findCurrentHostFiber$1 = function(parent) { - var currentParent = findCurrentFiberUsingSlowPath(parent); - if (!currentParent) return null; - for (var node = currentParent; !0; ) { - if (node.tag === HostComponent$1 || node.tag === HostText) return node; - if (node.child) node.child.return = node, node = node.child; else { - if (node === currentParent) return null; - for (;!node.sibling; ) { - if (!node.return || node.return === currentParent) return null; - node = node.return; - } - node.sibling.return = node.return, node = node.sibling; - } - } - return null; -}, findCurrentHostFiberWithNoPortals$1 = function(parent) { - var currentParent = findCurrentFiberUsingSlowPath(parent); - if (!currentParent) return null; - for (var node = currentParent; !0; ) { - if (node.tag === HostComponent$1 || node.tag === HostText) return node; - if (node.child && node.tag !== HostPortal) node.child.return = node, node = node.child; else { - if (node === currentParent) return null; - for (;!node.sibling; ) { - if (!node.return || node.return === currentParent) return null; - node = node.return; - } - node.sibling.return = node.return, node = node.sibling; - } - } - return null; -}, ReactFiberTreeReflection = { - isFiberMounted: isFiberMounted$1, - isMounted: isMounted, - findCurrentFiberUsingSlowPath: findCurrentFiberUsingSlowPath_1, - findCurrentHostFiber: findCurrentHostFiber$1, - findCurrentHostFiberWithNoPortals: findCurrentHostFiberWithNoPortals$1 -}, valueStack = [], index = -1, createCursor$1 = function(defaultValue) { - return { - current: defaultValue - }; -}, isEmpty = function() { - return -1 === index; -}, pop$1 = function(cursor, fiber) { - index < 0 || (cursor.current = valueStack[index], valueStack[index] = null, index--); -}, push$1 = function(cursor, value, fiber) { - index++, valueStack[index] = cursor.current, cursor.current = value; -}, reset = function() { - for (;index > -1; ) valueStack[index] = null, index--; -}, ReactFiberStack = { - createCursor: createCursor$1, - isEmpty: isEmpty, - pop: pop$1, - push: push$1, - reset: reset -}, isFiberMounted = ReactFiberTreeReflection.isFiberMounted, ClassComponent$1 = ReactTypeOfWork.ClassComponent, HostRoot$1 = ReactTypeOfWork.HostRoot, createCursor = ReactFiberStack.createCursor, pop = ReactFiberStack.pop, push = ReactFiberStack.push, contextStackCursor = createCursor(emptyObject), didPerformWorkStackCursor = createCursor(!1), previousContext = emptyObject; - -function getUnmaskedContext(workInProgress) { - return isContextProvider$1(workInProgress) ? previousContext : contextStackCursor.current; -} - -var getUnmaskedContext_1 = getUnmaskedContext; - -function cacheContext(workInProgress, unmaskedContext, maskedContext) { - var instance = workInProgress.stateNode; - instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext, instance.__reactInternalMemoizedMaskedChildContext = maskedContext; -} - -var cacheContext_1 = cacheContext, getMaskedContext = function(workInProgress, unmaskedContext) { - var type = workInProgress.type, contextTypes = type.contextTypes; - if (!contextTypes) return emptyObject; - var instance = workInProgress.stateNode; - if (instance && instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext) return instance.__reactInternalMemoizedMaskedChildContext; - var context = {}; - for (var key in contextTypes) context[key] = unmaskedContext[key]; - return instance && cacheContext(workInProgress, unmaskedContext, context), context; -}, hasContextChanged = function() { - return didPerformWorkStackCursor.current; -}; - -function isContextConsumer(fiber) { - return fiber.tag === ClassComponent$1 && null != fiber.type.contextTypes; -} - -var isContextConsumer_1 = isContextConsumer; - -function isContextProvider$1(fiber) { - return fiber.tag === ClassComponent$1 && null != fiber.type.childContextTypes; -} - -var isContextProvider_1 = isContextProvider$1; - -function popContextProvider(fiber) { - isContextProvider$1(fiber) && (pop(didPerformWorkStackCursor, fiber), pop(contextStackCursor, fiber)); -} - -var popContextProvider_1 = popContextProvider, popTopLevelContextObject = function(fiber) { - pop(didPerformWorkStackCursor, fiber), pop(contextStackCursor, fiber); -}, pushTopLevelContextObject = function(fiber, context, didChange) { - invariant(null == contextStackCursor.cursor, "Unexpected context found on stack. " + "This error is likely caused by a bug in React. Please file an issue."), - push(contextStackCursor, context, fiber), push(didPerformWorkStackCursor, didChange, fiber); -}; - -function processChildContext$1(fiber, parentContext) { - var instance = fiber.stateNode, childContextTypes = fiber.type.childContextTypes; - if ("function" != typeof instance.getChildContext) return parentContext; - var childContext = void 0; - childContext = instance.getChildContext(); - for (var contextKey in childContext) invariant(contextKey in childContextTypes, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', getComponentName_1(fiber) || "Unknown", contextKey); - return Object.assign({}, parentContext, childContext); -} - -var processChildContext_1 = processChildContext$1, pushContextProvider = function(workInProgress) { - if (!isContextProvider$1(workInProgress)) return !1; - var instance = workInProgress.stateNode, memoizedMergedChildContext = instance && instance.__reactInternalMemoizedMergedChildContext || emptyObject; - return previousContext = contextStackCursor.current, push(contextStackCursor, memoizedMergedChildContext, workInProgress), - push(didPerformWorkStackCursor, didPerformWorkStackCursor.current, workInProgress), - !0; -}, invalidateContextProvider = function(workInProgress, didChange) { - var instance = workInProgress.stateNode; - if (invariant(instance, "Expected to have an instance by this point. " + "This error is likely caused by a bug in React. Please file an issue."), - didChange) { - var mergedContext = processChildContext$1(workInProgress, previousContext); - instance.__reactInternalMemoizedMergedChildContext = mergedContext, pop(didPerformWorkStackCursor, workInProgress), - pop(contextStackCursor, workInProgress), push(contextStackCursor, mergedContext, workInProgress), - push(didPerformWorkStackCursor, didChange, workInProgress); - } else pop(didPerformWorkStackCursor, workInProgress), push(didPerformWorkStackCursor, didChange, workInProgress); -}, resetContext = function() { - previousContext = emptyObject, contextStackCursor.current = emptyObject, didPerformWorkStackCursor.current = !1; -}, findCurrentUnmaskedContext$1 = function(fiber) { - invariant(isFiberMounted(fiber) && fiber.tag === ClassComponent$1, "Expected subtree parent to be a mounted class component. " + "This error is likely caused by a bug in React. Please file an issue."); - for (var node = fiber; node.tag !== HostRoot$1; ) { - if (isContextProvider$1(node)) return node.stateNode.__reactInternalMemoizedMergedChildContext; - var parent = node.return; - invariant(parent, "Found unexpected detached subtree parent. " + "This error is likely caused by a bug in React. Please file an issue."), - node = parent; - } - return node.stateNode.context; -}, ReactFiberContext = { - getUnmaskedContext: getUnmaskedContext_1, - cacheContext: cacheContext_1, - getMaskedContext: getMaskedContext, - hasContextChanged: hasContextChanged, - isContextConsumer: isContextConsumer_1, - isContextProvider: isContextProvider_1, - popContextProvider: popContextProvider_1, - popTopLevelContextObject: popTopLevelContextObject, - pushTopLevelContextObject: pushTopLevelContextObject, - processChildContext: processChildContext_1, - pushContextProvider: pushContextProvider, - invalidateContextProvider: invalidateContextProvider, - resetContext: resetContext, - findCurrentUnmaskedContext: findCurrentUnmaskedContext$1 -}, ReactTypeOfInternalContext = { - NoContext: 0, - AsyncUpdates: 1 -}, IndeterminateComponent = ReactTypeOfWork.IndeterminateComponent, ClassComponent$3 = ReactTypeOfWork.ClassComponent, HostRoot$3 = ReactTypeOfWork.HostRoot, HostComponent$2 = ReactTypeOfWork.HostComponent, HostText$1 = ReactTypeOfWork.HostText, HostPortal$1 = ReactTypeOfWork.HostPortal, CoroutineComponent = ReactTypeOfWork.CoroutineComponent, YieldComponent = ReactTypeOfWork.YieldComponent, Fragment = ReactTypeOfWork.Fragment, NoWork$1 = ReactPriorityLevel.NoWork, NoContext = ReactTypeOfInternalContext.NoContext, NoEffect$1 = ReactTypeOfSideEffect.NoEffect; - -function FiberNode(tag, key, internalContextTag) { - this.tag = tag, this.key = key, this.type = null, this.stateNode = null, this.return = null, - this.child = null, this.sibling = null, this.index = 0, this.ref = null, this.pendingProps = null, - this.memoizedProps = null, this.updateQueue = null, this.memoizedState = null, this.internalContextTag = internalContextTag, - this.effectTag = NoEffect$1, this.nextEffect = null, this.firstEffect = null, this.lastEffect = null, - this.pendingWorkPriority = NoWork$1, this.alternate = null; -} - -var createFiber = function(tag, key, internalContextTag) { - return new FiberNode(tag, key, internalContextTag); -}; - -function shouldConstruct(Component) { - return !(!Component.prototype || !Component.prototype.isReactComponent); -} - -var createWorkInProgress = function(current, renderPriority) { - var workInProgress = current.alternate; - return null === workInProgress ? (workInProgress = createFiber(current.tag, current.key, current.internalContextTag), - workInProgress.type = current.type, workInProgress.stateNode = current.stateNode, - workInProgress.alternate = current, current.alternate = workInProgress) : (workInProgress.effectTag = NoEffect$1, - workInProgress.nextEffect = null, workInProgress.firstEffect = null, workInProgress.lastEffect = null), - workInProgress.pendingWorkPriority = renderPriority, workInProgress.child = current.child, - workInProgress.memoizedProps = current.memoizedProps, workInProgress.memoizedState = current.memoizedState, - workInProgress.updateQueue = current.updateQueue, workInProgress.sibling = current.sibling, - workInProgress.index = current.index, workInProgress.ref = current.ref, workInProgress; -}, createHostRootFiber$1 = function() { - return createFiber(HostRoot$3, null, NoContext); -}, createFiberFromElement = function(element, internalContextTag, priorityLevel) { - var owner = null, fiber = createFiberFromElementType(element.type, element.key, internalContextTag, owner); - return fiber.pendingProps = element.props, fiber.pendingWorkPriority = priorityLevel, - fiber; -}, createFiberFromFragment = function(elements, internalContextTag, priorityLevel) { - var fiber = createFiber(Fragment, null, internalContextTag); - return fiber.pendingProps = elements, fiber.pendingWorkPriority = priorityLevel, - fiber; -}, createFiberFromText = function(content, internalContextTag, priorityLevel) { - var fiber = createFiber(HostText$1, null, internalContextTag); - return fiber.pendingProps = content, fiber.pendingWorkPriority = priorityLevel, - fiber; -}; - -function createFiberFromElementType(type, key, internalContextTag, debugOwner) { - var fiber = void 0; - if ("function" == typeof type) fiber = shouldConstruct(type) ? createFiber(ClassComponent$3, key, internalContextTag) : createFiber(IndeterminateComponent, key, internalContextTag), - fiber.type = type; else if ("string" == typeof type) fiber = createFiber(HostComponent$2, key, internalContextTag), - fiber.type = type; else if ("object" == typeof type && null !== type && "number" == typeof type.tag) fiber = type; else { - var info = ""; - invariant(!1, "Element type is invalid: expected a string (for built-in components) " + "or a class/function (for composite components) but got: %s.%s", null == type ? type : typeof type, info); - } - return fiber; -} - -var createFiberFromElementType_1 = createFiberFromElementType, createFiberFromHostInstanceForDeletion = function() { - var fiber = createFiber(HostComponent$2, null, NoContext); - return fiber.type = "DELETED", fiber; -}, createFiberFromCoroutine = function(coroutine, internalContextTag, priorityLevel) { - var fiber = createFiber(CoroutineComponent, coroutine.key, internalContextTag); - return fiber.type = coroutine.handler, fiber.pendingProps = coroutine, fiber.pendingWorkPriority = priorityLevel, - fiber; -}, createFiberFromYield = function(yieldNode, internalContextTag, priorityLevel) { - return createFiber(YieldComponent, null, internalContextTag); -}, createFiberFromPortal = function(portal, internalContextTag, priorityLevel) { - var fiber = createFiber(HostPortal$1, portal.key, internalContextTag); - return fiber.pendingProps = portal.children || [], fiber.pendingWorkPriority = priorityLevel, - fiber.stateNode = { - containerInfo: portal.containerInfo, - implementation: portal.implementation - }, fiber; -}, largerPriority = function(p1, p2) { - return p1 !== NoWork$1 && (p2 === NoWork$1 || p2 > p1) ? p1 : p2; -}, ReactFiber = { - createWorkInProgress: createWorkInProgress, - createHostRootFiber: createHostRootFiber$1, - createFiberFromElement: createFiberFromElement, - createFiberFromFragment: createFiberFromFragment, - createFiberFromText: createFiberFromText, - createFiberFromElementType: createFiberFromElementType_1, - createFiberFromHostInstanceForDeletion: createFiberFromHostInstanceForDeletion, - createFiberFromCoroutine: createFiberFromCoroutine, - createFiberFromYield: createFiberFromYield, - createFiberFromPortal: createFiberFromPortal, - largerPriority: largerPriority -}, createHostRootFiber = ReactFiber.createHostRootFiber, createFiberRoot$1 = function(containerInfo) { - var uninitializedFiber = createHostRootFiber(), root = { - current: uninitializedFiber, - containerInfo: containerInfo, - isScheduled: !1, - nextScheduledRoot: null, - context: null, - pendingContext: null - }; - return uninitializedFiber.stateNode = root, root; -}, ReactFiberRoot = { - createFiberRoot: createFiberRoot$1 -}, describeComponentFrame = function(name, source, ownerName) { - return "\n in " + (name || "Unknown") + (source ? " (at " + source.fileName.replace(/^.*[\\\/]/, "") + ":" + source.lineNumber + ")" : ownerName ? " (created by " + ownerName + ")" : ""); -}, IndeterminateComponent$1 = ReactTypeOfWork.IndeterminateComponent, FunctionalComponent = ReactTypeOfWork.FunctionalComponent, ClassComponent$5 = ReactTypeOfWork.ClassComponent, HostComponent$4 = ReactTypeOfWork.HostComponent; - -function describeFiber(fiber) { - switch (fiber.tag) { - case IndeterminateComponent$1: - case FunctionalComponent: - case ClassComponent$5: - case HostComponent$4: - var owner = fiber._debugOwner, source = fiber._debugSource, name = getComponentName_1(fiber), ownerName = null; - return owner && (ownerName = getComponentName_1(owner)), describeComponentFrame(name, source, ownerName); - - default: - return ""; - } -} - -function getStackAddendumByWorkInProgressFiber$1(workInProgress) { - var info = "", node = workInProgress; - do { - info += describeFiber(node), node = node.return; - } while (node); - return info; -} - -var ReactFiberComponentTreeHook = { - getStackAddendumByWorkInProgressFiber: getStackAddendumByWorkInProgressFiber$1 -}, REACT_COROUTINE_TYPE$1, REACT_YIELD_TYPE$1; - -"function" == typeof Symbol && Symbol.for ? (REACT_COROUTINE_TYPE$1 = Symbol.for("react.coroutine"), -REACT_YIELD_TYPE$1 = Symbol.for("react.yield")) : (REACT_COROUTINE_TYPE$1 = 60104, -REACT_YIELD_TYPE$1 = 60105); - -var createCoroutine = function(children, handler, props) { - var key = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : null; - return { - $$typeof: REACT_COROUTINE_TYPE$1, - key: null == key ? null : "" + key, - children: children, - handler: handler, - props: props - }; -}, createYield = function(value) { - return { - $$typeof: REACT_YIELD_TYPE$1, - value: value - }; -}, isCoroutine = function(object) { - return "object" == typeof object && null !== object && object.$$typeof === REACT_COROUTINE_TYPE$1; -}, isYield = function(object) { - return "object" == typeof object && null !== object && object.$$typeof === REACT_YIELD_TYPE$1; -}, REACT_YIELD_TYPE_1 = REACT_YIELD_TYPE$1, REACT_COROUTINE_TYPE_1 = REACT_COROUTINE_TYPE$1, ReactCoroutine = { - createCoroutine: createCoroutine, - createYield: createYield, - isCoroutine: isCoroutine, - isYield: isYield, - REACT_YIELD_TYPE: REACT_YIELD_TYPE_1, - REACT_COROUTINE_TYPE: REACT_COROUTINE_TYPE_1 -}, REACT_COROUTINE_TYPE = ReactCoroutine.REACT_COROUTINE_TYPE, REACT_YIELD_TYPE = ReactCoroutine.REACT_YIELD_TYPE, REACT_PORTAL_TYPE$1 = ReactPortal.REACT_PORTAL_TYPE, createWorkInProgress$2 = ReactFiber.createWorkInProgress, createFiberFromElement$1 = ReactFiber.createFiberFromElement, createFiberFromFragment$1 = ReactFiber.createFiberFromFragment, createFiberFromText$1 = ReactFiber.createFiberFromText, createFiberFromCoroutine$1 = ReactFiber.createFiberFromCoroutine, createFiberFromYield$1 = ReactFiber.createFiberFromYield, createFiberFromPortal$1 = ReactFiber.createFiberFromPortal, isArray = Array.isArray, FunctionalComponent$2 = ReactTypeOfWork.FunctionalComponent, ClassComponent$7 = ReactTypeOfWork.ClassComponent, HostText$3 = ReactTypeOfWork.HostText, HostPortal$4 = ReactTypeOfWork.HostPortal, CoroutineComponent$2 = ReactTypeOfWork.CoroutineComponent, YieldComponent$2 = ReactTypeOfWork.YieldComponent, Fragment$2 = ReactTypeOfWork.Fragment, NoEffect$2 = ReactTypeOfSideEffect.NoEffect, Placement$3 = ReactTypeOfSideEffect.Placement, Deletion$1 = ReactTypeOfSideEffect.Deletion, ITERATOR_SYMBOL = "function" == typeof Symbol && Symbol.iterator, FAUX_ITERATOR_SYMBOL = "@@iterator", REACT_ELEMENT_TYPE = "function" == typeof Symbol && Symbol.for && Symbol.for("react.element") || 60103; - -function getIteratorFn(maybeIterable) { - if (null === maybeIterable || void 0 === maybeIterable) return null; - var iteratorFn = ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]; - return "function" == typeof iteratorFn ? iteratorFn : null; -} - -function coerceRef(current, element) { - var mixedRef = element.ref; - if (null !== mixedRef && "function" != typeof mixedRef) { - if (element._owner) { - var owner = element._owner, inst = void 0; - if (owner) { - var ownerFiber = owner; - invariant(ownerFiber.tag === ClassComponent$7, "Stateless function components cannot have refs."), - inst = ownerFiber.stateNode; - } - invariant(inst, "Missing owner for string ref %s. This error is likely caused by a " + "bug in React. Please file an issue.", mixedRef); - var stringRef = "" + mixedRef; - if (null !== current && null !== current.ref && current.ref._stringRef === stringRef) return current.ref; - var ref = function(value) { - var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs; - null === value ? delete refs[stringRef] : refs[stringRef] = value; - }; - return ref._stringRef = stringRef, ref; - } - invariant("string" == typeof mixedRef, "Expected ref to be a function or a string."), - invariant(element._owner, "Element ref was specified as a string (%s) but no owner was " + "set. You may have multiple copies of React loaded. " + "(details: https://fb.me/react-refs-must-have-owner).", mixedRef); - } - return mixedRef; -} - -function throwOnInvalidObjectType(returnFiber, newChild) { - if ("textarea" !== returnFiber.type) { - invariant(!1, "Objects are not valid as a React child (found: %s).%s", "[object Object]" === Object.prototype.toString.call(newChild) ? "object with keys {" + Object.keys(newChild).join(", ") + "}" : newChild, ""); - } -} - -function ChildReconciler(shouldClone, shouldTrackSideEffects) { - function deleteChild(returnFiber, childToDelete) { - if (shouldTrackSideEffects) { - if (!shouldClone) { - if (null === childToDelete.alternate) return; - childToDelete = childToDelete.alternate; - } - var last = returnFiber.lastEffect; - null !== last ? (last.nextEffect = childToDelete, returnFiber.lastEffect = childToDelete) : returnFiber.firstEffect = returnFiber.lastEffect = childToDelete, - childToDelete.nextEffect = null, childToDelete.effectTag = Deletion$1; - } - } - function deleteRemainingChildren(returnFiber, currentFirstChild) { - if (!shouldTrackSideEffects) return null; - for (var childToDelete = currentFirstChild; null !== childToDelete; ) deleteChild(returnFiber, childToDelete), - childToDelete = childToDelete.sibling; - return null; - } - function mapRemainingChildren(returnFiber, currentFirstChild) { - for (var existingChildren = new Map(), existingChild = currentFirstChild; null !== existingChild; ) null !== existingChild.key ? existingChildren.set(existingChild.key, existingChild) : existingChildren.set(existingChild.index, existingChild), - existingChild = existingChild.sibling; - return existingChildren; - } - function useFiber(fiber, priority) { - if (shouldClone) { - var clone = createWorkInProgress$2(fiber, priority); - return clone.index = 0, clone.sibling = null, clone; - } - return fiber.pendingWorkPriority = priority, fiber.effectTag = NoEffect$2, fiber.index = 0, - fiber.sibling = null, fiber; - } - function placeChild(newFiber, lastPlacedIndex, newIndex) { - if (newFiber.index = newIndex, !shouldTrackSideEffects) return lastPlacedIndex; - var current = newFiber.alternate; - if (null !== current) { - var oldIndex = current.index; - return oldIndex < lastPlacedIndex ? (newFiber.effectTag = Placement$3, lastPlacedIndex) : oldIndex; - } - return newFiber.effectTag = Placement$3, lastPlacedIndex; - } - function placeSingleChild(newFiber) { - return shouldTrackSideEffects && null === newFiber.alternate && (newFiber.effectTag = Placement$3), - newFiber; - } - function updateTextNode(returnFiber, current, textContent, priority) { - if (null === current || current.tag !== HostText$3) { - var created = createFiberFromText$1(textContent, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - var existing = useFiber(current, priority); - return existing.pendingProps = textContent, existing.return = returnFiber, existing; - } - function updateElement(returnFiber, current, element, priority) { - if (null === current || current.type !== element.type) { - var created = createFiberFromElement$1(element, returnFiber.internalContextTag, priority); - return created.ref = coerceRef(current, element), created.return = returnFiber, - created; - } - var existing = useFiber(current, priority); - return existing.ref = coerceRef(current, element), existing.pendingProps = element.props, - existing.return = returnFiber, existing; - } - function updateCoroutine(returnFiber, current, coroutine, priority) { - if (null === current || current.tag !== CoroutineComponent$2) { - var created = createFiberFromCoroutine$1(coroutine, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - var existing = useFiber(current, priority); - return existing.pendingProps = coroutine, existing.return = returnFiber, existing; - } - function updateYield(returnFiber, current, yieldNode, priority) { - if (null === current || current.tag !== YieldComponent$2) { - var created = createFiberFromYield$1(yieldNode, returnFiber.internalContextTag, priority); - return created.type = yieldNode.value, created.return = returnFiber, created; - } - var existing = useFiber(current, priority); - return existing.type = yieldNode.value, existing.return = returnFiber, existing; - } - function updatePortal(returnFiber, current, portal, priority) { - if (null === current || current.tag !== HostPortal$4 || current.stateNode.containerInfo !== portal.containerInfo || current.stateNode.implementation !== portal.implementation) { - var created = createFiberFromPortal$1(portal, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - var existing = useFiber(current, priority); - return existing.pendingProps = portal.children || [], existing.return = returnFiber, - existing; - } - function updateFragment(returnFiber, current, fragment, priority) { - if (null === current || current.tag !== Fragment$2) { - var created = createFiberFromFragment$1(fragment, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - var existing = useFiber(current, priority); - return existing.pendingProps = fragment, existing.return = returnFiber, existing; - } - function createChild(returnFiber, newChild, priority) { - if ("string" == typeof newChild || "number" == typeof newChild) { - var created = createFiberFromText$1("" + newChild, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - if ("object" == typeof newChild && null !== newChild) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: - var _created = createFiberFromElement$1(newChild, returnFiber.internalContextTag, priority); - return _created.ref = coerceRef(null, newChild), _created.return = returnFiber, - _created; - - case REACT_COROUTINE_TYPE: - var _created2 = createFiberFromCoroutine$1(newChild, returnFiber.internalContextTag, priority); - return _created2.return = returnFiber, _created2; - - case REACT_YIELD_TYPE: - var _created3 = createFiberFromYield$1(newChild, returnFiber.internalContextTag, priority); - return _created3.type = newChild.value, _created3.return = returnFiber, _created3; - - case REACT_PORTAL_TYPE$1: - var _created4 = createFiberFromPortal$1(newChild, returnFiber.internalContextTag, priority); - return _created4.return = returnFiber, _created4; - } - if (isArray(newChild) || getIteratorFn(newChild)) { - var _created5 = createFiberFromFragment$1(newChild, returnFiber.internalContextTag, priority); - return _created5.return = returnFiber, _created5; - } - throwOnInvalidObjectType(returnFiber, newChild); - } - return null; - } - function updateSlot(returnFiber, oldFiber, newChild, priority) { - var key = null !== oldFiber ? oldFiber.key : null; - if ("string" == typeof newChild || "number" == typeof newChild) return null !== key ? null : updateTextNode(returnFiber, oldFiber, "" + newChild, priority); - if ("object" == typeof newChild && null !== newChild) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: - return newChild.key === key ? updateElement(returnFiber, oldFiber, newChild, priority) : null; - - case REACT_COROUTINE_TYPE: - return newChild.key === key ? updateCoroutine(returnFiber, oldFiber, newChild, priority) : null; - - case REACT_YIELD_TYPE: - return null === key ? updateYield(returnFiber, oldFiber, newChild, priority) : null; - - case REACT_PORTAL_TYPE$1: - return newChild.key === key ? updatePortal(returnFiber, oldFiber, newChild, priority) : null; - } - if (isArray(newChild) || getIteratorFn(newChild)) return null !== key ? null : updateFragment(returnFiber, oldFiber, newChild, priority); - throwOnInvalidObjectType(returnFiber, newChild); - } - return null; - } - function updateFromMap(existingChildren, returnFiber, newIdx, newChild, priority) { - if ("string" == typeof newChild || "number" == typeof newChild) { - return updateTextNode(returnFiber, existingChildren.get(newIdx) || null, "" + newChild, priority); - } - if ("object" == typeof newChild && null !== newChild) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: - return updateElement(returnFiber, existingChildren.get(null === newChild.key ? newIdx : newChild.key) || null, newChild, priority); - - case REACT_COROUTINE_TYPE: - return updateCoroutine(returnFiber, existingChildren.get(null === newChild.key ? newIdx : newChild.key) || null, newChild, priority); - - case REACT_YIELD_TYPE: - return updateYield(returnFiber, existingChildren.get(newIdx) || null, newChild, priority); - - case REACT_PORTAL_TYPE$1: - return updatePortal(returnFiber, existingChildren.get(null === newChild.key ? newIdx : newChild.key) || null, newChild, priority); - } - if (isArray(newChild) || getIteratorFn(newChild)) { - return updateFragment(returnFiber, existingChildren.get(newIdx) || null, newChild, priority); - } - throwOnInvalidObjectType(returnFiber, newChild); - } - return null; - } - function reconcileChildrenArray(returnFiber, currentFirstChild, newChildren, priority) { - for (var resultingFirstChild = null, previousNewFiber = null, oldFiber = currentFirstChild, lastPlacedIndex = 0, newIdx = 0, nextOldFiber = null; null !== oldFiber && newIdx < newChildren.length; newIdx++) { - oldFiber.index > newIdx ? (nextOldFiber = oldFiber, oldFiber = null) : nextOldFiber = oldFiber.sibling; - var newFiber = updateSlot(returnFiber, oldFiber, newChildren[newIdx], priority); - if (null === newFiber) { - null === oldFiber && (oldFiber = nextOldFiber); - break; - } - shouldTrackSideEffects && oldFiber && null === newFiber.alternate && deleteChild(returnFiber, oldFiber), - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx), null === previousNewFiber ? resultingFirstChild = newFiber : previousNewFiber.sibling = newFiber, - previousNewFiber = newFiber, oldFiber = nextOldFiber; - } - if (newIdx === newChildren.length) return deleteRemainingChildren(returnFiber, oldFiber), - resultingFirstChild; - if (null === oldFiber) { - for (;newIdx < newChildren.length; newIdx++) { - var _newFiber = createChild(returnFiber, newChildren[newIdx], priority); - _newFiber && (lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx), - null === previousNewFiber ? resultingFirstChild = _newFiber : previousNewFiber.sibling = _newFiber, - previousNewFiber = _newFiber); - } - return resultingFirstChild; - } - for (var existingChildren = mapRemainingChildren(returnFiber, oldFiber); newIdx < newChildren.length; newIdx++) { - var _newFiber2 = updateFromMap(existingChildren, returnFiber, newIdx, newChildren[newIdx], priority); - _newFiber2 && (shouldTrackSideEffects && null !== _newFiber2.alternate && existingChildren.delete(null === _newFiber2.key ? newIdx : _newFiber2.key), - lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx), null === previousNewFiber ? resultingFirstChild = _newFiber2 : previousNewFiber.sibling = _newFiber2, - previousNewFiber = _newFiber2); - } - return shouldTrackSideEffects && existingChildren.forEach(function(child) { - return deleteChild(returnFiber, child); - }), resultingFirstChild; - } - function reconcileChildrenIterator(returnFiber, currentFirstChild, newChildrenIterable, priority) { - var iteratorFn = getIteratorFn(newChildrenIterable); - invariant("function" == typeof iteratorFn, "An object is not an iterable. This error is likely caused by a bug in " + "React. Please file an issue."); - var newChildren = iteratorFn.call(newChildrenIterable); - invariant(null != newChildren, "An iterable object provided no iterator."); - for (var resultingFirstChild = null, previousNewFiber = null, oldFiber = currentFirstChild, lastPlacedIndex = 0, newIdx = 0, nextOldFiber = null, step = newChildren.next(); null !== oldFiber && !step.done; newIdx++, - step = newChildren.next()) { - oldFiber.index > newIdx ? (nextOldFiber = oldFiber, oldFiber = null) : nextOldFiber = oldFiber.sibling; - var newFiber = updateSlot(returnFiber, oldFiber, step.value, priority); - if (null === newFiber) { - oldFiber || (oldFiber = nextOldFiber); - break; - } - shouldTrackSideEffects && oldFiber && null === newFiber.alternate && deleteChild(returnFiber, oldFiber), - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx), null === previousNewFiber ? resultingFirstChild = newFiber : previousNewFiber.sibling = newFiber, - previousNewFiber = newFiber, oldFiber = nextOldFiber; - } - if (step.done) return deleteRemainingChildren(returnFiber, oldFiber), resultingFirstChild; - if (null === oldFiber) { - for (;!step.done; newIdx++, step = newChildren.next()) { - var _newFiber3 = createChild(returnFiber, step.value, priority); - null !== _newFiber3 && (lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx), - null === previousNewFiber ? resultingFirstChild = _newFiber3 : previousNewFiber.sibling = _newFiber3, - previousNewFiber = _newFiber3); - } - return resultingFirstChild; - } - for (var existingChildren = mapRemainingChildren(returnFiber, oldFiber); !step.done; newIdx++, - step = newChildren.next()) { - var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, priority); - null !== _newFiber4 && (shouldTrackSideEffects && null !== _newFiber4.alternate && existingChildren.delete(null === _newFiber4.key ? newIdx : _newFiber4.key), - lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx), null === previousNewFiber ? resultingFirstChild = _newFiber4 : previousNewFiber.sibling = _newFiber4, - previousNewFiber = _newFiber4); - } - return shouldTrackSideEffects && existingChildren.forEach(function(child) { - return deleteChild(returnFiber, child); - }), resultingFirstChild; - } - function reconcileSingleTextNode(returnFiber, currentFirstChild, textContent, priority) { - if (null !== currentFirstChild && currentFirstChild.tag === HostText$3) { - deleteRemainingChildren(returnFiber, currentFirstChild.sibling); - var existing = useFiber(currentFirstChild, priority); - return existing.pendingProps = textContent, existing.return = returnFiber, existing; - } - deleteRemainingChildren(returnFiber, currentFirstChild); - var created = createFiberFromText$1(textContent, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - function reconcileSingleElement(returnFiber, currentFirstChild, element, priority) { - for (var key = element.key, child = currentFirstChild; null !== child; ) { - if (child.key === key) { - if (child.type === element.type) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, priority); - return existing.ref = coerceRef(child, element), existing.pendingProps = element.props, - existing.return = returnFiber, existing; - } - deleteRemainingChildren(returnFiber, child); - break; - } - deleteChild(returnFiber, child), child = child.sibling; - } - var created = createFiberFromElement$1(element, returnFiber.internalContextTag, priority); - return created.ref = coerceRef(currentFirstChild, element), created.return = returnFiber, - created; - } - function reconcileSingleCoroutine(returnFiber, currentFirstChild, coroutine, priority) { - for (var key = coroutine.key, child = currentFirstChild; null !== child; ) { - if (child.key === key) { - if (child.tag === CoroutineComponent$2) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, priority); - return existing.pendingProps = coroutine, existing.return = returnFiber, existing; - } - deleteRemainingChildren(returnFiber, child); - break; - } - deleteChild(returnFiber, child), child = child.sibling; - } - var created = createFiberFromCoroutine$1(coroutine, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - function reconcileSingleYield(returnFiber, currentFirstChild, yieldNode, priority) { - var child = currentFirstChild; - if (null !== child) { - if (child.tag === YieldComponent$2) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, priority); - return existing.type = yieldNode.value, existing.return = returnFiber, existing; - } - deleteRemainingChildren(returnFiber, child); - } - var created = createFiberFromYield$1(yieldNode, returnFiber.internalContextTag, priority); - return created.type = yieldNode.value, created.return = returnFiber, created; - } - function reconcileSinglePortal(returnFiber, currentFirstChild, portal, priority) { - for (var key = portal.key, child = currentFirstChild; null !== child; ) { - if (child.key === key) { - if (child.tag === HostPortal$4 && child.stateNode.containerInfo === portal.containerInfo && child.stateNode.implementation === portal.implementation) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, priority); - return existing.pendingProps = portal.children || [], existing.return = returnFiber, - existing; - } - deleteRemainingChildren(returnFiber, child); - break; - } - deleteChild(returnFiber, child), child = child.sibling; - } - var created = createFiberFromPortal$1(portal, returnFiber.internalContextTag, priority); - return created.return = returnFiber, created; - } - function reconcileChildFibers(returnFiber, currentFirstChild, newChild, priority) { - var isObject = "object" == typeof newChild && null !== newChild; - if (isObject) switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: - return placeSingleChild(reconcileSingleElement(returnFiber, currentFirstChild, newChild, priority)); - - case REACT_COROUTINE_TYPE: - return placeSingleChild(reconcileSingleCoroutine(returnFiber, currentFirstChild, newChild, priority)); - - case REACT_YIELD_TYPE: - return placeSingleChild(reconcileSingleYield(returnFiber, currentFirstChild, newChild, priority)); - - case REACT_PORTAL_TYPE$1: - return placeSingleChild(reconcileSinglePortal(returnFiber, currentFirstChild, newChild, priority)); - } - if ("string" == typeof newChild || "number" == typeof newChild) return placeSingleChild(reconcileSingleTextNode(returnFiber, currentFirstChild, "" + newChild, priority)); - if (isArray(newChild)) return reconcileChildrenArray(returnFiber, currentFirstChild, newChild, priority); - if (getIteratorFn(newChild)) return reconcileChildrenIterator(returnFiber, currentFirstChild, newChild, priority); - if (isObject && throwOnInvalidObjectType(returnFiber, newChild), void 0 === newChild) switch (returnFiber.tag) { - case ClassComponent$7: - case FunctionalComponent$2: - var Component = returnFiber.type; - invariant(!1, "%s(...): Nothing was returned from render. This usually means a " + "return statement is missing. Or, to render nothing, " + "return null.", Component.displayName || Component.name || "Component"); - } - return deleteRemainingChildren(returnFiber, currentFirstChild); - } - return reconcileChildFibers; -} - -var reconcileChildFibers$1 = ChildReconciler(!0, !0), reconcileChildFibersInPlace$1 = ChildReconciler(!1, !0), mountChildFibersInPlace$1 = ChildReconciler(!1, !1), cloneChildFibers$1 = function(current, workInProgress) { - if (invariant(null === current || workInProgress.child === current.child, "Resuming work not yet implemented."), - null !== workInProgress.child) { - var currentChild = workInProgress.child, newChild = createWorkInProgress$2(currentChild, currentChild.pendingWorkPriority); - for (newChild.pendingProps = currentChild.pendingProps, workInProgress.child = newChild, - newChild.return = workInProgress; null !== currentChild.sibling; ) currentChild = currentChild.sibling, - newChild = newChild.sibling = createWorkInProgress$2(currentChild, currentChild.pendingWorkPriority), - newChild.pendingProps = currentChild.pendingProps, newChild.return = workInProgress; - newChild.sibling = null; - } -}, ReactChildFiber = { - reconcileChildFibers: reconcileChildFibers$1, - reconcileChildFibersInPlace: reconcileChildFibersInPlace$1, - mountChildFibersInPlace: mountChildFibersInPlace$1, - cloneChildFibers: cloneChildFibers$1 -}, Update$1 = ReactTypeOfSideEffect.Update, AsyncUpdates$1 = ReactTypeOfInternalContext.AsyncUpdates, cacheContext$1 = ReactFiberContext.cacheContext, getMaskedContext$2 = ReactFiberContext.getMaskedContext, getUnmaskedContext$2 = ReactFiberContext.getUnmaskedContext, isContextConsumer$1 = ReactFiberContext.isContextConsumer, addUpdate$1 = ReactFiberUpdateQueue.addUpdate, addReplaceUpdate$1 = ReactFiberUpdateQueue.addReplaceUpdate, addForceUpdate$1 = ReactFiberUpdateQueue.addForceUpdate, beginUpdateQueue$2 = ReactFiberUpdateQueue.beginUpdateQueue, _require5 = ReactFiberContext, hasContextChanged$2 = _require5.hasContextChanged, isMounted$1 = ReactFiberTreeReflection.isMounted, ReactFiberClassComponent = function(scheduleUpdate, getPriorityContext, memoizeProps, memoizeState) { - var updater = { - isMounted: isMounted$1, - enqueueSetState: function(instance, partialState, callback) { - var fiber = ReactInstanceMap_1.get(instance), priorityLevel = getPriorityContext(fiber, !1); - callback = void 0 === callback ? null : callback, addUpdate$1(fiber, partialState, callback, priorityLevel), - scheduleUpdate(fiber, priorityLevel); - }, - enqueueReplaceState: function(instance, state, callback) { - var fiber = ReactInstanceMap_1.get(instance), priorityLevel = getPriorityContext(fiber, !1); - callback = void 0 === callback ? null : callback, addReplaceUpdate$1(fiber, state, callback, priorityLevel), - scheduleUpdate(fiber, priorityLevel); - }, - enqueueForceUpdate: function(instance, callback) { - var fiber = ReactInstanceMap_1.get(instance), priorityLevel = getPriorityContext(fiber, !1); - callback = void 0 === callback ? null : callback, addForceUpdate$1(fiber, callback, priorityLevel), - scheduleUpdate(fiber, priorityLevel); - } - }; - function checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext) { - if (null === oldProps || null !== workInProgress.updateQueue && workInProgress.updateQueue.hasForceUpdate) return !0; - var instance = workInProgress.stateNode, type = workInProgress.type; - if ("function" == typeof instance.shouldComponentUpdate) { - return instance.shouldComponentUpdate(newProps, newState, newContext); - } - return !type.prototype || !type.prototype.isPureReactComponent || (!shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)); - } - function resetInputPointers(workInProgress, instance) { - instance.props = workInProgress.memoizedProps, instance.state = workInProgress.memoizedState; - } - function adoptClassInstance(workInProgress, instance) { - instance.updater = updater, workInProgress.stateNode = instance, ReactInstanceMap_1.set(instance, workInProgress); - } - function constructClassInstance(workInProgress, props) { - var ctor = workInProgress.type, unmaskedContext = getUnmaskedContext$2(workInProgress), needsContext = isContextConsumer$1(workInProgress), context = needsContext ? getMaskedContext$2(workInProgress, unmaskedContext) : emptyObject, instance = new ctor(props, context); - return adoptClassInstance(workInProgress, instance), needsContext && cacheContext$1(workInProgress, unmaskedContext, context), - instance; - } - function callComponentWillMount(workInProgress, instance) { - var oldState = instance.state; - instance.componentWillMount(), oldState !== instance.state && updater.enqueueReplaceState(instance, instance.state, null); - } - function callComponentWillReceiveProps(workInProgress, instance, newProps, newContext) { - var oldState = instance.state; - instance.componentWillReceiveProps(newProps, newContext), instance.state !== oldState && updater.enqueueReplaceState(instance, instance.state, null); - } - function mountClassInstance(workInProgress, priorityLevel) { - var current = workInProgress.alternate, instance = workInProgress.stateNode, state = instance.state || null, props = workInProgress.pendingProps; - invariant(props, "There must be pending props for an initial mount. This error is " + "likely caused by a bug in React. Please file an issue."); - var unmaskedContext = getUnmaskedContext$2(workInProgress); - if (instance.props = props, instance.state = state, instance.refs = emptyObject, - instance.context = getMaskedContext$2(workInProgress, unmaskedContext), ReactFeatureFlags_1.enableAsyncSubtreeAPI && null != workInProgress.type && null != workInProgress.type.prototype && !0 === workInProgress.type.prototype.unstable_isAsyncReactComponent && (workInProgress.internalContextTag |= AsyncUpdates$1), - "function" == typeof instance.componentWillMount) { - callComponentWillMount(workInProgress, instance); - var updateQueue = workInProgress.updateQueue; - null !== updateQueue && (instance.state = beginUpdateQueue$2(current, workInProgress, updateQueue, instance, state, props, priorityLevel)); - } - "function" == typeof instance.componentDidMount && (workInProgress.effectTag |= Update$1); - } - function updateClassInstance(current, workInProgress, priorityLevel) { - var instance = workInProgress.stateNode; - resetInputPointers(workInProgress, instance); - var oldProps = workInProgress.memoizedProps, newProps = workInProgress.pendingProps; - newProps || (newProps = oldProps, invariant(null != newProps, "There should always be pending or memoized props. This error is " + "likely caused by a bug in React. Please file an issue.")); - var oldContext = instance.context, newUnmaskedContext = getUnmaskedContext$2(workInProgress), newContext = getMaskedContext$2(workInProgress, newUnmaskedContext); - "function" != typeof instance.componentWillReceiveProps || oldProps === newProps && oldContext === newContext || callComponentWillReceiveProps(workInProgress, instance, newProps, newContext); - var oldState = workInProgress.memoizedState, newState = void 0; - if (newState = null !== workInProgress.updateQueue ? beginUpdateQueue$2(current, workInProgress, workInProgress.updateQueue, instance, oldState, newProps, priorityLevel) : oldState, - !(oldProps !== newProps || oldState !== newState || hasContextChanged$2() || null !== workInProgress.updateQueue && workInProgress.updateQueue.hasForceUpdate)) return "function" == typeof instance.componentDidUpdate && (oldProps === current.memoizedProps && oldState === current.memoizedState || (workInProgress.effectTag |= Update$1)), - !1; - var shouldUpdate = checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext); - return shouldUpdate ? ("function" == typeof instance.componentWillUpdate && instance.componentWillUpdate(newProps, newState, newContext), - "function" == typeof instance.componentDidUpdate && (workInProgress.effectTag |= Update$1)) : ("function" == typeof instance.componentDidUpdate && (oldProps === current.memoizedProps && oldState === current.memoizedState || (workInProgress.effectTag |= Update$1)), - memoizeProps(workInProgress, newProps), memoizeState(workInProgress, newState)), - instance.props = newProps, instance.state = newState, instance.context = newContext, - shouldUpdate; - } - return { - adoptClassInstance: adoptClassInstance, - constructClassInstance: constructClassInstance, - mountClassInstance: mountClassInstance, - updateClassInstance: updateClassInstance - }; -}, mountChildFibersInPlace = ReactChildFiber.mountChildFibersInPlace, reconcileChildFibers = ReactChildFiber.reconcileChildFibers, reconcileChildFibersInPlace = ReactChildFiber.reconcileChildFibersInPlace, cloneChildFibers = ReactChildFiber.cloneChildFibers, beginUpdateQueue$1 = ReactFiberUpdateQueue.beginUpdateQueue, getMaskedContext$1 = ReactFiberContext.getMaskedContext, getUnmaskedContext$1 = ReactFiberContext.getUnmaskedContext, hasContextChanged$1 = ReactFiberContext.hasContextChanged, pushContextProvider$1 = ReactFiberContext.pushContextProvider, pushTopLevelContextObject$1 = ReactFiberContext.pushTopLevelContextObject, invalidateContextProvider$1 = ReactFiberContext.invalidateContextProvider, IndeterminateComponent$2 = ReactTypeOfWork.IndeterminateComponent, FunctionalComponent$1 = ReactTypeOfWork.FunctionalComponent, ClassComponent$6 = ReactTypeOfWork.ClassComponent, HostRoot$5 = ReactTypeOfWork.HostRoot, HostComponent$5 = ReactTypeOfWork.HostComponent, HostText$2 = ReactTypeOfWork.HostText, HostPortal$3 = ReactTypeOfWork.HostPortal, CoroutineComponent$1 = ReactTypeOfWork.CoroutineComponent, CoroutineHandlerPhase = ReactTypeOfWork.CoroutineHandlerPhase, YieldComponent$1 = ReactTypeOfWork.YieldComponent, Fragment$1 = ReactTypeOfWork.Fragment, NoWork$3 = ReactPriorityLevel.NoWork, OffscreenPriority$1 = ReactPriorityLevel.OffscreenPriority, PerformedWork$1 = ReactTypeOfSideEffect.PerformedWork, Placement$2 = ReactTypeOfSideEffect.Placement, ContentReset$1 = ReactTypeOfSideEffect.ContentReset, Err$1 = ReactTypeOfSideEffect.Err, Ref$1 = ReactTypeOfSideEffect.Ref, ReactCurrentOwner$2 = ReactGlobalSharedState_1.ReactCurrentOwner, ReactFiberBeginWork = function(config, hostContext, hydrationContext, scheduleUpdate, getPriorityContext) { - var shouldSetTextContent = config.shouldSetTextContent, useSyncScheduling = config.useSyncScheduling, shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree, pushHostContext = hostContext.pushHostContext, pushHostContainer = hostContext.pushHostContainer, enterHydrationState = hydrationContext.enterHydrationState, resetHydrationState = hydrationContext.resetHydrationState, tryToClaimNextHydratableInstance = hydrationContext.tryToClaimNextHydratableInstance, _ReactFiberClassCompo = ReactFiberClassComponent(scheduleUpdate, getPriorityContext, memoizeProps, memoizeState), adoptClassInstance = _ReactFiberClassCompo.adoptClassInstance, constructClassInstance = _ReactFiberClassCompo.constructClassInstance, mountClassInstance = _ReactFiberClassCompo.mountClassInstance, updateClassInstance = _ReactFiberClassCompo.updateClassInstance; - function reconcileChildren(current, workInProgress, nextChildren) { - reconcileChildrenAtPriority(current, workInProgress, nextChildren, workInProgress.pendingWorkPriority); - } - function reconcileChildrenAtPriority(current, workInProgress, nextChildren, priorityLevel) { - null === current ? workInProgress.child = mountChildFibersInPlace(workInProgress, workInProgress.child, nextChildren, priorityLevel) : current.child === workInProgress.child ? workInProgress.child = reconcileChildFibers(workInProgress, workInProgress.child, nextChildren, priorityLevel) : workInProgress.child = reconcileChildFibersInPlace(workInProgress, workInProgress.child, nextChildren, priorityLevel); - } - function updateFragment(current, workInProgress) { - var nextChildren = workInProgress.pendingProps; - if (hasContextChanged$1()) null === nextChildren && (nextChildren = workInProgress.memoizedProps); else if (null === nextChildren || workInProgress.memoizedProps === nextChildren) return bailoutOnAlreadyFinishedWork(current, workInProgress); - return reconcileChildren(current, workInProgress, nextChildren), memoizeProps(workInProgress, nextChildren), - workInProgress.child; - } - function markRef(current, workInProgress) { - var ref = workInProgress.ref; - null === ref || current && current.ref === ref || (workInProgress.effectTag |= Ref$1); - } - function updateFunctionalComponent(current, workInProgress) { - var fn = workInProgress.type, nextProps = workInProgress.pendingProps, memoizedProps = workInProgress.memoizedProps; - if (hasContextChanged$1()) null === nextProps && (nextProps = memoizedProps); else if (null === nextProps || memoizedProps === nextProps) return bailoutOnAlreadyFinishedWork(current, workInProgress); - var nextChildren, unmaskedContext = getUnmaskedContext$1(workInProgress), context = getMaskedContext$1(workInProgress, unmaskedContext); - return nextChildren = fn(nextProps, context), workInProgress.effectTag |= PerformedWork$1, - reconcileChildren(current, workInProgress, nextChildren), memoizeProps(workInProgress, nextProps), - workInProgress.child; - } - function updateClassComponent(current, workInProgress, priorityLevel) { - var hasContext = pushContextProvider$1(workInProgress), shouldUpdate = void 0; - return null === current ? workInProgress.stateNode ? invariant(!1, "Resuming work not yet implemented.") : (constructClassInstance(workInProgress, workInProgress.pendingProps), - mountClassInstance(workInProgress, priorityLevel), shouldUpdate = !0) : shouldUpdate = updateClassInstance(current, workInProgress, priorityLevel), - finishClassComponent(current, workInProgress, shouldUpdate, hasContext); - } - function finishClassComponent(current, workInProgress, shouldUpdate, hasContext) { - if (markRef(current, workInProgress), !shouldUpdate) return hasContext && invalidateContextProvider$1(workInProgress, !1), - bailoutOnAlreadyFinishedWork(current, workInProgress); - var instance = workInProgress.stateNode; - ReactCurrentOwner$2.current = workInProgress; - var nextChildren = void 0; - return nextChildren = instance.render(), workInProgress.effectTag |= PerformedWork$1, - reconcileChildren(current, workInProgress, nextChildren), memoizeState(workInProgress, instance.state), - memoizeProps(workInProgress, instance.props), hasContext && invalidateContextProvider$1(workInProgress, !0), - workInProgress.child; - } - function pushHostRootContext(workInProgress) { - var root = workInProgress.stateNode; - root.pendingContext ? pushTopLevelContextObject$1(workInProgress, root.pendingContext, root.pendingContext !== root.context) : root.context && pushTopLevelContextObject$1(workInProgress, root.context, !1), - pushHostContainer(workInProgress, root.containerInfo); - } - function updateHostRoot(current, workInProgress, priorityLevel) { - pushHostRootContext(workInProgress); - var updateQueue = workInProgress.updateQueue; - if (null !== updateQueue) { - var prevState = workInProgress.memoizedState, state = beginUpdateQueue$1(current, workInProgress, updateQueue, null, prevState, null, priorityLevel); - if (prevState === state) return resetHydrationState(), bailoutOnAlreadyFinishedWork(current, workInProgress); - var element = state.element; - return null !== current && null !== current.child || !enterHydrationState(workInProgress) ? (resetHydrationState(), - reconcileChildren(current, workInProgress, element)) : (workInProgress.effectTag |= Placement$2, - workInProgress.child = mountChildFibersInPlace(workInProgress, workInProgress.child, element, priorityLevel)), - memoizeState(workInProgress, state), workInProgress.child; - } - return resetHydrationState(), bailoutOnAlreadyFinishedWork(current, workInProgress); - } - function updateHostComponent(current, workInProgress, renderPriority) { - pushHostContext(workInProgress), null === current && tryToClaimNextHydratableInstance(workInProgress); - var type = workInProgress.type, memoizedProps = workInProgress.memoizedProps, nextProps = workInProgress.pendingProps; - null === nextProps && (nextProps = memoizedProps, invariant(null !== nextProps, "We should always have pending or current props. This error is " + "likely caused by a bug in React. Please file an issue.")); - var prevProps = null !== current ? current.memoizedProps : null; - if (hasContextChanged$1()) ; else if (null === nextProps || memoizedProps === nextProps) return bailoutOnAlreadyFinishedWork(current, workInProgress); - var nextChildren = nextProps.children; - return shouldSetTextContent(type, nextProps) ? nextChildren = null : prevProps && shouldSetTextContent(type, prevProps) && (workInProgress.effectTag |= ContentReset$1), - markRef(current, workInProgress), renderPriority !== OffscreenPriority$1 && !useSyncScheduling && shouldDeprioritizeSubtree(type, nextProps) ? (workInProgress.pendingWorkPriority = OffscreenPriority$1, - null) : (reconcileChildren(current, workInProgress, nextChildren), memoizeProps(workInProgress, nextProps), - workInProgress.child); - } - function updateHostText(current, workInProgress) { - null === current && tryToClaimNextHydratableInstance(workInProgress); - var nextProps = workInProgress.pendingProps; - return null === nextProps && (nextProps = workInProgress.memoizedProps), memoizeProps(workInProgress, nextProps), - null; - } - function mountIndeterminateComponent(current, workInProgress, priorityLevel) { - invariant(null === current, "An indeterminate component should never have mounted. This error is " + "likely caused by a bug in React. Please file an issue."); - var value, fn = workInProgress.type, props = workInProgress.pendingProps, unmaskedContext = getUnmaskedContext$1(workInProgress), context = getMaskedContext$1(workInProgress, unmaskedContext); - if (value = fn(props, context), workInProgress.effectTag |= PerformedWork$1, "object" == typeof value && null !== value && "function" == typeof value.render) { - workInProgress.tag = ClassComponent$6; - var hasContext = pushContextProvider$1(workInProgress); - return adoptClassInstance(workInProgress, value), mountClassInstance(workInProgress, priorityLevel), - finishClassComponent(current, workInProgress, !0, hasContext); - } - return workInProgress.tag = FunctionalComponent$1, reconcileChildren(current, workInProgress, value), - memoizeProps(workInProgress, props), workInProgress.child; - } - function updateCoroutineComponent(current, workInProgress) { - var nextCoroutine = workInProgress.pendingProps; - hasContextChanged$1() ? null === nextCoroutine && (nextCoroutine = current && current.memoizedProps, - invariant(null !== nextCoroutine, "We should always have pending or current props. This error is " + "likely caused by a bug in React. Please file an issue.")) : null !== nextCoroutine && workInProgress.memoizedProps !== nextCoroutine || (nextCoroutine = workInProgress.memoizedProps); - var nextChildren = nextCoroutine.children, priorityLevel = workInProgress.pendingWorkPriority; - return null === current ? workInProgress.stateNode = mountChildFibersInPlace(workInProgress, workInProgress.stateNode, nextChildren, priorityLevel) : current.child === workInProgress.child ? workInProgress.stateNode = reconcileChildFibers(workInProgress, workInProgress.stateNode, nextChildren, priorityLevel) : workInProgress.stateNode = reconcileChildFibersInPlace(workInProgress, workInProgress.stateNode, nextChildren, priorityLevel), - memoizeProps(workInProgress, nextCoroutine), workInProgress.stateNode; - } - function updatePortalComponent(current, workInProgress) { - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - var priorityLevel = workInProgress.pendingWorkPriority, nextChildren = workInProgress.pendingProps; - if (hasContextChanged$1()) null === nextChildren && (nextChildren = current && current.memoizedProps, - invariant(null != nextChildren, "We should always have pending or current props. This error is " + "likely caused by a bug in React. Please file an issue.")); else if (null === nextChildren || workInProgress.memoizedProps === nextChildren) return bailoutOnAlreadyFinishedWork(current, workInProgress); - return null === current ? (workInProgress.child = reconcileChildFibersInPlace(workInProgress, workInProgress.child, nextChildren, priorityLevel), - memoizeProps(workInProgress, nextChildren)) : (reconcileChildren(current, workInProgress, nextChildren), - memoizeProps(workInProgress, nextChildren)), workInProgress.child; - } - function bailoutOnAlreadyFinishedWork(current, workInProgress) { - return cloneChildFibers(current, workInProgress), workInProgress.child; - } - function bailoutOnLowPriority(current, workInProgress) { - switch (workInProgress.tag) { - case HostRoot$5: - pushHostRootContext(workInProgress); - break; - - case ClassComponent$6: - pushContextProvider$1(workInProgress); - break; - - case HostPortal$3: - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - } - return null; - } - function memoizeProps(workInProgress, nextProps) { - workInProgress.memoizedProps = nextProps; - } - function memoizeState(workInProgress, nextState) { - workInProgress.memoizedState = nextState; - } - function beginWork(current, workInProgress, priorityLevel) { - if (workInProgress.pendingWorkPriority === NoWork$3 || workInProgress.pendingWorkPriority > priorityLevel) return bailoutOnLowPriority(current, workInProgress); - switch (workInProgress.tag) { - case IndeterminateComponent$2: - return mountIndeterminateComponent(current, workInProgress, priorityLevel); - - case FunctionalComponent$1: - return updateFunctionalComponent(current, workInProgress); - - case ClassComponent$6: - return updateClassComponent(current, workInProgress, priorityLevel); - - case HostRoot$5: - return updateHostRoot(current, workInProgress, priorityLevel); - - case HostComponent$5: - return updateHostComponent(current, workInProgress, priorityLevel); - - case HostText$2: - return updateHostText(current, workInProgress); - - case CoroutineHandlerPhase: - workInProgress.tag = CoroutineComponent$1; - - case CoroutineComponent$1: - return updateCoroutineComponent(current, workInProgress); - - case YieldComponent$1: - return null; - - case HostPortal$3: - return updatePortalComponent(current, workInProgress); - - case Fragment$1: - return updateFragment(current, workInProgress); - - default: - invariant(!1, "Unknown unit of work tag. This error is likely caused by a bug in " + "React. Please file an issue."); - } - } - function beginFailedWork(current, workInProgress, priorityLevel) { - switch (workInProgress.tag) { - case ClassComponent$6: - pushContextProvider$1(workInProgress); - break; - - case HostRoot$5: - pushHostRootContext(workInProgress); - break; - - default: - invariant(!1, "Invalid type of work. This error is likely caused by a bug in React. " + "Please file an issue."); - } - if (workInProgress.effectTag |= Err$1, null === current ? workInProgress.child = null : workInProgress.child !== current.child && (workInProgress.child = current.child), - workInProgress.pendingWorkPriority === NoWork$3 || workInProgress.pendingWorkPriority > priorityLevel) return bailoutOnLowPriority(current, workInProgress); - if (workInProgress.firstEffect = null, workInProgress.lastEffect = null, reconcileChildrenAtPriority(current, workInProgress, null, priorityLevel), - workInProgress.tag === ClassComponent$6) { - var instance = workInProgress.stateNode; - workInProgress.memoizedProps = instance.props, workInProgress.memoizedState = instance.state; - } - return workInProgress.child; - } - return { - beginWork: beginWork, - beginFailedWork: beginFailedWork - }; -}, reconcileChildFibers$2 = ReactChildFiber.reconcileChildFibers, popContextProvider$2 = ReactFiberContext.popContextProvider, popTopLevelContextObject$1 = ReactFiberContext.popTopLevelContextObject, IndeterminateComponent$3 = ReactTypeOfWork.IndeterminateComponent, FunctionalComponent$3 = ReactTypeOfWork.FunctionalComponent, ClassComponent$8 = ReactTypeOfWork.ClassComponent, HostRoot$6 = ReactTypeOfWork.HostRoot, HostComponent$6 = ReactTypeOfWork.HostComponent, HostText$4 = ReactTypeOfWork.HostText, HostPortal$5 = ReactTypeOfWork.HostPortal, CoroutineComponent$3 = ReactTypeOfWork.CoroutineComponent, CoroutineHandlerPhase$1 = ReactTypeOfWork.CoroutineHandlerPhase, YieldComponent$3 = ReactTypeOfWork.YieldComponent, Fragment$3 = ReactTypeOfWork.Fragment, Placement$4 = ReactTypeOfSideEffect.Placement, Ref$2 = ReactTypeOfSideEffect.Ref, Update$2 = ReactTypeOfSideEffect.Update, OffscreenPriority$2 = ReactPriorityLevel.OffscreenPriority, ReactFiberCompleteWork = function(config, hostContext, hydrationContext) { - var createInstance = config.createInstance, createTextInstance = config.createTextInstance, appendInitialChild = config.appendInitialChild, finalizeInitialChildren = config.finalizeInitialChildren, prepareUpdate = config.prepareUpdate, getRootHostContainer = hostContext.getRootHostContainer, popHostContext = hostContext.popHostContext, getHostContext = hostContext.getHostContext, popHostContainer = hostContext.popHostContainer, prepareToHydrateHostInstance = hydrationContext.prepareToHydrateHostInstance, prepareToHydrateHostTextInstance = hydrationContext.prepareToHydrateHostTextInstance, popHydrationState = hydrationContext.popHydrationState; - function markUpdate(workInProgress) { - workInProgress.effectTag |= Update$2; - } - function markRef(workInProgress) { - workInProgress.effectTag |= Ref$2; - } - function appendAllYields(yields, workInProgress) { - var node = workInProgress.stateNode; - for (node && (node.return = workInProgress); null !== node; ) { - if (node.tag === HostComponent$6 || node.tag === HostText$4 || node.tag === HostPortal$5) invariant(!1, "A coroutine cannot have host component children."); else if (node.tag === YieldComponent$3) yields.push(node.type); else if (null !== node.child) { - node.child.return = node, node = node.child; - continue; - } - for (;null === node.sibling; ) { - if (null === node.return || node.return === workInProgress) return; - node = node.return; - } - node.sibling.return = node.return, node = node.sibling; - } - } - function moveCoroutineToHandlerPhase(current, workInProgress) { - var coroutine = workInProgress.memoizedProps; - invariant(coroutine, "Should be resolved by now. This error is likely caused by a bug in " + "React. Please file an issue."), - workInProgress.tag = CoroutineHandlerPhase$1; - var yields = []; - appendAllYields(yields, workInProgress); - var fn = coroutine.handler, props = coroutine.props, nextChildren = fn(props, yields), currentFirstChild = null !== current ? current.child : null, priority = workInProgress.pendingWorkPriority; - return workInProgress.child = reconcileChildFibers$2(workInProgress, currentFirstChild, nextChildren, priority), - workInProgress.child; - } - function appendAllChildren(parent, workInProgress) { - for (var node = workInProgress.child; null !== node; ) { - if (node.tag === HostComponent$6 || node.tag === HostText$4) appendInitialChild(parent, node.stateNode); else if (node.tag === HostPortal$5) ; else if (null !== node.child) { - node = node.child; - continue; - } - if (node === workInProgress) return; - for (;null === node.sibling; ) { - if (null === node.return || node.return === workInProgress) return; - node = node.return; - } - node = node.sibling; - } - } - function completeWork(current, workInProgress, renderPriority) { - var newProps = workInProgress.pendingProps; - switch (null === newProps ? newProps = workInProgress.memoizedProps : workInProgress.pendingWorkPriority === OffscreenPriority$2 && renderPriority !== OffscreenPriority$2 || (workInProgress.pendingProps = null), - workInProgress.tag) { - case FunctionalComponent$3: - return null; - - case ClassComponent$8: - return popContextProvider$2(workInProgress), null; - - case HostRoot$6: - popHostContainer(workInProgress), popTopLevelContextObject$1(workInProgress); - var fiberRoot = workInProgress.stateNode; - return fiberRoot.pendingContext && (fiberRoot.context = fiberRoot.pendingContext, - fiberRoot.pendingContext = null), null !== current && null !== current.child || (popHydrationState(workInProgress), - workInProgress.effectTag &= ~Placement$4), null; - - case HostComponent$6: - popHostContext(workInProgress); - var rootContainerInstance = getRootHostContainer(), type = workInProgress.type; - if (null !== current && null != workInProgress.stateNode) { - var oldProps = current.memoizedProps, instance = workInProgress.stateNode, currentHostContext = getHostContext(), updatePayload = prepareUpdate(instance, type, oldProps, newProps, rootContainerInstance, currentHostContext); - workInProgress.updateQueue = updatePayload, updatePayload && markUpdate(workInProgress), - current.ref !== workInProgress.ref && markRef(workInProgress); - } else { - if (!newProps) return invariant(null !== workInProgress.stateNode, "We must have new props for new mounts. This error is likely " + "caused by a bug in React. Please file an issue."), - null; - var _currentHostContext = getHostContext(); - if (popHydrationState(workInProgress)) prepareToHydrateHostInstance(workInProgress, rootContainerInstance, _currentHostContext) && markUpdate(workInProgress); else { - var _instance = createInstance(type, newProps, rootContainerInstance, _currentHostContext, workInProgress); - appendAllChildren(_instance, workInProgress), finalizeInitialChildren(_instance, type, newProps, rootContainerInstance) && markUpdate(workInProgress), - workInProgress.stateNode = _instance; - } - null !== workInProgress.ref && markRef(workInProgress); - } - return null; - - case HostText$4: - var newText = newProps; - if (current && null != workInProgress.stateNode) { - current.memoizedProps !== newText && markUpdate(workInProgress); - } else { - if ("string" != typeof newText) return invariant(null !== workInProgress.stateNode, "We must have new props for new mounts. This error is likely " + "caused by a bug in React. Please file an issue."), - null; - var _rootContainerInstance = getRootHostContainer(), _currentHostContext2 = getHostContext(); - popHydrationState(workInProgress) ? prepareToHydrateHostTextInstance(workInProgress) && markUpdate(workInProgress) : workInProgress.stateNode = createTextInstance(newText, _rootContainerInstance, _currentHostContext2, workInProgress); - } - return null; - - case CoroutineComponent$3: - return moveCoroutineToHandlerPhase(current, workInProgress); - - case CoroutineHandlerPhase$1: - return workInProgress.tag = CoroutineComponent$3, null; - - case YieldComponent$3: - case Fragment$3: - return null; - - case HostPortal$5: - return markUpdate(workInProgress), popHostContainer(workInProgress), null; - - case IndeterminateComponent$3: - invariant(!1, "An indeterminate component should have become determinate before " + "completing. This error is likely caused by a bug in React. Please " + "file an issue."); - - default: - invariant(!1, "Unknown unit of work tag. This error is likely caused by a bug in " + "React. Please file an issue."); - } - } - return { - completeWork: completeWork - }; -}, onCommitFiberRoot = null, onCommitFiberUnmount = null, hasLoggedError = !1; - -function catchErrors(fn) { - return function(arg) { - try { - return fn(arg); - } catch (err) { - 1 || hasLoggedError || (hasLoggedError = !0); - } - }; -} - -function injectInternals$1(internals) { - if ("undefined" == typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) return !1; - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - if (!hook.supportsFiber) return !0; - try { - var rendererID = hook.inject(internals); - onCommitFiberRoot = catchErrors(function(root) { - return hook.onCommitFiberRoot(rendererID, root); - }), onCommitFiberUnmount = catchErrors(function(fiber) { - return hook.onCommitFiberUnmount(rendererID, fiber); - }); - } catch (err) {} - return !0; -} - -function onCommitRoot$1(root) { - "function" == typeof onCommitFiberRoot && onCommitFiberRoot(root); -} - -function onCommitUnmount$1(fiber) { - "function" == typeof onCommitFiberUnmount && onCommitFiberUnmount(fiber); -} - -var injectInternals_1 = injectInternals$1, onCommitRoot_1 = onCommitRoot$1, onCommitUnmount_1 = onCommitUnmount$1, ReactFiberDevToolsHook = { - injectInternals: injectInternals_1, - onCommitRoot: onCommitRoot_1, - onCommitUnmount: onCommitUnmount_1 -}, ClassComponent$9 = ReactTypeOfWork.ClassComponent, HostRoot$7 = ReactTypeOfWork.HostRoot, HostComponent$7 = ReactTypeOfWork.HostComponent, HostText$5 = ReactTypeOfWork.HostText, HostPortal$6 = ReactTypeOfWork.HostPortal, CoroutineComponent$4 = ReactTypeOfWork.CoroutineComponent, commitCallbacks$1 = ReactFiberUpdateQueue.commitCallbacks, onCommitUnmount = ReactFiberDevToolsHook.onCommitUnmount, Placement$5 = ReactTypeOfSideEffect.Placement, Update$3 = ReactTypeOfSideEffect.Update, Callback$1 = ReactTypeOfSideEffect.Callback, ContentReset$2 = ReactTypeOfSideEffect.ContentReset, ReactFiberCommitWork = function(config, captureError) { - var commitMount = config.commitMount, commitUpdate = config.commitUpdate, resetTextContent = config.resetTextContent, commitTextUpdate = config.commitTextUpdate, appendChild = config.appendChild, appendChildToContainer = config.appendChildToContainer, insertBefore = config.insertBefore, insertInContainerBefore = config.insertInContainerBefore, removeChild = config.removeChild, removeChildFromContainer = config.removeChildFromContainer, getPublicInstance = config.getPublicInstance; - function safelyCallComponentWillUnmount(current, instance) { - try { - instance.props = current.memoizedProps, instance.state = current.memoizedState, - instance.componentWillUnmount(); - } catch (unmountError) { - captureError(current, unmountError); - } - } - function safelyDetachRef(current) { - var ref = current.ref; - if (null !== ref) { - try { - ref(null); - } catch (refError) { - captureError(current, refError); - } - } - } - function getHostParentFiber(fiber) { - for (var parent = fiber.return; null !== parent; ) { - if (isHostParent(parent)) return parent; - parent = parent.return; - } - invariant(!1, "Expected to find a host parent. This error is likely caused by a bug " + "in React. Please file an issue."); - } - function isHostParent(fiber) { - return fiber.tag === HostComponent$7 || fiber.tag === HostRoot$7 || fiber.tag === HostPortal$6; - } - function getHostSibling(fiber) { - var node = fiber; - siblings: for (;!0; ) { - for (;null === node.sibling; ) { - if (null === node.return || isHostParent(node.return)) return null; - node = node.return; - } - for (node.sibling.return = node.return, node = node.sibling; node.tag !== HostComponent$7 && node.tag !== HostText$5; ) { - if (node.effectTag & Placement$5) continue siblings; - if (null === node.child || node.tag === HostPortal$6) continue siblings; - node.child.return = node, node = node.child; - } - if (!(node.effectTag & Placement$5)) return node.stateNode; - } - } - function commitPlacement(finishedWork) { - var parentFiber = getHostParentFiber(finishedWork), parent = void 0, isContainer = void 0; - switch (parentFiber.tag) { - case HostComponent$7: - parent = parentFiber.stateNode, isContainer = !1; - break; - - case HostRoot$7: - case HostPortal$6: - parent = parentFiber.stateNode.containerInfo, isContainer = !0; - break; - - default: - invariant(!1, "Invalid host parent fiber. This error is likely caused by a bug " + "in React. Please file an issue."); - } - parentFiber.effectTag & ContentReset$2 && (resetTextContent(parent), parentFiber.effectTag &= ~ContentReset$2); - for (var before = getHostSibling(finishedWork), node = finishedWork; !0; ) { - if (node.tag === HostComponent$7 || node.tag === HostText$5) before ? isContainer ? insertInContainerBefore(parent, node.stateNode, before) : insertBefore(parent, node.stateNode, before) : isContainer ? appendChildToContainer(parent, node.stateNode) : appendChild(parent, node.stateNode); else if (node.tag === HostPortal$6) ; else if (null !== node.child) { - node.child.return = node, node = node.child; - continue; - } - if (node === finishedWork) return; - for (;null === node.sibling; ) { - if (null === node.return || node.return === finishedWork) return; - node = node.return; - } - node.sibling.return = node.return, node = node.sibling; - } - } - function commitNestedUnmounts(root) { - for (var node = root; !0; ) if (commitUnmount(node), null === node.child || node.tag === HostPortal$6) { - if (node === root) return; - for (;null === node.sibling; ) { - if (null === node.return || node.return === root) return; - node = node.return; - } - node.sibling.return = node.return, node = node.sibling; - } else node.child.return = node, node = node.child; - } - function unmountHostComponents(current) { - for (var node = current, currentParentIsValid = !1, currentParent = void 0, currentParentIsContainer = void 0; !0; ) { - if (!currentParentIsValid) { - var parent = node.return; - findParent: for (;!0; ) { - switch (invariant(null !== parent, "Expected to find a host parent. This error is likely caused by " + "a bug in React. Please file an issue."), - parent.tag) { - case HostComponent$7: - currentParent = parent.stateNode, currentParentIsContainer = !1; - break findParent; - - case HostRoot$7: - case HostPortal$6: - currentParent = parent.stateNode.containerInfo, currentParentIsContainer = !0; - break findParent; - } - parent = parent.return; - } - currentParentIsValid = !0; - } - if (node.tag === HostComponent$7 || node.tag === HostText$5) commitNestedUnmounts(node), - currentParentIsContainer ? removeChildFromContainer(currentParent, node.stateNode) : removeChild(currentParent, node.stateNode); else if (node.tag === HostPortal$6) { - if (currentParent = node.stateNode.containerInfo, null !== node.child) { - node.child.return = node, node = node.child; - continue; - } - } else if (commitUnmount(node), null !== node.child) { - node.child.return = node, node = node.child; - continue; - } - if (node === current) return; - for (;null === node.sibling; ) { - if (null === node.return || node.return === current) return; - node = node.return, node.tag === HostPortal$6 && (currentParentIsValid = !1); - } - node.sibling.return = node.return, node = node.sibling; - } - } - function commitDeletion(current) { - unmountHostComponents(current), current.return = null, current.child = null, current.alternate && (current.alternate.child = null, - current.alternate.return = null); - } - function commitUnmount(current) { - switch ("function" == typeof onCommitUnmount && onCommitUnmount(current), current.tag) { - case ClassComponent$9: - safelyDetachRef(current); - var instance = current.stateNode; - return void ("function" == typeof instance.componentWillUnmount && safelyCallComponentWillUnmount(current, instance)); - - case HostComponent$7: - return void safelyDetachRef(current); - - case CoroutineComponent$4: - return void commitNestedUnmounts(current.stateNode); - - case HostPortal$6: - return void unmountHostComponents(current); - } - } - function commitWork(current, finishedWork) { - switch (finishedWork.tag) { - case ClassComponent$9: - return; - - case HostComponent$7: - var instance = finishedWork.stateNode; - if (null != instance) { - var newProps = finishedWork.memoizedProps, oldProps = null !== current ? current.memoizedProps : newProps, type = finishedWork.type, updatePayload = finishedWork.updateQueue; - finishedWork.updateQueue = null, null !== updatePayload && commitUpdate(instance, updatePayload, type, oldProps, newProps, finishedWork); - } - return; - - case HostText$5: - invariant(null !== finishedWork.stateNode, "This should have a text node initialized. This error is likely " + "caused by a bug in React. Please file an issue."); - var textInstance = finishedWork.stateNode, newText = finishedWork.memoizedProps, oldText = null !== current ? current.memoizedProps : newText; - return void commitTextUpdate(textInstance, oldText, newText); - - case HostRoot$7: - case HostPortal$6: - return; - - default: - invariant(!1, "This unit of work tag should not have side-effects. This error is " + "likely caused by a bug in React. Please file an issue."); - } - } - function commitLifeCycles(current, finishedWork) { - switch (finishedWork.tag) { - case ClassComponent$9: - var instance = finishedWork.stateNode; - if (finishedWork.effectTag & Update$3) if (null === current) instance.props = finishedWork.memoizedProps, - instance.state = finishedWork.memoizedState, instance.componentDidMount(); else { - var prevProps = current.memoizedProps, prevState = current.memoizedState; - instance.props = finishedWork.memoizedProps, instance.state = finishedWork.memoizedState, - instance.componentDidUpdate(prevProps, prevState); - } - return void (finishedWork.effectTag & Callback$1 && null !== finishedWork.updateQueue && commitCallbacks$1(finishedWork, finishedWork.updateQueue, instance)); - - case HostRoot$7: - var updateQueue = finishedWork.updateQueue; - if (null !== updateQueue) { - var _instance = finishedWork.child && finishedWork.child.stateNode; - commitCallbacks$1(finishedWork, updateQueue, _instance); - } - return; - - case HostComponent$7: - var _instance2 = finishedWork.stateNode; - if (null === current && finishedWork.effectTag & Update$3) { - var type = finishedWork.type, props = finishedWork.memoizedProps; - commitMount(_instance2, type, props, finishedWork); - } - return; - - case HostText$5: - case HostPortal$6: - return; - - default: - invariant(!1, "This unit of work tag should not have side-effects. This error is " + "likely caused by a bug in React. Please file an issue."); - } - } - function commitAttachRef(finishedWork) { - var ref = finishedWork.ref; - if (null !== ref) { - var instance = finishedWork.stateNode; - switch (finishedWork.tag) { - case HostComponent$7: - ref(getPublicInstance(instance)); - break; - - default: - ref(instance); - } - } - } - function commitDetachRef(current) { - var currentRef = current.ref; - null !== currentRef && currentRef(null); - } - return { - commitPlacement: commitPlacement, - commitDeletion: commitDeletion, - commitWork: commitWork, - commitLifeCycles: commitLifeCycles, - commitAttachRef: commitAttachRef, - commitDetachRef: commitDetachRef - }; -}, createCursor$2 = ReactFiberStack.createCursor, pop$2 = ReactFiberStack.pop, push$2 = ReactFiberStack.push, NO_CONTEXT = {}, ReactFiberHostContext = function(config) { - var getChildHostContext = config.getChildHostContext, getRootHostContext = config.getRootHostContext, contextStackCursor = createCursor$2(NO_CONTEXT), contextFiberStackCursor = createCursor$2(NO_CONTEXT), rootInstanceStackCursor = createCursor$2(NO_CONTEXT); - function requiredContext(c) { - return invariant(c !== NO_CONTEXT, "Expected host context to exist. This error is likely caused by a bug " + "in React. Please file an issue."), - c; - } - function getRootHostContainer() { - return requiredContext(rootInstanceStackCursor.current); - } - function pushHostContainer(fiber, nextRootInstance) { - push$2(rootInstanceStackCursor, nextRootInstance, fiber); - var nextRootContext = getRootHostContext(nextRootInstance); - push$2(contextFiberStackCursor, fiber, fiber), push$2(contextStackCursor, nextRootContext, fiber); - } - function popHostContainer(fiber) { - pop$2(contextStackCursor, fiber), pop$2(contextFiberStackCursor, fiber), pop$2(rootInstanceStackCursor, fiber); - } - function getHostContext() { - return requiredContext(contextStackCursor.current); - } - function pushHostContext(fiber) { - var rootInstance = requiredContext(rootInstanceStackCursor.current), context = requiredContext(contextStackCursor.current), nextContext = getChildHostContext(context, fiber.type, rootInstance); - context !== nextContext && (push$2(contextFiberStackCursor, fiber, fiber), push$2(contextStackCursor, nextContext, fiber)); - } - function popHostContext(fiber) { - contextFiberStackCursor.current === fiber && (pop$2(contextStackCursor, fiber), - pop$2(contextFiberStackCursor, fiber)); - } - function resetHostContainer() { - contextStackCursor.current = NO_CONTEXT, rootInstanceStackCursor.current = NO_CONTEXT; - } - return { - getHostContext: getHostContext, - getRootHostContainer: getRootHostContainer, - popHostContainer: popHostContainer, - popHostContext: popHostContext, - pushHostContainer: pushHostContainer, - pushHostContext: pushHostContext, - resetHostContainer: resetHostContainer - }; -}, HostComponent$8 = ReactTypeOfWork.HostComponent, HostText$6 = ReactTypeOfWork.HostText, HostRoot$8 = ReactTypeOfWork.HostRoot, Deletion$2 = ReactTypeOfSideEffect.Deletion, Placement$6 = ReactTypeOfSideEffect.Placement, createFiberFromHostInstanceForDeletion$1 = ReactFiber.createFiberFromHostInstanceForDeletion, ReactFiberHydrationContext = function(config) { - var shouldSetTextContent = config.shouldSetTextContent, canHydrateInstance = config.canHydrateInstance, canHydrateTextInstance = config.canHydrateTextInstance, getNextHydratableSibling = config.getNextHydratableSibling, getFirstHydratableChild = config.getFirstHydratableChild, hydrateInstance = config.hydrateInstance, hydrateTextInstance = config.hydrateTextInstance, didNotHydrateInstance = config.didNotHydrateInstance, didNotFindHydratableInstance = config.didNotFindHydratableInstance, didNotFindHydratableTextInstance = config.didNotFindHydratableTextInstance; - if (!(canHydrateInstance && canHydrateTextInstance && getNextHydratableSibling && getFirstHydratableChild && hydrateInstance && hydrateTextInstance && didNotHydrateInstance && didNotFindHydratableInstance && didNotFindHydratableTextInstance)) return { - enterHydrationState: function() { - return !1; - }, - resetHydrationState: function() {}, - tryToClaimNextHydratableInstance: function() {}, - prepareToHydrateHostInstance: function() { - invariant(!1, "Expected prepareToHydrateHostInstance() to never be called. " + "This error is likely caused by a bug in React. Please file an issue."); - }, - prepareToHydrateHostTextInstance: function() { - invariant(!1, "Expected prepareToHydrateHostTextInstance() to never be called. " + "This error is likely caused by a bug in React. Please file an issue."); - }, - popHydrationState: function(fiber) { - return !1; - } - }; - var hydrationParentFiber = null, nextHydratableInstance = null, isHydrating = !1; - function enterHydrationState(fiber) { - var parentInstance = fiber.stateNode.containerInfo; - return nextHydratableInstance = getFirstHydratableChild(parentInstance), hydrationParentFiber = fiber, - isHydrating = !0, !0; - } - function deleteHydratableInstance(returnFiber, instance) { - var childToDelete = createFiberFromHostInstanceForDeletion$1(); - childToDelete.stateNode = instance, childToDelete.return = returnFiber, childToDelete.effectTag = Deletion$2, - null !== returnFiber.lastEffect ? (returnFiber.lastEffect.nextEffect = childToDelete, - returnFiber.lastEffect = childToDelete) : returnFiber.firstEffect = returnFiber.lastEffect = childToDelete; - } - function insertNonHydratedInstance(returnFiber, fiber) { - fiber.effectTag |= Placement$6; - } - function canHydrate(fiber, nextInstance) { - switch (fiber.tag) { - case HostComponent$8: - var type = fiber.type, props = fiber.pendingProps; - return canHydrateInstance(nextInstance, type, props); - - case HostText$6: - var text = fiber.pendingProps; - return canHydrateTextInstance(nextInstance, text); - - default: - return !1; - } - } - function tryToClaimNextHydratableInstance(fiber) { - if (isHydrating) { - var nextInstance = nextHydratableInstance; - if (!nextInstance) return insertNonHydratedInstance(hydrationParentFiber, fiber), - isHydrating = !1, void (hydrationParentFiber = fiber); - if (!canHydrate(fiber, nextInstance)) { - if (!(nextInstance = getNextHydratableSibling(nextInstance)) || !canHydrate(fiber, nextInstance)) return insertNonHydratedInstance(hydrationParentFiber, fiber), - isHydrating = !1, void (hydrationParentFiber = fiber); - deleteHydratableInstance(hydrationParentFiber, nextHydratableInstance); - } - fiber.stateNode = nextInstance, hydrationParentFiber = fiber, nextHydratableInstance = getFirstHydratableChild(nextInstance); - } - } - function prepareToHydrateHostInstance(fiber, rootContainerInstance, hostContext) { - var instance = fiber.stateNode, updatePayload = hydrateInstance(instance, fiber.type, fiber.memoizedProps, rootContainerInstance, hostContext, fiber); - return fiber.updateQueue = updatePayload, null !== updatePayload; - } - function prepareToHydrateHostTextInstance(fiber) { - var textInstance = fiber.stateNode; - return hydrateTextInstance(textInstance, fiber.memoizedProps, fiber); - } - function popToNextHostParent(fiber) { - for (var parent = fiber.return; null !== parent && parent.tag !== HostComponent$8 && parent.tag !== HostRoot$8; ) parent = parent.return; - hydrationParentFiber = parent; - } - function popHydrationState(fiber) { - if (fiber !== hydrationParentFiber) return !1; - if (!isHydrating) return popToNextHostParent(fiber), isHydrating = !0, !1; - var type = fiber.type; - if (fiber.tag !== HostComponent$8 || "head" !== type && "body" !== type && !shouldSetTextContent(type, fiber.memoizedProps)) for (var nextInstance = nextHydratableInstance; nextInstance; ) deleteHydratableInstance(fiber, nextInstance), - nextInstance = getNextHydratableSibling(nextInstance); - return popToNextHostParent(fiber), nextHydratableInstance = hydrationParentFiber ? getNextHydratableSibling(fiber.stateNode) : null, - !0; - } - function resetHydrationState() { - hydrationParentFiber = null, nextHydratableInstance = null, isHydrating = !1; - } - return { - enterHydrationState: enterHydrationState, - resetHydrationState: resetHydrationState, - tryToClaimNextHydratableInstance: tryToClaimNextHydratableInstance, - prepareToHydrateHostInstance: prepareToHydrateHostInstance, - prepareToHydrateHostTextInstance: prepareToHydrateHostTextInstance, - popHydrationState: popHydrationState - }; -}, popContextProvider$1 = ReactFiberContext.popContextProvider, reset$1 = ReactFiberStack.reset, getStackAddendumByWorkInProgressFiber = ReactFiberComponentTreeHook.getStackAddendumByWorkInProgressFiber, logCapturedError$1 = ReactFiberErrorLogger.logCapturedError, ReactCurrentOwner$1 = ReactGlobalSharedState_1.ReactCurrentOwner, createWorkInProgress$1 = ReactFiber.createWorkInProgress, largerPriority$1 = ReactFiber.largerPriority, onCommitRoot = ReactFiberDevToolsHook.onCommitRoot, NoWork$2 = ReactPriorityLevel.NoWork, SynchronousPriority$1 = ReactPriorityLevel.SynchronousPriority, TaskPriority$1 = ReactPriorityLevel.TaskPriority, HighPriority = ReactPriorityLevel.HighPriority, LowPriority = ReactPriorityLevel.LowPriority, OffscreenPriority = ReactPriorityLevel.OffscreenPriority, AsyncUpdates = ReactTypeOfInternalContext.AsyncUpdates, PerformedWork = ReactTypeOfSideEffect.PerformedWork, Placement$1 = ReactTypeOfSideEffect.Placement, Update = ReactTypeOfSideEffect.Update, PlacementAndUpdate = ReactTypeOfSideEffect.PlacementAndUpdate, Deletion = ReactTypeOfSideEffect.Deletion, ContentReset = ReactTypeOfSideEffect.ContentReset, Callback = ReactTypeOfSideEffect.Callback, Err = ReactTypeOfSideEffect.Err, Ref = ReactTypeOfSideEffect.Ref, HostRoot$4 = ReactTypeOfWork.HostRoot, HostComponent$3 = ReactTypeOfWork.HostComponent, HostPortal$2 = ReactTypeOfWork.HostPortal, ClassComponent$4 = ReactTypeOfWork.ClassComponent, getUpdatePriority$1 = ReactFiberUpdateQueue.getUpdatePriority, _require14 = ReactFiberContext, resetContext$1 = _require14.resetContext, ReactFiberInstrumentation$1, timeHeuristicForUnitOfWork = 1, ReactFiberScheduler = function(config) { - var hostContext = ReactFiberHostContext(config), hydrationContext = ReactFiberHydrationContext(config), popHostContainer = hostContext.popHostContainer, popHostContext = hostContext.popHostContext, resetHostContainer = hostContext.resetHostContainer, _ReactFiberBeginWork = ReactFiberBeginWork(config, hostContext, hydrationContext, scheduleUpdate, getPriorityContext), beginWork = _ReactFiberBeginWork.beginWork, beginFailedWork = _ReactFiberBeginWork.beginFailedWork, _ReactFiberCompleteWo = ReactFiberCompleteWork(config, hostContext, hydrationContext), completeWork = _ReactFiberCompleteWo.completeWork, _ReactFiberCommitWork = ReactFiberCommitWork(config, captureError), commitPlacement = _ReactFiberCommitWork.commitPlacement, commitDeletion = _ReactFiberCommitWork.commitDeletion, commitWork = _ReactFiberCommitWork.commitWork, commitLifeCycles = _ReactFiberCommitWork.commitLifeCycles, commitAttachRef = _ReactFiberCommitWork.commitAttachRef, commitDetachRef = _ReactFiberCommitWork.commitDetachRef, scheduleDeferredCallback = config.scheduleDeferredCallback, useSyncScheduling = config.useSyncScheduling, prepareForCommit = config.prepareForCommit, resetAfterCommit = config.resetAfterCommit, priorityContext = NoWork$2, isPerformingWork = !1, deadlineHasExpired = !1, isBatchingUpdates = !1, isUnbatchingUpdates = !1, nextUnitOfWork = null, nextPriorityLevel = NoWork$2, nextEffect = null, pendingCommit = null, nextScheduledRoot = null, lastScheduledRoot = null, isCallbackScheduled = !1, capturedErrors = null, failedBoundaries = null, commitPhaseBoundaries = null, firstUncaughtError = null, didFatal = !1, isCommitting = !1, isUnmounting = !1, NESTED_UPDATE_LIMIT = 1e3, nestedUpdateCount = 0, nextRenderedTree = null; - function resetContextStack() { - reset$1(), resetContext$1(), resetHostContainer(); - } - function resetNextUnitOfWork() { - for (;null !== nextScheduledRoot && nextScheduledRoot.current.pendingWorkPriority === NoWork$2; ) { - nextScheduledRoot.isScheduled = !1; - var next = nextScheduledRoot.nextScheduledRoot; - if (nextScheduledRoot.nextScheduledRoot = null, nextScheduledRoot === lastScheduledRoot) return nextScheduledRoot = null, - lastScheduledRoot = null, nextPriorityLevel = NoWork$2, null; - nextScheduledRoot = next; - } - for (var root = nextScheduledRoot, highestPriorityRoot = null, highestPriorityLevel = NoWork$2; null !== root; ) root.current.pendingWorkPriority !== NoWork$2 && (highestPriorityLevel === NoWork$2 || highestPriorityLevel > root.current.pendingWorkPriority) && (highestPriorityLevel = root.current.pendingWorkPriority, - highestPriorityRoot = root), root = root.nextScheduledRoot; - if (null !== highestPriorityRoot) return nextPriorityLevel = highestPriorityLevel, - resetContextStack(), nextUnitOfWork = createWorkInProgress$1(highestPriorityRoot.current, highestPriorityLevel), - void (highestPriorityRoot !== nextRenderedTree && (nestedUpdateCount = 0, nextRenderedTree = highestPriorityRoot)); - nextPriorityLevel = NoWork$2, nextUnitOfWork = null, nextRenderedTree = null; - } - function commitAllHostEffects() { - for (;null !== nextEffect; ) { - var effectTag = nextEffect.effectTag; - if (effectTag & ContentReset && config.resetTextContent(nextEffect.stateNode), effectTag & Ref) { - var current = nextEffect.alternate; - null !== current && commitDetachRef(current); - } - switch (effectTag & ~(Callback | Err | ContentReset | Ref | PerformedWork)) { - case Placement$1: - commitPlacement(nextEffect), nextEffect.effectTag &= ~Placement$1; - break; - - case PlacementAndUpdate: - commitPlacement(nextEffect), nextEffect.effectTag &= ~Placement$1; - var _current = nextEffect.alternate; - commitWork(_current, nextEffect); - break; - - case Update: - var _current2 = nextEffect.alternate; - commitWork(_current2, nextEffect); - break; - - case Deletion: - isUnmounting = !0, commitDeletion(nextEffect), isUnmounting = !1; - } - nextEffect = nextEffect.nextEffect; - } - } - function commitAllLifeCycles() { - for (;null !== nextEffect; ) { - var effectTag = nextEffect.effectTag; - if (effectTag & (Update | Callback)) { - var current = nextEffect.alternate; - commitLifeCycles(current, nextEffect); - } - effectTag & Ref && commitAttachRef(nextEffect), effectTag & Err && commitErrorHandling(nextEffect); - var next = nextEffect.nextEffect; - nextEffect.nextEffect = null, nextEffect = next; - } - } - function commitAllWork(finishedWork) { - isCommitting = !0, pendingCommit = null; - var root = finishedWork.stateNode; - invariant(root.current !== finishedWork, "Cannot commit the same tree as before. This is probably a bug " + "related to the return field. This error is likely caused by a bug " + "in React. Please file an issue."), - nextPriorityLevel !== SynchronousPriority$1 && nextPriorityLevel !== TaskPriority$1 || nestedUpdateCount++, - ReactCurrentOwner$1.current = null; - var firstEffect = void 0; - for (finishedWork.effectTag > PerformedWork ? null !== finishedWork.lastEffect ? (finishedWork.lastEffect.nextEffect = finishedWork, - firstEffect = finishedWork.firstEffect) : firstEffect = finishedWork : firstEffect = finishedWork.firstEffect, - prepareForCommit(), nextEffect = firstEffect; null !== nextEffect; ) { - var didError = !1, _error = void 0; - try { - commitAllHostEffects(); - } catch (e) { - didError = !0, _error = e; - } - didError && (invariant(null !== nextEffect, "Should have next effect. This error is likely caused by a bug " + "in React. Please file an issue."), - captureError(nextEffect, _error), null !== nextEffect && (nextEffect = nextEffect.nextEffect)); - } - for (resetAfterCommit(), root.current = finishedWork, nextEffect = firstEffect; null !== nextEffect; ) { - var _didError = !1, _error2 = void 0; - try { - commitAllLifeCycles(); - } catch (e) { - _didError = !0, _error2 = e; - } - _didError && (invariant(null !== nextEffect, "Should have next effect. This error is likely caused by a bug " + "in React. Please file an issue."), - captureError(nextEffect, _error2), null !== nextEffect && (nextEffect = nextEffect.nextEffect)); - } - isCommitting = !1, "function" == typeof onCommitRoot && onCommitRoot(finishedWork.stateNode), - !1 && ReactFiberInstrumentation$1.debugTool && ReactFiberInstrumentation$1.debugTool.onCommitWork(finishedWork), - commitPhaseBoundaries && (commitPhaseBoundaries.forEach(scheduleErrorRecovery), - commitPhaseBoundaries = null), resetNextUnitOfWork(); - } - function resetWorkPriority(workInProgress, renderPriority) { - if (!(workInProgress.pendingWorkPriority !== NoWork$2 && workInProgress.pendingWorkPriority > renderPriority)) { - for (var newPriority = getUpdatePriority$1(workInProgress), child = workInProgress.child; null !== child; ) newPriority = largerPriority$1(newPriority, child.pendingWorkPriority), - child = child.sibling; - workInProgress.pendingWorkPriority = newPriority; - } - } - function completeUnitOfWork(workInProgress) { - for (;!0; ) { - var current = workInProgress.alternate, next = completeWork(current, workInProgress, nextPriorityLevel), returnFiber = workInProgress.return, siblingFiber = workInProgress.sibling; - if (resetWorkPriority(workInProgress, nextPriorityLevel), null !== next) return !1 && ReactFiberInstrumentation$1.debugTool && ReactFiberInstrumentation$1.debugTool.onCompleteWork(workInProgress), - next; - if (null !== returnFiber) { - null === returnFiber.firstEffect && (returnFiber.firstEffect = workInProgress.firstEffect), - null !== workInProgress.lastEffect && (null !== returnFiber.lastEffect && (returnFiber.lastEffect.nextEffect = workInProgress.firstEffect), - returnFiber.lastEffect = workInProgress.lastEffect); - workInProgress.effectTag > PerformedWork && (null !== returnFiber.lastEffect ? returnFiber.lastEffect.nextEffect = workInProgress : returnFiber.firstEffect = workInProgress, - returnFiber.lastEffect = workInProgress); - } - if (!1 && ReactFiberInstrumentation$1.debugTool && ReactFiberInstrumentation$1.debugTool.onCompleteWork(workInProgress), - null !== siblingFiber) return siblingFiber; - if (null === returnFiber) return pendingCommit = workInProgress, null; - workInProgress = returnFiber; - } - return null; - } - function performUnitOfWork(workInProgress) { - var current = workInProgress.alternate, next = beginWork(current, workInProgress, nextPriorityLevel); - return !1 && ReactFiberInstrumentation$1.debugTool && ReactFiberInstrumentation$1.debugTool.onBeginWork(workInProgress), - null === next && (next = completeUnitOfWork(workInProgress)), ReactCurrentOwner$1.current = null, - next; - } - function performFailedUnitOfWork(workInProgress) { - var current = workInProgress.alternate, next = beginFailedWork(current, workInProgress, nextPriorityLevel); - return !1 && ReactFiberInstrumentation$1.debugTool && ReactFiberInstrumentation$1.debugTool.onBeginWork(workInProgress), - null === next && (next = completeUnitOfWork(workInProgress)), ReactCurrentOwner$1.current = null, - next; - } - function performDeferredWork(deadline) { - performWork(OffscreenPriority, deadline); - } - function handleCommitPhaseErrors() { - if (null !== capturedErrors && capturedErrors.size > 0 && nextPriorityLevel === TaskPriority$1) for (;null !== nextUnitOfWork && (null !== (nextUnitOfWork = hasCapturedError(nextUnitOfWork) ? performFailedUnitOfWork(nextUnitOfWork) : performUnitOfWork(nextUnitOfWork)) || (invariant(null !== pendingCommit, "Should have a pending commit. This error is likely caused by " + "a bug in React. Please file an issue."), - priorityContext = TaskPriority$1, commitAllWork(pendingCommit), priorityContext = nextPriorityLevel, - null !== capturedErrors && 0 !== capturedErrors.size && nextPriorityLevel === TaskPriority$1)); ) ; - } - function workLoop(minPriorityLevel, deadline) { - if (null !== pendingCommit ? (priorityContext = TaskPriority$1, commitAllWork(pendingCommit), - handleCommitPhaseErrors()) : null === nextUnitOfWork && resetNextUnitOfWork(), !(nextPriorityLevel === NoWork$2 || nextPriorityLevel > minPriorityLevel)) { - priorityContext = nextPriorityLevel; - loop: do { - if (nextPriorityLevel <= TaskPriority$1) for (;null !== nextUnitOfWork && !(null === (nextUnitOfWork = performUnitOfWork(nextUnitOfWork)) && (invariant(null !== pendingCommit, "Should have a pending commit. This error is likely caused by " + "a bug in React. Please file an issue."), - priorityContext = TaskPriority$1, commitAllWork(pendingCommit), priorityContext = nextPriorityLevel, - handleCommitPhaseErrors(), nextPriorityLevel === NoWork$2 || nextPriorityLevel > minPriorityLevel || nextPriorityLevel > TaskPriority$1)); ) ; else if (null !== deadline) for (;null !== nextUnitOfWork && !deadlineHasExpired; ) if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) { - if (null === (nextUnitOfWork = performUnitOfWork(nextUnitOfWork))) if (invariant(null !== pendingCommit, "Should have a pending commit. This error is likely caused by " + "a bug in React. Please file an issue."), - deadline.timeRemaining() > timeHeuristicForUnitOfWork) { - if (priorityContext = TaskPriority$1, commitAllWork(pendingCommit), priorityContext = nextPriorityLevel, - handleCommitPhaseErrors(), nextPriorityLevel === NoWork$2 || nextPriorityLevel > minPriorityLevel || nextPriorityLevel < HighPriority) break; - } else deadlineHasExpired = !0; - } else deadlineHasExpired = !0; - switch (nextPriorityLevel) { - case SynchronousPriority$1: - case TaskPriority$1: - if (nextPriorityLevel <= minPriorityLevel) continue loop; - break loop; - - case HighPriority: - case LowPriority: - case OffscreenPriority: - if (null === deadline) break loop; - if (!deadlineHasExpired && nextPriorityLevel <= minPriorityLevel) continue loop; - break loop; - - case NoWork$2: - break loop; - - default: - invariant(!1, "Switch statement should be exhuastive. " + "This error is likely caused by a bug in React. Please file an issue."); - } - } while (!0); - } - } - function performWorkCatchBlock(failedWork, boundary, minPriorityLevel, deadline) { - unwindContexts(failedWork, boundary), nextUnitOfWork = performFailedUnitOfWork(boundary), - workLoop(minPriorityLevel, deadline); - } - function performWork(minPriorityLevel, deadline) { - invariant(!isPerformingWork, "performWork was called recursively. This error is likely caused " + "by a bug in React. Please file an issue."), - isPerformingWork = !0; - var previousPriorityContext = priorityContext, didError = !1, error = null; - try { - workLoop(minPriorityLevel, deadline); - } catch (e) { - didError = !0, error = e; - } - for (;didError; ) { - if (didFatal) { - firstUncaughtError = error; - break; - } - var failedWork = nextUnitOfWork; - if (null !== failedWork) { - var boundary = captureError(failedWork, error); - if (invariant(null !== boundary, "Should have found an error boundary. This error is likely " + "caused by a bug in React. Please file an issue."), - !didFatal) { - didError = !1, error = null; - try { - performWorkCatchBlock(failedWork, boundary, minPriorityLevel, deadline), error = null; - } catch (e) { - didError = !0, error = e; - continue; - } - break; - } - } else didFatal = !0; - } - priorityContext = previousPriorityContext, null !== deadline && (isCallbackScheduled = !1), - nextPriorityLevel > TaskPriority$1 && !isCallbackScheduled && (scheduleDeferredCallback(performDeferredWork), - isCallbackScheduled = !0); - var errorToThrow = firstUncaughtError; - if (isPerformingWork = !1, deadlineHasExpired = !1, didFatal = !1, firstUncaughtError = null, - capturedErrors = null, failedBoundaries = null, nextRenderedTree = null, nestedUpdateCount = 0, - null !== errorToThrow) throw errorToThrow; - } - function captureError(failedWork, error) { - ReactCurrentOwner$1.current = null; - var boundary = null, errorBoundaryFound = !1, willRetry = !1, errorBoundaryName = null; - if (failedWork.tag === HostRoot$4) boundary = failedWork, isFailedBoundary(failedWork) && (didFatal = !0); else for (var node = failedWork.return; null !== node && null === boundary; ) { - if (node.tag === ClassComponent$4) { - var instance = node.stateNode; - "function" == typeof instance.componentDidCatch && (errorBoundaryFound = !0, errorBoundaryName = getComponentName_1(node), - boundary = node, willRetry = !0); - } else node.tag === HostRoot$4 && (boundary = node); - if (isFailedBoundary(node)) { - if (isUnmounting) return null; - if (null !== commitPhaseBoundaries && (commitPhaseBoundaries.has(node) || null !== node.alternate && commitPhaseBoundaries.has(node.alternate))) return null; - boundary = null, willRetry = !1; - } - node = node.return; - } - if (null !== boundary) { - null === failedBoundaries && (failedBoundaries = new Set()), failedBoundaries.add(boundary); - var _componentStack = getStackAddendumByWorkInProgressFiber(failedWork), _componentName = getComponentName_1(failedWork); - null === capturedErrors && (capturedErrors = new Map()); - var capturedError = { - componentName: _componentName, - componentStack: _componentStack, - error: error, - errorBoundary: errorBoundaryFound ? boundary.stateNode : null, - errorBoundaryFound: errorBoundaryFound, - errorBoundaryName: errorBoundaryName, - willRetry: willRetry - }; - capturedErrors.set(boundary, capturedError); - try { - logCapturedError$1(capturedError); - } catch (e) { - console.error(e); - } - return isCommitting ? (null === commitPhaseBoundaries && (commitPhaseBoundaries = new Set()), - commitPhaseBoundaries.add(boundary)) : scheduleErrorRecovery(boundary), boundary; - } - return null === firstUncaughtError && (firstUncaughtError = error), null; - } - function hasCapturedError(fiber) { - return null !== capturedErrors && (capturedErrors.has(fiber) || null !== fiber.alternate && capturedErrors.has(fiber.alternate)); - } - function isFailedBoundary(fiber) { - return null !== failedBoundaries && (failedBoundaries.has(fiber) || null !== fiber.alternate && failedBoundaries.has(fiber.alternate)); - } - function commitErrorHandling(effectfulFiber) { - var capturedError = void 0; - switch (null !== capturedErrors && (capturedError = capturedErrors.get(effectfulFiber), - capturedErrors.delete(effectfulFiber), null == capturedError && null !== effectfulFiber.alternate && (effectfulFiber = effectfulFiber.alternate, - capturedError = capturedErrors.get(effectfulFiber), capturedErrors.delete(effectfulFiber))), - invariant(null != capturedError, "No error for given unit of work. This error is likely caused by a " + "bug in React. Please file an issue."), - effectfulFiber.tag) { - case ClassComponent$4: - var instance = effectfulFiber.stateNode, info = { - componentStack: capturedError.componentStack - }; - return void instance.componentDidCatch(capturedError.error, info); - - case HostRoot$4: - return void (null === firstUncaughtError && (firstUncaughtError = capturedError.error)); - - default: - invariant(!1, "Invalid type of work. This error is likely caused by a bug in " + "React. Please file an issue."); - } - } - function unwindContexts(from, to) { - for (var node = from; null !== node; ) { - switch (node.tag) { - case ClassComponent$4: - popContextProvider$1(node); - break; - - case HostComponent$3: - popHostContext(node); - break; - - case HostRoot$4: - case HostPortal$2: - popHostContainer(node); - } - if (node === to || node.alternate === to) break; - node = node.return; - } - } - function scheduleRoot(root, priorityLevel) { - priorityLevel !== NoWork$2 && (root.isScheduled || (root.isScheduled = !0, lastScheduledRoot ? (lastScheduledRoot.nextScheduledRoot = root, - lastScheduledRoot = root) : (nextScheduledRoot = root, lastScheduledRoot = root))); - } - function scheduleUpdate(fiber, priorityLevel) { - return scheduleUpdateImpl(fiber, priorityLevel, !1); - } - function scheduleUpdateImpl(fiber, priorityLevel, isErrorRecovery) { - nestedUpdateCount > NESTED_UPDATE_LIMIT && (didFatal = !0, invariant(!1, "Maximum update depth exceeded. This can happen when a " + "component repeatedly calls setState inside componentWillUpdate or " + "componentDidUpdate. React limits the number of nested updates to " + "prevent infinite loops.")), - !isPerformingWork && priorityLevel <= nextPriorityLevel && (nextUnitOfWork = null); - for (var node = fiber, shouldContinue = !0; null !== node && shouldContinue; ) { - if (shouldContinue = !1, (node.pendingWorkPriority === NoWork$2 || node.pendingWorkPriority > priorityLevel) && (shouldContinue = !0, - node.pendingWorkPriority = priorityLevel), null !== node.alternate && (node.alternate.pendingWorkPriority === NoWork$2 || node.alternate.pendingWorkPriority > priorityLevel) && (shouldContinue = !0, - node.alternate.pendingWorkPriority = priorityLevel), null === node.return) { - if (node.tag !== HostRoot$4) return; - if (scheduleRoot(node.stateNode, priorityLevel), !isPerformingWork) switch (priorityLevel) { - case SynchronousPriority$1: - isUnbatchingUpdates ? performWork(SynchronousPriority$1, null) : performWork(TaskPriority$1, null); - break; - - case TaskPriority$1: - invariant(isBatchingUpdates, "Task updates can only be scheduled as a nested update or " + "inside batchedUpdates."); - break; - - default: - isCallbackScheduled || (scheduleDeferredCallback(performDeferredWork), isCallbackScheduled = !0); - } - } - node = node.return; - } - } - function getPriorityContext(fiber, forceAsync) { - var priorityLevel = priorityContext; - return priorityLevel === NoWork$2 && (priorityLevel = !useSyncScheduling || fiber.internalContextTag & AsyncUpdates || forceAsync ? LowPriority : SynchronousPriority$1), - priorityLevel === SynchronousPriority$1 && (isPerformingWork || isBatchingUpdates) ? TaskPriority$1 : priorityLevel; - } - function scheduleErrorRecovery(fiber) { - scheduleUpdateImpl(fiber, TaskPriority$1, !0); - } - function batchedUpdates(fn, a) { - var previousIsBatchingUpdates = isBatchingUpdates; - isBatchingUpdates = !0; - try { - return fn(a); - } finally { - isBatchingUpdates = previousIsBatchingUpdates, isPerformingWork || isBatchingUpdates || performWork(TaskPriority$1, null); - } - } - function unbatchedUpdates(fn) { - var previousIsUnbatchingUpdates = isUnbatchingUpdates, previousIsBatchingUpdates = isBatchingUpdates; - isUnbatchingUpdates = isBatchingUpdates, isBatchingUpdates = !1; - try { - return fn(); - } finally { - isBatchingUpdates = previousIsBatchingUpdates, isUnbatchingUpdates = previousIsUnbatchingUpdates; - } - } - function flushSync(batch) { - var previousIsBatchingUpdates = isBatchingUpdates, previousPriorityContext = priorityContext; - isBatchingUpdates = !0, priorityContext = SynchronousPriority$1; - try { - return batch(); - } finally { - isBatchingUpdates = previousIsBatchingUpdates, priorityContext = previousPriorityContext, - invariant(!isPerformingWork, "flushSync was called from inside a lifecycle method. It cannot be " + "called when React is already rendering."), - performWork(TaskPriority$1, null); - } - } - function deferredUpdates(fn) { - var previousPriorityContext = priorityContext; - priorityContext = LowPriority; - try { - return fn(); - } finally { - priorityContext = previousPriorityContext; - } - } - return { - scheduleUpdate: scheduleUpdate, - getPriorityContext: getPriorityContext, - batchedUpdates: batchedUpdates, - unbatchedUpdates: unbatchedUpdates, - flushSync: flushSync, - deferredUpdates: deferredUpdates - }; -}, addTopLevelUpdate = ReactFiberUpdateQueue.addTopLevelUpdate, findCurrentUnmaskedContext = ReactFiberContext.findCurrentUnmaskedContext, isContextProvider = ReactFiberContext.isContextProvider, processChildContext = ReactFiberContext.processChildContext, createFiberRoot = ReactFiberRoot.createFiberRoot, HostComponent = ReactTypeOfWork.HostComponent, findCurrentHostFiber = ReactFiberTreeReflection.findCurrentHostFiber, findCurrentHostFiberWithNoPortals = ReactFiberTreeReflection.findCurrentHostFiberWithNoPortals; - -function getContextForSubtree(parentComponent) { - if (!parentComponent) return emptyObject; - var fiber = ReactInstanceMap_1.get(parentComponent), parentContext = findCurrentUnmaskedContext(fiber); - return isContextProvider(fiber) ? processChildContext(fiber, parentContext) : parentContext; -} - -var ReactFiberReconciler = function(config) { - var getPublicInstance = config.getPublicInstance, _ReactFiberScheduler = ReactFiberScheduler(config), scheduleUpdate = _ReactFiberScheduler.scheduleUpdate, getPriorityContext = _ReactFiberScheduler.getPriorityContext, batchedUpdates = _ReactFiberScheduler.batchedUpdates, unbatchedUpdates = _ReactFiberScheduler.unbatchedUpdates, flushSync = _ReactFiberScheduler.flushSync, deferredUpdates = _ReactFiberScheduler.deferredUpdates; - function scheduleTopLevelUpdate(current, element, callback) { - var forceAsync = ReactFeatureFlags_1.enableAsyncSubtreeAPI && null != element && null != element.type && null != element.type.prototype && !0 === element.type.prototype.unstable_isAsyncReactComponent, priorityLevel = getPriorityContext(current, forceAsync), nextState = { - element: element - }; - callback = void 0 === callback ? null : callback, addTopLevelUpdate(current, nextState, callback, priorityLevel), - scheduleUpdate(current, priorityLevel); - } - return { - createContainer: function(containerInfo) { - return createFiberRoot(containerInfo); - }, - updateContainer: function(element, container, parentComponent, callback) { - var current = container.current, context = getContextForSubtree(parentComponent); - null === container.context ? container.context = context : container.pendingContext = context, - scheduleTopLevelUpdate(current, element, callback); - }, - batchedUpdates: batchedUpdates, - unbatchedUpdates: unbatchedUpdates, - deferredUpdates: deferredUpdates, - flushSync: flushSync, - getPublicRootInstance: function(container) { - var containerFiber = container.current; - if (!containerFiber.child) return null; - switch (containerFiber.child.tag) { - case HostComponent: - return getPublicInstance(containerFiber.child.stateNode); - - default: - return containerFiber.child.stateNode; - } - }, - findHostInstance: function(fiber) { - var hostFiber = findCurrentHostFiber(fiber); - return null === hostFiber ? null : hostFiber.stateNode; - }, - findHostInstanceWithNoPortals: function(fiber) { - var hostFiber = findCurrentHostFiberWithNoPortals(fiber); - return null === hostFiber ? null : hostFiber.stateNode; - } - }; -}; - -function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function"); -} - -var objects = {}, uniqueID = 1, emptyObject$3 = {}, ReactNativePropRegistry = function() { - function ReactNativePropRegistry() { - _classCallCheck(this, ReactNativePropRegistry); - } - return ReactNativePropRegistry.register = function(object) { - var id = ++uniqueID; - return objects[id] = object, id; - }, ReactNativePropRegistry.getByID = function(id) { - if (!id) return emptyObject$3; - var object = objects[id]; - return object || (console.warn("Invalid style with id `" + id + "`. Skipping ..."), - emptyObject$3); - }, ReactNativePropRegistry; -}(), ReactNativePropRegistry_1 = ReactNativePropRegistry, emptyObject$2 = {}, removedKeys = null, removedKeyCount = 0; - -function defaultDiffer(prevProp, nextProp) { - return "object" != typeof nextProp || null === nextProp || deepDiffer(prevProp, nextProp); -} - -function resolveObject(idOrObject) { - return "number" == typeof idOrObject ? ReactNativePropRegistry_1.getByID(idOrObject) : idOrObject; -} - -function restoreDeletedValuesInNestedArray(updatePayload, node, validAttributes) { - if (Array.isArray(node)) for (var i = node.length; i-- && removedKeyCount > 0; ) restoreDeletedValuesInNestedArray(updatePayload, node[i], validAttributes); else if (node && removedKeyCount > 0) { - var obj = resolveObject(node); - for (var propKey in removedKeys) if (removedKeys[propKey]) { - var nextProp = obj[propKey]; - if (void 0 !== nextProp) { - var attributeConfig = validAttributes[propKey]; - if (attributeConfig) { - if ("function" == typeof nextProp && (nextProp = !0), void 0 === nextProp && (nextProp = null), - "object" != typeof attributeConfig) updatePayload[propKey] = nextProp; else if ("function" == typeof attributeConfig.diff || "function" == typeof attributeConfig.process) { - var nextValue = "function" == typeof attributeConfig.process ? attributeConfig.process(nextProp) : nextProp; - updatePayload[propKey] = nextValue; - } - removedKeys[propKey] = !1, removedKeyCount--; - } - } - } - } -} - -function diffNestedArrayProperty(updatePayload, prevArray, nextArray, validAttributes) { - var i, minLength = prevArray.length < nextArray.length ? prevArray.length : nextArray.length; - for (i = 0; i < minLength; i++) updatePayload = diffNestedProperty(updatePayload, prevArray[i], nextArray[i], validAttributes); - for (;i < prevArray.length; i++) updatePayload = clearNestedProperty(updatePayload, prevArray[i], validAttributes); - for (;i < nextArray.length; i++) updatePayload = addNestedProperty(updatePayload, nextArray[i], validAttributes); - return updatePayload; -} - -function diffNestedProperty(updatePayload, prevProp, nextProp, validAttributes) { - return updatePayload || prevProp !== nextProp ? prevProp && nextProp ? Array.isArray(prevProp) || Array.isArray(nextProp) ? Array.isArray(prevProp) && Array.isArray(nextProp) ? diffNestedArrayProperty(updatePayload, prevProp, nextProp, validAttributes) : Array.isArray(prevProp) ? diffProperties(updatePayload, flattenStyle(prevProp), resolveObject(nextProp), validAttributes) : diffProperties(updatePayload, resolveObject(prevProp), flattenStyle(nextProp), validAttributes) : diffProperties(updatePayload, resolveObject(prevProp), resolveObject(nextProp), validAttributes) : nextProp ? addNestedProperty(updatePayload, nextProp, validAttributes) : prevProp ? clearNestedProperty(updatePayload, prevProp, validAttributes) : updatePayload : updatePayload; -} - -function addNestedProperty(updatePayload, nextProp, validAttributes) { - if (!nextProp) return updatePayload; - if (!Array.isArray(nextProp)) return addProperties(updatePayload, resolveObject(nextProp), validAttributes); - for (var i = 0; i < nextProp.length; i++) updatePayload = addNestedProperty(updatePayload, nextProp[i], validAttributes); - return updatePayload; -} - -function clearNestedProperty(updatePayload, prevProp, validAttributes) { - if (!prevProp) return updatePayload; - if (!Array.isArray(prevProp)) return clearProperties(updatePayload, resolveObject(prevProp), validAttributes); - for (var i = 0; i < prevProp.length; i++) updatePayload = clearNestedProperty(updatePayload, prevProp[i], validAttributes); - return updatePayload; -} - -function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { - var attributeConfig, nextProp, prevProp; - for (var propKey in nextProps) if (attributeConfig = validAttributes[propKey]) if (prevProp = prevProps[propKey], - nextProp = nextProps[propKey], "function" == typeof nextProp && (nextProp = !0, - "function" == typeof prevProp && (prevProp = !0)), void 0 === nextProp && (nextProp = null, - void 0 === prevProp && (prevProp = null)), removedKeys && (removedKeys[propKey] = !1), - updatePayload && void 0 !== updatePayload[propKey]) { - if ("object" != typeof attributeConfig) updatePayload[propKey] = nextProp; else if ("function" == typeof attributeConfig.diff || "function" == typeof attributeConfig.process) { - var nextValue = "function" == typeof attributeConfig.process ? attributeConfig.process(nextProp) : nextProp; - updatePayload[propKey] = nextValue; - } - } else if (prevProp !== nextProp) if ("object" != typeof attributeConfig) defaultDiffer(prevProp, nextProp) && ((updatePayload || (updatePayload = {}))[propKey] = nextProp); else if ("function" == typeof attributeConfig.diff || "function" == typeof attributeConfig.process) { - var shouldUpdate = void 0 === prevProp || ("function" == typeof attributeConfig.diff ? attributeConfig.diff(prevProp, nextProp) : defaultDiffer(prevProp, nextProp)); - shouldUpdate && (nextValue = "function" == typeof attributeConfig.process ? attributeConfig.process(nextProp) : nextProp, - (updatePayload || (updatePayload = {}))[propKey] = nextValue); - } else removedKeys = null, removedKeyCount = 0, updatePayload = diffNestedProperty(updatePayload, prevProp, nextProp, attributeConfig), - removedKeyCount > 0 && updatePayload && (restoreDeletedValuesInNestedArray(updatePayload, nextProp, attributeConfig), - removedKeys = null); - for (propKey in prevProps) void 0 === nextProps[propKey] && (attributeConfig = validAttributes[propKey]) && (updatePayload && void 0 !== updatePayload[propKey] || void 0 !== (prevProp = prevProps[propKey]) && ("object" != typeof attributeConfig || "function" == typeof attributeConfig.diff || "function" == typeof attributeConfig.process ? ((updatePayload || (updatePayload = {}))[propKey] = null, - removedKeys || (removedKeys = {}), removedKeys[propKey] || (removedKeys[propKey] = !0, - removedKeyCount++)) : updatePayload = clearNestedProperty(updatePayload, prevProp, attributeConfig))); - return updatePayload; -} - -function addProperties(updatePayload, props, validAttributes) { - return diffProperties(updatePayload, emptyObject$2, props, validAttributes); -} - -function clearProperties(updatePayload, prevProps, validAttributes) { - return diffProperties(updatePayload, prevProps, emptyObject$2, validAttributes); -} - -var ReactNativeAttributePayload = { - create: function(props, validAttributes) { - return addProperties(null, props, validAttributes); - }, - diff: function(prevProps, nextProps, validAttributes) { - return diffProperties(null, prevProps, nextProps, validAttributes); - } -}, ReactNativeAttributePayload_1 = ReactNativeAttributePayload; - -function mountSafeCallback$1(context, callback) { - return function() { - if (callback) { - if ("boolean" == typeof context.__isMounted) { - if (!context.__isMounted) return; - } else if ("function" == typeof context.isMounted && !context.isMounted()) return; - return callback.apply(context, arguments); - } - }; -} - -function throwOnStylesProp(component, props) { - if (void 0 !== props.styles) { - var owner = component._owner || null, name = component.constructor.displayName, msg = "`styles` is not a supported property of `" + name + "`, did " + "you mean `style` (singular)?"; - throw owner && owner.constructor && owner.constructor.displayName && (msg += "\n\nCheck the `" + owner.constructor.displayName + "` parent " + " component."), - new Error(msg); - } -} - -function warnForStyleProps$1(props, validAttributes) { - for (var key in validAttributes.style) validAttributes[key] || void 0 === props[key] || console.error("You are setting the style `{ " + key + ": ... }` as a prop. You " + "should nest it in a style object. " + "E.g. `{ style: { " + key + ": ... } }`"); -} - -var NativeMethodsMixinUtils = { - mountSafeCallback: mountSafeCallback$1, - throwOnStylesProp: throwOnStylesProp, - warnForStyleProps: warnForStyleProps$1 -}; - -function _classCallCheck$1(instance, Constructor) { - if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function"); -} - -var mountSafeCallback = NativeMethodsMixinUtils.mountSafeCallback, ReactNativeFiberHostComponent = function() { - function ReactNativeFiberHostComponent(tag, viewConfig) { - _classCallCheck$1(this, ReactNativeFiberHostComponent), this._nativeTag = tag, this._children = [], - this.viewConfig = viewConfig; - } - return ReactNativeFiberHostComponent.prototype.blur = function() { - TextInputState.blurTextInput(this._nativeTag); - }, ReactNativeFiberHostComponent.prototype.focus = function() { - TextInputState.focusTextInput(this._nativeTag); - }, ReactNativeFiberHostComponent.prototype.measure = function(callback) { - UIManager.measure(this._nativeTag, mountSafeCallback(this, callback)); - }, ReactNativeFiberHostComponent.prototype.measureInWindow = function(callback) { - UIManager.measureInWindow(this._nativeTag, mountSafeCallback(this, callback)); - }, ReactNativeFiberHostComponent.prototype.measureLayout = function(relativeToNativeNode, onSuccess, onFail) { - UIManager.measureLayout(this._nativeTag, relativeToNativeNode, mountSafeCallback(this, onFail), mountSafeCallback(this, onSuccess)); - }, ReactNativeFiberHostComponent.prototype.setNativeProps = function(nativeProps) { - var updatePayload = ReactNativeAttributePayload_1.create(nativeProps, this.viewConfig.validAttributes); - null != updatePayload && UIManager.updateView(this._nativeTag, this.viewConfig.uiViewClassName, updatePayload); - }, ReactNativeFiberHostComponent; -}(), ReactNativeFiberHostComponent_1 = ReactNativeFiberHostComponent, INITIAL_TAG_COUNT = 1, ReactNativeTagHandles = { - tagsStartAt: INITIAL_TAG_COUNT, - tagCount: INITIAL_TAG_COUNT, - allocateTag: function() { - for (;this.reactTagIsNativeTopRootID(ReactNativeTagHandles.tagCount); ) ReactNativeTagHandles.tagCount++; - var tag = ReactNativeTagHandles.tagCount; - return ReactNativeTagHandles.tagCount++, tag; - }, - assertRootTag: function(tag) { - invariant(this.reactTagIsNativeTopRootID(tag), "Expect a native root tag, instead got %s", tag); - }, - reactTagIsNativeTopRootID: function(reactTag) { - return reactTag % 10 == 1; - } -}, ReactNativeTagHandles_1 = ReactNativeTagHandles, viewConfigCallbacks = new Map(), viewConfigs = new Map(), ReactNativeViewConfigRegistry = { - register: function(name, callback) { - return invariant(!viewConfigCallbacks.has(name), "Tried to register two views with the same name %s", name), - viewConfigCallbacks.set(name, callback), name; - }, - get: function(name) { - var viewConfig = void 0; - if (viewConfigs.has(name)) viewConfig = viewConfigs.get(name); else { - var callback = viewConfigCallbacks.get(name); - invariant("function" == typeof callback, "View config not found for name %s", name), - viewConfigCallbacks.set(name, null), viewConfig = callback(), viewConfigs.set(name, viewConfig); - } - return invariant(viewConfig, "View config not found for name %s", name), viewConfig; - } -}, ReactNativeViewConfigRegistry_1 = ReactNativeViewConfigRegistry, precacheFiberNode$1 = ReactNativeComponentTree_1.precacheFiberNode, uncacheFiberNode$1 = ReactNativeComponentTree_1.uncacheFiberNode, updateFiberProps$1 = ReactNativeComponentTree_1.updateFiberProps; - -function recursivelyUncacheFiberNode(node) { - "number" == typeof node ? uncacheFiberNode$1(node) : (uncacheFiberNode$1(node._nativeTag), - node._children.forEach(recursivelyUncacheFiberNode)); -} - -var NativeRenderer = ReactFiberReconciler({ - appendChild: function(parentInstance, child) { - var childTag = "number" == typeof child ? child : child._nativeTag, children = parentInstance._children, index = children.indexOf(child); - index >= 0 ? (children.splice(index, 1), children.push(child), UIManager.manageChildren(parentInstance._nativeTag, [ index ], [ children.length - 1 ], [], [], [])) : (children.push(child), - UIManager.manageChildren(parentInstance._nativeTag, [], [], [ childTag ], [ children.length - 1 ], [])); - }, - appendChildToContainer: function(parentInstance, child) { - var childTag = "number" == typeof child ? child : child._nativeTag; - UIManager.setChildren(parentInstance, [ childTag ]); - }, - appendInitialChild: function(parentInstance, child) { - parentInstance._children.push(child); - }, - commitTextUpdate: function(textInstance, oldText, newText) { - UIManager.updateView(textInstance, "RCTRawText", { - text: newText - }); - }, - commitMount: function(instance, type, newProps, internalInstanceHandle) {}, - commitUpdate: function(instance, updatePayloadTODO, type, oldProps, newProps, internalInstanceHandle) { - var viewConfig = instance.viewConfig; - updateFiberProps$1(instance._nativeTag, newProps); - var updatePayload = ReactNativeAttributePayload_1.diff(oldProps, newProps, viewConfig.validAttributes); - null != updatePayload && UIManager.updateView(instance._nativeTag, viewConfig.uiViewClassName, updatePayload); - }, - createInstance: function(type, props, rootContainerInstance, hostContext, internalInstanceHandle) { - var tag = ReactNativeTagHandles_1.allocateTag(), viewConfig = ReactNativeViewConfigRegistry_1.get(type), updatePayload = ReactNativeAttributePayload_1.create(props, viewConfig.validAttributes); - UIManager.createView(tag, viewConfig.uiViewClassName, rootContainerInstance, updatePayload); - var component = new ReactNativeFiberHostComponent_1(tag, viewConfig); - return precacheFiberNode$1(internalInstanceHandle, tag), updateFiberProps$1(tag, props), - component; - }, - createTextInstance: function(text, rootContainerInstance, hostContext, internalInstanceHandle) { - var tag = ReactNativeTagHandles_1.allocateTag(); - return UIManager.createView(tag, "RCTRawText", rootContainerInstance, { - text: text - }), precacheFiberNode$1(internalInstanceHandle, tag), tag; - }, - finalizeInitialChildren: function(parentInstance, type, props, rootContainerInstance) { - if (0 === parentInstance._children.length) return !1; - var nativeTags = parentInstance._children.map(function(child) { - return "number" == typeof child ? child : child._nativeTag; - }); - return UIManager.setChildren(parentInstance._nativeTag, nativeTags), !1; - }, - getRootHostContext: function() { - return emptyObject; - }, - getChildHostContext: function() { - return emptyObject; - }, - getPublicInstance: function(instance) { - return instance; - }, - insertBefore: function(parentInstance, child, beforeChild) { - var children = parentInstance._children, index = children.indexOf(child); - if (index >= 0) { - children.splice(index, 1); - var beforeChildIndex = children.indexOf(beforeChild); - children.splice(beforeChildIndex, 0, child), UIManager.manageChildren(parentInstance._nativeTag, [ index ], [ beforeChildIndex ], [], [], []); - } else { - var _beforeChildIndex = children.indexOf(beforeChild); - children.splice(_beforeChildIndex, 0, child); - var childTag = "number" == typeof child ? child : child._nativeTag; - UIManager.manageChildren(parentInstance._nativeTag, [], [], [ childTag ], [ _beforeChildIndex ], []); - } - }, - insertInContainerBefore: function(parentInstance, child, beforeChild) { - invariant("number" != typeof parentInstance, "Container does not support insertBefore operation"); - }, - prepareForCommit: function() {}, - prepareUpdate: function(instance, type, oldProps, newProps, rootContainerInstance, hostContext) { - return emptyObject; - }, - removeChild: function(parentInstance, child) { - recursivelyUncacheFiberNode(child); - var children = parentInstance._children, index = children.indexOf(child); - children.splice(index, 1), UIManager.manageChildren(parentInstance._nativeTag, [], [], [], [], [ index ]); - }, - removeChildFromContainer: function(parentInstance, child) { - recursivelyUncacheFiberNode(child), UIManager.manageChildren(parentInstance, [], [], [], [], [ 0 ]); - }, - resetAfterCommit: function() {}, - resetTextContent: function(instance) {}, - shouldDeprioritizeSubtree: function(type, props) { - return !1; - }, - scheduleDeferredCallback: commonjsGlobal.requestIdleCallback, - shouldSetTextContent: function(type, props) { - return !1; - }, - useSyncScheduling: !0 -}), ReactNativeFiberRenderer = NativeRenderer, getInspectorDataForViewTag = void 0; - -getInspectorDataForViewTag = function() { - invariant(!1, "getInspectorDataForViewTag() is not available in production"); -}; - -var ReactNativeFiberInspector = { - getInspectorDataForViewTag: getInspectorDataForViewTag -}, ReactVersion = "16.0.0"; - -function findNodeHandle(componentOrHandle) { - if (null == componentOrHandle) return null; - if ("number" == typeof componentOrHandle) return componentOrHandle; - var component = componentOrHandle, internalInstance = ReactInstanceMap_1.get(component); - return internalInstance ? ReactNativeFiberRenderer.findHostInstance(internalInstance) : component || (invariant("object" == typeof component && "_nativeTag" in component || null != component.render && "function" == typeof component.render, "findNodeHandle(...): Argument is not a component " + "(type: %s, keys: %s)", typeof component, Object.keys(component)), - void invariant(!1, "findNodeHandle(...): Unable to find node handle for unmounted " + "component.")); -} - -var findNodeHandle_1 = findNodeHandle, findNumericNodeHandle = function(componentOrHandle) { - var instance = findNodeHandle_1(componentOrHandle); - return null == instance || "number" == typeof instance ? instance : instance._nativeTag; -}, eventPluginOrder = null, namesToPlugins = {}; - -function recomputePluginOrdering() { - if (eventPluginOrder) for (var pluginName in namesToPlugins) { - var pluginModule = namesToPlugins[pluginName], pluginIndex = eventPluginOrder.indexOf(pluginName); - if (invariant(pluginIndex > -1, "EventPluginRegistry: Cannot inject event plugins that do not exist in " + "the plugin ordering, `%s`.", pluginName), - !EventPluginRegistry.plugins[pluginIndex]) { - invariant(pluginModule.extractEvents, "EventPluginRegistry: Event plugins must implement an `extractEvents` " + "method, but `%s` does not.", pluginName), - EventPluginRegistry.plugins[pluginIndex] = pluginModule; - var publishedEvents = pluginModule.eventTypes; - for (var eventName in publishedEvents) invariant(publishEventForPlugin(publishedEvents[eventName], pluginModule, eventName), "EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.", eventName, pluginName); - } - } -} - -function publishEventForPlugin(dispatchConfig, pluginModule, eventName) { - invariant(!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName), "EventPluginHub: More than one plugin attempted to publish the same " + "event name, `%s`.", eventName), - EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig; - var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; - if (phasedRegistrationNames) { - for (var phaseName in phasedRegistrationNames) if (phasedRegistrationNames.hasOwnProperty(phaseName)) { - var phasedRegistrationName = phasedRegistrationNames[phaseName]; - publishRegistrationName(phasedRegistrationName, pluginModule, eventName); - } - return !0; - } - return !!dispatchConfig.registrationName && (publishRegistrationName(dispatchConfig.registrationName, pluginModule, eventName), - !0); -} - -function publishRegistrationName(registrationName, pluginModule, eventName) { - invariant(!EventPluginRegistry.registrationNameModules[registrationName], "EventPluginHub: More than one plugin attempted to publish the same " + "registration name, `%s`.", registrationName), - EventPluginRegistry.registrationNameModules[registrationName] = pluginModule, EventPluginRegistry.registrationNameDependencies[registrationName] = pluginModule.eventTypes[eventName].dependencies; -} - -var EventPluginRegistry = { - plugins: [], - eventNameDispatchConfigs: {}, - registrationNameModules: {}, - registrationNameDependencies: {}, - possibleRegistrationNames: null, - injectEventPluginOrder: function(injectedEventPluginOrder) { - invariant(!eventPluginOrder, "EventPluginRegistry: Cannot inject event plugin ordering more than " + "once. You are likely trying to load more than one copy of React."), - eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder), recomputePluginOrdering(); - }, - injectEventPluginsByName: function(injectedNamesToPlugins) { - var isOrderingDirty = !1; - for (var pluginName in injectedNamesToPlugins) if (injectedNamesToPlugins.hasOwnProperty(pluginName)) { - var pluginModule = injectedNamesToPlugins[pluginName]; - namesToPlugins.hasOwnProperty(pluginName) && namesToPlugins[pluginName] === pluginModule || (invariant(!namesToPlugins[pluginName], "EventPluginRegistry: Cannot inject two different event plugins " + "using the same name, `%s`.", pluginName), - namesToPlugins[pluginName] = pluginModule, isOrderingDirty = !0); - } - isOrderingDirty && recomputePluginOrdering(); - } -}, EventPluginRegistry_1 = EventPluginRegistry; - -function accumulateInto(current, next) { - return invariant(null != next, "accumulateInto(...): Accumulated items must not be null or undefined."), - null == current ? next : Array.isArray(current) ? Array.isArray(next) ? (current.push.apply(current, next), - current) : (current.push(next), current) : Array.isArray(next) ? [ current ].concat(next) : [ current, next ]; -} - -var accumulateInto_1 = accumulateInto; - -function forEachAccumulated(arr, cb, scope) { - Array.isArray(arr) ? arr.forEach(cb, scope) : arr && cb.call(scope, arr); -} - -var forEachAccumulated_1 = forEachAccumulated, eventQueue = null, executeDispatchesAndRelease = function(event, simulated) { - event && (EventPluginUtils_1.executeDispatchesInOrder(event, simulated), event.isPersistent() || event.constructor.release(event)); -}, executeDispatchesAndReleaseSimulated = function(e) { - return executeDispatchesAndRelease(e, !0); -}, executeDispatchesAndReleaseTopLevel = function(e) { - return executeDispatchesAndRelease(e, !1); -}; - -function isInteractive(tag) { - return "button" === tag || "input" === tag || "select" === tag || "textarea" === tag; -} - -function shouldPreventMouseEvent(name, type, props) { - switch (name) { - case "onClick": - case "onClickCapture": - case "onDoubleClick": - case "onDoubleClickCapture": - case "onMouseDown": - case "onMouseDownCapture": - case "onMouseMove": - case "onMouseMoveCapture": - case "onMouseUp": - case "onMouseUpCapture": - return !(!props.disabled || !isInteractive(type)); - - default: - return !1; - } -} - -var EventPluginHub = { - injection: { - injectEventPluginOrder: EventPluginRegistry_1.injectEventPluginOrder, - injectEventPluginsByName: EventPluginRegistry_1.injectEventPluginsByName - }, - getListener: function(inst, registrationName) { - var listener, stateNode = inst.stateNode; - if (!stateNode) return null; - var props = EventPluginUtils_1.getFiberCurrentPropsFromNode(stateNode); - return props ? (listener = props[registrationName], shouldPreventMouseEvent(registrationName, inst.type, props) ? null : (invariant(!listener || "function" == typeof listener, "Expected `%s` listener to be a function, instead got a value of `%s` type.", registrationName, typeof listener), - listener)) : null; - }, - extractEvents: function(topLevelType, targetInst, nativeEvent, nativeEventTarget) { - for (var events, plugins = EventPluginRegistry_1.plugins, i = 0; i < plugins.length; i++) { - var possiblePlugin = plugins[i]; - if (possiblePlugin) { - var extractedEvents = possiblePlugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget); - extractedEvents && (events = accumulateInto_1(events, extractedEvents)); - } - } - return events; - }, - enqueueEvents: function(events) { - events && (eventQueue = accumulateInto_1(eventQueue, events)); - }, - processEventQueue: function(simulated) { - var processingEventQueue = eventQueue; - eventQueue = null, simulated ? forEachAccumulated_1(processingEventQueue, executeDispatchesAndReleaseSimulated) : forEachAccumulated_1(processingEventQueue, executeDispatchesAndReleaseTopLevel), - invariant(!eventQueue, "processEventQueue(): Additional events were enqueued while processing " + "an event queue. Support for this has not yet been implemented."), - ReactErrorUtils_1.rethrowCaughtError(); - } -}, EventPluginHub_1 = EventPluginHub, HostComponent$10 = ReactTypeOfWork.HostComponent; - -function getParent(inst) { - do { - inst = inst.return; - } while (inst && inst.tag !== HostComponent$10); - return inst || null; -} - -function getLowestCommonAncestor(instA, instB) { - for (var depthA = 0, tempA = instA; tempA; tempA = getParent(tempA)) depthA++; - for (var depthB = 0, tempB = instB; tempB; tempB = getParent(tempB)) depthB++; - for (;depthA - depthB > 0; ) instA = getParent(instA), depthA--; - for (;depthB - depthA > 0; ) instB = getParent(instB), depthB--; - for (var depth = depthA; depth--; ) { - if (instA === instB || instA === instB.alternate) return instA; - instA = getParent(instA), instB = getParent(instB); - } - return null; -} - -function isAncestor(instA, instB) { - for (;instB; ) { - if (instA === instB || instA === instB.alternate) return !0; - instB = getParent(instB); - } - return !1; -} - -function getParentInstance(inst) { - return getParent(inst); -} - -function traverseTwoPhase(inst, fn, arg) { - for (var path = []; inst; ) path.push(inst), inst = getParent(inst); - var i; - for (i = path.length; i-- > 0; ) fn(path[i], "captured", arg); - for (i = 0; i < path.length; i++) fn(path[i], "bubbled", arg); -} - -function traverseEnterLeave(from, to, fn, argFrom, argTo) { - for (var common = from && to ? getLowestCommonAncestor(from, to) : null, pathFrom = []; from && from !== common; ) pathFrom.push(from), - from = getParent(from); - for (var pathTo = []; to && to !== common; ) pathTo.push(to), to = getParent(to); - var i; - for (i = 0; i < pathFrom.length; i++) fn(pathFrom[i], "bubbled", argFrom); - for (i = pathTo.length; i-- > 0; ) fn(pathTo[i], "captured", argTo); -} - -var ReactTreeTraversal = { - isAncestor: isAncestor, - getLowestCommonAncestor: getLowestCommonAncestor, - getParentInstance: getParentInstance, - traverseTwoPhase: traverseTwoPhase, - traverseEnterLeave: traverseEnterLeave -}, getListener = EventPluginHub_1.getListener; - -function listenerAtPhase(inst, event, propagationPhase) { - var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase]; - return getListener(inst, registrationName); -} - -function accumulateDirectionalDispatches(inst, phase, event) { - var listener = listenerAtPhase(inst, event, phase); - listener && (event._dispatchListeners = accumulateInto_1(event._dispatchListeners, listener), - event._dispatchInstances = accumulateInto_1(event._dispatchInstances, inst)); -} - -function accumulateTwoPhaseDispatchesSingle(event) { - event && event.dispatchConfig.phasedRegistrationNames && ReactTreeTraversal.traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); -} - -function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - var targetInst = event._targetInst, parentInst = targetInst ? ReactTreeTraversal.getParentInstance(targetInst) : null; - ReactTreeTraversal.traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event); - } -} - -function accumulateDispatches(inst, ignoredDirection, event) { - if (inst && event && event.dispatchConfig.registrationName) { - var registrationName = event.dispatchConfig.registrationName, listener = getListener(inst, registrationName); - listener && (event._dispatchListeners = accumulateInto_1(event._dispatchListeners, listener), - event._dispatchInstances = accumulateInto_1(event._dispatchInstances, inst)); - } -} - -function accumulateDirectDispatchesSingle(event) { - event && event.dispatchConfig.registrationName && accumulateDispatches(event._targetInst, null, event); -} - -function accumulateTwoPhaseDispatches(events) { - forEachAccumulated_1(events, accumulateTwoPhaseDispatchesSingle); -} - -function accumulateTwoPhaseDispatchesSkipTarget(events) { - forEachAccumulated_1(events, accumulateTwoPhaseDispatchesSingleSkipTarget); -} - -function accumulateEnterLeaveDispatches(leave, enter, from, to) { - ReactTreeTraversal.traverseEnterLeave(from, to, accumulateDispatches, leave, enter); -} - -function accumulateDirectDispatches(events) { - forEachAccumulated_1(events, accumulateDirectDispatchesSingle); -} - -var EventPropagators = { - accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches, - accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget, - accumulateDirectDispatches: accumulateDirectDispatches, - accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches -}, EventPropagators_1 = EventPropagators, EVENT_POOL_SIZE = 10, shouldBeReleasedProperties = [ "dispatchConfig", "_targetInst", "nativeEvent", "isDefaultPrevented", "isPropagationStopped", "_dispatchListeners", "_dispatchInstances" ], EventInterface = { - type: null, - target: null, - currentTarget: emptyFunction.thatReturnsNull, - eventPhase: null, - bubbles: null, - cancelable: null, - timeStamp: function(event) { - return event.timeStamp || Date.now(); - }, - defaultPrevented: null, - isTrusted: null -}; - -function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) { - this.dispatchConfig = dispatchConfig, this._targetInst = targetInst, this.nativeEvent = nativeEvent; - var Interface = this.constructor.Interface; - for (var propName in Interface) if (Interface.hasOwnProperty(propName)) { - var normalize = Interface[propName]; - normalize ? this[propName] = normalize(nativeEvent) : "target" === propName ? this.target = nativeEventTarget : this[propName] = nativeEvent[propName]; - } - var defaultPrevented = null != nativeEvent.defaultPrevented ? nativeEvent.defaultPrevented : !1 === nativeEvent.returnValue; - return this.isDefaultPrevented = defaultPrevented ? emptyFunction.thatReturnsTrue : emptyFunction.thatReturnsFalse, - this.isPropagationStopped = emptyFunction.thatReturnsFalse, this; -} - -Object.assign(SyntheticEvent.prototype, { - preventDefault: function() { - this.defaultPrevented = !0; - var event = this.nativeEvent; - event && (event.preventDefault ? event.preventDefault() : "unknown" != typeof event.returnValue && (event.returnValue = !1), - this.isDefaultPrevented = emptyFunction.thatReturnsTrue); - }, - stopPropagation: function() { - var event = this.nativeEvent; - event && (event.stopPropagation ? event.stopPropagation() : "unknown" != typeof event.cancelBubble && (event.cancelBubble = !0), - this.isPropagationStopped = emptyFunction.thatReturnsTrue); - }, - persist: function() { - this.isPersistent = emptyFunction.thatReturnsTrue; - }, - isPersistent: emptyFunction.thatReturnsFalse, - destructor: function() { - var Interface = this.constructor.Interface; - for (var propName in Interface) this[propName] = null; - for (var i = 0; i < shouldBeReleasedProperties.length; i++) this[shouldBeReleasedProperties[i]] = null; - } -}), SyntheticEvent.Interface = EventInterface, SyntheticEvent.augmentClass = function(Class, Interface) { - var Super = this, E = function() {}; - E.prototype = Super.prototype; - var prototype = new E(); - Object.assign(prototype, Class.prototype), Class.prototype = prototype, Class.prototype.constructor = Class, - Class.Interface = Object.assign({}, Super.Interface, Interface), Class.augmentClass = Super.augmentClass, - addEventPoolingTo(Class); -}, addEventPoolingTo(SyntheticEvent); - -var SyntheticEvent_1 = SyntheticEvent; - -function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) { - var EventConstructor = this; - if (EventConstructor.eventPool.length) { - var instance = EventConstructor.eventPool.pop(); - return EventConstructor.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst), - instance; - } - return new EventConstructor(dispatchConfig, targetInst, nativeEvent, nativeInst); -} - -function releasePooledEvent(event) { - var EventConstructor = this; - invariant(event instanceof EventConstructor, "Trying to release an event instance into a pool of a different type."), - event.destructor(), EventConstructor.eventPool.length < EVENT_POOL_SIZE && EventConstructor.eventPool.push(event); -} - -function addEventPoolingTo(EventConstructor) { - EventConstructor.eventPool = [], EventConstructor.getPooled = getPooledEvent, EventConstructor.release = releasePooledEvent; -} - -var customBubblingEventTypes = {}, customDirectEventTypes = {}, ReactNativeBridgeEventPlugin = { - eventTypes: {}, - extractEvents: function(topLevelType, targetInst, nativeEvent, nativeEventTarget) { - var bubbleDispatchConfig = customBubblingEventTypes[topLevelType], directDispatchConfig = customDirectEventTypes[topLevelType]; - invariant(bubbleDispatchConfig || directDispatchConfig, 'Unsupported top level event type "%s" dispatched', topLevelType); - var event = SyntheticEvent_1.getPooled(bubbleDispatchConfig || directDispatchConfig, targetInst, nativeEvent, nativeEventTarget); - if (bubbleDispatchConfig) EventPropagators_1.accumulateTwoPhaseDispatches(event); else { - if (!directDispatchConfig) return null; - EventPropagators_1.accumulateDirectDispatches(event); - } - return event; - }, - processEventTypes: function(viewConfig) { - var bubblingEventTypes = viewConfig.bubblingEventTypes, directEventTypes = viewConfig.directEventTypes; - if (null != bubblingEventTypes) for (var _topLevelType in bubblingEventTypes) null == customBubblingEventTypes[_topLevelType] && (ReactNativeBridgeEventPlugin.eventTypes[_topLevelType] = customBubblingEventTypes[_topLevelType] = bubblingEventTypes[_topLevelType]); - if (null != directEventTypes) for (var _topLevelType2 in directEventTypes) null == customDirectEventTypes[_topLevelType2] && (ReactNativeBridgeEventPlugin.eventTypes[_topLevelType2] = customDirectEventTypes[_topLevelType2] = directEventTypes[_topLevelType2]); - } -}, ReactNativeBridgeEventPlugin_1 = ReactNativeBridgeEventPlugin; - -function runEventQueueInBatch(events) { - EventPluginHub_1.enqueueEvents(events), EventPluginHub_1.processEventQueue(!1); -} - -var ReactEventEmitterMixin = { - handleTopLevel: function(topLevelType, targetInst, nativeEvent, nativeEventTarget) { - runEventQueueInBatch(EventPluginHub_1.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget)); - } -}, ReactEventEmitterMixin_1 = ReactEventEmitterMixin, EMPTY_NATIVE_EVENT = {}, touchSubsequence = function(touches, indices) { - for (var ret = [], i = 0; i < indices.length; i++) ret.push(touches[indices[i]]); - return ret; -}, removeTouchesAtIndices = function(touches, indices) { - for (var rippedOut = [], temp = touches, i = 0; i < indices.length; i++) { - var index = indices[i]; - rippedOut.push(touches[index]), temp[index] = null; - } - for (var fillAt = 0, j = 0; j < temp.length; j++) { - var cur = temp[j]; - null !== cur && (temp[fillAt++] = cur); - } - return temp.length = fillAt, rippedOut; -}, ReactNativeEventEmitter = Object.assign({}, ReactEventEmitterMixin_1, { - registrationNames: EventPluginRegistry_1.registrationNameModules, - getListener: EventPluginHub_1.getListener, - _receiveRootNodeIDEvent: function(rootNodeID, topLevelType, nativeEventParam) { - var nativeEvent = nativeEventParam || EMPTY_NATIVE_EVENT, inst = ReactNativeComponentTree_1.getInstanceFromNode(rootNodeID); - ReactGenericBatching_1.batchedUpdates(function() { - ReactNativeEventEmitter.handleTopLevel(topLevelType, inst, nativeEvent, nativeEvent.target); - }); - }, - receiveEvent: function(rootNodeID, topLevelType, nativeEventParam) { - ReactNativeEventEmitter._receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam); - }, - receiveTouches: function(eventTopLevelType, touches, changedIndices) { - for (var changedTouches = "topTouchEnd" === eventTopLevelType || "topTouchCancel" === eventTopLevelType ? removeTouchesAtIndices(touches, changedIndices) : touchSubsequence(touches, changedIndices), jj = 0; jj < changedTouches.length; jj++) { - var touch = changedTouches[jj]; - touch.changedTouches = changedTouches, touch.touches = touches; - var nativeEvent = touch, rootNodeID = null, target = nativeEvent.target; - null !== target && void 0 !== target && (target < ReactNativeTagHandles_1.tagsStartAt || (rootNodeID = target)), - ReactNativeEventEmitter._receiveRootNodeIDEvent(rootNodeID, eventTopLevelType, nativeEvent); - } - } -}), ReactNativeEventEmitter_1 = ReactNativeEventEmitter, ReactNativeEventPluginOrder = [ "ResponderEventPlugin", "ReactNativeBridgeEventPlugin" ], ReactNativeEventPluginOrder_1 = ReactNativeEventPluginOrder, ReactNativeGlobalResponderHandler = { - onChange: function(from, to, blockNativeResponder) { - if (null !== to) { - var tag = to.stateNode._nativeTag; - UIManager.setJSResponder(tag, blockNativeResponder); - } else UIManager.clearJSResponder(); - } -}, ReactNativeGlobalResponderHandler_1 = ReactNativeGlobalResponderHandler, ResponderEventInterface = { - touchHistory: function(nativeEvent) { - return null; - } -}; - -function ResponderSyntheticEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { - return SyntheticEvent_1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); -} - -SyntheticEvent_1.augmentClass(ResponderSyntheticEvent, ResponderEventInterface); - -var ResponderSyntheticEvent_1 = ResponderSyntheticEvent, isEndish$2 = EventPluginUtils_1.isEndish, isMoveish$2 = EventPluginUtils_1.isMoveish, isStartish$2 = EventPluginUtils_1.isStartish, MAX_TOUCH_BANK = 20, touchBank = [], touchHistory = { - touchBank: touchBank, - numberActiveTouches: 0, - indexOfSingleActiveTouch: -1, - mostRecentTimeStamp: 0 -}; - -function timestampForTouch(touch) { - return touch.timeStamp || touch.timestamp; -} - -function createTouchRecord(touch) { - return { - touchActive: !0, - startPageX: touch.pageX, - startPageY: touch.pageY, - startTimeStamp: timestampForTouch(touch), - currentPageX: touch.pageX, - currentPageY: touch.pageY, - currentTimeStamp: timestampForTouch(touch), - previousPageX: touch.pageX, - previousPageY: touch.pageY, - previousTimeStamp: timestampForTouch(touch) - }; -} - -function resetTouchRecord(touchRecord, touch) { - touchRecord.touchActive = !0, touchRecord.startPageX = touch.pageX, touchRecord.startPageY = touch.pageY, - touchRecord.startTimeStamp = timestampForTouch(touch), touchRecord.currentPageX = touch.pageX, - touchRecord.currentPageY = touch.pageY, touchRecord.currentTimeStamp = timestampForTouch(touch), - touchRecord.previousPageX = touch.pageX, touchRecord.previousPageY = touch.pageY, - touchRecord.previousTimeStamp = timestampForTouch(touch); -} - -function getTouchIdentifier(_ref) { - var identifier = _ref.identifier; - return invariant(null != identifier, "Touch object is missing identifier."), identifier; -} - -function recordTouchStart(touch) { - var identifier = getTouchIdentifier(touch), touchRecord = touchBank[identifier]; - touchRecord ? resetTouchRecord(touchRecord, touch) : touchBank[identifier] = createTouchRecord(touch), - touchHistory.mostRecentTimeStamp = timestampForTouch(touch); -} - -function recordTouchMove(touch) { - var touchRecord = touchBank[getTouchIdentifier(touch)]; - touchRecord ? (touchRecord.touchActive = !0, touchRecord.previousPageX = touchRecord.currentPageX, - touchRecord.previousPageY = touchRecord.currentPageY, touchRecord.previousTimeStamp = touchRecord.currentTimeStamp, - touchRecord.currentPageX = touch.pageX, touchRecord.currentPageY = touch.pageY, - touchRecord.currentTimeStamp = timestampForTouch(touch), touchHistory.mostRecentTimeStamp = timestampForTouch(touch)) : console.error("Cannot record touch move without a touch start.\n" + "Touch Move: %s\n", "Touch Bank: %s", printTouch(touch), printTouchBank()); -} - -function recordTouchEnd(touch) { - var touchRecord = touchBank[getTouchIdentifier(touch)]; - touchRecord ? (touchRecord.touchActive = !1, touchRecord.previousPageX = touchRecord.currentPageX, - touchRecord.previousPageY = touchRecord.currentPageY, touchRecord.previousTimeStamp = touchRecord.currentTimeStamp, - touchRecord.currentPageX = touch.pageX, touchRecord.currentPageY = touch.pageY, - touchRecord.currentTimeStamp = timestampForTouch(touch), touchHistory.mostRecentTimeStamp = timestampForTouch(touch)) : console.error("Cannot record touch end without a touch start.\n" + "Touch End: %s\n", "Touch Bank: %s", printTouch(touch), printTouchBank()); -} - -function printTouch(touch) { - return JSON.stringify({ - identifier: touch.identifier, - pageX: touch.pageX, - pageY: touch.pageY, - timestamp: timestampForTouch(touch) - }); -} - -function printTouchBank() { - var printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK)); - return touchBank.length > MAX_TOUCH_BANK && (printed += " (original size: " + touchBank.length + ")"), - printed; -} - -var ResponderTouchHistoryStore = { - recordTouchTrack: function(topLevelType, nativeEvent) { - if (isMoveish$2(topLevelType)) nativeEvent.changedTouches.forEach(recordTouchMove); else if (isStartish$2(topLevelType)) nativeEvent.changedTouches.forEach(recordTouchStart), - touchHistory.numberActiveTouches = nativeEvent.touches.length, 1 === touchHistory.numberActiveTouches && (touchHistory.indexOfSingleActiveTouch = nativeEvent.touches[0].identifier); else if (isEndish$2(topLevelType) && (nativeEvent.changedTouches.forEach(recordTouchEnd), - touchHistory.numberActiveTouches = nativeEvent.touches.length, 1 === touchHistory.numberActiveTouches)) for (var i = 0; i < touchBank.length; i++) { - var touchTrackToCheck = touchBank[i]; - if (null != touchTrackToCheck && touchTrackToCheck.touchActive) { - touchHistory.indexOfSingleActiveTouch = i; - break; - } - } - }, - touchHistory: touchHistory -}, ResponderTouchHistoryStore_1 = ResponderTouchHistoryStore; - -function accumulate(current, next) { - return invariant(null != next, "accumulate(...): Accumulated items must be not be null or undefined."), - null == current ? next : Array.isArray(current) ? current.concat(next) : Array.isArray(next) ? [ current ].concat(next) : [ current, next ]; -} - -var accumulate_1 = accumulate, isStartish$1 = EventPluginUtils_1.isStartish, isMoveish$1 = EventPluginUtils_1.isMoveish, isEndish$1 = EventPluginUtils_1.isEndish, executeDirectDispatch$1 = EventPluginUtils_1.executeDirectDispatch, hasDispatches$1 = EventPluginUtils_1.hasDispatches, executeDispatchesInOrderStopAtTrue$1 = EventPluginUtils_1.executeDispatchesInOrderStopAtTrue, responderInst = null, trackedTouchCount = 0, previousActiveTouches = 0, changeResponder = function(nextResponderInst, blockHostResponder) { - var oldResponderInst = responderInst; - responderInst = nextResponderInst, null !== ResponderEventPlugin.GlobalResponderHandler && ResponderEventPlugin.GlobalResponderHandler.onChange(oldResponderInst, nextResponderInst, blockHostResponder); -}, eventTypes = { - startShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onStartShouldSetResponder", - captured: "onStartShouldSetResponderCapture" - } - }, - scrollShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onScrollShouldSetResponder", - captured: "onScrollShouldSetResponderCapture" - } - }, - selectionChangeShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onSelectionChangeShouldSetResponder", - captured: "onSelectionChangeShouldSetResponderCapture" - } - }, - moveShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onMoveShouldSetResponder", - captured: "onMoveShouldSetResponderCapture" - } - }, - responderStart: { - registrationName: "onResponderStart" - }, - responderMove: { - registrationName: "onResponderMove" - }, - responderEnd: { - registrationName: "onResponderEnd" - }, - responderRelease: { - registrationName: "onResponderRelease" - }, - responderTerminationRequest: { - registrationName: "onResponderTerminationRequest" - }, - responderGrant: { - registrationName: "onResponderGrant" - }, - responderReject: { - registrationName: "onResponderReject" - }, - responderTerminate: { - registrationName: "onResponderTerminate" - } -}; - -function setResponderAndExtractTransfer(topLevelType, targetInst, nativeEvent, nativeEventTarget) { - var shouldSetEventType = isStartish$1(topLevelType) ? eventTypes.startShouldSetResponder : isMoveish$1(topLevelType) ? eventTypes.moveShouldSetResponder : "topSelectionChange" === topLevelType ? eventTypes.selectionChangeShouldSetResponder : eventTypes.scrollShouldSetResponder, bubbleShouldSetFrom = responderInst ? ReactTreeTraversal.getLowestCommonAncestor(responderInst, targetInst) : targetInst, skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst, shouldSetEvent = ResponderSyntheticEvent_1.getPooled(shouldSetEventType, bubbleShouldSetFrom, nativeEvent, nativeEventTarget); - shouldSetEvent.touchHistory = ResponderTouchHistoryStore_1.touchHistory, skipOverBubbleShouldSetFrom ? EventPropagators_1.accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent) : EventPropagators_1.accumulateTwoPhaseDispatches(shouldSetEvent); - var wantsResponderInst = executeDispatchesInOrderStopAtTrue$1(shouldSetEvent); - if (shouldSetEvent.isPersistent() || shouldSetEvent.constructor.release(shouldSetEvent), - !wantsResponderInst || wantsResponderInst === responderInst) return null; - var extracted, grantEvent = ResponderSyntheticEvent_1.getPooled(eventTypes.responderGrant, wantsResponderInst, nativeEvent, nativeEventTarget); - grantEvent.touchHistory = ResponderTouchHistoryStore_1.touchHistory, EventPropagators_1.accumulateDirectDispatches(grantEvent); - var blockHostResponder = !0 === executeDirectDispatch$1(grantEvent); - if (responderInst) { - var terminationRequestEvent = ResponderSyntheticEvent_1.getPooled(eventTypes.responderTerminationRequest, responderInst, nativeEvent, nativeEventTarget); - terminationRequestEvent.touchHistory = ResponderTouchHistoryStore_1.touchHistory, - EventPropagators_1.accumulateDirectDispatches(terminationRequestEvent); - var shouldSwitch = !hasDispatches$1(terminationRequestEvent) || executeDirectDispatch$1(terminationRequestEvent); - if (terminationRequestEvent.isPersistent() || terminationRequestEvent.constructor.release(terminationRequestEvent), - shouldSwitch) { - var terminateEvent = ResponderSyntheticEvent_1.getPooled(eventTypes.responderTerminate, responderInst, nativeEvent, nativeEventTarget); - terminateEvent.touchHistory = ResponderTouchHistoryStore_1.touchHistory, EventPropagators_1.accumulateDirectDispatches(terminateEvent), - extracted = accumulate_1(extracted, [ grantEvent, terminateEvent ]), changeResponder(wantsResponderInst, blockHostResponder); - } else { - var rejectEvent = ResponderSyntheticEvent_1.getPooled(eventTypes.responderReject, wantsResponderInst, nativeEvent, nativeEventTarget); - rejectEvent.touchHistory = ResponderTouchHistoryStore_1.touchHistory, EventPropagators_1.accumulateDirectDispatches(rejectEvent), - extracted = accumulate_1(extracted, rejectEvent); - } - } else extracted = accumulate_1(extracted, grantEvent), changeResponder(wantsResponderInst, blockHostResponder); - return extracted; -} - -function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) { - return topLevelInst && ("topScroll" === topLevelType && !nativeEvent.responderIgnoreScroll || trackedTouchCount > 0 && "topSelectionChange" === topLevelType || isStartish$1(topLevelType) || isMoveish$1(topLevelType)); -} - -function noResponderTouches(nativeEvent) { - var touches = nativeEvent.touches; - if (!touches || 0 === touches.length) return !0; - for (var i = 0; i < touches.length; i++) { - var activeTouch = touches[i], target = activeTouch.target; - if (null !== target && void 0 !== target && 0 !== target) { - var targetInst = EventPluginUtils_1.getInstanceFromNode(target); - if (ReactTreeTraversal.isAncestor(responderInst, targetInst)) return !1; - } - } - return !0; -} - -var ResponderEventPlugin = { - _getResponder: function() { - return responderInst; - }, - eventTypes: eventTypes, - extractEvents: function(topLevelType, targetInst, nativeEvent, nativeEventTarget) { - if (isStartish$1(topLevelType)) trackedTouchCount += 1; else if (isEndish$1(topLevelType)) { - if (!(trackedTouchCount >= 0)) return console.error("Ended a touch event which was not counted in `trackedTouchCount`."), - null; - trackedTouchCount -= 1; - } - ResponderTouchHistoryStore_1.recordTouchTrack(topLevelType, nativeEvent); - var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent) ? setResponderAndExtractTransfer(topLevelType, targetInst, nativeEvent, nativeEventTarget) : null, isResponderTouchStart = responderInst && isStartish$1(topLevelType), isResponderTouchMove = responderInst && isMoveish$1(topLevelType), isResponderTouchEnd = responderInst && isEndish$1(topLevelType), incrementalTouch = isResponderTouchStart ? eventTypes.responderStart : isResponderTouchMove ? eventTypes.responderMove : isResponderTouchEnd ? eventTypes.responderEnd : null; - if (incrementalTouch) { - var gesture = ResponderSyntheticEvent_1.getPooled(incrementalTouch, responderInst, nativeEvent, nativeEventTarget); - gesture.touchHistory = ResponderTouchHistoryStore_1.touchHistory, EventPropagators_1.accumulateDirectDispatches(gesture), - extracted = accumulate_1(extracted, gesture); - } - var isResponderTerminate = responderInst && "topTouchCancel" === topLevelType, isResponderRelease = responderInst && !isResponderTerminate && isEndish$1(topLevelType) && noResponderTouches(nativeEvent), finalTouch = isResponderTerminate ? eventTypes.responderTerminate : isResponderRelease ? eventTypes.responderRelease : null; - if (finalTouch) { - var finalEvent = ResponderSyntheticEvent_1.getPooled(finalTouch, responderInst, nativeEvent, nativeEventTarget); - finalEvent.touchHistory = ResponderTouchHistoryStore_1.touchHistory, EventPropagators_1.accumulateDirectDispatches(finalEvent), - extracted = accumulate_1(extracted, finalEvent), changeResponder(null); - } - var numberActiveTouches = ResponderTouchHistoryStore_1.touchHistory.numberActiveTouches; - return ResponderEventPlugin.GlobalInteractionHandler && numberActiveTouches !== previousActiveTouches && ResponderEventPlugin.GlobalInteractionHandler.onChange(numberActiveTouches), - previousActiveTouches = numberActiveTouches, extracted; - }, - GlobalResponderHandler: null, - GlobalInteractionHandler: null, - injection: { - injectGlobalResponderHandler: function(GlobalResponderHandler) { - ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; - }, - injectGlobalInteractionHandler: function(GlobalInteractionHandler) { - ResponderEventPlugin.GlobalInteractionHandler = GlobalInteractionHandler; - } - } -}, ResponderEventPlugin_1 = ResponderEventPlugin; - -RCTEventEmitter.register(ReactNativeEventEmitter_1), EventPluginHub_1.injection.injectEventPluginOrder(ReactNativeEventPluginOrder_1), -EventPluginUtils_1.injection.injectComponentTree(ReactNativeComponentTree_1), ResponderEventPlugin_1.injection.injectGlobalResponderHandler(ReactNativeGlobalResponderHandler_1), -EventPluginHub_1.injection.injectEventPluginsByName({ - ResponderEventPlugin: ResponderEventPlugin_1, - ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin_1 -}); - -function _classCallCheck$2(instance, Constructor) { - if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function"); -} - -function _possibleConstructorReturn(self, call) { - if (!self) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - return !call || "object" != typeof call && "function" != typeof call ? self : call; -} - -function _inherits(subClass, superClass) { - if ("function" != typeof superClass && null !== superClass) throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: !1, - writable: !0, - configurable: !0 - } - }), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass); -} - -var mountSafeCallback$2 = NativeMethodsMixinUtils.mountSafeCallback, ReactNativeComponent = function(_React$Component) { - _inherits(ReactNativeComponent, _React$Component); - function ReactNativeComponent() { - return _classCallCheck$2(this, ReactNativeComponent), _possibleConstructorReturn(this, _React$Component.apply(this, arguments)); - } - return ReactNativeComponent.prototype.blur = function() { - TextInputState.blurTextInput(findNumericNodeHandle(this)); - }, ReactNativeComponent.prototype.focus = function() { - TextInputState.focusTextInput(findNumericNodeHandle(this)); - }, ReactNativeComponent.prototype.measure = function(callback) { - UIManager.measure(findNumericNodeHandle(this), mountSafeCallback$2(this, callback)); - }, ReactNativeComponent.prototype.measureInWindow = function(callback) { - UIManager.measureInWindow(findNumericNodeHandle(this), mountSafeCallback$2(this, callback)); - }, ReactNativeComponent.prototype.measureLayout = function(relativeToNativeNode, onSuccess, onFail) { - UIManager.measureLayout(findNumericNodeHandle(this), relativeToNativeNode, mountSafeCallback$2(this, onFail), mountSafeCallback$2(this, onSuccess)); - }, ReactNativeComponent.prototype.setNativeProps = function(nativeProps) { - var maybeInstance = void 0; - try { - maybeInstance = findNodeHandle_1(this); - } catch (error) {} - if (null != maybeInstance) { - var viewConfig = maybeInstance.viewConfig, updatePayload = ReactNativeAttributePayload_1.create(nativeProps, viewConfig.validAttributes); - null != updatePayload && UIManager.updateView(maybeInstance._nativeTag, viewConfig.uiViewClassName, updatePayload); - } - }, ReactNativeComponent; -}(react.Component), ReactNativeComponent_1 = ReactNativeComponent, mountSafeCallback$3 = NativeMethodsMixinUtils.mountSafeCallback, NativeMethodsMixin = { - measure: function(callback) { - UIManager.measure(findNumericNodeHandle(this), mountSafeCallback$3(this, callback)); - }, - measureInWindow: function(callback) { - UIManager.measureInWindow(findNumericNodeHandle(this), mountSafeCallback$3(this, callback)); - }, - measureLayout: function(relativeToNativeNode, onSuccess, onFail) { - UIManager.measureLayout(findNumericNodeHandle(this), relativeToNativeNode, mountSafeCallback$3(this, onFail), mountSafeCallback$3(this, onSuccess)); - }, - setNativeProps: function(nativeProps) { - var maybeInstance = void 0; - try { - maybeInstance = findNodeHandle_1(this); - } catch (error) {} - if (null != maybeInstance) { - var viewConfig = maybeInstance.viewConfig, updatePayload = ReactNativeAttributePayload_1.create(nativeProps, viewConfig.validAttributes); - null != updatePayload && UIManager.updateView(maybeInstance._nativeTag, viewConfig.uiViewClassName, updatePayload); - } - }, - focus: function() { - TextInputState.focusTextInput(findNumericNodeHandle(this)); - }, - blur: function() { - TextInputState.blurTextInput(findNumericNodeHandle(this)); - } -}, NativeMethodsMixin_1 = NativeMethodsMixin, TouchHistoryMath = { - centroidDimension: function(touchHistory, touchesChangedAfter, isXAxis, ofCurrent) { - var touchBank = touchHistory.touchBank, total = 0, count = 0, oneTouchData = 1 === touchHistory.numberActiveTouches ? touchHistory.touchBank[touchHistory.indexOfSingleActiveTouch] : null; - if (null !== oneTouchData) oneTouchData.touchActive && oneTouchData.currentTimeStamp > touchesChangedAfter && (total += ofCurrent && isXAxis ? oneTouchData.currentPageX : ofCurrent && !isXAxis ? oneTouchData.currentPageY : !ofCurrent && isXAxis ? oneTouchData.previousPageX : oneTouchData.previousPageY, - count = 1); else for (var i = 0; i < touchBank.length; i++) { - var touchTrack = touchBank[i]; - if (null !== touchTrack && void 0 !== touchTrack && touchTrack.touchActive && touchTrack.currentTimeStamp >= touchesChangedAfter) { - var toAdd; - toAdd = ofCurrent && isXAxis ? touchTrack.currentPageX : ofCurrent && !isXAxis ? touchTrack.currentPageY : !ofCurrent && isXAxis ? touchTrack.previousPageX : touchTrack.previousPageY, - total += toAdd, count++; - } - } - return count > 0 ? total / count : TouchHistoryMath.noCentroid; - }, - currentCentroidXOfTouchesChangedAfter: function(touchHistory, touchesChangedAfter) { - return TouchHistoryMath.centroidDimension(touchHistory, touchesChangedAfter, !0, !0); - }, - currentCentroidYOfTouchesChangedAfter: function(touchHistory, touchesChangedAfter) { - return TouchHistoryMath.centroidDimension(touchHistory, touchesChangedAfter, !1, !0); - }, - previousCentroidXOfTouchesChangedAfter: function(touchHistory, touchesChangedAfter) { - return TouchHistoryMath.centroidDimension(touchHistory, touchesChangedAfter, !0, !1); - }, - previousCentroidYOfTouchesChangedAfter: function(touchHistory, touchesChangedAfter) { - return TouchHistoryMath.centroidDimension(touchHistory, touchesChangedAfter, !1, !1); - }, - currentCentroidX: function(touchHistory) { - return TouchHistoryMath.centroidDimension(touchHistory, 0, !0, !0); - }, - currentCentroidY: function(touchHistory) { - return TouchHistoryMath.centroidDimension(touchHistory, 0, !1, !0); - }, - noCentroid: -1 -}, TouchHistoryMath_1 = TouchHistoryMath, createReactNativeComponentClass = function(name, callback) { - return ReactNativeViewConfigRegistry_1.register(name, callback); -}, createReactNativeComponentClass_1 = createReactNativeComponentClass; - -function takeSnapshot(view, options) { - return "number" != typeof view && "window" !== view && (view = findNumericNodeHandle(view) || "window"), - UIManager.__takeSnapshot(view, options); -} - -var takeSnapshot_1 = takeSnapshot, injectInternals = ReactFiberDevToolsHook.injectInternals; - -ReactGenericBatching_1.injection.injectFiberBatchedUpdates(ReactNativeFiberRenderer.batchedUpdates); - -var roots = new Map(); - -ReactFiberErrorLogger.injection.injectDialog(ReactNativeFiberErrorDialog_1.showDialog); - -var ReactNativeFiber = { - NativeComponent: ReactNativeComponent_1, - findNodeHandle: findNumericNodeHandle, - render: function(element, containerTag, callback) { - var root = roots.get(containerTag); - return root || (root = ReactNativeFiberRenderer.createContainer(containerTag), roots.set(containerTag, root)), - ReactNativeFiberRenderer.updateContainer(element, root, null, callback), ReactNativeFiberRenderer.getPublicRootInstance(root); - }, - unmountComponentAtNode: function(containerTag) { - var root = roots.get(containerTag); - root && ReactNativeFiberRenderer.updateContainer(null, root, null, function() { - roots.delete(containerTag); - }); - }, - unmountComponentAtNodeAndRemoveContainer: function(containerTag) { - ReactNativeFiber.unmountComponentAtNode(containerTag), UIManager.removeRootView(containerTag); - }, - createPortal: function(children, containerTag) { - var key = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : null; - return ReactPortal.createPortal(children, containerTag, null, key); - }, - unstable_batchedUpdates: ReactGenericBatching_1.batchedUpdates, - flushSync: ReactNativeFiberRenderer.flushSync, - __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: { - NativeMethodsMixin: NativeMethodsMixin_1, - ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin_1, - ReactGlobalSharedState: ReactGlobalSharedState_1, - ReactNativeComponentTree: ReactNativeComponentTree_1, - ReactNativePropRegistry: ReactNativePropRegistry_1, - TouchHistoryMath: TouchHistoryMath_1, - createReactNativeComponentClass: createReactNativeComponentClass_1, - takeSnapshot: takeSnapshot_1 - } -}; - -injectInternals({ - findFiberByHostInstance: ReactNativeComponentTree_1.getClosestInstanceFromNode, - findHostInstanceByFiber: ReactNativeFiberRenderer.findHostInstance, - getInspectorDataForViewTag: ReactNativeFiberInspector.getInspectorDataForViewTag, - bundleType: 0, - version: ReactVersion, - rendererPackageName: "react-native" -}); - -var ReactNativeFiberEntry = ReactNativeFiber; - -module.exports = ReactNativeFiberEntry; diff --git a/Libraries/Renderer/ReactNativeRenderer-dev.js b/Libraries/Renderer/ReactNativeRenderer-dev.js new file mode 100644 index 00000000000000..26ed7534db9856 --- /dev/null +++ b/Libraries/Renderer/ReactNativeRenderer-dev.js @@ -0,0 +1,12927 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @noflow + * @providesModule ReactNativeRenderer-dev + * @preventMunge + */ + +'use strict'; + +if (__DEV__) { + (function() { +"use strict"; + +require("InitializeCore"); +var invariant = require("fbjs/lib/invariant"); +var warning = require("fbjs/lib/warning"); +var emptyFunction = require("fbjs/lib/emptyFunction"); +var RCTEventEmitter = require("RCTEventEmitter"); +var UIManager = require("UIManager"); +var React = require("react"); +var ExceptionsManager = require("ExceptionsManager"); +var TextInputState = require("TextInputState"); +var deepDiffer = require("deepDiffer"); +var flattenStyle = require("flattenStyle"); +var emptyObject = require("fbjs/lib/emptyObject"); +var checkPropTypes = require("prop-types/checkPropTypes"); +var shallowEqual = require("fbjs/lib/shallowEqual"); +var deepFreezeAndThrowOnMutationInDev = require("deepFreezeAndThrowOnMutationInDev"); + +var ReactErrorUtils = { + // Used by Fiber to simulate a try-catch. + _caughtError: null, + _hasCaughtError: false, + + // Used by event system to capture/rethrow the first error. + _rethrowError: null, + _hasRethrowError: false, + + injection: { + injectErrorUtils: function(injectedErrorUtils) { + invariant( + typeof injectedErrorUtils.invokeGuardedCallback === "function", + "Injected invokeGuardedCallback() must be a function." + ); + invokeGuardedCallback = injectedErrorUtils.invokeGuardedCallback; + } + }, + + /** + * Call a function while guarding against errors that happens within it. + * Returns an error if it throws, otherwise null. + * + * In production, this is implemented using a try-catch. The reason we don't + * use a try-catch directly is so that we can swap out a different + * implementation in DEV mode. + * + * @param {String} name of the guard to use for logging or debugging + * @param {Function} func The function to invoke + * @param {*} context The context to use when calling the function + * @param {...*} args Arguments for function + */ + invokeGuardedCallback: function(name, func, context, a, b, c, d, e, f) { + invokeGuardedCallback.apply(ReactErrorUtils, arguments); + }, + + /** + * Same as invokeGuardedCallback, but instead of returning an error, it stores + * it in a global so it can be rethrown by `rethrowCaughtError` later. + * TODO: See if _caughtError and _rethrowError can be unified. + * + * @param {String} name of the guard to use for logging or debugging + * @param {Function} func The function to invoke + * @param {*} context The context to use when calling the function + * @param {...*} args Arguments for function + */ + invokeGuardedCallbackAndCatchFirstError: function( + name, + func, + context, + a, + b, + c, + d, + e, + f + ) { + ReactErrorUtils.invokeGuardedCallback.apply(this, arguments); + if (ReactErrorUtils.hasCaughtError()) { + var error = ReactErrorUtils.clearCaughtError(); + if (!ReactErrorUtils._hasRethrowError) { + ReactErrorUtils._hasRethrowError = true; + ReactErrorUtils._rethrowError = error; + } + } + }, + + /** + * During execution of guarded functions we will capture the first error which + * we will rethrow to be handled by the top level error handler. + */ + rethrowCaughtError: function() { + return rethrowCaughtError.apply(ReactErrorUtils, arguments); + }, + + hasCaughtError: function() { + return ReactErrorUtils._hasCaughtError; + }, + + clearCaughtError: function() { + if (ReactErrorUtils._hasCaughtError) { + var error = ReactErrorUtils._caughtError; + ReactErrorUtils._caughtError = null; + ReactErrorUtils._hasCaughtError = false; + return error; + } else { + invariant( + false, + "clearCaughtError was called but no error was captured. This error " + + "is likely caused by a bug in React. Please file an issue." + ); + } + } +}; + +var invokeGuardedCallback = function(name, func, context, a, b, c, d, e, f) { + ReactErrorUtils._hasCaughtError = false; + ReactErrorUtils._caughtError = null; + var funcArgs = Array.prototype.slice.call(arguments, 3); + try { + func.apply(context, funcArgs); + } catch (error) { + ReactErrorUtils._caughtError = error; + ReactErrorUtils._hasCaughtError = true; + } +}; + +{ + // In DEV mode, we swap out invokeGuardedCallback for a special version + // that plays more nicely with the browser's DevTools. The idea is to preserve + // "Pause on exceptions" behavior. Because React wraps all user-provided + // functions in invokeGuardedCallback, and the production version of + // invokeGuardedCallback uses a try-catch, all user exceptions are treated + // like caught exceptions, and the DevTools won't pause unless the developer + // takes the extra step of enabling pause on caught exceptions. This is + // untintuitive, though, because even though React has caught the error, from + // the developer's perspective, the error is uncaught. + // + // To preserve the expected "Pause on exceptions" behavior, we don't use a + // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake + // DOM node, and call the user-provided callback from inside an event handler + // for that fake event. If the callback throws, the error is "captured" using + // a global event handler. But because the error happens in a different + // event loop context, it does not interrupt the normal program flow. + // Effectively, this gives us try-catch behavior without actually using + // try-catch. Neat! + + // Check that the browser supports the APIs we need to implement our special + // DEV version of invokeGuardedCallback + if ( + typeof window !== "undefined" && + typeof window.dispatchEvent === "function" && + typeof document !== "undefined" && + typeof document.createEvent === "function" + ) { + var fakeNode = document.createElement("react"); + + var invokeGuardedCallbackDev = function( + name, + func, + context, + a, + b, + c, + d, + e, + f + ) { + // Keeps track of whether the user-provided callback threw an error. We + // set this to true at the beginning, then set it to false right after + // calling the function. If the function errors, `didError` will never be + // set to false. This strategy works even if the browser is flaky and + // fails to call our global error handler, because it doesn't rely on + // the error event at all. + var didError = true; + + // Create an event handler for our fake event. We will synchronously + // dispatch our fake event using `dispatchEvent`. Inside the handler, we + // call the user-provided callback. + var funcArgs = Array.prototype.slice.call(arguments, 3); + function callCallback() { + // We immediately remove the callback from event listeners so that + // nested `invokeGuardedCallback` calls do not clash. Otherwise, a + // nested call would trigger the fake event handlers of any call higher + // in the stack. + fakeNode.removeEventListener(evtType, callCallback, false); + func.apply(context, funcArgs); + didError = false; + } + + // Create a global error event handler. We use this to capture the value + // that was thrown. It's possible that this error handler will fire more + // than once; for example, if non-React code also calls `dispatchEvent` + // and a handler for that event throws. We should be resilient to most of + // those cases. Even if our error event handler fires more than once, the + // last error event is always used. If the callback actually does error, + // we know that the last error event is the correct one, because it's not + // possible for anything else to have happened in between our callback + // erroring and the code that follows the `dispatchEvent` call below. If + // the callback doesn't error, but the error event was fired, we know to + // ignore it because `didError` will be false, as described above. + var error = void 0; + // Use this to track whether the error event is ever called. + var didSetError = false; + var isCrossOriginError = false; + + function onError(event) { + error = event.error; + didSetError = true; + if (error === null && event.colno === 0 && event.lineno === 0) { + isCrossOriginError = true; + } + } + + // Create a fake event type. + var evtType = "react-" + (name ? name : "invokeguardedcallback"); + + // Attach our event handlers + window.addEventListener("error", onError); + fakeNode.addEventListener(evtType, callCallback, false); + + // Synchronously dispatch our fake event. If the user-provided function + // errors, it will trigger our global error handler. + var evt = document.createEvent("Event"); + evt.initEvent(evtType, false, false); + fakeNode.dispatchEvent(evt); + + if (didError) { + if (!didSetError) { + // The callback errored, but the error event never fired. + error = new Error( + "An error was thrown inside one of your components, but React " + + "doesn't know what it was. This is likely due to browser " + + 'flakiness. React does its best to preserve the "Pause on ' + + 'exceptions" behavior of the DevTools, which requires some ' + + "DEV-mode only tricks. It's possible that these don't work in " + + "your browser. Try triggering the error in production mode, " + + "or switching to a modern browser. If you suspect that this is " + + "actually an issue with React, please file an issue." + ); + } else if (isCrossOriginError) { + error = new Error( + "A cross-origin error was thrown. React doesn't have access to " + + "the actual error object in development. " + + "See https://fb.me/react-crossorigin-error for more information." + ); + } + ReactErrorUtils._hasCaughtError = true; + ReactErrorUtils._caughtError = error; + } else { + ReactErrorUtils._hasCaughtError = false; + ReactErrorUtils._caughtError = null; + } + + // Remove our event listeners + window.removeEventListener("error", onError); + }; + + invokeGuardedCallback = invokeGuardedCallbackDev; + } +} + +var rethrowCaughtError = function() { + if (ReactErrorUtils._hasRethrowError) { + var error = ReactErrorUtils._rethrowError; + ReactErrorUtils._rethrowError = null; + ReactErrorUtils._hasRethrowError = false; + throw error; + } +}; + +/** + * Injectable ordering of event plugins. + */ +var eventPluginOrder = null; + +/** + * Injectable mapping from names to event plugin modules. + */ +var namesToPlugins = {}; + +/** + * Recomputes the plugin list using the injected plugins and plugin ordering. + * + * @private + */ +function recomputePluginOrdering() { + if (!eventPluginOrder) { + // Wait until an `eventPluginOrder` is injected. + return; + } + for (var pluginName in namesToPlugins) { + var pluginModule = namesToPlugins[pluginName]; + var pluginIndex = eventPluginOrder.indexOf(pluginName); + invariant( + pluginIndex > -1, + "EventPluginRegistry: Cannot inject event plugins that do not exist in " + + "the plugin ordering, `%s`.", + pluginName + ); + if (plugins[pluginIndex]) { + continue; + } + invariant( + pluginModule.extractEvents, + "EventPluginRegistry: Event plugins must implement an `extractEvents` " + + "method, but `%s` does not.", + pluginName + ); + plugins[pluginIndex] = pluginModule; + var publishedEvents = pluginModule.eventTypes; + for (var eventName in publishedEvents) { + invariant( + publishEventForPlugin( + publishedEvents[eventName], + pluginModule, + eventName + ), + "EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.", + eventName, + pluginName + ); + } + } +} + +/** + * Publishes an event so that it can be dispatched by the supplied plugin. + * + * @param {object} dispatchConfig Dispatch configuration for the event. + * @param {object} PluginModule Plugin publishing the event. + * @return {boolean} True if the event was successfully published. + * @private + */ +function publishEventForPlugin(dispatchConfig, pluginModule, eventName) { + invariant( + !eventNameDispatchConfigs.hasOwnProperty(eventName), + "EventPluginHub: More than one plugin attempted to publish the same " + + "event name, `%s`.", + eventName + ); + eventNameDispatchConfigs[eventName] = dispatchConfig; + + var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; + if (phasedRegistrationNames) { + for (var phaseName in phasedRegistrationNames) { + if (phasedRegistrationNames.hasOwnProperty(phaseName)) { + var phasedRegistrationName = phasedRegistrationNames[phaseName]; + publishRegistrationName( + phasedRegistrationName, + pluginModule, + eventName + ); + } + } + return true; + } else if (dispatchConfig.registrationName) { + publishRegistrationName( + dispatchConfig.registrationName, + pluginModule, + eventName + ); + return true; + } + return false; +} + +/** + * Publishes a registration name that is used to identify dispatched events. + * + * @param {string} registrationName Registration name to add. + * @param {object} PluginModule Plugin publishing the event. + * @private + */ +function publishRegistrationName(registrationName, pluginModule, eventName) { + invariant( + !registrationNameModules[registrationName], + "EventPluginHub: More than one plugin attempted to publish the same " + + "registration name, `%s`.", + registrationName + ); + registrationNameModules[registrationName] = pluginModule; + { + var lowerCasedName = registrationName.toLowerCase(); + possibleRegistrationNames[lowerCasedName] = registrationName; + + if (registrationName === "onDoubleClick") { + possibleRegistrationNames.ondblclick = registrationName; + } + } +} + +/** + * Registers plugins so that they can extract and dispatch events. + * + * @see {EventPluginHub} + */ + +/** + * Ordered list of injected plugins. + */ +var plugins = []; + +/** + * Mapping from event name to dispatch config + */ +var eventNameDispatchConfigs = {}; + +/** + * Mapping from registration name to plugin module + */ +var registrationNameModules = {}; + +/** + * Mapping from registration name to event name + */ + +/** + * Mapping from lowercase registration names to the properly cased version, + * used to warn in the case of missing event handlers. Available + * only in true. + * @type {Object} + */ +var possibleRegistrationNames = {}; +// Trust the developer to only use possibleRegistrationNames in true + +/** + * Injects an ordering of plugins (by plugin name). This allows the ordering + * to be decoupled from injection of the actual plugins so that ordering is + * always deterministic regardless of packaging, on-the-fly injection, etc. + * + * @param {array} InjectedEventPluginOrder + * @internal + * @see {EventPluginHub.injection.injectEventPluginOrder} + */ +function injectEventPluginOrder(injectedEventPluginOrder) { + invariant( + !eventPluginOrder, + "EventPluginRegistry: Cannot inject event plugin ordering more than " + + "once. You are likely trying to load more than one copy of React." + ); + // Clone the ordering so it cannot be dynamically mutated. + eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder); + recomputePluginOrdering(); +} + +/** + * Injects plugins to be used by `EventPluginHub`. The plugin names must be + * in the ordering injected by `injectEventPluginOrder`. + * + * Plugins can be injected as part of page initialization or on-the-fly. + * + * @param {object} injectedNamesToPlugins Map from names to plugin modules. + * @internal + * @see {EventPluginHub.injection.injectEventPluginsByName} + */ +function injectEventPluginsByName(injectedNamesToPlugins) { + var isOrderingDirty = false; + for (var pluginName in injectedNamesToPlugins) { + if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) { + continue; + } + var pluginModule = injectedNamesToPlugins[pluginName]; + if ( + !namesToPlugins.hasOwnProperty(pluginName) || + namesToPlugins[pluginName] !== pluginModule + ) { + invariant( + !namesToPlugins[pluginName], + "EventPluginRegistry: Cannot inject two different event plugins " + + "using the same name, `%s`.", + pluginName + ); + namesToPlugins[pluginName] = pluginModule; + isOrderingDirty = true; + } + } + if (isOrderingDirty) { + recomputePluginOrdering(); + } +} + +var getFiberCurrentPropsFromNode = null; +var getInstanceFromNode = null; +var getNodeFromInstance = null; + +var injection$1 = { + injectComponentTree: function(Injected) { + getFiberCurrentPropsFromNode = Injected.getFiberCurrentPropsFromNode; + getInstanceFromNode = Injected.getInstanceFromNode; + getNodeFromInstance = Injected.getNodeFromInstance; + + { + warning( + getNodeFromInstance && getInstanceFromNode, + "EventPluginUtils.injection.injectComponentTree(...): Injected " + + "module is missing getNodeFromInstance or getInstanceFromNode." + ); + } + } +}; + +function isEndish(topLevelType) { + return ( + topLevelType === "topMouseUp" || + topLevelType === "topTouchEnd" || + topLevelType === "topTouchCancel" + ); +} + +function isMoveish(topLevelType) { + return topLevelType === "topMouseMove" || topLevelType === "topTouchMove"; +} +function isStartish(topLevelType) { + return topLevelType === "topMouseDown" || topLevelType === "topTouchStart"; +} + +var validateEventDispatches; +{ + validateEventDispatches = function(event) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; + + var listenersIsArr = Array.isArray(dispatchListeners); + var listenersLen = listenersIsArr + ? dispatchListeners.length + : dispatchListeners ? 1 : 0; + + var instancesIsArr = Array.isArray(dispatchInstances); + var instancesLen = instancesIsArr + ? dispatchInstances.length + : dispatchInstances ? 1 : 0; + + warning( + instancesIsArr === listenersIsArr && instancesLen === listenersLen, + "EventPluginUtils: Invalid `event`." + ); + }; +} + +/** + * Dispatch the event to the listener. + * @param {SyntheticEvent} event SyntheticEvent to handle + * @param {boolean} simulated If the event is simulated (changes exn behavior) + * @param {function} listener Application-level callback + * @param {*} inst Internal component instance + */ +function executeDispatch(event, simulated, listener, inst) { + var type = event.type || "unknown-event"; + event.currentTarget = getNodeFromInstance(inst); + ReactErrorUtils.invokeGuardedCallbackAndCatchFirstError( + type, + listener, + undefined, + event + ); + event.currentTarget = null; +} + +/** + * Standard/simple iteration through an event's collected dispatches. + */ +function executeDispatchesInOrder(event, simulated) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; + { + validateEventDispatches(event); + } + if (Array.isArray(dispatchListeners)) { + for (var i = 0; i < dispatchListeners.length; i++) { + if (event.isPropagationStopped()) { + break; + } + // Listeners and Instances are two parallel arrays that are always in sync. + executeDispatch( + event, + simulated, + dispatchListeners[i], + dispatchInstances[i] + ); + } + } else if (dispatchListeners) { + executeDispatch(event, simulated, dispatchListeners, dispatchInstances); + } + event._dispatchListeners = null; + event._dispatchInstances = null; +} + +/** + * Standard/simple iteration through an event's collected dispatches, but stops + * at the first dispatch execution returning true, and returns that id. + * + * @return {?string} id of the first dispatch execution who's listener returns + * true, or null if no listener returned true. + */ +function executeDispatchesInOrderStopAtTrueImpl(event) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; + { + validateEventDispatches(event); + } + if (Array.isArray(dispatchListeners)) { + for (var i = 0; i < dispatchListeners.length; i++) { + if (event.isPropagationStopped()) { + break; + } + // Listeners and Instances are two parallel arrays that are always in sync. + if (dispatchListeners[i](event, dispatchInstances[i])) { + return dispatchInstances[i]; + } + } + } else if (dispatchListeners) { + if (dispatchListeners(event, dispatchInstances)) { + return dispatchInstances; + } + } + return null; +} + +/** + * @see executeDispatchesInOrderStopAtTrueImpl + */ +function executeDispatchesInOrderStopAtTrue(event) { + var ret = executeDispatchesInOrderStopAtTrueImpl(event); + event._dispatchInstances = null; + event._dispatchListeners = null; + return ret; +} + +/** + * Execution of a "direct" dispatch - there must be at most one dispatch + * accumulated on the event or it is considered an error. It doesn't really make + * sense for an event with multiple dispatches (bubbled) to keep track of the + * return values at each dispatch execution, but it does tend to make sense when + * dealing with "direct" dispatches. + * + * @return {*} The return value of executing the single dispatch. + */ +function executeDirectDispatch(event) { + { + validateEventDispatches(event); + } + var dispatchListener = event._dispatchListeners; + var dispatchInstance = event._dispatchInstances; + invariant( + !Array.isArray(dispatchListener), + "executeDirectDispatch(...): Invalid `event`." + ); + event.currentTarget = dispatchListener + ? getNodeFromInstance(dispatchInstance) + : null; + var res = dispatchListener ? dispatchListener(event) : null; + event.currentTarget = null; + event._dispatchListeners = null; + event._dispatchInstances = null; + return res; +} + +/** + * @param {SyntheticEvent} event + * @return {boolean} True iff number of dispatches accumulated is greater than 0. + */ +function hasDispatches(event) { + return !!event._dispatchListeners; +} + +/** + * Accumulates items that must not be null or undefined into the first one. This + * is used to conserve memory by avoiding array allocations, and thus sacrifices + * API cleanness. Since `current` can be null before being passed in and not + * null after this function, make sure to assign it back to `current`: + * + * `a = accumulateInto(a, b);` + * + * This API should be sparingly used. Try `accumulate` for something cleaner. + * + * @return {*|array<*>} An accumulation of items. + */ + +function accumulateInto(current, next) { + invariant( + next != null, + "accumulateInto(...): Accumulated items must not be null or undefined." + ); + + if (current == null) { + return next; + } + + // Both are not empty. Warning: Never call x.concat(y) when you are not + // certain that x is an Array (x could be a string with concat method). + if (Array.isArray(current)) { + if (Array.isArray(next)) { + current.push.apply(current, next); + return current; + } + current.push(next); + return current; + } + + if (Array.isArray(next)) { + // A bit too dangerous to mutate `next`. + return [current].concat(next); + } + + return [current, next]; +} + +/** + * @param {array} arr an "accumulation" of items which is either an Array or + * a single item. Useful when paired with the `accumulate` module. This is a + * simple utility that allows us to reason about a collection of items, but + * handling the case when there is exactly one item (and we do not need to + * allocate an array). + * @param {function} cb Callback invoked with each element or a collection. + * @param {?} [scope] Scope used as `this` in a callback. + */ +function forEachAccumulated(arr, cb, scope) { + if (Array.isArray(arr)) { + arr.forEach(cb, scope); + } else if (arr) { + cb.call(scope, arr); + } +} + +/** + * Internal queue of events that have accumulated their dispatches and are + * waiting to have their dispatches executed. + */ +var eventQueue = null; + +/** + * Dispatches an event and releases it back into the pool, unless persistent. + * + * @param {?object} event Synthetic event to be dispatched. + * @param {boolean} simulated If the event is simulated (changes exn behavior) + * @private + */ +var executeDispatchesAndRelease = function(event, simulated) { + if (event) { + executeDispatchesInOrder(event, simulated); + + if (!event.isPersistent()) { + event.constructor.release(event); + } + } +}; +var executeDispatchesAndReleaseSimulated = function(e) { + return executeDispatchesAndRelease(e, true); +}; +var executeDispatchesAndReleaseTopLevel = function(e) { + return executeDispatchesAndRelease(e, false); +}; + +function isInteractive(tag) { + return ( + tag === "button" || + tag === "input" || + tag === "select" || + tag === "textarea" + ); +} + +function shouldPreventMouseEvent(name, type, props) { + switch (name) { + case "onClick": + case "onClickCapture": + case "onDoubleClick": + case "onDoubleClickCapture": + case "onMouseDown": + case "onMouseDownCapture": + case "onMouseMove": + case "onMouseMoveCapture": + case "onMouseUp": + case "onMouseUpCapture": + return !!(props.disabled && isInteractive(type)); + default: + return false; + } +} + +/** + * This is a unified interface for event plugins to be installed and configured. + * + * Event plugins can implement the following properties: + * + * `extractEvents` {function(string, DOMEventTarget, string, object): *} + * Required. When a top-level event is fired, this method is expected to + * extract synthetic events that will in turn be queued and dispatched. + * + * `eventTypes` {object} + * Optional, plugins that fire events must publish a mapping of registration + * names that are used to register listeners. Values of this mapping must + * be objects that contain `registrationName` or `phasedRegistrationNames`. + * + * `executeDispatch` {function(object, function, string)} + * Optional, allows plugins to override how an event gets dispatched. By + * default, the listener is simply invoked. + * + * Each plugin that is injected into `EventsPluginHub` is immediately operable. + * + * @public + */ + +/** + * Methods for injecting dependencies. + */ +var injection = { + /** + * @param {array} InjectedEventPluginOrder + * @public + */ + injectEventPluginOrder: injectEventPluginOrder, + + /** + * @param {object} injectedNamesToPlugins Map from names to plugin modules. + */ + injectEventPluginsByName: injectEventPluginsByName +}; + +/** + * @param {object} inst The instance, which is the source of events. + * @param {string} registrationName Name of listener (e.g. `onClick`). + * @return {?function} The stored callback. + */ +function getListener(inst, registrationName) { + var listener; + + // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not + // live here; needs to be moved to a better place soon + var stateNode = inst.stateNode; + if (!stateNode) { + // Work in progress (ex: onload events in incremental mode). + return null; + } + var props = getFiberCurrentPropsFromNode(stateNode); + if (!props) { + // Work in progress. + return null; + } + listener = props[registrationName]; + if (shouldPreventMouseEvent(registrationName, inst.type, props)) { + return null; + } + invariant( + !listener || typeof listener === "function", + "Expected `%s` listener to be a function, instead got a value of `%s` type.", + registrationName, + typeof listener + ); + return listener; +} + +/** + * Allows registered plugins an opportunity to extract events from top-level + * native browser events. + * + * @return {*} An accumulation of synthetic events. + * @internal + */ +function extractEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget +) { + var events; + for (var i = 0; i < plugins.length; i++) { + // Not every plugin in the ordering may be loaded at runtime. + var possiblePlugin = plugins[i]; + if (possiblePlugin) { + var extractedEvents = possiblePlugin.extractEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ); + if (extractedEvents) { + events = accumulateInto(events, extractedEvents); + } + } + } + return events; +} + +/** + * Enqueues a synthetic event that should be dispatched when + * `processEventQueue` is invoked. + * + * @param {*} events An accumulation of synthetic events. + * @internal + */ +function enqueueEvents(events) { + if (events) { + eventQueue = accumulateInto(eventQueue, events); + } +} + +/** + * Dispatches all synthetic events on the event queue. + * + * @internal + */ +function processEventQueue(simulated) { + // Set `eventQueue` to null before processing it so that we can tell if more + // events get enqueued while processing. + var processingEventQueue = eventQueue; + eventQueue = null; + if (simulated) { + forEachAccumulated( + processingEventQueue, + executeDispatchesAndReleaseSimulated + ); + } else { + forEachAccumulated( + processingEventQueue, + executeDispatchesAndReleaseTopLevel + ); + } + invariant( + !eventQueue, + "processEventQueue(): Additional events were enqueued while processing " + + "an event queue. Support for this has not yet been implemented." + ); + // This would be a good time to rethrow if any of the event handlers threw. + ReactErrorUtils.rethrowCaughtError(); +} + +var IndeterminateComponent = 0; // Before we know whether it is functional or class +var FunctionalComponent = 1; +var ClassComponent = 2; +var HostRoot = 3; // Root of a host tree. Could be nested inside another node. +var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. +var HostComponent = 5; +var HostText = 6; +var CallComponent = 7; +var CallHandlerPhase = 8; +var ReturnComponent = 9; +var Fragment = 10; + +function getParent(inst) { + do { + inst = inst["return"]; + // TODO: If this is a HostRoot we might want to bail out. + // That is depending on if we want nested subtrees (layers) to bubble + // events to their parent. We could also go through parentNode on the + // host node but that wouldn't work for React Native and doesn't let us + // do the portal feature. + } while (inst && inst.tag !== HostComponent); + if (inst) { + return inst; + } + return null; +} + +/** + * Return the lowest common ancestor of A and B, or null if they are in + * different trees. + */ +function getLowestCommonAncestor(instA, instB) { + var depthA = 0; + for (var tempA = instA; tempA; tempA = getParent(tempA)) { + depthA++; + } + var depthB = 0; + for (var tempB = instB; tempB; tempB = getParent(tempB)) { + depthB++; + } + + // If A is deeper, crawl up. + while (depthA - depthB > 0) { + instA = getParent(instA); + depthA--; + } + + // If B is deeper, crawl up. + while (depthB - depthA > 0) { + instB = getParent(instB); + depthB--; + } + + // Walk in lockstep until we find a match. + var depth = depthA; + while (depth--) { + if (instA === instB || instA === instB.alternate) { + return instA; + } + instA = getParent(instA); + instB = getParent(instB); + } + return null; +} + +/** + * Return if A is an ancestor of B. + */ +function isAncestor(instA, instB) { + while (instB) { + if (instA === instB || instA === instB.alternate) { + return true; + } + instB = getParent(instB); + } + return false; +} + +/** + * Return the parent instance of the passed-in instance. + */ +function getParentInstance(inst) { + return getParent(inst); +} + +/** + * Simulates the traversal of a two-phase, capture/bubble event dispatch. + */ +function traverseTwoPhase(inst, fn, arg) { + var path = []; + while (inst) { + path.push(inst); + inst = getParent(inst); + } + var i; + for (i = path.length; i-- > 0; ) { + fn(path[i], "captured", arg); + } + for (i = 0; i < path.length; i++) { + fn(path[i], "bubbled", arg); + } +} + +/** + * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that + * should would receive a `mouseEnter` or `mouseLeave` event. + * + * Does not invoke the callback on the nearest common ancestor because nothing + * "entered" or "left" that element. + */ + +/** + * Some event types have a notion of different registration names for different + * "phases" of propagation. This finds listeners by a given phase. + */ +function listenerAtPhase(inst, event, propagationPhase) { + var registrationName = + event.dispatchConfig.phasedRegistrationNames[propagationPhase]; + return getListener(inst, registrationName); +} + +/** + * A small set of propagation patterns, each of which will accept a small amount + * of information, and generate a set of "dispatch ready event objects" - which + * are sets of events that have already been annotated with a set of dispatched + * listener functions/ids. The API is designed this way to discourage these + * propagation strategies from actually executing the dispatches, since we + * always want to collect the entire set of dispatches before executing even a + * single one. + */ + +/** + * Tags a `SyntheticEvent` with dispatched listeners. Creating this function + * here, allows us to not have to bind or create functions for each event. + * Mutating the event's members allows us to not have to create a wrapping + * "dispatch" object that pairs the event with the listener. + */ +function accumulateDirectionalDispatches(inst, phase, event) { + { + warning(inst, "Dispatching inst must not be null"); + } + var listener = listenerAtPhase(inst, event, phase); + if (listener) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + ); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } +} + +/** + * Collect dispatches (must be entirely collected before dispatching - see unit + * tests). Lazily allocate the array to conserve memory. We must loop through + * each event and perform the traversal for each one. We cannot perform a + * single traversal for the entire collection of events because each event may + * have a different target. + */ +function accumulateTwoPhaseDispatchesSingle(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); + } +} + +/** + * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID. + */ +function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + var targetInst = event._targetInst; + var parentInst = targetInst ? getParentInstance(targetInst) : null; + traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event); + } +} + +/** + * Accumulates without regard to direction, does not look for phased + * registration names. Same as `accumulateDirectDispatchesSingle` but without + * requiring that the `dispatchMarker` be the same as the dispatched ID. + */ +function accumulateDispatches(inst, ignoredDirection, event) { + if (inst && event && event.dispatchConfig.registrationName) { + var registrationName = event.dispatchConfig.registrationName; + var listener = getListener(inst, registrationName); + if (listener) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + ); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } + } +} + +/** + * Accumulates dispatches on an `SyntheticEvent`, but only for the + * `dispatchMarker`. + * @param {SyntheticEvent} event + */ +function accumulateDirectDispatchesSingle(event) { + if (event && event.dispatchConfig.registrationName) { + accumulateDispatches(event._targetInst, null, event); + } +} + +function accumulateTwoPhaseDispatches(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); +} + +function accumulateTwoPhaseDispatchesSkipTarget(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget); +} + +function accumulateDirectDispatches(events) { + forEachAccumulated(events, accumulateDirectDispatchesSingle); +} + +/* eslint valid-typeof: 0 */ + +var didWarnForAddedNewProperty = false; +var isProxySupported = typeof Proxy === "function"; +var EVENT_POOL_SIZE = 10; + +var shouldBeReleasedProperties = [ + "dispatchConfig", + "_targetInst", + "nativeEvent", + "isDefaultPrevented", + "isPropagationStopped", + "_dispatchListeners", + "_dispatchInstances" +]; + +/** + * @interface Event + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ +var EventInterface = { + type: null, + target: null, + // currentTarget is set when dispatching; no use in copying it here + currentTarget: emptyFunction.thatReturnsNull, + eventPhase: null, + bubbles: null, + cancelable: null, + timeStamp: function(event) { + return event.timeStamp || Date.now(); + }, + defaultPrevented: null, + isTrusted: null +}; + +/** + * Synthetic events are dispatched by event plugins, typically in response to a + * top-level event delegation handler. + * + * These systems should generally use pooling to reduce the frequency of garbage + * collection. The system should check `isPersistent` to determine whether the + * event should be released into the pool after being dispatched. Users that + * need a persisted event should invoke `persist`. + * + * Synthetic events (and subclasses) implement the DOM Level 3 Events API by + * normalizing browser quirks. Subclasses do not necessarily have to implement a + * DOM interface; custom application-specific events can also subclass this. + * + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {*} targetInst Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @param {DOMEventTarget} nativeEventTarget Target node. + */ +function SyntheticEvent( + dispatchConfig, + targetInst, + nativeEvent, + nativeEventTarget +) { + { + // these have a getter/setter for warnings + delete this.nativeEvent; + delete this.preventDefault; + delete this.stopPropagation; + } + + this.dispatchConfig = dispatchConfig; + this._targetInst = targetInst; + this.nativeEvent = nativeEvent; + + var Interface = this.constructor.Interface; + for (var propName in Interface) { + if (!Interface.hasOwnProperty(propName)) { + continue; + } + { + delete this[propName]; // this has a getter/setter for warnings + } + var normalize = Interface[propName]; + if (normalize) { + this[propName] = normalize(nativeEvent); + } else { + if (propName === "target") { + this.target = nativeEventTarget; + } else { + this[propName] = nativeEvent[propName]; + } + } + } + + var defaultPrevented = + nativeEvent.defaultPrevented != null + ? nativeEvent.defaultPrevented + : nativeEvent.returnValue === false; + if (defaultPrevented) { + this.isDefaultPrevented = emptyFunction.thatReturnsTrue; + } else { + this.isDefaultPrevented = emptyFunction.thatReturnsFalse; + } + this.isPropagationStopped = emptyFunction.thatReturnsFalse; + return this; +} + +Object.assign(SyntheticEvent.prototype, { + preventDefault: function() { + this.defaultPrevented = true; + var event = this.nativeEvent; + if (!event) { + return; + } + + if (event.preventDefault) { + event.preventDefault(); + } else if (typeof event.returnValue !== "unknown") { + event.returnValue = false; + } + this.isDefaultPrevented = emptyFunction.thatReturnsTrue; + }, + + stopPropagation: function() { + var event = this.nativeEvent; + if (!event) { + return; + } + + if (event.stopPropagation) { + event.stopPropagation(); + } else if (typeof event.cancelBubble !== "unknown") { + // The ChangeEventPlugin registers a "propertychange" event for + // IE. This event does not support bubbling or cancelling, and + // any references to cancelBubble throw "Member not found". A + // typeof check of "unknown" circumvents this issue (and is also + // IE specific). + event.cancelBubble = true; + } + + this.isPropagationStopped = emptyFunction.thatReturnsTrue; + }, + + /** + * We release all dispatched `SyntheticEvent`s after each event loop, adding + * them back into the pool. This allows a way to hold onto a reference that + * won't be added back into the pool. + */ + persist: function() { + this.isPersistent = emptyFunction.thatReturnsTrue; + }, + + /** + * Checks if this event should be released back into the pool. + * + * @return {boolean} True if this should not be released, false otherwise. + */ + isPersistent: emptyFunction.thatReturnsFalse, + + /** + * `PooledClass` looks for `destructor` on each instance it releases. + */ + destructor: function() { + var Interface = this.constructor.Interface; + for (var propName in Interface) { + { + Object.defineProperty( + this, + propName, + getPooledWarningPropertyDefinition(propName, Interface[propName]) + ); + } + } + for (var i = 0; i < shouldBeReleasedProperties.length; i++) { + this[shouldBeReleasedProperties[i]] = null; + } + { + Object.defineProperty( + this, + "nativeEvent", + getPooledWarningPropertyDefinition("nativeEvent", null) + ); + Object.defineProperty( + this, + "preventDefault", + getPooledWarningPropertyDefinition("preventDefault", emptyFunction) + ); + Object.defineProperty( + this, + "stopPropagation", + getPooledWarningPropertyDefinition("stopPropagation", emptyFunction) + ); + } + } +}); + +SyntheticEvent.Interface = EventInterface; + +/** + * Helper to reduce boilerplate when creating subclasses. + * + * @param {function} Class + * @param {?object} Interface + */ +SyntheticEvent.augmentClass = function(Class, Interface) { + var Super = this; + + var E = function() {}; + E.prototype = Super.prototype; + var prototype = new E(); + + Object.assign(prototype, Class.prototype); + Class.prototype = prototype; + Class.prototype.constructor = Class; + + Class.Interface = Object.assign({}, Super.Interface, Interface); + Class.augmentClass = Super.augmentClass; + addEventPoolingTo(Class); +}; + +/** Proxying after everything set on SyntheticEvent + * to resolve Proxy issue on some WebKit browsers + * in which some Event properties are set to undefined (GH#10010) + */ +{ + if (isProxySupported) { + /*eslint-disable no-func-assign */ + SyntheticEvent = new Proxy(SyntheticEvent, { + construct: function(target, args) { + return this.apply(target, Object.create(target.prototype), args); + }, + apply: function(constructor, that, args) { + return new Proxy(constructor.apply(that, args), { + set: function(target, prop, value) { + if ( + prop !== "isPersistent" && + !target.constructor.Interface.hasOwnProperty(prop) && + shouldBeReleasedProperties.indexOf(prop) === -1 + ) { + warning( + didWarnForAddedNewProperty || target.isPersistent(), + "This synthetic event is reused for performance reasons. If you're " + + "seeing this, you're adding a new property in the synthetic event object. " + + "The property is never released. See " + + "https://fb.me/react-event-pooling for more information." + ); + didWarnForAddedNewProperty = true; + } + target[prop] = value; + return true; + } + }); + } + }); + /*eslint-enable no-func-assign */ + } +} + +addEventPoolingTo(SyntheticEvent); + +/** + * Helper to nullify syntheticEvent instance properties when destructing + * + * @param {String} propName + * @param {?object} getVal + * @return {object} defineProperty object + */ +function getPooledWarningPropertyDefinition(propName, getVal) { + var isFunction = typeof getVal === "function"; + return { + configurable: true, + set: set, + get: get + }; + + function set(val) { + var action = isFunction ? "setting the method" : "setting the property"; + warn(action, "This is effectively a no-op"); + return val; + } + + function get() { + var action = isFunction ? "accessing the method" : "accessing the property"; + var result = isFunction + ? "This is a no-op function" + : "This is set to null"; + warn(action, result); + return getVal; + } + + function warn(action, result) { + var warningCondition = false; + warning( + warningCondition, + "This synthetic event is reused for performance reasons. If you're seeing this, " + + "you're %s `%s` on a released/nullified synthetic event. %s. " + + "If you must keep the original synthetic event around, use event.persist(). " + + "See https://fb.me/react-event-pooling for more information.", + action, + propName, + result + ); + } +} + +function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) { + var EventConstructor = this; + if (EventConstructor.eventPool.length) { + var instance = EventConstructor.eventPool.pop(); + EventConstructor.call( + instance, + dispatchConfig, + targetInst, + nativeEvent, + nativeInst + ); + return instance; + } + return new EventConstructor( + dispatchConfig, + targetInst, + nativeEvent, + nativeInst + ); +} + +function releasePooledEvent(event) { + var EventConstructor = this; + invariant( + event instanceof EventConstructor, + "Trying to release an event instance into a pool of a different type." + ); + event.destructor(); + if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) { + EventConstructor.eventPool.push(event); + } +} + +function addEventPoolingTo(EventConstructor) { + EventConstructor.eventPool = []; + EventConstructor.getPooled = getPooledEvent; + EventConstructor.release = releasePooledEvent; +} + +var SyntheticEvent$1 = SyntheticEvent; + +/** + * `touchHistory` isn't actually on the native event, but putting it in the + * interface will ensure that it is cleaned up when pooled/destroyed. The + * `ResponderEventPlugin` will populate it appropriately. + */ +var ResponderEventInterface = { + touchHistory: function(nativeEvent) { + return null; // Actually doesn't even look at the native event. + } +}; + +/** + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {string} dispatchMarker Marker identifying the event target. + * @param {object} nativeEvent Native event. + * @extends {SyntheticEvent} + */ +function ResponderSyntheticEvent( + dispatchConfig, + dispatchMarker, + nativeEvent, + nativeEventTarget +) { + return SyntheticEvent$1.call( + this, + dispatchConfig, + dispatchMarker, + nativeEvent, + nativeEventTarget + ); +} + +SyntheticEvent$1.augmentClass(ResponderSyntheticEvent, ResponderEventInterface); + +/** + * Tracks the position and time of each active touch by `touch.identifier`. We + * should typically only see IDs in the range of 1-20 because IDs get recycled + * when touches end and start again. + */ + +var MAX_TOUCH_BANK = 20; +var touchBank = []; +var touchHistory = { + touchBank: touchBank, + numberActiveTouches: 0, + // If there is only one active touch, we remember its location. This prevents + // us having to loop through all of the touches all the time in the most + // common case. + indexOfSingleActiveTouch: -1, + mostRecentTimeStamp: 0 +}; + +function timestampForTouch(touch) { + // The legacy internal implementation provides "timeStamp", which has been + // renamed to "timestamp". Let both work for now while we iron it out + // TODO (evv): rename timeStamp to timestamp in internal code + return touch.timeStamp || touch.timestamp; +} + +/** + * TODO: Instead of making gestures recompute filtered velocity, we could + * include a built in velocity computation that can be reused globally. + */ +function createTouchRecord(touch) { + return { + touchActive: true, + startPageX: touch.pageX, + startPageY: touch.pageY, + startTimeStamp: timestampForTouch(touch), + currentPageX: touch.pageX, + currentPageY: touch.pageY, + currentTimeStamp: timestampForTouch(touch), + previousPageX: touch.pageX, + previousPageY: touch.pageY, + previousTimeStamp: timestampForTouch(touch) + }; +} + +function resetTouchRecord(touchRecord, touch) { + touchRecord.touchActive = true; + touchRecord.startPageX = touch.pageX; + touchRecord.startPageY = touch.pageY; + touchRecord.startTimeStamp = timestampForTouch(touch); + touchRecord.currentPageX = touch.pageX; + touchRecord.currentPageY = touch.pageY; + touchRecord.currentTimeStamp = timestampForTouch(touch); + touchRecord.previousPageX = touch.pageX; + touchRecord.previousPageY = touch.pageY; + touchRecord.previousTimeStamp = timestampForTouch(touch); +} + +function getTouchIdentifier(_ref) { + var identifier = _ref.identifier; + + invariant(identifier != null, "Touch object is missing identifier."); + { + warning( + identifier <= MAX_TOUCH_BANK, + "Touch identifier %s is greater than maximum supported %s which causes " + + "performance issues backfilling array locations for all of the indices.", + identifier, + MAX_TOUCH_BANK + ); + } + return identifier; +} + +function recordTouchStart(touch) { + var identifier = getTouchIdentifier(touch); + var touchRecord = touchBank[identifier]; + if (touchRecord) { + resetTouchRecord(touchRecord, touch); + } else { + touchBank[identifier] = createTouchRecord(touch); + } + touchHistory.mostRecentTimeStamp = timestampForTouch(touch); +} + +function recordTouchMove(touch) { + var touchRecord = touchBank[getTouchIdentifier(touch)]; + if (touchRecord) { + touchRecord.touchActive = true; + touchRecord.previousPageX = touchRecord.currentPageX; + touchRecord.previousPageY = touchRecord.currentPageY; + touchRecord.previousTimeStamp = touchRecord.currentTimeStamp; + touchRecord.currentPageX = touch.pageX; + touchRecord.currentPageY = touch.pageY; + touchRecord.currentTimeStamp = timestampForTouch(touch); + touchHistory.mostRecentTimeStamp = timestampForTouch(touch); + } else { + console.error( + "Cannot record touch move without a touch start.\n" + "Touch Move: %s\n", + "Touch Bank: %s", + printTouch(touch), + printTouchBank() + ); + } +} + +function recordTouchEnd(touch) { + var touchRecord = touchBank[getTouchIdentifier(touch)]; + if (touchRecord) { + touchRecord.touchActive = false; + touchRecord.previousPageX = touchRecord.currentPageX; + touchRecord.previousPageY = touchRecord.currentPageY; + touchRecord.previousTimeStamp = touchRecord.currentTimeStamp; + touchRecord.currentPageX = touch.pageX; + touchRecord.currentPageY = touch.pageY; + touchRecord.currentTimeStamp = timestampForTouch(touch); + touchHistory.mostRecentTimeStamp = timestampForTouch(touch); + } else { + console.error( + "Cannot record touch end without a touch start.\n" + "Touch End: %s\n", + "Touch Bank: %s", + printTouch(touch), + printTouchBank() + ); + } +} + +function printTouch(touch) { + return JSON.stringify({ + identifier: touch.identifier, + pageX: touch.pageX, + pageY: touch.pageY, + timestamp: timestampForTouch(touch) + }); +} + +function printTouchBank() { + var printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK)); + if (touchBank.length > MAX_TOUCH_BANK) { + printed += " (original size: " + touchBank.length + ")"; + } + return printed; +} + +var ResponderTouchHistoryStore = { + recordTouchTrack: function(topLevelType, nativeEvent) { + if (isMoveish(topLevelType)) { + nativeEvent.changedTouches.forEach(recordTouchMove); + } else if (isStartish(topLevelType)) { + nativeEvent.changedTouches.forEach(recordTouchStart); + touchHistory.numberActiveTouches = nativeEvent.touches.length; + if (touchHistory.numberActiveTouches === 1) { + touchHistory.indexOfSingleActiveTouch = + nativeEvent.touches[0].identifier; + } + } else if (isEndish(topLevelType)) { + nativeEvent.changedTouches.forEach(recordTouchEnd); + touchHistory.numberActiveTouches = nativeEvent.touches.length; + if (touchHistory.numberActiveTouches === 1) { + for (var i = 0; i < touchBank.length; i++) { + var touchTrackToCheck = touchBank[i]; + if (touchTrackToCheck != null && touchTrackToCheck.touchActive) { + touchHistory.indexOfSingleActiveTouch = i; + break; + } + } + { + var activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch]; + warning( + activeRecord != null && activeRecord.touchActive, + "Cannot find single active touch." + ); + } + } + } + }, + + touchHistory: touchHistory +}; + +/** + * Accumulates items that must not be null or undefined. + * + * This is used to conserve memory by avoiding array allocations. + * + * @return {*|array<*>} An accumulation of items. + */ +function accumulate(current, next) { + invariant( + next != null, + "accumulate(...): Accumulated items must be not be null or undefined." + ); + + if (current == null) { + return next; + } + + // Both are not empty. Warning: Never call x.concat(y) when you are not + // certain that x is an Array (x could be a string with concat method). + if (Array.isArray(current)) { + return current.concat(next); + } + + if (Array.isArray(next)) { + return [current].concat(next); + } + + return [current, next]; +} + +/** + * Instance of element that should respond to touch/move types of interactions, + * as indicated explicitly by relevant callbacks. + */ +var responderInst = null; + +/** + * Count of current touches. A textInput should become responder iff the + * selection changes while there is a touch on the screen. + */ +var trackedTouchCount = 0; + +/** + * Last reported number of active touches. + */ +var previousActiveTouches = 0; + +var changeResponder = function(nextResponderInst, blockHostResponder) { + var oldResponderInst = responderInst; + responderInst = nextResponderInst; + if (ResponderEventPlugin.GlobalResponderHandler !== null) { + ResponderEventPlugin.GlobalResponderHandler.onChange( + oldResponderInst, + nextResponderInst, + blockHostResponder + ); + } +}; + +var eventTypes = { + /** + * On a `touchStart`/`mouseDown`, is it desired that this element become the + * responder? + */ + startShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onStartShouldSetResponder", + captured: "onStartShouldSetResponderCapture" + } + }, + + /** + * On a `scroll`, is it desired that this element become the responder? This + * is usually not needed, but should be used to retroactively infer that a + * `touchStart` had occurred during momentum scroll. During a momentum scroll, + * a touch start will be immediately followed by a scroll event if the view is + * currently scrolling. + * + * TODO: This shouldn't bubble. + */ + scrollShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onScrollShouldSetResponder", + captured: "onScrollShouldSetResponderCapture" + } + }, + + /** + * On text selection change, should this element become the responder? This + * is needed for text inputs or other views with native selection, so the + * JS view can claim the responder. + * + * TODO: This shouldn't bubble. + */ + selectionChangeShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onSelectionChangeShouldSetResponder", + captured: "onSelectionChangeShouldSetResponderCapture" + } + }, + + /** + * On a `touchMove`/`mouseMove`, is it desired that this element become the + * responder? + */ + moveShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onMoveShouldSetResponder", + captured: "onMoveShouldSetResponderCapture" + } + }, + + /** + * Direct responder events dispatched directly to responder. Do not bubble. + */ + responderStart: { registrationName: "onResponderStart" }, + responderMove: { registrationName: "onResponderMove" }, + responderEnd: { registrationName: "onResponderEnd" }, + responderRelease: { registrationName: "onResponderRelease" }, + responderTerminationRequest: { + registrationName: "onResponderTerminationRequest" + }, + responderGrant: { registrationName: "onResponderGrant" }, + responderReject: { registrationName: "onResponderReject" }, + responderTerminate: { registrationName: "onResponderTerminate" } +}; + +/** + * + * Responder System: + * ---------------- + * + * - A global, solitary "interaction lock" on a view. + * - If a node becomes the responder, it should convey visual feedback + * immediately to indicate so, either by highlighting or moving accordingly. + * - To be the responder means, that touches are exclusively important to that + * responder view, and no other view. + * - While touches are still occurring, the responder lock can be transferred to + * a new view, but only to increasingly "higher" views (meaning ancestors of + * the current responder). + * + * Responder being granted: + * ------------------------ + * + * - Touch starts, moves, and scrolls can cause an ID to become the responder. + * - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to + * the "appropriate place". + * - If nothing is currently the responder, the "appropriate place" is the + * initiating event's `targetID`. + * - If something *is* already the responder, the "appropriate place" is the + * first common ancestor of the event target and the current `responderInst`. + * - Some negotiation happens: See the timing diagram below. + * - Scrolled views automatically become responder. The reasoning is that a + * platform scroll view that isn't built on top of the responder system has + * began scrolling, and the active responder must now be notified that the + * interaction is no longer locked to it - the system has taken over. + * + * - Responder being released: + * As soon as no more touches that *started* inside of descendants of the + * *current* responderInst, an `onResponderRelease` event is dispatched to the + * current responder, and the responder lock is released. + * + * TODO: + * - on "end", a callback hook for `onResponderEndShouldRemainResponder` that + * determines if the responder lock should remain. + * - If a view shouldn't "remain" the responder, any active touches should by + * default be considered "dead" and do not influence future negotiations or + * bubble paths. It should be as if those touches do not exist. + * -- For multitouch: Usually a translate-z will choose to "remain" responder + * after one out of many touches ended. For translate-y, usually the view + * doesn't wish to "remain" responder after one of many touches end. + * - Consider building this on top of a `stopPropagation` model similar to + * `W3C` events. + * - Ensure that `onResponderTerminate` is called on touch cancels, whether or + * not `onResponderTerminationRequest` returns `true` or `false`. + * + */ + +/* Negotiation Performed + +-----------------------+ + / \ +Process low level events to + Current Responder + wantsResponderID +determine who to perform negot-| (if any exists at all) | +iation/transition | Otherwise just pass through| +-------------------------------+----------------------------+------------------+ +Bubble to find first ID | | +to return true:wantsResponderID| | + | | + +-------------+ | | + | onTouchStart| | | + +------+------+ none | | + | return| | ++-----------v-------------+true| +------------------------+ | +|onStartShouldSetResponder|----->|onResponderStart (cur) |<-----------+ ++-----------+-------------+ | +------------------------+ | | + | | | +--------+-------+ + | returned true for| false:REJECT +-------->|onResponderReject + | wantsResponderID | | | +----------------+ + | (now attempt | +------------------+-----+ | + | handoff) | | onResponder | | + +------------------->| TerminationRequest| | + | +------------------+-----+ | + | | | +----------------+ + | true:GRANT +-------->|onResponderGrant| + | | +--------+-------+ + | +------------------------+ | | + | | onResponderTerminate |<-----------+ + | +------------------+-----+ | + | | | +----------------+ + | +-------->|onResponderStart| + | | +----------------+ +Bubble to find first ID | | +to return true:wantsResponderID| | + | | + +-------------+ | | + | onTouchMove | | | + +------+------+ none | | + | return| | ++-----------v-------------+true| +------------------------+ | +|onMoveShouldSetResponder |----->|onResponderMove (cur) |<-----------+ ++-----------+-------------+ | +------------------------+ | | + | | | +--------+-------+ + | returned true for| false:REJECT +-------->|onResponderRejec| + | wantsResponderID | | | +----------------+ + | (now attempt | +------------------+-----+ | + | handoff) | | onResponder | | + +------------------->| TerminationRequest| | + | +------------------+-----+ | + | | | +----------------+ + | true:GRANT +-------->|onResponderGrant| + | | +--------+-------+ + | +------------------------+ | | + | | onResponderTerminate |<-----------+ + | +------------------+-----+ | + | | | +----------------+ + | +-------->|onResponderMove | + | | +----------------+ + | | + | | + Some active touch started| | + inside current responder | +------------------------+ | + +------------------------->| onResponderEnd | | + | | +------------------------+ | + +---+---------+ | | + | onTouchEnd | | | + +---+---------+ | | + | | +------------------------+ | + +------------------------->| onResponderEnd | | + No active touches started| +-----------+------------+ | + inside current responder | | | + | v | + | +------------------------+ | + | | onResponderRelease | | + | +------------------------+ | + | | + + + */ + +/** + * A note about event ordering in the `EventPluginHub`. + * + * Suppose plugins are injected in the following order: + * + * `[R, S, C]` + * + * To help illustrate the example, assume `S` is `SimpleEventPlugin` (for + * `onClick` etc) and `R` is `ResponderEventPlugin`. + * + * "Deferred-Dispatched Events": + * + * - The current event plugin system will traverse the list of injected plugins, + * in order, and extract events by collecting the plugin's return value of + * `extractEvents()`. + * - These events that are returned from `extractEvents` are "deferred + * dispatched events". + * - When returned from `extractEvents`, deferred-dispatched events contain an + * "accumulation" of deferred dispatches. + * - These deferred dispatches are accumulated/collected before they are + * returned, but processed at a later time by the `EventPluginHub` (hence the + * name deferred). + * + * In the process of returning their deferred-dispatched events, event plugins + * themselves can dispatch events on-demand without returning them from + * `extractEvents`. Plugins might want to do this, so that they can use event + * dispatching as a tool that helps them decide which events should be extracted + * in the first place. + * + * "On-Demand-Dispatched Events": + * + * - On-demand-dispatched events are not returned from `extractEvents`. + * - On-demand-dispatched events are dispatched during the process of returning + * the deferred-dispatched events. + * - They should not have side effects. + * - They should be avoided, and/or eventually be replaced with another + * abstraction that allows event plugins to perform multiple "rounds" of event + * extraction. + * + * Therefore, the sequence of event dispatches becomes: + * + * - `R`s on-demand events (if any) (dispatched by `R` on-demand) + * - `S`s on-demand events (if any) (dispatched by `S` on-demand) + * - `C`s on-demand events (if any) (dispatched by `C` on-demand) + * - `R`s extracted events (if any) (dispatched by `EventPluginHub`) + * - `S`s extracted events (if any) (dispatched by `EventPluginHub`) + * - `C`s extracted events (if any) (dispatched by `EventPluginHub`) + * + * In the case of `ResponderEventPlugin`: If the `startShouldSetResponder` + * on-demand dispatch returns `true` (and some other details are satisfied) the + * `onResponderGrant` deferred dispatched event is returned from + * `extractEvents`. The sequence of dispatch executions in this case + * will appear as follows: + * + * - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand) + * - `touchStartCapture` (`EventPluginHub` dispatches as usual) + * - `touchStart` (`EventPluginHub` dispatches as usual) + * - `responderGrant/Reject` (`EventPluginHub` dispatches as usual) + */ + +function setResponderAndExtractTransfer( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget +) { + var shouldSetEventType = isStartish(topLevelType) + ? eventTypes.startShouldSetResponder + : isMoveish(topLevelType) + ? eventTypes.moveShouldSetResponder + : topLevelType === "topSelectionChange" + ? eventTypes.selectionChangeShouldSetResponder + : eventTypes.scrollShouldSetResponder; + + // TODO: stop one short of the current responder. + var bubbleShouldSetFrom = !responderInst + ? targetInst + : getLowestCommonAncestor(responderInst, targetInst); + + // When capturing/bubbling the "shouldSet" event, we want to skip the target + // (deepest ID) if it happens to be the current responder. The reasoning: + // It's strange to get an `onMoveShouldSetResponder` when you're *already* + // the responder. + var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst; + var shouldSetEvent = ResponderSyntheticEvent.getPooled( + shouldSetEventType, + bubbleShouldSetFrom, + nativeEvent, + nativeEventTarget + ); + shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + if (skipOverBubbleShouldSetFrom) { + accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent); + } else { + accumulateTwoPhaseDispatches(shouldSetEvent); + } + var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent); + if (!shouldSetEvent.isPersistent()) { + shouldSetEvent.constructor.release(shouldSetEvent); + } + + if (!wantsResponderInst || wantsResponderInst === responderInst) { + return null; + } + var extracted; + var grantEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderGrant, + wantsResponderInst, + nativeEvent, + nativeEventTarget + ); + grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + + accumulateDirectDispatches(grantEvent); + var blockHostResponder = executeDirectDispatch(grantEvent) === true; + if (responderInst) { + var terminationRequestEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminationRequest, + responderInst, + nativeEvent, + nativeEventTarget + ); + terminationRequestEvent.touchHistory = + ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(terminationRequestEvent); + var shouldSwitch = + !hasDispatches(terminationRequestEvent) || + executeDirectDispatch(terminationRequestEvent); + if (!terminationRequestEvent.isPersistent()) { + terminationRequestEvent.constructor.release(terminationRequestEvent); + } + + if (shouldSwitch) { + var terminateEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminate, + responderInst, + nativeEvent, + nativeEventTarget + ); + terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(terminateEvent); + extracted = accumulate(extracted, [grantEvent, terminateEvent]); + changeResponder(wantsResponderInst, blockHostResponder); + } else { + var rejectEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderReject, + wantsResponderInst, + nativeEvent, + nativeEventTarget + ); + rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(rejectEvent); + extracted = accumulate(extracted, rejectEvent); + } + } else { + extracted = accumulate(extracted, grantEvent); + changeResponder(wantsResponderInst, blockHostResponder); + } + return extracted; +} + +/** + * A transfer is a negotiation between a currently set responder and the next + * element to claim responder status. Any start event could trigger a transfer + * of responderInst. Any move event could trigger a transfer. + * + * @param {string} topLevelType Record from `BrowserEventConstants`. + * @return {boolean} True if a transfer of responder could possibly occur. + */ +function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) { + return ( + topLevelInst && + // responderIgnoreScroll: We are trying to migrate away from specifically + // tracking native scroll events here and responderIgnoreScroll indicates we + // will send topTouchCancel to handle canceling touch events instead + ((topLevelType === "topScroll" && !nativeEvent.responderIgnoreScroll) || + (trackedTouchCount > 0 && topLevelType === "topSelectionChange") || + isStartish(topLevelType) || + isMoveish(topLevelType)) + ); +} + +/** + * Returns whether or not this touch end event makes it such that there are no + * longer any touches that started inside of the current `responderInst`. + * + * @param {NativeEvent} nativeEvent Native touch end event. + * @return {boolean} Whether or not this touch end event ends the responder. + */ +function noResponderTouches(nativeEvent) { + var touches = nativeEvent.touches; + if (!touches || touches.length === 0) { + return true; + } + for (var i = 0; i < touches.length; i++) { + var activeTouch = touches[i]; + var target = activeTouch.target; + if (target !== null && target !== undefined && target !== 0) { + // Is the original touch location inside of the current responder? + var targetInst = getInstanceFromNode(target); + if (isAncestor(responderInst, targetInst)) { + return false; + } + } + } + return true; +} + +var ResponderEventPlugin = { + /* For unit testing only */ + _getResponder: function() { + return responderInst; + }, + + eventTypes: eventTypes, + + /** + * We must be resilient to `targetInst` being `null` on `touchMove` or + * `touchEnd`. On certain platforms, this means that a native scroll has + * assumed control and the original touch targets are destroyed. + */ + extractEvents: function( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + if (isStartish(topLevelType)) { + trackedTouchCount += 1; + } else if (isEndish(topLevelType)) { + if (trackedTouchCount >= 0) { + trackedTouchCount -= 1; + } else { + console.error( + "Ended a touch event which was not counted in `trackedTouchCount`." + ); + return null; + } + } + + ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent); + + var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent) + ? setResponderAndExtractTransfer( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) + : null; + // Responder may or may not have transferred on a new touch start/move. + // Regardless, whoever is the responder after any potential transfer, we + // direct all touch start/move/ends to them in the form of + // `onResponderMove/Start/End`. These will be called for *every* additional + // finger that move/start/end, dispatched directly to whoever is the + // current responder at that moment, until the responder is "released". + // + // These multiple individual change touch events are are always bookended + // by `onResponderGrant`, and one of + // (`onResponderRelease/onResponderTerminate`). + var isResponderTouchStart = responderInst && isStartish(topLevelType); + var isResponderTouchMove = responderInst && isMoveish(topLevelType); + var isResponderTouchEnd = responderInst && isEndish(topLevelType); + var incrementalTouch = isResponderTouchStart + ? eventTypes.responderStart + : isResponderTouchMove + ? eventTypes.responderMove + : isResponderTouchEnd ? eventTypes.responderEnd : null; + + if (incrementalTouch) { + var gesture = ResponderSyntheticEvent.getPooled( + incrementalTouch, + responderInst, + nativeEvent, + nativeEventTarget + ); + gesture.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(gesture); + extracted = accumulate(extracted, gesture); + } + + var isResponderTerminate = + responderInst && topLevelType === "topTouchCancel"; + var isResponderRelease = + responderInst && + !isResponderTerminate && + isEndish(topLevelType) && + noResponderTouches(nativeEvent); + var finalTouch = isResponderTerminate + ? eventTypes.responderTerminate + : isResponderRelease ? eventTypes.responderRelease : null; + if (finalTouch) { + var finalEvent = ResponderSyntheticEvent.getPooled( + finalTouch, + responderInst, + nativeEvent, + nativeEventTarget + ); + finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(finalEvent); + extracted = accumulate(extracted, finalEvent); + changeResponder(null); + } + + var numberActiveTouches = + ResponderTouchHistoryStore.touchHistory.numberActiveTouches; + if ( + ResponderEventPlugin.GlobalInteractionHandler && + numberActiveTouches !== previousActiveTouches + ) { + ResponderEventPlugin.GlobalInteractionHandler.onChange( + numberActiveTouches + ); + } + previousActiveTouches = numberActiveTouches; + + return extracted; + }, + + GlobalResponderHandler: null, + GlobalInteractionHandler: null, + + injection: { + /** + * @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler + * Object that handles any change in responder. Use this to inject + * integration with an existing touch handling system etc. + */ + injectGlobalResponderHandler: function(GlobalResponderHandler) { + ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; + }, + + /** + * @param {{onChange: (numberActiveTouches) => void} GlobalInteractionHandler + * Object that handles any change in the number of active touches. + */ + injectGlobalInteractionHandler: function(GlobalInteractionHandler) { + ResponderEventPlugin.GlobalInteractionHandler = GlobalInteractionHandler; + } + } +}; + +var customBubblingEventTypes = {}; +var customDirectEventTypes = {}; + +var ReactNativeBridgeEventPlugin = { + eventTypes: {}, + + /** + * @see {EventPluginHub.extractEvents} + */ + extractEvents: function( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + var bubbleDispatchConfig = customBubblingEventTypes[topLevelType]; + var directDispatchConfig = customDirectEventTypes[topLevelType]; + invariant( + bubbleDispatchConfig || directDispatchConfig, + 'Unsupported top level event type "%s" dispatched', + topLevelType + ); + var event = SyntheticEvent$1.getPooled( + bubbleDispatchConfig || directDispatchConfig, + targetInst, + nativeEvent, + nativeEventTarget + ); + if (bubbleDispatchConfig) { + accumulateTwoPhaseDispatches(event); + } else if (directDispatchConfig) { + accumulateDirectDispatches(event); + } else { + return null; + } + return event; + }, + + processEventTypes: function(viewConfig) { + var bubblingEventTypes = viewConfig.bubblingEventTypes, + directEventTypes = viewConfig.directEventTypes; + + { + if (bubblingEventTypes != null && directEventTypes != null) { + for (var topLevelType in directEventTypes) { + invariant( + bubblingEventTypes[topLevelType] == null, + "Event cannot be both direct and bubbling: %s", + topLevelType + ); + } + } + } + + if (bubblingEventTypes != null) { + for (var _topLevelType in bubblingEventTypes) { + if (customBubblingEventTypes[_topLevelType] == null) { + ReactNativeBridgeEventPlugin.eventTypes[ + _topLevelType + ] = customBubblingEventTypes[_topLevelType] = + bubblingEventTypes[_topLevelType]; + } + } + } + + if (directEventTypes != null) { + for (var _topLevelType2 in directEventTypes) { + if (customDirectEventTypes[_topLevelType2] == null) { + ReactNativeBridgeEventPlugin.eventTypes[ + _topLevelType2 + ] = customDirectEventTypes[_topLevelType2] = + directEventTypes[_topLevelType2]; + } + } + } + } +}; + +var instanceCache = {}; +var instanceProps = {}; + +function precacheFiberNode(hostInst, tag) { + instanceCache[tag] = hostInst; +} + +function uncacheFiberNode(tag) { + delete instanceCache[tag]; + delete instanceProps[tag]; +} + +function getInstanceFromTag(tag) { + return instanceCache[tag] || null; +} + +function getTagFromInstance(inst) { + var tag = inst.stateNode._nativeTag; + invariant(tag, "All native instances should have a tag."); + return tag; +} + +function getFiberCurrentPropsFromNode$1(stateNode) { + return instanceProps[stateNode._nativeTag] || null; +} + +function updateFiberProps(tag, props) { + instanceProps[tag] = props; +} + +var ReactNativeComponentTree = Object.freeze({ + precacheFiberNode: precacheFiberNode, + uncacheFiberNode: uncacheFiberNode, + getClosestInstanceFromNode: getInstanceFromTag, + getInstanceFromNode: getInstanceFromTag, + getNodeFromInstance: getTagFromInstance, + getFiberCurrentPropsFromNode: getFiberCurrentPropsFromNode$1, + updateFiberProps: updateFiberProps +}); + +// Use to restore controlled state after a change event has fired. + +var fiberHostComponent = null; + +var restoreTarget = null; +var restoreQueue = null; + +function restoreStateOfTarget(target) { + // We perform this translation at the end of the event loop so that we + // always receive the correct fiber here + var internalInstance = getInstanceFromNode(target); + if (!internalInstance) { + // Unmounted + return; + } + invariant( + fiberHostComponent && + typeof fiberHostComponent.restoreControlledState === "function", + "Fiber needs to be injected to handle a fiber target for controlled " + + "events. This error is likely caused by a bug in React. Please file an issue." + ); + var props = getFiberCurrentPropsFromNode(internalInstance.stateNode); + fiberHostComponent.restoreControlledState( + internalInstance.stateNode, + internalInstance.type, + props + ); +} + +function restoreStateIfNeeded() { + if (!restoreTarget) { + return; + } + var target = restoreTarget; + var queuedTargets = restoreQueue; + restoreTarget = null; + restoreQueue = null; + + restoreStateOfTarget(target); + if (queuedTargets) { + for (var i = 0; i < queuedTargets.length; i++) { + restoreStateOfTarget(queuedTargets[i]); + } + } +} + +// Used as a way to call batchedUpdates when we don't have a reference to +// the renderer. Such as when we're dispatching events or if third party +// libraries need to call batchedUpdates. Eventually, this API will go away when +// everything is batched by default. We'll then have a similar API to opt-out of +// scheduled work and instead do synchronous work. + +// Defaults +var fiberBatchedUpdates = function(fn, bookkeeping) { + return fn(bookkeeping); +}; + +var isNestingBatched = false; +function batchedUpdates(fn, bookkeeping) { + if (isNestingBatched) { + // If we are currently inside another batch, we need to wait until it + // fully completes before restoring state. Therefore, we add the target to + // a queue of work. + return fiberBatchedUpdates(fn, bookkeeping); + } + isNestingBatched = true; + try { + return fiberBatchedUpdates(fn, bookkeeping); + } finally { + // Here we wait until all updates have propagated, which is important + // when using controlled components within layers: + // https://github.com/facebook/react/issues/1698 + // Then we restore state of any controlled component. + isNestingBatched = false; + restoreStateIfNeeded(); + } +} + +var ReactGenericBatchingInjection = { + injectFiberBatchedUpdates: function(_batchedUpdates) { + fiberBatchedUpdates = _batchedUpdates; + } +}; + +var injection$2 = ReactGenericBatchingInjection; + +function runEventQueueInBatch(events) { + enqueueEvents(events); + processEventQueue(false); +} + +/** + * Streams a fired top-level event to `EventPluginHub` where plugins have the + * opportunity to create `ReactEvent`s to be dispatched. + */ +function handleTopLevel( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget +) { + var events = extractEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ); + runEventQueueInBatch(events); +} + +/** + * Keeps track of allocating and associating native "tags" which are numeric, + * unique view IDs. All the native tags are negative numbers, to avoid + * collisions, but in the JS we keep track of them as positive integers to store + * them effectively in Arrays. So we must refer to them as "inverses" of the + * native tags (that are * normally negative). + * + * It *must* be the case that every `rootNodeID` always maps to the exact same + * `tag` forever. The easiest way to accomplish this is to never delete + * anything from this table. + * Why: Because `dangerouslyReplaceNodeWithMarkupByID` relies on being able to + * unmount a component with a `rootNodeID`, then mount a new one in its place, + */ +var INITIAL_TAG_COUNT = 1; +var ReactNativeTagHandles = { + tagsStartAt: INITIAL_TAG_COUNT, + tagCount: INITIAL_TAG_COUNT, + + allocateTag: function() { + // Skip over root IDs as those are reserved for native + while (this.reactTagIsNativeTopRootID(ReactNativeTagHandles.tagCount)) { + ReactNativeTagHandles.tagCount++; + } + var tag = ReactNativeTagHandles.tagCount; + ReactNativeTagHandles.tagCount++; + return tag; + }, + + assertRootTag: function(tag) { + invariant( + this.reactTagIsNativeTopRootID(tag), + "Expect a native root tag, instead got %s", + tag + ); + }, + + reactTagIsNativeTopRootID: function(reactTag) { + // We reserve all tags that are 1 mod 10 for native root views + return reactTag % 10 === 1; + } +}; + +/** + * Version of `ReactBrowserEventEmitter` that works on the receiving side of a + * serialized worker boundary. + */ + +// Shared default empty native event - conserve memory. +var EMPTY_NATIVE_EVENT = {}; + +/** + * Selects a subsequence of `Touch`es, without destroying `touches`. + * + * @param {Array} touches Deserialized touch objects. + * @param {Array} indices Indices by which to pull subsequence. + * @return {Array} Subsequence of touch objects. + */ +var touchSubsequence = function(touches, indices) { + var ret = []; + for (var i = 0; i < indices.length; i++) { + ret.push(touches[indices[i]]); + } + return ret; +}; + +/** + * TODO: Pool all of this. + * + * Destroys `touches` by removing touch objects at indices `indices`. This is + * to maintain compatibility with W3C touch "end" events, where the active + * touches don't include the set that has just been "ended". + * + * @param {Array} touches Deserialized touch objects. + * @param {Array} indices Indices to remove from `touches`. + * @return {Array} Subsequence of removed touch objects. + */ +var removeTouchesAtIndices = function(touches, indices) { + var rippedOut = []; + // use an unsafe downcast to alias to nullable elements, + // so we can delete and then compact. + var temp = touches; + for (var i = 0; i < indices.length; i++) { + var index = indices[i]; + rippedOut.push(touches[index]); + temp[index] = null; + } + var fillAt = 0; + for (var j = 0; j < temp.length; j++) { + var cur = temp[j]; + if (cur !== null) { + temp[fillAt++] = cur; + } + } + temp.length = fillAt; + return rippedOut; +}; + +/** + * Internal version of `receiveEvent` in terms of normalized (non-tag) + * `rootNodeID`. + * + * @see receiveEvent. + * + * @param {rootNodeID} rootNodeID React root node ID that event occurred on. + * @param {TopLevelType} topLevelType Top level type of event. + * @param {?object} nativeEventParam Object passed from native. + */ +function _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam) { + var nativeEvent = nativeEventParam || EMPTY_NATIVE_EVENT; + var inst = getInstanceFromTag(rootNodeID); + batchedUpdates(function() { + handleTopLevel(topLevelType, inst, nativeEvent, nativeEvent.target); + }); + // React Native doesn't use ReactControlledComponent but if it did, here's + // where it would do it. +} + +/** + * Publicly exposed method on module for native objc to invoke when a top + * level event is extracted. + * @param {rootNodeID} rootNodeID React root node ID that event occurred on. + * @param {TopLevelType} topLevelType Top level type of event. + * @param {object} nativeEventParam Object passed from native. + */ +function receiveEvent(rootNodeID, topLevelType, nativeEventParam) { + _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam); +} + +/** + * Simple multi-wrapper around `receiveEvent` that is intended to receive an + * efficient representation of `Touch` objects, and other information that + * can be used to construct W3C compliant `Event` and `Touch` lists. + * + * This may create dispatch behavior that differs than web touch handling. We + * loop through each of the changed touches and receive it as a single event. + * So two `touchStart`/`touchMove`s that occur simultaneously are received as + * two separate touch event dispatches - when they arguably should be one. + * + * This implementation reuses the `Touch` objects themselves as the `Event`s + * since we dispatch an event for each touch (though that might not be spec + * compliant). The main purpose of reusing them is to save allocations. + * + * TODO: Dispatch multiple changed touches in one event. The bubble path + * could be the first common ancestor of all the `changedTouches`. + * + * One difference between this behavior and W3C spec: cancelled touches will + * not appear in `.touches`, or in any future `.touches`, though they may + * still be "actively touching the surface". + * + * Web desktop polyfills only need to construct a fake touch event with + * identifier 0, also abandoning traditional click handlers. + */ +function receiveTouches(eventTopLevelType, touches, changedIndices) { + var changedTouches = + eventTopLevelType === "topTouchEnd" || + eventTopLevelType === "topTouchCancel" + ? removeTouchesAtIndices(touches, changedIndices) + : touchSubsequence(touches, changedIndices); + + for (var jj = 0; jj < changedTouches.length; jj++) { + var touch = changedTouches[jj]; + // Touch objects can fulfill the role of `DOM` `Event` objects if we set + // the `changedTouches`/`touches`. This saves allocations. + touch.changedTouches = changedTouches; + touch.touches = touches; + var nativeEvent = touch; + var rootNodeID = null; + var target = nativeEvent.target; + if (target !== null && target !== undefined) { + if (target < ReactNativeTagHandles.tagsStartAt) { + { + warning( + false, + "A view is reporting that a touch occurred on tag zero." + ); + } + } else { + rootNodeID = target; + } + } + // $FlowFixMe Shouldn't we *not* call it if rootNodeID is null? + _receiveRootNodeIDEvent(rootNodeID, eventTopLevelType, nativeEvent); + } +} + +var ReactNativeEventEmitter = Object.freeze({ + getListener: getListener, + registrationNames: registrationNameModules, + _receiveRootNodeIDEvent: _receiveRootNodeIDEvent, + receiveEvent: receiveEvent, + receiveTouches: receiveTouches, + handleTopLevel: handleTopLevel +}); + +var ReactNativeEventPluginOrder = [ + "ResponderEventPlugin", + "ReactNativeBridgeEventPlugin" +]; + +// Module provided by RN: +var ReactNativeGlobalResponderHandler = { + onChange: function(from, to, blockNativeResponder) { + if (to !== null) { + var tag = to.stateNode._nativeTag; + UIManager.setJSResponder(tag, blockNativeResponder); + } else { + UIManager.clearJSResponder(); + } + } +}; + +/** + * Make sure essential globals are available and are patched correctly. Please don't remove this + * line. Bundles created by react-packager `require` it before executing any application code. This + * ensures it exists in the dependency graph and can be `require`d. + * TODO: require this in packager, not in React #10932517 + */ +// Module provided by RN: +// Module provided by RN: +/** + * Register the event emitter with the native bridge + */ +RCTEventEmitter.register(ReactNativeEventEmitter); + +/** + * Inject module for resolving DOM hierarchy and plugin ordering. + */ +injection.injectEventPluginOrder(ReactNativeEventPluginOrder); +injection$1.injectComponentTree(ReactNativeComponentTree); + +ResponderEventPlugin.injection.injectGlobalResponderHandler( + ReactNativeGlobalResponderHandler +); + +/** + * Some important event plugins included by default (without having to require + * them). + */ +injection.injectEventPluginsByName({ + ResponderEventPlugin: ResponderEventPlugin, + ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin +}); + +var defaultShowDialog = function(capturedError) { + return true; +}; + +var showDialog = defaultShowDialog; + +function logCapturedError(capturedError) { + var logError = showDialog(capturedError); + + // Allow injected showDialog() to prevent default console.error logging. + // This enables renderers like ReactNative to better manage redbox behavior. + if (logError === false) { + return; + } + + { + var componentName = capturedError.componentName, + componentStack = capturedError.componentStack, + errorBoundaryName = capturedError.errorBoundaryName, + errorBoundaryFound = capturedError.errorBoundaryFound, + willRetry = capturedError.willRetry; + + var componentNameMessage = componentName + ? "The above error occurred in the <" + componentName + "> component:" + : "The above error occurred in one of your React components:"; + + var errorBoundaryMessage = void 0; + // errorBoundaryFound check is sufficient; errorBoundaryName check is to satisfy Flow. + if (errorBoundaryFound && errorBoundaryName) { + if (willRetry) { + errorBoundaryMessage = + "React will try to recreate this component tree from scratch " + + ("using the error boundary you provided, " + errorBoundaryName + "."); + } else { + errorBoundaryMessage = + "This error was initially handled by the error boundary " + + errorBoundaryName + + ".\n" + + "Recreating the tree from scratch failed so React will unmount the tree."; + } + } else { + errorBoundaryMessage = + "Consider adding an error boundary to your tree to customize error handling behavior.\n" + + "Visit https://fb.me/react-error-boundaries to learn more about error boundaries."; + } + var combinedMessage = + "" + + componentNameMessage + + componentStack + + "\n\n" + + ("" + errorBoundaryMessage); + + // In development, we provide our own message with just the component stack. + // We don't include the original error message and JS stack because the browser + // has already printed it. Even if the application swallows the error, it is still + // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils. + console.error(combinedMessage); + } +} + +var injection$4 = { + /** + * Display custom dialog for lifecycle errors. + * Return false to prevent default behavior of logging to console.error. + */ + injectDialog: function(fn) { + invariant( + showDialog === defaultShowDialog, + "The custom dialog was already injected." + ); + invariant( + typeof fn === "function", + "Injected showDialog() must be a function." + ); + showDialog = fn; + } +}; + +// The Symbol used to tag the special React types. If there is no native Symbol +// nor polyfill, then a plain number is used for performance. +var REACT_PORTAL_TYPE = + (typeof Symbol === "function" && + Symbol["for"] && + Symbol["for"]("react.portal")) || + 0xeaca; + +function createPortal( + children, + containerInfo, + // TODO: figure out the API for cross-renderer implementation. + implementation +) { + var key = + arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + + return { + // This tag allow us to uniquely identify this as a React Portal + $$typeof: REACT_PORTAL_TYPE, + key: key == null ? null : "" + key, + children: children, + containerInfo: containerInfo, + implementation: implementation + }; +} + +var TouchHistoryMath = { + /** + * This code is optimized and not intended to look beautiful. This allows + * computing of touch centroids that have moved after `touchesChangedAfter` + * timeStamp. You can compute the current centroid involving all touches + * moves after `touchesChangedAfter`, or you can compute the previous + * centroid of all touches that were moved after `touchesChangedAfter`. + * + * @param {TouchHistoryMath} touchHistory Standard Responder touch track + * data. + * @param {number} touchesChangedAfter timeStamp after which moved touches + * are considered "actively moving" - not just "active". + * @param {boolean} isXAxis Consider `x` dimension vs. `y` dimension. + * @param {boolean} ofCurrent Compute current centroid for actively moving + * touches vs. previous centroid of now actively moving touches. + * @return {number} value of centroid in specified dimension. + */ + centroidDimension: function( + touchHistory, + touchesChangedAfter, + isXAxis, + ofCurrent + ) { + var touchBank = touchHistory.touchBank; + var total = 0; + var count = 0; + + var oneTouchData = + touchHistory.numberActiveTouches === 1 + ? touchHistory.touchBank[touchHistory.indexOfSingleActiveTouch] + : null; + + if (oneTouchData !== null) { + if ( + oneTouchData.touchActive && + oneTouchData.currentTimeStamp > touchesChangedAfter + ) { + total += + ofCurrent && isXAxis + ? oneTouchData.currentPageX + : ofCurrent && !isXAxis + ? oneTouchData.currentPageY + : !ofCurrent && isXAxis + ? oneTouchData.previousPageX + : oneTouchData.previousPageY; + count = 1; + } + } else { + for (var i = 0; i < touchBank.length; i++) { + var touchTrack = touchBank[i]; + if ( + touchTrack !== null && + touchTrack !== undefined && + touchTrack.touchActive && + touchTrack.currentTimeStamp >= touchesChangedAfter + ) { + var toAdd; // Yuck, program temporarily in invalid state. + if (ofCurrent && isXAxis) { + toAdd = touchTrack.currentPageX; + } else if (ofCurrent && !isXAxis) { + toAdd = touchTrack.currentPageY; + } else if (!ofCurrent && isXAxis) { + toAdd = touchTrack.previousPageX; + } else { + toAdd = touchTrack.previousPageY; + } + total += toAdd; + count++; + } + } + } + return count > 0 ? total / count : TouchHistoryMath.noCentroid; + }, + + currentCentroidXOfTouchesChangedAfter: function( + touchHistory, + touchesChangedAfter + ) { + return TouchHistoryMath.centroidDimension( + touchHistory, + touchesChangedAfter, + true, // isXAxis + true + ); + }, + + currentCentroidYOfTouchesChangedAfter: function( + touchHistory, + touchesChangedAfter + ) { + return TouchHistoryMath.centroidDimension( + touchHistory, + touchesChangedAfter, + false, // isXAxis + true + ); + }, + + previousCentroidXOfTouchesChangedAfter: function( + touchHistory, + touchesChangedAfter + ) { + return TouchHistoryMath.centroidDimension( + touchHistory, + touchesChangedAfter, + true, // isXAxis + false + ); + }, + + previousCentroidYOfTouchesChangedAfter: function( + touchHistory, + touchesChangedAfter + ) { + return TouchHistoryMath.centroidDimension( + touchHistory, + touchesChangedAfter, + false, // isXAxis + false + ); + }, + + currentCentroidX: function(touchHistory) { + return TouchHistoryMath.centroidDimension( + touchHistory, + 0, // touchesChangedAfter + true, // isXAxis + true + ); + }, + + currentCentroidY: function(touchHistory) { + return TouchHistoryMath.centroidDimension( + touchHistory, + 0, // touchesChangedAfter + false, // isXAxis + true + ); + }, + + noCentroid: -1 +}; + +var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; + +var ReactCurrentOwner = ReactInternals.ReactCurrentOwner; +var ReactDebugCurrentFrame = ReactInternals.ReactDebugCurrentFrame; + +var ReactGlobalSharedState = Object.freeze({ + ReactCurrentOwner: ReactCurrentOwner, + ReactDebugCurrentFrame: ReactDebugCurrentFrame +}); + +// TODO: this is special because it gets imported during build. + +var ReactVersion = "16.1.1"; + +// Module provided by RN: +/** + * Intercept lifecycle errors and ensure they are shown with the correct stack + * trace within the native redbox component. + */ +function showDialog$1(capturedError) { + var componentStack = capturedError.componentStack, + error = capturedError.error; + + var errorToHandle = void 0; + + // Typically Errors are thrown but eg strings or null can be thrown as well. + if (error instanceof Error) { + var message = error.message, + name = error.name; + + var summary = message ? name + ": " + message : name; + + errorToHandle = error; + + try { + errorToHandle.message = + summary + "\n\nThis error is located at:" + componentStack; + } catch (e) {} + } else if (typeof error === "string") { + errorToHandle = new Error( + error + "\n\nThis error is located at:" + componentStack + ); + } else { + errorToHandle = new Error("Unspecified error at:" + componentStack); + } + + ExceptionsManager.handleException(errorToHandle, false); + + // Return false here to prevent ReactFiberErrorLogger default behavior of + // logging error details to console.error. Calls to console.error are + // automatically routed to the native redbox controller, which we've already + // done above by calling ExceptionsManager. + return false; +} + +function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} + +var objects = {}; +var uniqueID = 1; +var emptyObject$2 = {}; + +var ReactNativePropRegistry = (function() { + function ReactNativePropRegistry() { + _classCallCheck(this, ReactNativePropRegistry); + } + + ReactNativePropRegistry.register = function register(object) { + var id = ++uniqueID; + { + Object.freeze(object); + } + objects[id] = object; + return id; + }; + + ReactNativePropRegistry.getByID = function getByID(id) { + if (!id) { + // Used in the style={[condition && id]} pattern, + // we want it to be a no-op when the value is false or null + return emptyObject$2; + } + + var object = objects[id]; + if (!object) { + console.warn("Invalid style with id `" + id + "`. Skipping ..."); + return emptyObject$2; + } + return object; + }; + + return ReactNativePropRegistry; +})(); + +// Modules provided by RN: +var emptyObject$1 = {}; + +/** + * Create a payload that contains all the updates between two sets of props. + * + * These helpers are all encapsulated into a single module, because they use + * mutation as a performance optimization which leads to subtle shared + * dependencies between the code paths. To avoid this mutable state leaking + * across modules, I've kept them isolated to this module. + */ + +// Tracks removed keys +var removedKeys = null; +var removedKeyCount = 0; + +function defaultDiffer(prevProp, nextProp) { + if (typeof nextProp !== "object" || nextProp === null) { + // Scalars have already been checked for equality + return true; + } else { + // For objects and arrays, the default diffing algorithm is a deep compare + return deepDiffer(prevProp, nextProp); + } +} + +function resolveObject(idOrObject) { + if (typeof idOrObject === "number") { + return ReactNativePropRegistry.getByID(idOrObject); + } + return idOrObject; +} + +function restoreDeletedValuesInNestedArray( + updatePayload, + node, + validAttributes +) { + if (Array.isArray(node)) { + var i = node.length; + while (i-- && removedKeyCount > 0) { + restoreDeletedValuesInNestedArray( + updatePayload, + node[i], + validAttributes + ); + } + } else if (node && removedKeyCount > 0) { + var obj = resolveObject(node); + for (var propKey in removedKeys) { + if (!removedKeys[propKey]) { + continue; + } + var nextProp = obj[propKey]; + if (nextProp === undefined) { + continue; + } + + var attributeConfig = validAttributes[propKey]; + if (!attributeConfig) { + continue; // not a valid native prop + } + + if (typeof nextProp === "function") { + nextProp = true; + } + if (typeof nextProp === "undefined") { + nextProp = null; + } + + if (typeof attributeConfig !== "object") { + // case: !Object is the default case + updatePayload[propKey] = nextProp; + } else if ( + typeof attributeConfig.diff === "function" || + typeof attributeConfig.process === "function" + ) { + // case: CustomAttributeConfiguration + var nextValue = + typeof attributeConfig.process === "function" + ? attributeConfig.process(nextProp) + : nextProp; + updatePayload[propKey] = nextValue; + } + removedKeys[propKey] = false; + removedKeyCount--; + } + } +} + +function diffNestedArrayProperty( + updatePayload, + prevArray, + nextArray, + validAttributes +) { + var minLength = + prevArray.length < nextArray.length ? prevArray.length : nextArray.length; + var i; + for (i = 0; i < minLength; i++) { + // Diff any items in the array in the forward direction. Repeated keys + // will be overwritten by later values. + updatePayload = diffNestedProperty( + updatePayload, + prevArray[i], + nextArray[i], + validAttributes + ); + } + for (; i < prevArray.length; i++) { + // Clear out all remaining properties. + updatePayload = clearNestedProperty( + updatePayload, + prevArray[i], + validAttributes + ); + } + for (; i < nextArray.length; i++) { + // Add all remaining properties. + updatePayload = addNestedProperty( + updatePayload, + nextArray[i], + validAttributes + ); + } + return updatePayload; +} + +function diffNestedProperty( + updatePayload, + prevProp, + nextProp, + validAttributes +) { + if (!updatePayload && prevProp === nextProp) { + // If no properties have been added, then we can bail out quickly on object + // equality. + return updatePayload; + } + + if (!prevProp || !nextProp) { + if (nextProp) { + return addNestedProperty(updatePayload, nextProp, validAttributes); + } + if (prevProp) { + return clearNestedProperty(updatePayload, prevProp, validAttributes); + } + return updatePayload; + } + + if (!Array.isArray(prevProp) && !Array.isArray(nextProp)) { + // Both are leaves, we can diff the leaves. + return diffProperties( + updatePayload, + resolveObject(prevProp), + resolveObject(nextProp), + validAttributes + ); + } + + if (Array.isArray(prevProp) && Array.isArray(nextProp)) { + // Both are arrays, we can diff the arrays. + return diffNestedArrayProperty( + updatePayload, + prevProp, + nextProp, + validAttributes + ); + } + + if (Array.isArray(prevProp)) { + return diffProperties( + updatePayload, + // $FlowFixMe - We know that this is always an object when the input is. + flattenStyle(prevProp), + // $FlowFixMe - We know that this isn't an array because of above flow. + resolveObject(nextProp), + validAttributes + ); + } + + return diffProperties( + updatePayload, + resolveObject(prevProp), + // $FlowFixMe - We know that this is always an object when the input is. + flattenStyle(nextProp), + validAttributes + ); +} + +/** + * addNestedProperty takes a single set of props and valid attribute + * attribute configurations. It processes each prop and adds it to the + * updatePayload. + */ +function addNestedProperty(updatePayload, nextProp, validAttributes) { + if (!nextProp) { + return updatePayload; + } + + if (!Array.isArray(nextProp)) { + // Add each property of the leaf. + return addProperties( + updatePayload, + resolveObject(nextProp), + validAttributes + ); + } + + for (var i = 0; i < nextProp.length; i++) { + // Add all the properties of the array. + updatePayload = addNestedProperty( + updatePayload, + nextProp[i], + validAttributes + ); + } + + return updatePayload; +} + +/** + * clearNestedProperty takes a single set of props and valid attributes. It + * adds a null sentinel to the updatePayload, for each prop key. + */ +function clearNestedProperty(updatePayload, prevProp, validAttributes) { + if (!prevProp) { + return updatePayload; + } + + if (!Array.isArray(prevProp)) { + // Add each property of the leaf. + return clearProperties( + updatePayload, + resolveObject(prevProp), + validAttributes + ); + } + + for (var i = 0; i < prevProp.length; i++) { + // Add all the properties of the array. + updatePayload = clearNestedProperty( + updatePayload, + prevProp[i], + validAttributes + ); + } + return updatePayload; +} + +/** + * diffProperties takes two sets of props and a set of valid attributes + * and write to updatePayload the values that changed or were deleted. + * If no updatePayload is provided, a new one is created and returned if + * anything changed. + */ +function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { + var attributeConfig; + var nextProp; + var prevProp; + + for (var propKey in nextProps) { + attributeConfig = validAttributes[propKey]; + if (!attributeConfig) { + continue; // not a valid native prop + } + + prevProp = prevProps[propKey]; + nextProp = nextProps[propKey]; + + // functions are converted to booleans as markers that the associated + // events should be sent from native. + if (typeof nextProp === "function") { + nextProp = true; + // If nextProp is not a function, then don't bother changing prevProp + // since nextProp will win and go into the updatePayload regardless. + if (typeof prevProp === "function") { + prevProp = true; + } + } + + // An explicit value of undefined is treated as a null because it overrides + // any other preceding value. + if (typeof nextProp === "undefined") { + nextProp = null; + if (typeof prevProp === "undefined") { + prevProp = null; + } + } + + if (removedKeys) { + removedKeys[propKey] = false; + } + + if (updatePayload && updatePayload[propKey] !== undefined) { + // Something else already triggered an update to this key because another + // value diffed. Since we're now later in the nested arrays our value is + // more important so we need to calculate it and override the existing + // value. It doesn't matter if nothing changed, we'll set it anyway. + + // Pattern match on: attributeConfig + if (typeof attributeConfig !== "object") { + // case: !Object is the default case + updatePayload[propKey] = nextProp; + } else if ( + typeof attributeConfig.diff === "function" || + typeof attributeConfig.process === "function" + ) { + // case: CustomAttributeConfiguration + var nextValue = + typeof attributeConfig.process === "function" + ? attributeConfig.process(nextProp) + : nextProp; + updatePayload[propKey] = nextValue; + } + continue; + } + + if (prevProp === nextProp) { + continue; // nothing changed + } + + // Pattern match on: attributeConfig + if (typeof attributeConfig !== "object") { + // case: !Object is the default case + if (defaultDiffer(prevProp, nextProp)) { + // a normal leaf has changed + (updatePayload || (updatePayload = {}))[propKey] = nextProp; + } + } else if ( + typeof attributeConfig.diff === "function" || + typeof attributeConfig.process === "function" + ) { + // case: CustomAttributeConfiguration + var shouldUpdate = + prevProp === undefined || + (typeof attributeConfig.diff === "function" + ? attributeConfig.diff(prevProp, nextProp) + : defaultDiffer(prevProp, nextProp)); + if (shouldUpdate) { + nextValue = + typeof attributeConfig.process === "function" + ? attributeConfig.process(nextProp) + : nextProp; + (updatePayload || (updatePayload = {}))[propKey] = nextValue; + } + } else { + // default: fallthrough case when nested properties are defined + removedKeys = null; + removedKeyCount = 0; + // We think that attributeConfig is not CustomAttributeConfiguration at + // this point so we assume it must be AttributeConfiguration. + updatePayload = diffNestedProperty( + updatePayload, + prevProp, + nextProp, + attributeConfig + ); + if (removedKeyCount > 0 && updatePayload) { + restoreDeletedValuesInNestedArray( + updatePayload, + nextProp, + attributeConfig + ); + removedKeys = null; + } + } + } + + // Also iterate through all the previous props to catch any that have been + // removed and make sure native gets the signal so it can reset them to the + // default. + for (propKey in prevProps) { + if (nextProps[propKey] !== undefined) { + continue; // we've already covered this key in the previous pass + } + attributeConfig = validAttributes[propKey]; + if (!attributeConfig) { + continue; // not a valid native prop + } + + if (updatePayload && updatePayload[propKey] !== undefined) { + // This was already updated to a diff result earlier. + continue; + } + + prevProp = prevProps[propKey]; + if (prevProp === undefined) { + continue; // was already empty anyway + } + // Pattern match on: attributeConfig + if ( + typeof attributeConfig !== "object" || + typeof attributeConfig.diff === "function" || + typeof attributeConfig.process === "function" + ) { + // case: CustomAttributeConfiguration | !Object + // Flag the leaf property for removal by sending a sentinel. + (updatePayload || (updatePayload = {}))[propKey] = null; + if (!removedKeys) { + removedKeys = {}; + } + if (!removedKeys[propKey]) { + removedKeys[propKey] = true; + removedKeyCount++; + } + } else { + // default: + // This is a nested attribute configuration where all the properties + // were removed so we need to go through and clear out all of them. + updatePayload = clearNestedProperty( + updatePayload, + prevProp, + attributeConfig + ); + } + } + return updatePayload; +} + +/** + * addProperties adds all the valid props to the payload after being processed. + */ +function addProperties(updatePayload, props, validAttributes) { + // TODO: Fast path + return diffProperties(updatePayload, emptyObject$1, props, validAttributes); +} + +/** + * clearProperties clears all the previous props by adding a null sentinel + * to the payload for each valid key. + */ +function clearProperties(updatePayload, prevProps, validAttributes) { + // TODO: Fast path + return diffProperties( + updatePayload, + prevProps, + emptyObject$1, + validAttributes + ); +} + +function create(props, validAttributes) { + return addProperties( + null, // updatePayload + props, + validAttributes + ); +} + +function diff(prevProps, nextProps, validAttributes) { + return diffProperties( + null, // updatePayload + prevProps, + nextProps, + validAttributes + ); +} + +/** + * In the future, we should cleanup callbacks by cancelling them instead of + * using this. + */ +function mountSafeCallback(context, callback) { + return function() { + if (!callback) { + return undefined; + } + if (typeof context.__isMounted === "boolean") { + // TODO(gaearon): this is gross and should be removed. + // It is currently necessary because View uses createClass, + // and so any measure() calls on View (which are done by React + // DevTools) trigger the isMounted() deprecation warning. + if (!context.__isMounted) { + return undefined; + } + // The else branch is important so that we don't + // trigger the deprecation warning by calling isMounted. + } else if (typeof context.isMounted === "function") { + if (!context.isMounted()) { + return undefined; + } + } + return callback.apply(context, arguments); + }; +} + +function throwOnStylesProp(component, props) { + if (props.styles !== undefined) { + var owner = component._owner || null; + var name = component.constructor.displayName; + var msg = + "`styles` is not a supported property of `" + + name + + "`, did " + + "you mean `style` (singular)?"; + if (owner && owner.constructor && owner.constructor.displayName) { + msg += + "\n\nCheck the `" + + owner.constructor.displayName + + "` parent " + + " component."; + } + throw new Error(msg); + } +} + +function warnForStyleProps(props, validAttributes) { + for (var key in validAttributes.style) { + if (!(validAttributes[key] || props[key] === undefined)) { + console.error( + "You are setting the style `{ " + + key + + ": ... }` as a prop. You " + + "should nest it in a style object. " + + "E.g. `{ style: { " + + key + + ": ... } }`" + ); + } + } +} + +/** + * `ReactInstanceMap` maintains a mapping from a public facing stateful + * instance (key) and the internal representation (value). This allows public + * methods to accept the user facing instance as an argument and map them back + * to internal methods. + * + * Note that this module is currently shared and assumed to be stateless. + * If this becomes an actual Map, that will break. + */ + +/** + * This API should be called `delete` but we'd have to make sure to always + * transform these to strings for IE support. When this transform is fully + * supported we can rename it. + */ + +function get(key) { + return key._reactInternalFiber; +} + +function set(key, value) { + key._reactInternalFiber = value; +} + +function getComponentName(fiber) { + var type = fiber.type; + + if (typeof type === "string") { + return type; + } + if (typeof type === "function") { + return type.displayName || type.name; + } + return null; +} + +var enableAsyncSubtreeAPI = true; + +// Exports React.Fragment +var enableReactFragment = false; +// Exports ReactDOM.createRoot + +var enableUserTimingAPI = true; + +// Mutating mode (React DOM, React ART, React Native): +var enableMutatingReconciler = true; +// Experimental noop mode (currently unused): +var enableNoopReconciler = false; +// Experimental persistent mode (CS): +var enablePersistentReconciler = false; + +// Only used in www builds. + +// Don't change these two values: +var NoEffect = 0; // 0b00000000 +var PerformedWork = 1; // 0b00000001 + +// You can change the rest (and add more). +var Placement = 2; // 0b00000010 +var Update = 4; // 0b00000100 +var PlacementAndUpdate = 6; // 0b00000110 +var Deletion = 8; // 0b00001000 +var ContentReset = 16; // 0b00010000 +var Callback = 32; // 0b00100000 +var Err = 64; // 0b01000000 +var Ref = 128; // 0b10000000 + +var MOUNTING = 1; +var MOUNTED = 2; +var UNMOUNTED = 3; + +function isFiberMountedImpl(fiber) { + var node = fiber; + if (!fiber.alternate) { + // If there is no alternate, this might be a new tree that isn't inserted + // yet. If it is, then it will have a pending insertion effect on it. + if ((node.effectTag & Placement) !== NoEffect) { + return MOUNTING; + } + while (node["return"]) { + node = node["return"]; + if ((node.effectTag & Placement) !== NoEffect) { + return MOUNTING; + } + } + } else { + while (node["return"]) { + node = node["return"]; + } + } + if (node.tag === HostRoot) { + // TODO: Check if this was a nested HostRoot when used with + // renderContainerIntoSubtree. + return MOUNTED; + } + // If we didn't hit the root, that means that we're in an disconnected tree + // that has been unmounted. + return UNMOUNTED; +} + +function isFiberMounted(fiber) { + return isFiberMountedImpl(fiber) === MOUNTED; +} + +function isMounted(component) { + { + var owner = ReactCurrentOwner.current; + if (owner !== null && owner.tag === ClassComponent) { + var ownerFiber = owner; + var instance = ownerFiber.stateNode; + warning( + instance._warnedAboutRefsInRender, + "%s is accessing isMounted inside its render() function. " + + "render() should be a pure function of props and state. It should " + + "never access something that requires stale data from the previous " + + "render, such as refs. Move this logic to componentDidMount and " + + "componentDidUpdate instead.", + getComponentName(ownerFiber) || "A component" + ); + instance._warnedAboutRefsInRender = true; + } + } + + var fiber = get(component); + if (!fiber) { + return false; + } + return isFiberMountedImpl(fiber) === MOUNTED; +} + +function assertIsMounted(fiber) { + invariant( + isFiberMountedImpl(fiber) === MOUNTED, + "Unable to find node on an unmounted component." + ); +} + +function findCurrentFiberUsingSlowPath(fiber) { + var alternate = fiber.alternate; + if (!alternate) { + // If there is no alternate, then we only need to check if it is mounted. + var state = isFiberMountedImpl(fiber); + invariant( + state !== UNMOUNTED, + "Unable to find node on an unmounted component." + ); + if (state === MOUNTING) { + return null; + } + return fiber; + } + // If we have two possible branches, we'll walk backwards up to the root + // to see what path the root points to. On the way we may hit one of the + // special cases and we'll deal with them. + var a = fiber; + var b = alternate; + while (true) { + var parentA = a["return"]; + var parentB = parentA ? parentA.alternate : null; + if (!parentA || !parentB) { + // We're at the root. + break; + } + + // If both copies of the parent fiber point to the same child, we can + // assume that the child is current. This happens when we bailout on low + // priority: the bailed out fiber's child reuses the current child. + if (parentA.child === parentB.child) { + var child = parentA.child; + while (child) { + if (child === a) { + // We've determined that A is the current branch. + assertIsMounted(parentA); + return fiber; + } + if (child === b) { + // We've determined that B is the current branch. + assertIsMounted(parentA); + return alternate; + } + child = child.sibling; + } + // We should never have an alternate for any mounting node. So the only + // way this could possibly happen is if this was unmounted, if at all. + invariant(false, "Unable to find node on an unmounted component."); + } + + if (a["return"] !== b["return"]) { + // The return pointer of A and the return pointer of B point to different + // fibers. We assume that return pointers never criss-cross, so A must + // belong to the child set of A.return, and B must belong to the child + // set of B.return. + a = parentA; + b = parentB; + } else { + // The return pointers point to the same fiber. We'll have to use the + // default, slow path: scan the child sets of each parent alternate to see + // which child belongs to which set. + // + // Search parent A's child set + var didFindChild = false; + var _child = parentA.child; + while (_child) { + if (_child === a) { + didFindChild = true; + a = parentA; + b = parentB; + break; + } + if (_child === b) { + didFindChild = true; + b = parentA; + a = parentB; + break; + } + _child = _child.sibling; + } + if (!didFindChild) { + // Search parent B's child set + _child = parentB.child; + while (_child) { + if (_child === a) { + didFindChild = true; + a = parentB; + b = parentA; + break; + } + if (_child === b) { + didFindChild = true; + b = parentB; + a = parentA; + break; + } + _child = _child.sibling; + } + invariant( + didFindChild, + "Child was not found in either parent set. This indicates a bug " + + "in React related to the return pointer. Please file an issue." + ); + } + } + + invariant( + a.alternate === b, + "Return fibers should always be each others' alternates. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } + // If the root is not a host container, we're in a disconnected tree. I.e. + // unmounted. + invariant( + a.tag === HostRoot, + "Unable to find node on an unmounted component." + ); + if (a.stateNode.current === a) { + // We've determined that A is the current branch. + return fiber; + } + // Otherwise B has to be current branch. + return alternate; +} + +function findCurrentHostFiber(parent) { + var currentParent = findCurrentFiberUsingSlowPath(parent); + if (!currentParent) { + return null; + } + + // Next we'll drill down this component to find the first HostComponent/Text. + var node = currentParent; + while (true) { + if (node.tag === HostComponent || node.tag === HostText) { + return node; + } else if (node.child) { + node.child["return"] = node; + node = node.child; + continue; + } + if (node === currentParent) { + return null; + } + while (!node.sibling) { + if (!node["return"] || node["return"] === currentParent) { + return null; + } + node = node["return"]; + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } + // Flow needs the return null here, but ESLint complains about it. + // eslint-disable-next-line no-unreachable + return null; +} + +function findCurrentHostFiberWithNoPortals(parent) { + var currentParent = findCurrentFiberUsingSlowPath(parent); + if (!currentParent) { + return null; + } + + // Next we'll drill down this component to find the first HostComponent/Text. + var node = currentParent; + while (true) { + if (node.tag === HostComponent || node.tag === HostText) { + return node; + } else if (node.child && node.tag !== HostPortal) { + node.child["return"] = node; + node = node.child; + continue; + } + if (node === currentParent) { + return null; + } + while (!node.sibling) { + if (!node["return"] || node["return"] === currentParent) { + return null; + } + node = node["return"]; + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } + // Flow needs the return null here, but ESLint complains about it. + // eslint-disable-next-line no-unreachable + return null; +} + +var valueStack = []; + +{ + var fiberStack = []; +} + +var index = -1; + +function createCursor(defaultValue) { + return { + current: defaultValue + }; +} + +function pop(cursor, fiber) { + if (index < 0) { + { + warning(false, "Unexpected pop."); + } + return; + } + + { + if (fiber !== fiberStack[index]) { + warning(false, "Unexpected Fiber popped."); + } + } + + cursor.current = valueStack[index]; + + valueStack[index] = null; + + { + fiberStack[index] = null; + } + + index--; +} + +function push(cursor, value, fiber) { + index++; + + valueStack[index] = cursor.current; + + { + fiberStack[index] = fiber; + } + + cursor.current = value; +} + +function reset() { + while (index > -1) { + valueStack[index] = null; + + { + fiberStack[index] = null; + } + + index--; + } +} + +var describeComponentFrame = function(name, source, ownerName) { + return ( + "\n in " + + (name || "Unknown") + + (source + ? " (at " + + source.fileName.replace(/^.*[\\\/]/, "") + + ":" + + source.lineNumber + + ")" + : ownerName ? " (created by " + ownerName + ")" : "") + ); +}; + +function describeFiber(fiber) { + switch (fiber.tag) { + case IndeterminateComponent: + case FunctionalComponent: + case ClassComponent: + case HostComponent: + var owner = fiber._debugOwner; + var source = fiber._debugSource; + var name = getComponentName(fiber); + var ownerName = null; + if (owner) { + ownerName = getComponentName(owner); + } + return describeComponentFrame(name, source, ownerName); + default: + return ""; + } +} + +// This function can only be called with a work-in-progress fiber and +// only during begin or complete phase. Do not call it under any other +// circumstances. +function getStackAddendumByWorkInProgressFiber(workInProgress) { + var info = ""; + var node = workInProgress; + do { + info += describeFiber(node); + // Otherwise this return pointer might point to the wrong tree: + node = node["return"]; + } while (node); + return info; +} + +function getCurrentFiberOwnerName() { + { + var fiber = ReactDebugCurrentFiber.current; + if (fiber === null) { + return null; + } + var owner = fiber._debugOwner; + if (owner !== null && typeof owner !== "undefined") { + return getComponentName(owner); + } + } + return null; +} + +function getCurrentFiberStackAddendum() { + { + var fiber = ReactDebugCurrentFiber.current; + if (fiber === null) { + return null; + } + // Safe because if current fiber exists, we are reconciling, + // and it is guaranteed to be the work-in-progress version. + return getStackAddendumByWorkInProgressFiber(fiber); + } + return null; +} + +function resetCurrentFiber() { + ReactDebugCurrentFrame.getCurrentStack = null; + ReactDebugCurrentFiber.current = null; + ReactDebugCurrentFiber.phase = null; +} + +function setCurrentFiber(fiber) { + ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum; + ReactDebugCurrentFiber.current = fiber; + ReactDebugCurrentFiber.phase = null; +} + +function setCurrentPhase(phase) { + ReactDebugCurrentFiber.phase = phase; +} + +var ReactDebugCurrentFiber = { + current: null, + phase: null, + resetCurrentFiber: resetCurrentFiber, + setCurrentFiber: setCurrentFiber, + setCurrentPhase: setCurrentPhase, + getCurrentFiberOwnerName: getCurrentFiberOwnerName, + getCurrentFiberStackAddendum: getCurrentFiberStackAddendum +}; + +// Prefix measurements so that it's possible to filter them. +// Longer prefixes are hard to read in DevTools. +var reactEmoji = "\u269B"; +var warningEmoji = "\u26D4"; +var supportsUserTiming = + typeof performance !== "undefined" && + typeof performance.mark === "function" && + typeof performance.clearMarks === "function" && + typeof performance.measure === "function" && + typeof performance.clearMeasures === "function"; + +// Keep track of current fiber so that we know the path to unwind on pause. +// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them? +var currentFiber = null; +// If we're in the middle of user code, which fiber and method is it? +// Reusing `currentFiber` would be confusing for this because user code fiber +// can change during commit phase too, but we don't need to unwind it (since +// lifecycles in the commit phase don't resemble a tree). +var currentPhase = null; +var currentPhaseFiber = null; +// Did lifecycle hook schedule an update? This is often a performance problem, +// so we will keep track of it, and include it in the report. +// Track commits caused by cascading updates. +var isCommitting = false; +var hasScheduledUpdateInCurrentCommit = false; +var hasScheduledUpdateInCurrentPhase = false; +var commitCountInCurrentWorkLoop = 0; +var effectCountInCurrentCommit = 0; +var isWaitingForCallback = false; +// During commits, we only show a measurement once per method name +// to avoid stretch the commit phase with measurement overhead. +var labelsInCurrentCommit = new Set(); + +var formatMarkName = function(markName) { + return reactEmoji + " " + markName; +}; + +var formatLabel = function(label, warning$$1) { + var prefix = warning$$1 ? warningEmoji + " " : reactEmoji + " "; + var suffix = warning$$1 ? " Warning: " + warning$$1 : ""; + return "" + prefix + label + suffix; +}; + +var beginMark = function(markName) { + performance.mark(formatMarkName(markName)); +}; + +var clearMark = function(markName) { + performance.clearMarks(formatMarkName(markName)); +}; + +var endMark = function(label, markName, warning$$1) { + var formattedMarkName = formatMarkName(markName); + var formattedLabel = formatLabel(label, warning$$1); + try { + performance.measure(formattedLabel, formattedMarkName); + } catch (err) {} + // If previous mark was missing for some reason, this will throw. + // This could only happen if React crashed in an unexpected place earlier. + // Don't pile on with more errors. + + // Clear marks immediately to avoid growing buffer. + performance.clearMarks(formattedMarkName); + performance.clearMeasures(formattedLabel); +}; + +var getFiberMarkName = function(label, debugID) { + return label + " (#" + debugID + ")"; +}; + +var getFiberLabel = function(componentName, isMounted, phase) { + if (phase === null) { + // These are composite component total time measurements. + return componentName + " [" + (isMounted ? "update" : "mount") + "]"; + } else { + // Composite component methods. + return componentName + "." + phase; + } +}; + +var beginFiberMark = function(fiber, phase) { + var componentName = getComponentName(fiber) || "Unknown"; + var debugID = fiber._debugID; + var isMounted = fiber.alternate !== null; + var label = getFiberLabel(componentName, isMounted, phase); + + if (isCommitting && labelsInCurrentCommit.has(label)) { + // During the commit phase, we don't show duplicate labels because + // there is a fixed overhead for every measurement, and we don't + // want to stretch the commit phase beyond necessary. + return false; + } + labelsInCurrentCommit.add(label); + + var markName = getFiberMarkName(label, debugID); + beginMark(markName); + return true; +}; + +var clearFiberMark = function(fiber, phase) { + var componentName = getComponentName(fiber) || "Unknown"; + var debugID = fiber._debugID; + var isMounted = fiber.alternate !== null; + var label = getFiberLabel(componentName, isMounted, phase); + var markName = getFiberMarkName(label, debugID); + clearMark(markName); +}; + +var endFiberMark = function(fiber, phase, warning$$1) { + var componentName = getComponentName(fiber) || "Unknown"; + var debugID = fiber._debugID; + var isMounted = fiber.alternate !== null; + var label = getFiberLabel(componentName, isMounted, phase); + var markName = getFiberMarkName(label, debugID); + endMark(label, markName, warning$$1); +}; + +var shouldIgnoreFiber = function(fiber) { + // Host components should be skipped in the timeline. + // We could check typeof fiber.type, but does this work with RN? + switch (fiber.tag) { + case HostRoot: + case HostComponent: + case HostText: + case HostPortal: + case ReturnComponent: + case Fragment: + return true; + default: + return false; + } +}; + +var clearPendingPhaseMeasurement = function() { + if (currentPhase !== null && currentPhaseFiber !== null) { + clearFiberMark(currentPhaseFiber, currentPhase); + } + currentPhaseFiber = null; + currentPhase = null; + hasScheduledUpdateInCurrentPhase = false; +}; + +var pauseTimers = function() { + // Stops all currently active measurements so that they can be resumed + // if we continue in a later deferred loop from the same unit of work. + var fiber = currentFiber; + while (fiber) { + if (fiber._debugIsCurrentlyTiming) { + endFiberMark(fiber, null, null); + } + fiber = fiber["return"]; + } +}; + +var resumeTimersRecursively = function(fiber) { + if (fiber["return"] !== null) { + resumeTimersRecursively(fiber["return"]); + } + if (fiber._debugIsCurrentlyTiming) { + beginFiberMark(fiber, null); + } +}; + +var resumeTimers = function() { + // Resumes all measurements that were active during the last deferred loop. + if (currentFiber !== null) { + resumeTimersRecursively(currentFiber); + } +}; + +function recordEffect() { + if (enableUserTimingAPI) { + effectCountInCurrentCommit++; + } +} + +function recordScheduleUpdate() { + if (enableUserTimingAPI) { + if (isCommitting) { + hasScheduledUpdateInCurrentCommit = true; + } + if ( + currentPhase !== null && + currentPhase !== "componentWillMount" && + currentPhase !== "componentWillReceiveProps" + ) { + hasScheduledUpdateInCurrentPhase = true; + } + } +} + +function startRequestCallbackTimer() { + if (enableUserTimingAPI) { + if (supportsUserTiming && !isWaitingForCallback) { + isWaitingForCallback = true; + beginMark("(Waiting for async callback...)"); + } + } +} + +function stopRequestCallbackTimer(didExpire) { + if (enableUserTimingAPI) { + if (supportsUserTiming) { + isWaitingForCallback = false; + var warning$$1 = didExpire ? "React was blocked by main thread" : null; + endMark( + "(Waiting for async callback...)", + "(Waiting for async callback...)", + warning$$1 + ); + } + } +} + +function startWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return; + } + // If we pause, this is the fiber to unwind from. + currentFiber = fiber; + if (!beginFiberMark(fiber, null)) { + return; + } + fiber._debugIsCurrentlyTiming = true; + } +} + +function cancelWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return; + } + // Remember we shouldn't complete measurement for this fiber. + // Otherwise flamechart will be deep even for small updates. + fiber._debugIsCurrentlyTiming = false; + clearFiberMark(fiber, null); + } +} + +function stopWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return; + } + // If we pause, its parent is the fiber to unwind from. + currentFiber = fiber["return"]; + if (!fiber._debugIsCurrentlyTiming) { + return; + } + fiber._debugIsCurrentlyTiming = false; + endFiberMark(fiber, null, null); + } +} + +function stopFailedWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return; + } + // If we pause, its parent is the fiber to unwind from. + currentFiber = fiber["return"]; + if (!fiber._debugIsCurrentlyTiming) { + return; + } + fiber._debugIsCurrentlyTiming = false; + var warning$$1 = "An error was thrown inside this error boundary"; + endFiberMark(fiber, null, warning$$1); + } +} + +function startPhaseTimer(fiber, phase) { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + clearPendingPhaseMeasurement(); + if (!beginFiberMark(fiber, phase)) { + return; + } + currentPhaseFiber = fiber; + currentPhase = phase; + } +} + +function stopPhaseTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + if (currentPhase !== null && currentPhaseFiber !== null) { + var warning$$1 = hasScheduledUpdateInCurrentPhase + ? "Scheduled a cascading update" + : null; + endFiberMark(currentPhaseFiber, currentPhase, warning$$1); + } + currentPhase = null; + currentPhaseFiber = null; + } +} + +function startWorkLoopTimer(nextUnitOfWork) { + if (enableUserTimingAPI) { + currentFiber = nextUnitOfWork; + if (!supportsUserTiming) { + return; + } + commitCountInCurrentWorkLoop = 0; + // This is top level call. + // Any other measurements are performed within. + beginMark("(React Tree Reconciliation)"); + // Resume any measurements that were in progress during the last loop. + resumeTimers(); + } +} + +function stopWorkLoopTimer(interruptedBy) { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + var warning$$1 = null; + if (interruptedBy !== null) { + if (interruptedBy.tag === HostRoot) { + warning$$1 = "A top-level update interrupted the previous render"; + } else { + var componentName = getComponentName(interruptedBy) || "Unknown"; + warning$$1 = + "An update to " + componentName + " interrupted the previous render"; + } + } else if (commitCountInCurrentWorkLoop > 1) { + warning$$1 = "There were cascading updates"; + } + commitCountInCurrentWorkLoop = 0; + // Pause any measurements until the next loop. + pauseTimers(); + endMark( + "(React Tree Reconciliation)", + "(React Tree Reconciliation)", + warning$$1 + ); + } +} + +function startCommitTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + isCommitting = true; + hasScheduledUpdateInCurrentCommit = false; + labelsInCurrentCommit.clear(); + beginMark("(Committing Changes)"); + } +} + +function stopCommitTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + + var warning$$1 = null; + if (hasScheduledUpdateInCurrentCommit) { + warning$$1 = "Lifecycle hook scheduled a cascading update"; + } else if (commitCountInCurrentWorkLoop > 0) { + warning$$1 = "Caused by a cascading update in earlier commit"; + } + hasScheduledUpdateInCurrentCommit = false; + commitCountInCurrentWorkLoop++; + isCommitting = false; + labelsInCurrentCommit.clear(); + + endMark("(Committing Changes)", "(Committing Changes)", warning$$1); + } +} + +function startCommitHostEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + effectCountInCurrentCommit = 0; + beginMark("(Committing Host Effects)"); + } +} + +function stopCommitHostEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + var count = effectCountInCurrentCommit; + effectCountInCurrentCommit = 0; + endMark( + "(Committing Host Effects: " + count + " Total)", + "(Committing Host Effects)", + null + ); + } +} + +function startCommitLifeCyclesTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + effectCountInCurrentCommit = 0; + beginMark("(Calling Lifecycle Methods)"); + } +} + +function stopCommitLifeCyclesTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + var count = effectCountInCurrentCommit; + effectCountInCurrentCommit = 0; + endMark( + "(Calling Lifecycle Methods: " + count + " Total)", + "(Calling Lifecycle Methods)", + null + ); + } +} + +{ + var warnedAboutMissingGetChildContext = {}; +} + +// A cursor to the current merged context object on the stack. +var contextStackCursor = createCursor(emptyObject); +// A cursor to a boolean indicating whether the context has changed. +var didPerformWorkStackCursor = createCursor(false); +// Keep track of the previous context object that was on the stack. +// We use this to get access to the parent context after we have already +// pushed the next context provider, and now need to merge their contexts. +var previousContext = emptyObject; + +function getUnmaskedContext(workInProgress) { + var hasOwnContext = isContextProvider(workInProgress); + if (hasOwnContext) { + // If the fiber is a context provider itself, when we read its context + // we have already pushed its own child context on the stack. A context + // provider should not "see" its own child context. Therefore we read the + // previous (parent) context instead for a context provider. + return previousContext; + } + return contextStackCursor.current; +} + +function cacheContext(workInProgress, unmaskedContext, maskedContext) { + var instance = workInProgress.stateNode; + instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; + instance.__reactInternalMemoizedMaskedChildContext = maskedContext; +} + +function getMaskedContext(workInProgress, unmaskedContext) { + var type = workInProgress.type; + var contextTypes = type.contextTypes; + if (!contextTypes) { + return emptyObject; + } + + // Avoid recreating masked context unless unmasked context has changed. + // Failing to do this will result in unnecessary calls to componentWillReceiveProps. + // This may trigger infinite loops if componentWillReceiveProps calls setState. + var instance = workInProgress.stateNode; + if ( + instance && + instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext + ) { + return instance.__reactInternalMemoizedMaskedChildContext; + } + + var context = {}; + for (var key in contextTypes) { + context[key] = unmaskedContext[key]; + } + + { + var name = getComponentName(workInProgress) || "Unknown"; + checkPropTypes( + contextTypes, + context, + "context", + name, + ReactDebugCurrentFiber.getCurrentFiberStackAddendum + ); + } + + // Cache unmasked context so we can avoid recreating masked context unless necessary. + // Context is created before the class component is instantiated so check for instance. + if (instance) { + cacheContext(workInProgress, unmaskedContext, context); + } + + return context; +} + +function hasContextChanged() { + return didPerformWorkStackCursor.current; +} + +function isContextConsumer(fiber) { + return fiber.tag === ClassComponent && fiber.type.contextTypes != null; +} + +function isContextProvider(fiber) { + return fiber.tag === ClassComponent && fiber.type.childContextTypes != null; +} + +function popContextProvider(fiber) { + if (!isContextProvider(fiber)) { + return; + } + + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor, fiber); +} + +function popTopLevelContextObject(fiber) { + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor, fiber); +} + +function pushTopLevelContextObject(fiber, context, didChange) { + invariant( + contextStackCursor.cursor == null, + "Unexpected context found on stack. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + + push(contextStackCursor, context, fiber); + push(didPerformWorkStackCursor, didChange, fiber); +} + +function processChildContext(fiber, parentContext) { + var instance = fiber.stateNode; + var childContextTypes = fiber.type.childContextTypes; + + // TODO (bvaughn) Replace this behavior with an invariant() in the future. + // It has only been added in Fiber to match the (unintentional) behavior in Stack. + if (typeof instance.getChildContext !== "function") { + { + var componentName = getComponentName(fiber) || "Unknown"; + + if (!warnedAboutMissingGetChildContext[componentName]) { + warnedAboutMissingGetChildContext[componentName] = true; + warning( + false, + "%s.childContextTypes is specified but there is no getChildContext() method " + + "on the instance. You can either define getChildContext() on %s or remove " + + "childContextTypes from it.", + componentName, + componentName + ); + } + } + return parentContext; + } + + var childContext = void 0; + { + ReactDebugCurrentFiber.setCurrentPhase("getChildContext"); + } + startPhaseTimer(fiber, "getChildContext"); + childContext = instance.getChildContext(); + stopPhaseTimer(); + { + ReactDebugCurrentFiber.setCurrentPhase(null); + } + for (var contextKey in childContext) { + invariant( + contextKey in childContextTypes, + '%s.getChildContext(): key "%s" is not defined in childContextTypes.', + getComponentName(fiber) || "Unknown", + contextKey + ); + } + { + var name = getComponentName(fiber) || "Unknown"; + checkPropTypes( + childContextTypes, + childContext, + "child context", + name, + // In practice, there is one case in which we won't get a stack. It's when + // somebody calls unstable_renderSubtreeIntoContainer() and we process + // context from the parent component instance. The stack will be missing + // because it's outside of the reconciliation, and so the pointer has not + // been set. This is rare and doesn't matter. We'll also remove that API. + ReactDebugCurrentFiber.getCurrentFiberStackAddendum + ); + } + + return Object.assign({}, parentContext, childContext); +} + +function pushContextProvider(workInProgress) { + if (!isContextProvider(workInProgress)) { + return false; + } + + var instance = workInProgress.stateNode; + // We push the context as early as possible to ensure stack integrity. + // If the instance does not exist yet, we will push null at first, + // and replace it on the stack later when invalidating the context. + var memoizedMergedChildContext = + (instance && instance.__reactInternalMemoizedMergedChildContext) || + emptyObject; + + // Remember the parent context so we can merge with it later. + // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates. + previousContext = contextStackCursor.current; + push(contextStackCursor, memoizedMergedChildContext, workInProgress); + push( + didPerformWorkStackCursor, + didPerformWorkStackCursor.current, + workInProgress + ); + + return true; +} + +function invalidateContextProvider(workInProgress, didChange) { + var instance = workInProgress.stateNode; + invariant( + instance, + "Expected to have an instance by this point. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + + if (didChange) { + // Merge parent and own context. + // Skip this if we're not updating due to sCU. + // This avoids unnecessarily recomputing memoized values. + var mergedContext = processChildContext(workInProgress, previousContext); + instance.__reactInternalMemoizedMergedChildContext = mergedContext; + + // Replace the old (or empty) context with the new one. + // It is important to unwind the context in the reverse order. + pop(didPerformWorkStackCursor, workInProgress); + pop(contextStackCursor, workInProgress); + // Now push the new context and mark that it has changed. + push(contextStackCursor, mergedContext, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + } else { + pop(didPerformWorkStackCursor, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + } +} + +function resetContext() { + previousContext = emptyObject; + contextStackCursor.current = emptyObject; + didPerformWorkStackCursor.current = false; +} + +function findCurrentUnmaskedContext(fiber) { + // Currently this is only used with renderSubtreeIntoContainer; not sure if it + // makes sense elsewhere + invariant( + isFiberMounted(fiber) && fiber.tag === ClassComponent, + "Expected subtree parent to be a mounted class component. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + + var node = fiber; + while (node.tag !== HostRoot) { + if (isContextProvider(node)) { + return node.stateNode.__reactInternalMemoizedMergedChildContext; + } + var parent = node["return"]; + invariant( + parent, + "Found unexpected detached subtree parent. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + node = parent; + } + return node.stateNode.context; +} + +var NoWork = 0; // TODO: Use an opaque type once ESLint et al support the syntax + +var Sync = 1; +var Never = 2147483647; // Max int32: Math.pow(2, 31) - 1 + +var UNIT_SIZE = 10; +var MAGIC_NUMBER_OFFSET = 2; + +// 1 unit of expiration time represents 10ms. +function msToExpirationTime(ms) { + // Always add an offset so that we don't clash with the magic number for NoWork. + return ((ms / UNIT_SIZE) | 0) + MAGIC_NUMBER_OFFSET; +} + +function ceiling(num, precision) { + return (((num / precision) | 0) + 1) * precision; +} + +function computeExpirationBucket(currentTime, expirationInMs, bucketSizeMs) { + return ceiling( + currentTime + expirationInMs / UNIT_SIZE, + bucketSizeMs / UNIT_SIZE + ); +} + +var NoContext = 0; +var AsyncUpdates = 1; + +{ + var hasBadMapPolyfill = false; + try { + var nonExtensibleObject = Object.preventExtensions({}); + /* eslint-disable no-new */ + new Map([[nonExtensibleObject, null]]); + new Set([nonExtensibleObject]); + /* eslint-enable no-new */ + } catch (e) { + // TODO: Consider warning about bad polyfills + hasBadMapPolyfill = true; + } +} + +// A Fiber is work on a Component that needs to be done or was done. There can +// be more than one per component. + +{ + var debugCounter = 1; +} + +function FiberNode(tag, key, internalContextTag) { + // Instance + this.tag = tag; + this.key = key; + this.type = null; + this.stateNode = null; + + // Fiber + this["return"] = null; + this.child = null; + this.sibling = null; + this.index = 0; + + this.ref = null; + + this.pendingProps = null; + this.memoizedProps = null; + this.updateQueue = null; + this.memoizedState = null; + + this.internalContextTag = internalContextTag; + + // Effects + this.effectTag = NoEffect; + this.nextEffect = null; + + this.firstEffect = null; + this.lastEffect = null; + + this.expirationTime = NoWork; + + this.alternate = null; + + { + this._debugID = debugCounter++; + this._debugSource = null; + this._debugOwner = null; + this._debugIsCurrentlyTiming = false; + if (!hasBadMapPolyfill && typeof Object.preventExtensions === "function") { + Object.preventExtensions(this); + } + } +} + +// This is a constructor function, rather than a POJO constructor, still +// please ensure we do the following: +// 1) Nobody should add any instance methods on this. Instance methods can be +// more difficult to predict when they get optimized and they are almost +// never inlined properly in static compilers. +// 2) Nobody should rely on `instanceof Fiber` for type testing. We should +// always know when it is a fiber. +// 3) We might want to experiment with using numeric keys since they are easier +// to optimize in a non-JIT environment. +// 4) We can easily go from a constructor to a createFiber object literal if that +// is faster. +// 5) It should be easy to port this to a C struct and keep a C implementation +// compatible. +var createFiber = function(tag, key, internalContextTag) { + // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors + return new FiberNode(tag, key, internalContextTag); +}; + +function shouldConstruct(Component) { + return !!(Component.prototype && Component.prototype.isReactComponent); +} + +// This is used to create an alternate fiber to do work on. +function createWorkInProgress(current, pendingProps, expirationTime) { + var workInProgress = current.alternate; + if (workInProgress === null) { + // We use a double buffering pooling technique because we know that we'll + // only ever need at most two versions of a tree. We pool the "other" unused + // node that we're free to reuse. This is lazily created to avoid allocating + // extra objects for things that are never updated. It also allow us to + // reclaim the extra memory if needed. + workInProgress = createFiber( + current.tag, + current.key, + current.internalContextTag + ); + workInProgress.type = current.type; + workInProgress.stateNode = current.stateNode; + + { + // DEV-only fields + workInProgress._debugID = current._debugID; + workInProgress._debugSource = current._debugSource; + workInProgress._debugOwner = current._debugOwner; + } + + workInProgress.alternate = current; + current.alternate = workInProgress; + } else { + // We already have an alternate. + // Reset the effect tag. + workInProgress.effectTag = NoEffect; + + // The effect list is no longer valid. + workInProgress.nextEffect = null; + workInProgress.firstEffect = null; + workInProgress.lastEffect = null; + } + + workInProgress.expirationTime = expirationTime; + workInProgress.pendingProps = pendingProps; + + workInProgress.child = current.child; + workInProgress.memoizedProps = current.memoizedProps; + workInProgress.memoizedState = current.memoizedState; + workInProgress.updateQueue = current.updateQueue; + + // These will be overridden during the parent's reconciliation + workInProgress.sibling = current.sibling; + workInProgress.index = current.index; + workInProgress.ref = current.ref; + + return workInProgress; +} + +function createHostRootFiber() { + var fiber = createFiber(HostRoot, null, NoContext); + return fiber; +} + +function createFiberFromElement(element, internalContextTag, expirationTime) { + var owner = null; + { + owner = element._owner; + } + + var fiber = void 0; + var type = element.type, + key = element.key; + + if (typeof type === "function") { + fiber = shouldConstruct(type) + ? createFiber(ClassComponent, key, internalContextTag) + : createFiber(IndeterminateComponent, key, internalContextTag); + fiber.type = type; + fiber.pendingProps = element.props; + } else if (typeof type === "string") { + fiber = createFiber(HostComponent, key, internalContextTag); + fiber.type = type; + fiber.pendingProps = element.props; + } else if ( + typeof type === "object" && + type !== null && + typeof type.tag === "number" + ) { + // Currently assumed to be a continuation and therefore is a fiber already. + // TODO: The yield system is currently broken for updates in some cases. + // The reified yield stores a fiber, but we don't know which fiber that is; + // the current or a workInProgress? When the continuation gets rendered here + // we don't know if we can reuse that fiber or if we need to clone it. + // There is probably a clever way to restructure this. + fiber = type; + fiber.pendingProps = element.props; + } else { + var info = ""; + { + if ( + type === undefined || + (typeof type === "object" && + type !== null && + Object.keys(type).length === 0) + ) { + info += + " You likely forgot to export your component from the file " + + "it's defined in, or you might have mixed up default and named imports."; + } + var ownerName = owner ? getComponentName(owner) : null; + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } + } + invariant( + false, + "Element type is invalid: expected a string (for built-in components) " + + "or a class/function (for composite components) but got: %s.%s", + type == null ? type : typeof type, + info + ); + } + + { + fiber._debugSource = element._source; + fiber._debugOwner = element._owner; + } + + fiber.expirationTime = expirationTime; + + return fiber; +} + +function createFiberFromFragment( + elements, + internalContextTag, + expirationTime, + key +) { + var fiber = createFiber(Fragment, key, internalContextTag); + fiber.pendingProps = elements; + fiber.expirationTime = expirationTime; + return fiber; +} + +function createFiberFromText(content, internalContextTag, expirationTime) { + var fiber = createFiber(HostText, null, internalContextTag); + fiber.pendingProps = content; + fiber.expirationTime = expirationTime; + return fiber; +} + +function createFiberFromHostInstanceForDeletion() { + var fiber = createFiber(HostComponent, null, NoContext); + fiber.type = "DELETED"; + return fiber; +} + +function createFiberFromCall(call, internalContextTag, expirationTime) { + var fiber = createFiber(CallComponent, call.key, internalContextTag); + fiber.type = call.handler; + fiber.pendingProps = call; + fiber.expirationTime = expirationTime; + return fiber; +} + +function createFiberFromReturn(returnNode, internalContextTag, expirationTime) { + var fiber = createFiber(ReturnComponent, null, internalContextTag); + fiber.expirationTime = expirationTime; + return fiber; +} + +function createFiberFromPortal(portal, internalContextTag, expirationTime) { + var fiber = createFiber(HostPortal, portal.key, internalContextTag); + fiber.pendingProps = portal.children || []; + fiber.expirationTime = expirationTime; + fiber.stateNode = { + containerInfo: portal.containerInfo, + pendingChildren: null, // Used by persistent updates + implementation: portal.implementation + }; + return fiber; +} + +function createFiberRoot(containerInfo, hydrate) { + // Cyclic construction. This cheats the type system right now because + // stateNode is any. + var uninitializedFiber = createHostRootFiber(); + var root = { + current: uninitializedFiber, + containerInfo: containerInfo, + pendingChildren: null, + remainingExpirationTime: NoWork, + isReadyForCommit: false, + finishedWork: null, + context: null, + pendingContext: null, + hydrate: hydrate, + nextScheduledRoot: null + }; + uninitializedFiber.stateNode = root; + return root; +} + +var onCommitFiberRoot = null; +var onCommitFiberUnmount = null; +var hasLoggedError = false; + +function catchErrors(fn) { + return function(arg) { + try { + return fn(arg); + } catch (err) { + if (true && !hasLoggedError) { + hasLoggedError = true; + warning(false, "React DevTools encountered an error: %s", err); + } + } + }; +} + +function injectInternals(internals) { + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { + // No DevTools + return false; + } + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if (hook.isDisabled) { + // This isn't a real property on the hook, but it can be set to opt out + // of DevTools integration and associated warnings and logs. + // https://github.com/facebook/react/issues/3877 + return true; + } + if (!hook.supportsFiber) { + { + warning( + false, + "The installed version of React DevTools is too old and will not work " + + "with the current version of React. Please update React DevTools. " + + "https://fb.me/react-devtools" + ); + } + // DevTools exists, even though it doesn't support Fiber. + return true; + } + try { + var rendererID = hook.inject(internals); + // We have successfully injected, so now it is safe to set up hooks. + onCommitFiberRoot = catchErrors(function(root) { + return hook.onCommitFiberRoot(rendererID, root); + }); + onCommitFiberUnmount = catchErrors(function(fiber) { + return hook.onCommitFiberUnmount(rendererID, fiber); + }); + } catch (err) { + // Catch all errors because it is unsafe to throw during initialization. + { + warning(false, "React DevTools encountered an error: %s.", err); + } + } + // DevTools exists + return true; +} + +function onCommitRoot(root) { + if (typeof onCommitFiberRoot === "function") { + onCommitFiberRoot(root); + } +} + +function onCommitUnmount(fiber) { + if (typeof onCommitFiberUnmount === "function") { + onCommitFiberUnmount(fiber); + } +} + +{ + var didWarnUpdateInsideUpdate = false; +} + +// Callbacks are not validated until invocation + +// Singly linked-list of updates. When an update is scheduled, it is added to +// the queue of the current fiber and the work-in-progress fiber. The two queues +// are separate but they share a persistent structure. +// +// During reconciliation, updates are removed from the work-in-progress fiber, +// but they remain on the current fiber. That ensures that if a work-in-progress +// is aborted, the aborted updates are recovered by cloning from current. +// +// The work-in-progress queue is always a subset of the current queue. +// +// When the tree is committed, the work-in-progress becomes the current. + +function createUpdateQueue(baseState) { + var queue = { + baseState: baseState, + expirationTime: NoWork, + first: null, + last: null, + callbackList: null, + hasForceUpdate: false, + isInitialized: false + }; + { + queue.isProcessing = false; + } + return queue; +} + +function insertUpdateIntoQueue(queue, update) { + // Append the update to the end of the list. + if (queue.last === null) { + // Queue is empty + queue.first = queue.last = update; + } else { + queue.last.next = update; + queue.last = update; + } + if ( + queue.expirationTime === NoWork || + queue.expirationTime > update.expirationTime + ) { + queue.expirationTime = update.expirationTime; + } +} + +function insertUpdateIntoFiber(fiber, update) { + // We'll have at least one and at most two distinct update queues. + var alternateFiber = fiber.alternate; + var queue1 = fiber.updateQueue; + if (queue1 === null) { + // TODO: We don't know what the base state will be until we begin work. + // It depends on which fiber is the next current. Initialize with an empty + // base state, then set to the memoizedState when rendering. Not super + // happy with this approach. + queue1 = fiber.updateQueue = createUpdateQueue(null); + } + + var queue2 = void 0; + if (alternateFiber !== null) { + queue2 = alternateFiber.updateQueue; + if (queue2 === null) { + queue2 = alternateFiber.updateQueue = createUpdateQueue(null); + } + } else { + queue2 = null; + } + queue2 = queue2 !== queue1 ? queue2 : null; + + // Warn if an update is scheduled from inside an updater function. + { + if ( + (queue1.isProcessing || (queue2 !== null && queue2.isProcessing)) && + !didWarnUpdateInsideUpdate + ) { + warning( + false, + "An update (setState, replaceState, or forceUpdate) was scheduled " + + "from inside an update function. Update functions should be pure, " + + "with zero side-effects. Consider using componentDidUpdate or a " + + "callback." + ); + didWarnUpdateInsideUpdate = true; + } + } + + // If there's only one queue, add the update to that queue and exit. + if (queue2 === null) { + insertUpdateIntoQueue(queue1, update); + return; + } + + // If either queue is empty, we need to add to both queues. + if (queue1.last === null || queue2.last === null) { + insertUpdateIntoQueue(queue1, update); + insertUpdateIntoQueue(queue2, update); + return; + } + + // If both lists are not empty, the last update is the same for both lists + // because of structural sharing. So, we should only append to one of + // the lists. + insertUpdateIntoQueue(queue1, update); + // But we still need to update the `last` pointer of queue2. + queue2.last = update; +} + +function getUpdateExpirationTime(fiber) { + if (fiber.tag !== ClassComponent && fiber.tag !== HostRoot) { + return NoWork; + } + var updateQueue = fiber.updateQueue; + if (updateQueue === null) { + return NoWork; + } + return updateQueue.expirationTime; +} + +function getStateFromUpdate(update, instance, prevState, props) { + var partialState = update.partialState; + if (typeof partialState === "function") { + var updateFn = partialState; + return updateFn.call(instance, prevState, props); + } else { + return partialState; + } +} + +function processUpdateQueue( + current, + workInProgress, + queue, + instance, + props, + renderExpirationTime +) { + if (current !== null && current.updateQueue === queue) { + // We need to create a work-in-progress queue, by cloning the current queue. + var currentQueue = queue; + queue = workInProgress.updateQueue = { + baseState: currentQueue.baseState, + expirationTime: currentQueue.expirationTime, + first: currentQueue.first, + last: currentQueue.last, + isInitialized: currentQueue.isInitialized, + // These fields are no longer valid because they were already committed. + // Reset them. + callbackList: null, + hasForceUpdate: false + }; + } + + { + // Set this flag so we can warn if setState is called inside the update + // function of another setState. + queue.isProcessing = true; + } + + // Reset the remaining expiration time. If we skip over any updates, we'll + // increase this accordingly. + queue.expirationTime = NoWork; + + // TODO: We don't know what the base state will be until we begin work. + // It depends on which fiber is the next current. Initialize with an empty + // base state, then set to the memoizedState when rendering. Not super + // happy with this approach. + var state = void 0; + if (queue.isInitialized) { + state = queue.baseState; + } else { + state = queue.baseState = workInProgress.memoizedState; + queue.isInitialized = true; + } + var dontMutatePrevState = true; + var update = queue.first; + var didSkip = false; + while (update !== null) { + var updateExpirationTime = update.expirationTime; + if (updateExpirationTime > renderExpirationTime) { + // This update does not have sufficient priority. Skip it. + var remainingExpirationTime = queue.expirationTime; + if ( + remainingExpirationTime === NoWork || + remainingExpirationTime > updateExpirationTime + ) { + // Update the remaining expiration time. + queue.expirationTime = updateExpirationTime; + } + if (!didSkip) { + didSkip = true; + queue.baseState = state; + } + // Continue to the next update. + update = update.next; + continue; + } + + // This update does have sufficient priority. + + // If no previous updates were skipped, drop this update from the queue by + // advancing the head of the list. + if (!didSkip) { + queue.first = update.next; + if (queue.first === null) { + queue.last = null; + } + } + + // Process the update + var _partialState = void 0; + if (update.isReplace) { + state = getStateFromUpdate(update, instance, state, props); + dontMutatePrevState = true; + } else { + _partialState = getStateFromUpdate(update, instance, state, props); + if (_partialState) { + if (dontMutatePrevState) { + // $FlowFixMe: Idk how to type this properly. + state = Object.assign({}, state, _partialState); + } else { + state = Object.assign(state, _partialState); + } + dontMutatePrevState = false; + } + } + if (update.isForced) { + queue.hasForceUpdate = true; + } + if (update.callback !== null) { + // Append to list of callbacks. + var _callbackList = queue.callbackList; + if (_callbackList === null) { + _callbackList = queue.callbackList = []; + } + _callbackList.push(update); + } + update = update.next; + } + + if (queue.callbackList !== null) { + workInProgress.effectTag |= Callback; + } else if (queue.first === null && !queue.hasForceUpdate) { + // The queue is empty. We can reset it. + workInProgress.updateQueue = null; + } + + if (!didSkip) { + didSkip = true; + queue.baseState = state; + } + + { + // No longer processing. + queue.isProcessing = false; + } + + return state; +} + +function commitCallbacks(queue, context) { + var callbackList = queue.callbackList; + if (callbackList === null) { + return; + } + // Set the list to null to make sure they don't get called more than once. + queue.callbackList = null; + for (var i = 0; i < callbackList.length; i++) { + var update = callbackList[i]; + var _callback = update.callback; + // This update might be processed again. Clear the callback so it's only + // called once. + update.callback = null; + invariant( + typeof _callback === "function", + "Invalid argument passed as callback. Expected a function. Instead " + + "received: %s", + _callback + ); + _callback.call(context); + } +} + +var fakeInternalInstance = {}; +var isArray = Array.isArray; + +{ + var didWarnAboutStateAssignmentForComponent = {}; + + var warnOnInvalidCallback = function(callback, callerName) { + warning( + callback === null || typeof callback === "function", + "%s(...): Expected the last optional `callback` argument to be a " + + "function. Instead received: %s.", + callerName, + callback + ); + }; + + // This is so gross but it's at least non-critical and can be removed if + // it causes problems. This is meant to give a nicer error message for + // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component, + // ...)) which otherwise throws a "_processChildContext is not a function" + // exception. + Object.defineProperty(fakeInternalInstance, "_processChildContext", { + enumerable: false, + value: function() { + invariant( + false, + "_processChildContext is not available in React 16+. This likely " + + "means you have multiple copies of React and are attempting to nest " + + "a React 15 tree inside a React 16 tree using " + + "unstable_renderSubtreeIntoContainer, which isn't supported. Try " + + "to make sure you have only one copy of React (and ideally, switch " + + "to ReactDOM.createPortal)." + ); + } + }); + Object.freeze(fakeInternalInstance); +} + +var ReactFiberClassComponent = function( + scheduleWork, + computeExpirationForFiber, + memoizeProps, + memoizeState +) { + // Class component state updater + var updater = { + isMounted: isMounted, + enqueueSetState: function(instance, partialState, callback) { + var fiber = get(instance); + callback = callback === undefined ? null : callback; + { + warnOnInvalidCallback(callback, "setState"); + } + var expirationTime = computeExpirationForFiber(fiber); + var update = { + expirationTime: expirationTime, + partialState: partialState, + callback: callback, + isReplace: false, + isForced: false, + nextCallback: null, + next: null + }; + insertUpdateIntoFiber(fiber, update); + scheduleWork(fiber, expirationTime); + }, + enqueueReplaceState: function(instance, state, callback) { + var fiber = get(instance); + callback = callback === undefined ? null : callback; + { + warnOnInvalidCallback(callback, "replaceState"); + } + var expirationTime = computeExpirationForFiber(fiber); + var update = { + expirationTime: expirationTime, + partialState: state, + callback: callback, + isReplace: true, + isForced: false, + nextCallback: null, + next: null + }; + insertUpdateIntoFiber(fiber, update); + scheduleWork(fiber, expirationTime); + }, + enqueueForceUpdate: function(instance, callback) { + var fiber = get(instance); + callback = callback === undefined ? null : callback; + { + warnOnInvalidCallback(callback, "forceUpdate"); + } + var expirationTime = computeExpirationForFiber(fiber); + var update = { + expirationTime: expirationTime, + partialState: null, + callback: callback, + isReplace: false, + isForced: true, + nextCallback: null, + next: null + }; + insertUpdateIntoFiber(fiber, update); + scheduleWork(fiber, expirationTime); + } + }; + + function checkShouldComponentUpdate( + workInProgress, + oldProps, + newProps, + oldState, + newState, + newContext + ) { + if ( + oldProps === null || + (workInProgress.updateQueue !== null && + workInProgress.updateQueue.hasForceUpdate) + ) { + // If the workInProgress already has an Update effect, return true + return true; + } + + var instance = workInProgress.stateNode; + var type = workInProgress.type; + if (typeof instance.shouldComponentUpdate === "function") { + startPhaseTimer(workInProgress, "shouldComponentUpdate"); + var shouldUpdate = instance.shouldComponentUpdate( + newProps, + newState, + newContext + ); + stopPhaseTimer(); + + { + warning( + shouldUpdate !== undefined, + "%s.shouldComponentUpdate(): Returned undefined instead of a " + + "boolean value. Make sure to return true or false.", + getComponentName(workInProgress) || "Unknown" + ); + } + + return shouldUpdate; + } + + if (type.prototype && type.prototype.isPureReactComponent) { + return ( + !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) + ); + } + + return true; + } + + function checkClassInstance(workInProgress) { + var instance = workInProgress.stateNode; + var type = workInProgress.type; + { + var name = getComponentName(workInProgress); + var renderPresent = instance.render; + + if (!renderPresent) { + if (type.prototype && typeof type.prototype.render === "function") { + warning( + false, + "%s(...): No `render` method found on the returned component " + + "instance: did you accidentally return an object from the constructor?", + name + ); + } else { + warning( + false, + "%s(...): No `render` method found on the returned component " + + "instance: you may have forgotten to define `render`.", + name + ); + } + } + + var noGetInitialStateOnES6 = + !instance.getInitialState || + instance.getInitialState.isReactClassApproved || + instance.state; + warning( + noGetInitialStateOnES6, + "getInitialState was defined on %s, a plain JavaScript class. " + + "This is only supported for classes created using React.createClass. " + + "Did you mean to define a state property instead?", + name + ); + var noGetDefaultPropsOnES6 = + !instance.getDefaultProps || + instance.getDefaultProps.isReactClassApproved; + warning( + noGetDefaultPropsOnES6, + "getDefaultProps was defined on %s, a plain JavaScript class. " + + "This is only supported for classes created using React.createClass. " + + "Use a static property to define defaultProps instead.", + name + ); + var noInstancePropTypes = !instance.propTypes; + warning( + noInstancePropTypes, + "propTypes was defined as an instance property on %s. Use a static " + + "property to define propTypes instead.", + name + ); + var noInstanceContextTypes = !instance.contextTypes; + warning( + noInstanceContextTypes, + "contextTypes was defined as an instance property on %s. Use a static " + + "property to define contextTypes instead.", + name + ); + var noComponentShouldUpdate = + typeof instance.componentShouldUpdate !== "function"; + warning( + noComponentShouldUpdate, + "%s has a method called " + + "componentShouldUpdate(). Did you mean shouldComponentUpdate()? " + + "The name is phrased as a question because the function is " + + "expected to return a value.", + name + ); + if ( + type.prototype && + type.prototype.isPureReactComponent && + typeof instance.shouldComponentUpdate !== "undefined" + ) { + warning( + false, + "%s has a method called shouldComponentUpdate(). " + + "shouldComponentUpdate should not be used when extending React.PureComponent. " + + "Please extend React.Component if shouldComponentUpdate is used.", + getComponentName(workInProgress) || "A pure component" + ); + } + var noComponentDidUnmount = + typeof instance.componentDidUnmount !== "function"; + warning( + noComponentDidUnmount, + "%s has a method called " + + "componentDidUnmount(). But there is no such lifecycle method. " + + "Did you mean componentWillUnmount()?", + name + ); + var noComponentDidReceiveProps = + typeof instance.componentDidReceiveProps !== "function"; + warning( + noComponentDidReceiveProps, + "%s has a method called " + + "componentDidReceiveProps(). But there is no such lifecycle method. " + + "If you meant to update the state in response to changing props, " + + "use componentWillReceiveProps(). If you meant to fetch data or " + + "run side-effects or mutations after React has updated the UI, use componentDidUpdate().", + name + ); + var noComponentWillRecieveProps = + typeof instance.componentWillRecieveProps !== "function"; + warning( + noComponentWillRecieveProps, + "%s has a method called " + + "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", + name + ); + var hasMutatedProps = instance.props !== workInProgress.pendingProps; + warning( + instance.props === undefined || !hasMutatedProps, + "%s(...): When calling super() in `%s`, make sure to pass " + + "up the same props that your component's constructor was passed.", + name, + name + ); + var noInstanceDefaultProps = !instance.defaultProps; + warning( + noInstanceDefaultProps, + "Setting defaultProps as an instance property on %s is not supported and will be ignored." + + " Instead, define defaultProps as a static property on %s.", + name, + name + ); + } + + var state = instance.state; + if (state && (typeof state !== "object" || isArray(state))) { + invariant( + false, + "%s.state: must be set to an object or null", + getComponentName(workInProgress) + ); + } + if (typeof instance.getChildContext === "function") { + invariant( + typeof workInProgress.type.childContextTypes === "object", + "%s.getChildContext(): childContextTypes must be defined in order to " + + "use getChildContext().", + getComponentName(workInProgress) + ); + } + } + + function resetInputPointers(workInProgress, instance) { + instance.props = workInProgress.memoizedProps; + instance.state = workInProgress.memoizedState; + } + + function adoptClassInstance(workInProgress, instance) { + instance.updater = updater; + workInProgress.stateNode = instance; + // The instance needs access to the fiber so that it can schedule updates + set(instance, workInProgress); + { + instance._reactInternalInstance = fakeInternalInstance; + } + } + + function constructClassInstance(workInProgress, props) { + var ctor = workInProgress.type; + var unmaskedContext = getUnmaskedContext(workInProgress); + var needsContext = isContextConsumer(workInProgress); + var context = needsContext + ? getMaskedContext(workInProgress, unmaskedContext) + : emptyObject; + var instance = new ctor(props, context); + adoptClassInstance(workInProgress, instance); + + // Cache unmasked context so we can avoid recreating masked context unless necessary. + // ReactFiberContext usually updates this cache but can't for newly-created instances. + if (needsContext) { + cacheContext(workInProgress, unmaskedContext, context); + } + + return instance; + } + + function callComponentWillMount(workInProgress, instance) { + startPhaseTimer(workInProgress, "componentWillMount"); + var oldState = instance.state; + instance.componentWillMount(); + + stopPhaseTimer(); + + if (oldState !== instance.state) { + { + warning( + false, + "%s.componentWillMount(): Assigning directly to this.state is " + + "deprecated (except inside a component's " + + "constructor). Use setState instead.", + getComponentName(workInProgress) + ); + } + updater.enqueueReplaceState(instance, instance.state, null); + } + } + + function callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + newContext + ) { + startPhaseTimer(workInProgress, "componentWillReceiveProps"); + var oldState = instance.state; + instance.componentWillReceiveProps(newProps, newContext); + stopPhaseTimer(); + + if (instance.state !== oldState) { + { + var componentName = getComponentName(workInProgress) || "Component"; + if (!didWarnAboutStateAssignmentForComponent[componentName]) { + warning( + false, + "%s.componentWillReceiveProps(): Assigning directly to " + + "this.state is deprecated (except inside a component's " + + "constructor). Use setState instead.", + componentName + ); + didWarnAboutStateAssignmentForComponent[componentName] = true; + } + } + updater.enqueueReplaceState(instance, instance.state, null); + } + } + + // Invokes the mount life-cycles on a previously never rendered instance. + function mountClassInstance(workInProgress, renderExpirationTime) { + var current = workInProgress.alternate; + + { + checkClassInstance(workInProgress); + } + + var instance = workInProgress.stateNode; + var state = instance.state || null; + + var props = workInProgress.pendingProps; + invariant( + props, + "There must be pending props for an initial mount. This error is " + + "likely caused by a bug in React. Please file an issue." + ); + + var unmaskedContext = getUnmaskedContext(workInProgress); + + instance.props = props; + instance.state = workInProgress.memoizedState = state; + instance.refs = emptyObject; + instance.context = getMaskedContext(workInProgress, unmaskedContext); + + if ( + enableAsyncSubtreeAPI && + workInProgress.type != null && + workInProgress.type.prototype != null && + workInProgress.type.prototype.unstable_isAsyncReactComponent === true + ) { + workInProgress.internalContextTag |= AsyncUpdates; + } + + if (typeof instance.componentWillMount === "function") { + callComponentWillMount(workInProgress, instance); + // If we had additional state updates during this life-cycle, let's + // process them now. + var updateQueue = workInProgress.updateQueue; + if (updateQueue !== null) { + instance.state = processUpdateQueue( + current, + workInProgress, + updateQueue, + instance, + props, + renderExpirationTime + ); + } + } + if (typeof instance.componentDidMount === "function") { + workInProgress.effectTag |= Update; + } + } + + // Called on a preexisting class instance. Returns false if a resumed render + // could be reused. + // function resumeMountClassInstance( + // workInProgress: Fiber, + // priorityLevel: PriorityLevel, + // ): boolean { + // const instance = workInProgress.stateNode; + // resetInputPointers(workInProgress, instance); + + // let newState = workInProgress.memoizedState; + // let newProps = workInProgress.pendingProps; + // if (!newProps) { + // // If there isn't any new props, then we'll reuse the memoized props. + // // This could be from already completed work. + // newProps = workInProgress.memoizedProps; + // invariant( + // newProps != null, + // 'There should always be pending or memoized props. This error is ' + + // 'likely caused by a bug in React. Please file an issue.', + // ); + // } + // const newUnmaskedContext = getUnmaskedContext(workInProgress); + // const newContext = getMaskedContext(workInProgress, newUnmaskedContext); + + // const oldContext = instance.context; + // const oldProps = workInProgress.memoizedProps; + + // if ( + // typeof instance.componentWillReceiveProps === 'function' && + // (oldProps !== newProps || oldContext !== newContext) + // ) { + // callComponentWillReceiveProps( + // workInProgress, + // instance, + // newProps, + // newContext, + // ); + // } + + // // Process the update queue before calling shouldComponentUpdate + // const updateQueue = workInProgress.updateQueue; + // if (updateQueue !== null) { + // newState = processUpdateQueue( + // workInProgress, + // updateQueue, + // instance, + // newState, + // newProps, + // priorityLevel, + // ); + // } + + // // TODO: Should we deal with a setState that happened after the last + // // componentWillMount and before this componentWillMount? Probably + // // unsupported anyway. + + // if ( + // !checkShouldComponentUpdate( + // workInProgress, + // workInProgress.memoizedProps, + // newProps, + // workInProgress.memoizedState, + // newState, + // newContext, + // ) + // ) { + // // Update the existing instance's state, props, and context pointers even + // // though we're bailing out. + // instance.props = newProps; + // instance.state = newState; + // instance.context = newContext; + // return false; + // } + + // // Update the input pointers now so that they are correct when we call + // // componentWillMount + // instance.props = newProps; + // instance.state = newState; + // instance.context = newContext; + + // if (typeof instance.componentWillMount === 'function') { + // callComponentWillMount(workInProgress, instance); + // // componentWillMount may have called setState. Process the update queue. + // const newUpdateQueue = workInProgress.updateQueue; + // if (newUpdateQueue !== null) { + // newState = processUpdateQueue( + // workInProgress, + // newUpdateQueue, + // instance, + // newState, + // newProps, + // priorityLevel, + // ); + // } + // } + + // if (typeof instance.componentDidMount === 'function') { + // workInProgress.effectTag |= Update; + // } + + // instance.state = newState; + + // return true; + // } + + // Invokes the update life-cycles and returns false if it shouldn't rerender. + function updateClassInstance(current, workInProgress, renderExpirationTime) { + var instance = workInProgress.stateNode; + resetInputPointers(workInProgress, instance); + + var oldProps = workInProgress.memoizedProps; + var newProps = workInProgress.pendingProps; + if (!newProps) { + // If there aren't any new props, then we'll reuse the memoized props. + // This could be from already completed work. + newProps = oldProps; + invariant( + newProps != null, + "There should always be pending or memoized props. This error is " + + "likely caused by a bug in React. Please file an issue." + ); + } + var oldContext = instance.context; + var newUnmaskedContext = getUnmaskedContext(workInProgress); + var newContext = getMaskedContext(workInProgress, newUnmaskedContext); + + // Note: During these life-cycles, instance.props/instance.state are what + // ever the previously attempted to render - not the "current". However, + // during componentDidUpdate we pass the "current" props. + + if ( + typeof instance.componentWillReceiveProps === "function" && + (oldProps !== newProps || oldContext !== newContext) + ) { + callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + newContext + ); + } + + // Compute the next state using the memoized state and the update queue. + var oldState = workInProgress.memoizedState; + // TODO: Previous state can be null. + var newState = void 0; + if (workInProgress.updateQueue !== null) { + newState = processUpdateQueue( + current, + workInProgress, + workInProgress.updateQueue, + instance, + newProps, + renderExpirationTime + ); + } else { + newState = oldState; + } + + if ( + oldProps === newProps && + oldState === newState && + !hasContextChanged() && + !( + workInProgress.updateQueue !== null && + workInProgress.updateQueue.hasForceUpdate + ) + ) { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidUpdate === "function") { + if ( + oldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.effectTag |= Update; + } + } + return false; + } + + var shouldUpdate = checkShouldComponentUpdate( + workInProgress, + oldProps, + newProps, + oldState, + newState, + newContext + ); + + if (shouldUpdate) { + if (typeof instance.componentWillUpdate === "function") { + startPhaseTimer(workInProgress, "componentWillUpdate"); + instance.componentWillUpdate(newProps, newState, newContext); + stopPhaseTimer(); + } + if (typeof instance.componentDidUpdate === "function") { + workInProgress.effectTag |= Update; + } + } else { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidUpdate === "function") { + if ( + oldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.effectTag |= Update; + } + } + + // If shouldComponentUpdate returned false, we should still update the + // memoized props/state to indicate that this work can be reused. + memoizeProps(workInProgress, newProps); + memoizeState(workInProgress, newState); + } + + // Update the existing instance's state, props, and context pointers even + // if shouldComponentUpdate returns false. + instance.props = newProps; + instance.state = newState; + instance.context = newContext; + + return shouldUpdate; + } + + return { + adoptClassInstance: adoptClassInstance, + constructClassInstance: constructClassInstance, + mountClassInstance: mountClassInstance, + // resumeMountClassInstance, + updateClassInstance: updateClassInstance + }; +}; + +var getCurrentFiberStackAddendum$1 = + ReactDebugCurrentFiber.getCurrentFiberStackAddendum; + +{ + var didWarnAboutMaps = false; + /** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ + var ownerHasKeyUseWarning = {}; + var ownerHasFunctionTypeWarning = {}; + + var warnForMissingKey = function(child) { + if (child === null || typeof child !== "object") { + return; + } + if (!child._store || child._store.validated || child.key != null) { + return; + } + invariant( + typeof child._store === "object", + "React Component in warnForMissingKey should have a _store. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + child._store.validated = true; + + var currentComponentErrorInfo = + "Each child in an array or iterator should have a unique " + + '"key" prop. See https://fb.me/react-warning-keys for ' + + "more information." + + (getCurrentFiberStackAddendum$1() || ""); + if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { + return; + } + ownerHasKeyUseWarning[currentComponentErrorInfo] = true; + + warning( + false, + "Each child in an array or iterator should have a unique " + + '"key" prop. See https://fb.me/react-warning-keys for ' + + "more information.%s", + getCurrentFiberStackAddendum$1() + ); + }; +} + +var isArray$1 = Array.isArray; + +var ITERATOR_SYMBOL = typeof Symbol === "function" && Symbol.iterator; +var FAUX_ITERATOR_SYMBOL = "@@iterator"; // Before Symbol spec. + +// The Symbol used to tag the ReactElement-like types. If there is no native Symbol +// nor polyfill, then a plain number is used for performance. +var REACT_ELEMENT_TYPE; +var REACT_CALL_TYPE; +var REACT_RETURN_TYPE; +var REACT_FRAGMENT_TYPE; +if (typeof Symbol === "function" && Symbol["for"]) { + REACT_ELEMENT_TYPE = Symbol["for"]("react.element"); + REACT_CALL_TYPE = Symbol["for"]("react.call"); + REACT_RETURN_TYPE = Symbol["for"]("react.return"); + REACT_FRAGMENT_TYPE = Symbol["for"]("react.fragment"); +} else { + REACT_ELEMENT_TYPE = 0xeac7; + REACT_CALL_TYPE = 0xeac8; + REACT_RETURN_TYPE = 0xeac9; + REACT_FRAGMENT_TYPE = 0xeacb; +} + +function getIteratorFn(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable === "undefined") { + return null; + } + var iteratorFn = + (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL]) || + maybeIterable[FAUX_ITERATOR_SYMBOL]; + if (typeof iteratorFn === "function") { + return iteratorFn; + } + return null; +} + +function coerceRef(current, element) { + var mixedRef = element.ref; + if (mixedRef !== null && typeof mixedRef !== "function") { + if (element._owner) { + var owner = element._owner; + var inst = void 0; + if (owner) { + var ownerFiber = owner; + invariant( + ownerFiber.tag === ClassComponent, + "Stateless function components cannot have refs." + ); + inst = ownerFiber.stateNode; + } + invariant( + inst, + "Missing owner for string ref %s. This error is likely caused by a " + + "bug in React. Please file an issue.", + mixedRef + ); + var stringRef = "" + mixedRef; + // Check if previous string ref matches new string ref + if ( + current !== null && + current.ref !== null && + current.ref._stringRef === stringRef + ) { + return current.ref; + } + var ref = function(value) { + var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs; + if (value === null) { + delete refs[stringRef]; + } else { + refs[stringRef] = value; + } + }; + ref._stringRef = stringRef; + return ref; + } else { + invariant( + typeof mixedRef === "string", + "Expected ref to be a function or a string." + ); + invariant( + element._owner, + "Element ref was specified as a string (%s) but no owner was " + + "set. You may have multiple copies of React loaded. " + + "(details: https://fb.me/react-refs-must-have-owner).", + mixedRef + ); + } + } + return mixedRef; +} + +function throwOnInvalidObjectType(returnFiber, newChild) { + if (returnFiber.type !== "textarea") { + var addendum = ""; + { + addendum = + " If you meant to render a collection of children, use an array " + + "instead." + + (getCurrentFiberStackAddendum$1() || ""); + } + invariant( + false, + "Objects are not valid as a React child (found: %s).%s", + Object.prototype.toString.call(newChild) === "[object Object]" + ? "object with keys {" + Object.keys(newChild).join(", ") + "}" + : newChild, + addendum + ); + } +} + +function warnOnFunctionType() { + var currentComponentErrorInfo = + "Functions are not valid as a React child. This may happen if " + + "you return a Component instead of from render. " + + "Or maybe you meant to call this function rather than return it." + + (getCurrentFiberStackAddendum$1() || ""); + + if (ownerHasFunctionTypeWarning[currentComponentErrorInfo]) { + return; + } + ownerHasFunctionTypeWarning[currentComponentErrorInfo] = true; + + warning( + false, + "Functions are not valid as a React child. This may happen if " + + "you return a Component instead of from render. " + + "Or maybe you meant to call this function rather than return it.%s", + getCurrentFiberStackAddendum$1() || "" + ); +} + +// This wrapper function exists because I expect to clone the code in each path +// to be able to optimize each path individually by branching early. This needs +// a compiler or we can do it manually. Helpers that don't need this branching +// live outside of this function. +function ChildReconciler(shouldClone, shouldTrackSideEffects) { + function deleteChild(returnFiber, childToDelete) { + if (!shouldTrackSideEffects) { + // Noop. + return; + } + if (!shouldClone) { + // When we're reconciling in place we have a work in progress copy. We + // actually want the current copy. If there is no current copy, then we + // don't need to track deletion side-effects. + if (childToDelete.alternate === null) { + return; + } + childToDelete = childToDelete.alternate; + } + // Deletions are added in reversed order so we add it to the front. + // At this point, the return fiber's effect list is empty except for + // deletions, so we can just append the deletion to the list. The remaining + // effects aren't added until the complete phase. Once we implement + // resuming, this may not be true. + var last = returnFiber.lastEffect; + if (last !== null) { + last.nextEffect = childToDelete; + returnFiber.lastEffect = childToDelete; + } else { + returnFiber.firstEffect = returnFiber.lastEffect = childToDelete; + } + childToDelete.nextEffect = null; + childToDelete.effectTag = Deletion; + } + + function deleteRemainingChildren(returnFiber, currentFirstChild) { + if (!shouldTrackSideEffects) { + // Noop. + return null; + } + + // TODO: For the shouldClone case, this could be micro-optimized a bit by + // assuming that after the first child we've already added everything. + var childToDelete = currentFirstChild; + while (childToDelete !== null) { + deleteChild(returnFiber, childToDelete); + childToDelete = childToDelete.sibling; + } + return null; + } + + function mapRemainingChildren(returnFiber, currentFirstChild) { + // Add the remaining children to a temporary map so that we can find them by + // keys quickly. Implicit (null) keys get added to this set with their index + var existingChildren = new Map(); + + var existingChild = currentFirstChild; + while (existingChild !== null) { + if (existingChild.key !== null) { + existingChildren.set(existingChild.key, existingChild); + } else { + existingChildren.set(existingChild.index, existingChild); + } + existingChild = existingChild.sibling; + } + return existingChildren; + } + + function useFiber(fiber, pendingProps, expirationTime) { + // We currently set sibling to null and index to 0 here because it is easy + // to forget to do before returning it. E.g. for the single child case. + if (shouldClone) { + var clone = createWorkInProgress(fiber, pendingProps, expirationTime); + clone.index = 0; + clone.sibling = null; + return clone; + } else { + // We override the expiration time even if it is earlier, because if + // we're reconciling at a later time that means that this was + // down-prioritized. + fiber.expirationTime = expirationTime; + fiber.effectTag = NoEffect; + fiber.index = 0; + fiber.sibling = null; + fiber.pendingProps = pendingProps; + return fiber; + } + } + + function placeChild(newFiber, lastPlacedIndex, newIndex) { + newFiber.index = newIndex; + if (!shouldTrackSideEffects) { + // Noop. + return lastPlacedIndex; + } + var current = newFiber.alternate; + if (current !== null) { + var oldIndex = current.index; + if (oldIndex < lastPlacedIndex) { + // This is a move. + newFiber.effectTag = Placement; + return lastPlacedIndex; + } else { + // This item can stay in place. + return oldIndex; + } + } else { + // This is an insertion. + newFiber.effectTag = Placement; + return lastPlacedIndex; + } + } + + function placeSingleChild(newFiber) { + // This is simpler for the single child case. We only need to do a + // placement for inserting new children. + if (shouldTrackSideEffects && newFiber.alternate === null) { + newFiber.effectTag = Placement; + } + return newFiber; + } + + function updateTextNode(returnFiber, current, textContent, expirationTime) { + if (current === null || current.tag !== HostText) { + // Insert + var created = createFiberFromText( + textContent, + returnFiber.internalContextTag, + expirationTime + ); + created["return"] = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, textContent, expirationTime); + existing["return"] = returnFiber; + return existing; + } + } + + function updateElement(returnFiber, current, element, expirationTime) { + if (current !== null && current.type === element.type) { + // Move based on index + var existing = useFiber(current, element.props, expirationTime); + existing.ref = coerceRef(current, element); + existing["return"] = returnFiber; + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } + return existing; + } else { + // Insert + var created = createFiberFromElement( + element, + returnFiber.internalContextTag, + expirationTime + ); + created.ref = coerceRef(current, element); + created["return"] = returnFiber; + return created; + } + } + + function updateCall(returnFiber, current, call, expirationTime) { + // TODO: Should this also compare handler to determine whether to reuse? + if (current === null || current.tag !== CallComponent) { + // Insert + var created = createFiberFromCall( + call, + returnFiber.internalContextTag, + expirationTime + ); + created["return"] = returnFiber; + return created; + } else { + // Move based on index + var existing = useFiber(current, call, expirationTime); + existing["return"] = returnFiber; + return existing; + } + } + + function updateReturn(returnFiber, current, returnNode, expirationTime) { + if (current === null || current.tag !== ReturnComponent) { + // Insert + var created = createFiberFromReturn( + returnNode, + returnFiber.internalContextTag, + expirationTime + ); + created.type = returnNode.value; + created["return"] = returnFiber; + return created; + } else { + // Move based on index + var existing = useFiber(current, null, expirationTime); + existing.type = returnNode.value; + existing["return"] = returnFiber; + return existing; + } + } + + function updatePortal(returnFiber, current, portal, expirationTime) { + if ( + current === null || + current.tag !== HostPortal || + current.stateNode.containerInfo !== portal.containerInfo || + current.stateNode.implementation !== portal.implementation + ) { + // Insert + var created = createFiberFromPortal( + portal, + returnFiber.internalContextTag, + expirationTime + ); + created["return"] = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, portal.children || [], expirationTime); + existing["return"] = returnFiber; + return existing; + } + } + + function updateFragment(returnFiber, current, fragment, expirationTime, key) { + if (current === null || current.tag !== Fragment) { + // Insert + var created = createFiberFromFragment( + fragment, + returnFiber.internalContextTag, + expirationTime, + key + ); + created["return"] = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, fragment, expirationTime); + existing["return"] = returnFiber; + return existing; + } + } + + function createChild(returnFiber, newChild, expirationTime) { + if (typeof newChild === "string" || typeof newChild === "number") { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + var created = createFiberFromText( + "" + newChild, + returnFiber.internalContextTag, + expirationTime + ); + created["return"] = returnFiber; + return created; + } + + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + if (newChild.type === REACT_FRAGMENT_TYPE) { + var _created = createFiberFromFragment( + newChild.props.children, + returnFiber.internalContextTag, + expirationTime, + newChild.key + ); + _created["return"] = returnFiber; + return _created; + } else { + var _created2 = createFiberFromElement( + newChild, + returnFiber.internalContextTag, + expirationTime + ); + _created2.ref = coerceRef(null, newChild); + _created2["return"] = returnFiber; + return _created2; + } + } + + case REACT_CALL_TYPE: { + var _created3 = createFiberFromCall( + newChild, + returnFiber.internalContextTag, + expirationTime + ); + _created3["return"] = returnFiber; + return _created3; + } + + case REACT_RETURN_TYPE: { + var _created4 = createFiberFromReturn( + newChild, + returnFiber.internalContextTag, + expirationTime + ); + _created4.type = newChild.value; + _created4["return"] = returnFiber; + return _created4; + } + + case REACT_PORTAL_TYPE: { + var _created5 = createFiberFromPortal( + newChild, + returnFiber.internalContextTag, + expirationTime + ); + _created5["return"] = returnFiber; + return _created5; + } + } + + if (isArray$1(newChild) || getIteratorFn(newChild)) { + var _created6 = createFiberFromFragment( + newChild, + returnFiber.internalContextTag, + expirationTime, + null + ); + _created6["return"] = returnFiber; + return _created6; + } + + throwOnInvalidObjectType(returnFiber, newChild); + } + + { + if (typeof newChild === "function") { + warnOnFunctionType(); + } + } + + return null; + } + + function updateSlot(returnFiber, oldFiber, newChild, expirationTime) { + // Update the fiber if the keys match, otherwise return null. + + var key = oldFiber !== null ? oldFiber.key : null; + + if (typeof newChild === "string" || typeof newChild === "number") { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + if (key !== null) { + return null; + } + return updateTextNode( + returnFiber, + oldFiber, + "" + newChild, + expirationTime + ); + } + + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + if (newChild.key === key) { + if (newChild.type === REACT_FRAGMENT_TYPE) { + return updateFragment( + returnFiber, + oldFiber, + newChild.props.children, + expirationTime, + key + ); + } + return updateElement( + returnFiber, + oldFiber, + newChild, + expirationTime + ); + } else { + return null; + } + } + + case REACT_CALL_TYPE: { + if (newChild.key === key) { + return updateCall(returnFiber, oldFiber, newChild, expirationTime); + } else { + return null; + } + } + + case REACT_RETURN_TYPE: { + // Returns don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a + // yield. + if (key === null) { + return updateReturn( + returnFiber, + oldFiber, + newChild, + expirationTime + ); + } else { + return null; + } + } + + case REACT_PORTAL_TYPE: { + if (newChild.key === key) { + return updatePortal( + returnFiber, + oldFiber, + newChild, + expirationTime + ); + } else { + return null; + } + } + } + + if (isArray$1(newChild) || getIteratorFn(newChild)) { + if (key !== null) { + return null; + } + + return updateFragment( + returnFiber, + oldFiber, + newChild, + expirationTime, + null + ); + } + + throwOnInvalidObjectType(returnFiber, newChild); + } + + { + if (typeof newChild === "function") { + warnOnFunctionType(); + } + } + + return null; + } + + function updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChild, + expirationTime + ) { + if (typeof newChild === "string" || typeof newChild === "number") { + // Text nodes don't have keys, so we neither have to check the old nor + // new node for the key. If both are text nodes, they match. + var matchedFiber = existingChildren.get(newIdx) || null; + return updateTextNode( + returnFiber, + matchedFiber, + "" + newChild, + expirationTime + ); + } + + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _matchedFiber = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; + if (newChild.type === REACT_FRAGMENT_TYPE) { + return updateFragment( + returnFiber, + _matchedFiber, + newChild.props.children, + expirationTime, + newChild.key + ); + } + return updateElement( + returnFiber, + _matchedFiber, + newChild, + expirationTime + ); + } + + case REACT_CALL_TYPE: { + var _matchedFiber2 = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; + return updateCall( + returnFiber, + _matchedFiber2, + newChild, + expirationTime + ); + } + + case REACT_RETURN_TYPE: { + // Returns don't have keys, so we neither have to check the old nor + // new node for the key. If both are returns, they match. + var _matchedFiber3 = existingChildren.get(newIdx) || null; + return updateReturn( + returnFiber, + _matchedFiber3, + newChild, + expirationTime + ); + } + + case REACT_PORTAL_TYPE: { + var _matchedFiber4 = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; + return updatePortal( + returnFiber, + _matchedFiber4, + newChild, + expirationTime + ); + } + } + + if (isArray$1(newChild) || getIteratorFn(newChild)) { + var _matchedFiber5 = existingChildren.get(newIdx) || null; + return updateFragment( + returnFiber, + _matchedFiber5, + newChild, + expirationTime, + null + ); + } + + throwOnInvalidObjectType(returnFiber, newChild); + } + + { + if (typeof newChild === "function") { + warnOnFunctionType(); + } + } + + return null; + } + + /** + * Warns if there is a duplicate or missing key + */ + function warnOnInvalidKey(child, knownKeys) { + { + if (typeof child !== "object" || child === null) { + return knownKeys; + } + switch (child.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_CALL_TYPE: + case REACT_PORTAL_TYPE: + warnForMissingKey(child); + var key = child.key; + if (typeof key !== "string") { + break; + } + if (knownKeys === null) { + knownKeys = new Set(); + knownKeys.add(key); + break; + } + if (!knownKeys.has(key)) { + knownKeys.add(key); + break; + } + warning( + false, + "Encountered two children with the same key, `%s`. " + + "Keys should be unique so that components maintain their identity " + + "across updates. Non-unique keys may cause children to be " + + "duplicated and/or omitted — the behavior is unsupported and " + + "could change in a future version.%s", + key, + getCurrentFiberStackAddendum$1() + ); + break; + default: + break; + } + } + return knownKeys; + } + + function reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChildren, + expirationTime + ) { + // This algorithm can't optimize by searching from boths ends since we + // don't have backpointers on fibers. I'm trying to see how far we can get + // with that model. If it ends up not being worth the tradeoffs, we can + // add it later. + + // Even with a two ended optimization, we'd want to optimize for the case + // where there are few changes and brute force the comparison instead of + // going for the Map. It'd like to explore hitting that path first in + // forward-only mode and only go for the Map once we notice that we need + // lots of look ahead. This doesn't handle reversal as well as two ended + // search but that's unusual. Besides, for the two ended optimization to + // work on Iterables, we'd need to copy the whole set. + + // In this first iteration, we'll just live with hitting the bad case + // (adding everything to a Map) in for every insert/move. + + // If you change this code, also update reconcileChildrenIterator() which + // uses the same algorithm. + + { + // First, validate keys. + var knownKeys = null; + for (var i = 0; i < newChildren.length; i++) { + var child = newChildren[i]; + knownKeys = warnOnInvalidKey(child, knownKeys); + } + } + + var resultingFirstChild = null; + var previousNewFiber = null; + + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; + for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } + var newFiber = updateSlot( + returnFiber, + oldFiber, + newChildren[newIdx], + expirationTime + ); + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (oldFiber === null) { + oldFiber = nextOldFiber; + } + break; + } + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } + } + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; + } + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } + + if (newIdx === newChildren.length) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); + return resultingFirstChild; + } + + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber = createChild( + returnFiber, + newChildren[newIdx], + expirationTime + ); + if (!_newFiber) { + continue; + } + lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber; + } else { + previousNewFiber.sibling = _newFiber; + } + previousNewFiber = _newFiber; + } + return resultingFirstChild; + } + + // Add all children to a key map for quick lookups. + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); + + // Keep scanning and use the map to restore deleted items as moves. + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber2 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChildren[newIdx], + expirationTime + ); + if (_newFiber2) { + if (shouldTrackSideEffects) { + if (_newFiber2.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren["delete"]( + _newFiber2.key === null ? newIdx : _newFiber2.key + ); + } + } + lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); + if (previousNewFiber === null) { + resultingFirstChild = _newFiber2; + } else { + previousNewFiber.sibling = _newFiber2; + } + previousNewFiber = _newFiber2; + } + } + + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function(child) { + return deleteChild(returnFiber, child); + }); + } + + return resultingFirstChild; + } + + function reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChildrenIterable, + expirationTime + ) { + // This is the same implementation as reconcileChildrenArray(), + // but using the iterator instead. + + var iteratorFn = getIteratorFn(newChildrenIterable); + invariant( + typeof iteratorFn === "function", + "An object is not an iterable. This error is likely caused by a bug in " + + "React. Please file an issue." + ); + + { + // Warn about using Maps as children + if (typeof newChildrenIterable.entries === "function") { + var possibleMap = newChildrenIterable; + if (possibleMap.entries === iteratorFn) { + warning( + didWarnAboutMaps, + "Using Maps as children is unsupported and will likely yield " + + "unexpected results. Convert it to a sequence/iterable of keyed " + + "ReactElements instead.%s", + getCurrentFiberStackAddendum$1() + ); + didWarnAboutMaps = true; + } + } + + // First, validate keys. + // We'll get a different iterator later for the main pass. + var _newChildren = iteratorFn.call(newChildrenIterable); + if (_newChildren) { + var knownKeys = null; + var _step = _newChildren.next(); + for (; !_step.done; _step = _newChildren.next()) { + var child = _step.value; + knownKeys = warnOnInvalidKey(child, knownKeys); + } + } + } + + var newChildren = iteratorFn.call(newChildrenIterable); + invariant(newChildren != null, "An iterable object provided no iterator."); + + var resultingFirstChild = null; + var previousNewFiber = null; + + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; + + var step = newChildren.next(); + for ( + ; + oldFiber !== null && !step.done; + newIdx++, step = newChildren.next() + ) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } + var newFiber = updateSlot( + returnFiber, + oldFiber, + step.value, + expirationTime + ); + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (!oldFiber) { + oldFiber = nextOldFiber; + } + break; + } + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } + } + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; + } + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } + + if (step.done) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); + return resultingFirstChild; + } + + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber3 = createChild(returnFiber, step.value, expirationTime); + if (_newFiber3 === null) { + continue; + } + lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber3; + } else { + previousNewFiber.sibling = _newFiber3; + } + previousNewFiber = _newFiber3; + } + return resultingFirstChild; + } + + // Add all children to a key map for quick lookups. + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); + + // Keep scanning and use the map to restore deleted items as moves. + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber4 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + step.value, + expirationTime + ); + if (_newFiber4 !== null) { + if (shouldTrackSideEffects) { + if (_newFiber4.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren["delete"]( + _newFiber4.key === null ? newIdx : _newFiber4.key + ); + } + } + lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); + if (previousNewFiber === null) { + resultingFirstChild = _newFiber4; + } else { + previousNewFiber.sibling = _newFiber4; + } + previousNewFiber = _newFiber4; + } + } + + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function(child) { + return deleteChild(returnFiber, child); + }); + } + + return resultingFirstChild; + } + + function reconcileSingleTextNode( + returnFiber, + currentFirstChild, + textContent, + expirationTime + ) { + // There's no need to check for keys on text nodes since we don't have a + // way to define them. + if (currentFirstChild !== null && currentFirstChild.tag === HostText) { + // We already have an existing node so let's just update it and delete + // the rest. + deleteRemainingChildren(returnFiber, currentFirstChild.sibling); + var existing = useFiber(currentFirstChild, textContent, expirationTime); + existing["return"] = returnFiber; + return existing; + } + // The existing first child is not a text node so we need to create one + // and delete the existing ones. + deleteRemainingChildren(returnFiber, currentFirstChild); + var created = createFiberFromText( + textContent, + returnFiber.internalContextTag, + expirationTime + ); + created["return"] = returnFiber; + return created; + } + + function reconcileSingleElement( + returnFiber, + currentFirstChild, + element, + expirationTime + ) { + var key = element.key; + var child = currentFirstChild; + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + if ( + child.tag === Fragment + ? element.type === REACT_FRAGMENT_TYPE + : child.type === element.type + ) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber( + child, + element.type === REACT_FRAGMENT_TYPE + ? element.props.children + : element.props, + expirationTime + ); + existing.ref = coerceRef(child, element); + existing["return"] = returnFiber; + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } + return existing; + } else { + deleteRemainingChildren(returnFiber, child); + break; + } + } else { + deleteChild(returnFiber, child); + } + child = child.sibling; + } + + if (element.type === REACT_FRAGMENT_TYPE) { + var created = createFiberFromFragment( + element.props.children, + returnFiber.internalContextTag, + expirationTime, + element.key + ); + created["return"] = returnFiber; + return created; + } else { + var _created7 = createFiberFromElement( + element, + returnFiber.internalContextTag, + expirationTime + ); + _created7.ref = coerceRef(currentFirstChild, element); + _created7["return"] = returnFiber; + return _created7; + } + } + + function reconcileSingleCall( + returnFiber, + currentFirstChild, + call, + expirationTime + ) { + var key = call.key; + var child = currentFirstChild; + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + if (child.tag === CallComponent) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, call, expirationTime); + existing["return"] = returnFiber; + return existing; + } else { + deleteRemainingChildren(returnFiber, child); + break; + } + } else { + deleteChild(returnFiber, child); + } + child = child.sibling; + } + + var created = createFiberFromCall( + call, + returnFiber.internalContextTag, + expirationTime + ); + created["return"] = returnFiber; + return created; + } + + function reconcileSingleReturn( + returnFiber, + currentFirstChild, + returnNode, + expirationTime + ) { + // There's no need to check for keys on yields since they're stateless. + var child = currentFirstChild; + if (child !== null) { + if (child.tag === ReturnComponent) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, null, expirationTime); + existing.type = returnNode.value; + existing["return"] = returnFiber; + return existing; + } else { + deleteRemainingChildren(returnFiber, child); + } + } + + var created = createFiberFromReturn( + returnNode, + returnFiber.internalContextTag, + expirationTime + ); + created.type = returnNode.value; + created["return"] = returnFiber; + return created; + } + + function reconcileSinglePortal( + returnFiber, + currentFirstChild, + portal, + expirationTime + ) { + var key = portal.key; + var child = currentFirstChild; + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + if ( + child.tag === HostPortal && + child.stateNode.containerInfo === portal.containerInfo && + child.stateNode.implementation === portal.implementation + ) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, portal.children || [], expirationTime); + existing["return"] = returnFiber; + return existing; + } else { + deleteRemainingChildren(returnFiber, child); + break; + } + } else { + deleteChild(returnFiber, child); + } + child = child.sibling; + } + + var created = createFiberFromPortal( + portal, + returnFiber.internalContextTag, + expirationTime + ); + created["return"] = returnFiber; + return created; + } + + // This API will tag the children with the side-effect of the reconciliation + // itself. They will be added to the side-effect list as we pass through the + // children and the parent. + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + expirationTime + ) { + // This function is not recursive. + // If the top level item is an array, we treat it as a set of children, + // not as a fragment. Nested arrays on the other hand will be treated as + // fragment nodes. Recursion happens at the normal flow. + + // Handle top level unkeyed fragments as if they were arrays. + // This leads to an ambiguity between <>{[...]} and <>.... + // We treat the ambiguous cases above the same. + if ( + enableReactFragment && + typeof newChild === "object" && + newChild !== null && + newChild.type === REACT_FRAGMENT_TYPE && + newChild.key === null + ) { + newChild = newChild.props.children; + } + + // Handle object types + var isObject = typeof newChild === "object" && newChild !== null; + + if (isObject) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + return placeSingleChild( + reconcileSingleElement( + returnFiber, + currentFirstChild, + newChild, + expirationTime + ) + ); + + case REACT_CALL_TYPE: + return placeSingleChild( + reconcileSingleCall( + returnFiber, + currentFirstChild, + newChild, + expirationTime + ) + ); + case REACT_RETURN_TYPE: + return placeSingleChild( + reconcileSingleReturn( + returnFiber, + currentFirstChild, + newChild, + expirationTime + ) + ); + case REACT_PORTAL_TYPE: + return placeSingleChild( + reconcileSinglePortal( + returnFiber, + currentFirstChild, + newChild, + expirationTime + ) + ); + } + } + + if (typeof newChild === "string" || typeof newChild === "number") { + return placeSingleChild( + reconcileSingleTextNode( + returnFiber, + currentFirstChild, + "" + newChild, + expirationTime + ) + ); + } + + if (isArray$1(newChild)) { + return reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChild, + expirationTime + ); + } + + if (getIteratorFn(newChild)) { + return reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChild, + expirationTime + ); + } + + if (isObject) { + throwOnInvalidObjectType(returnFiber, newChild); + } + + { + if (typeof newChild === "function") { + warnOnFunctionType(); + } + } + if (typeof newChild === "undefined") { + // If the new child is undefined, and the return fiber is a composite + // component, throw an error. If Fiber return types are disabled, + // we already threw above. + switch (returnFiber.tag) { + case ClassComponent: { + { + var instance = returnFiber.stateNode; + if (instance.render._isMockFunction) { + // We allow auto-mocks to proceed as if they're returning null. + break; + } + } + } + // Intentionally fall through to the next case, which handles both + // functions and classes + // eslint-disable-next-lined no-fallthrough + case FunctionalComponent: { + var Component = returnFiber.type; + invariant( + false, + "%s(...): Nothing was returned from render. This usually means a " + + "return statement is missing. Or, to render nothing, " + + "return null.", + Component.displayName || Component.name || "Component" + ); + } + } + } + + // Remaining cases are all treated as empty. + return deleteRemainingChildren(returnFiber, currentFirstChild); + } + + return reconcileChildFibers; +} + +var reconcileChildFibers = ChildReconciler(true, true); + +var reconcileChildFibersInPlace = ChildReconciler(false, true); + +var mountChildFibersInPlace = ChildReconciler(false, false); + +function cloneChildFibers(current, workInProgress) { + invariant( + current === null || workInProgress.child === current.child, + "Resuming work not yet implemented." + ); + + if (workInProgress.child === null) { + return; + } + + var currentChild = workInProgress.child; + var newChild = createWorkInProgress( + currentChild, + currentChild.pendingProps, + currentChild.expirationTime + ); + workInProgress.child = newChild; + + newChild["return"] = workInProgress; + while (currentChild.sibling !== null) { + currentChild = currentChild.sibling; + newChild = newChild.sibling = createWorkInProgress( + currentChild, + currentChild.pendingProps, + currentChild.expirationTime + ); + newChild["return"] = workInProgress; + } + newChild.sibling = null; +} + +{ + var warnedAboutStatelessRefs = {}; +} + +var ReactFiberBeginWork = function( + config, + hostContext, + hydrationContext, + scheduleWork, + computeExpirationForFiber +) { + var shouldSetTextContent = config.shouldSetTextContent, + useSyncScheduling = config.useSyncScheduling, + shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree; + var pushHostContext = hostContext.pushHostContext, + pushHostContainer = hostContext.pushHostContainer; + var enterHydrationState = hydrationContext.enterHydrationState, + resetHydrationState = hydrationContext.resetHydrationState, + tryToClaimNextHydratableInstance = + hydrationContext.tryToClaimNextHydratableInstance; + + var _ReactFiberClassCompo = ReactFiberClassComponent( + scheduleWork, + computeExpirationForFiber, + memoizeProps, + memoizeState + ), + adoptClassInstance = _ReactFiberClassCompo.adoptClassInstance, + constructClassInstance = _ReactFiberClassCompo.constructClassInstance, + mountClassInstance = _ReactFiberClassCompo.mountClassInstance, + updateClassInstance = _ReactFiberClassCompo.updateClassInstance; + + // TODO: Remove this and use reconcileChildrenAtExpirationTime directly. + + function reconcileChildren(current, workInProgress, nextChildren) { + reconcileChildrenAtExpirationTime( + current, + workInProgress, + nextChildren, + workInProgress.expirationTime + ); + } + + function reconcileChildrenAtExpirationTime( + current, + workInProgress, + nextChildren, + renderExpirationTime + ) { + if (current === null) { + // If this is a fresh new component that hasn't been rendered yet, we + // won't update its child set by applying minimal side-effects. Instead, + // we will add them all to the child before it gets rendered. That means + // we can optimize this reconciliation pass by not tracking side-effects. + workInProgress.child = mountChildFibersInPlace( + workInProgress, + workInProgress.child, + nextChildren, + renderExpirationTime + ); + } else if (current.child === workInProgress.child) { + // If the current child is the same as the work in progress, it means that + // we haven't yet started any work on these children. Therefore, we use + // the clone algorithm to create a copy of all the current children. + + // If we had any progressed work already, that is invalid at this point so + // let's throw it out. + workInProgress.child = reconcileChildFibers( + workInProgress, + workInProgress.child, + nextChildren, + renderExpirationTime + ); + } else { + // If, on the other hand, it is already using a clone, that means we've + // already begun some work on this tree and we can continue where we left + // off by reconciling against the existing children. + workInProgress.child = reconcileChildFibersInPlace( + workInProgress, + workInProgress.child, + nextChildren, + renderExpirationTime + ); + } + } + + function updateFragment(current, workInProgress) { + var nextChildren = workInProgress.pendingProps; + if (hasContextChanged()) { + // Normally we can bail out on props equality but if context has changed + // we don't do the bailout and we have to reuse existing props instead. + if (nextChildren === null) { + nextChildren = workInProgress.memoizedProps; + } + } else if ( + nextChildren === null || + workInProgress.memoizedProps === nextChildren + ) { + return bailoutOnAlreadyFinishedWork(current, workInProgress); + } + reconcileChildren(current, workInProgress, nextChildren); + memoizeProps(workInProgress, nextChildren); + return workInProgress.child; + } + + function markRef(current, workInProgress) { + var ref = workInProgress.ref; + if (ref !== null && (!current || current.ref !== ref)) { + // Schedule a Ref effect + workInProgress.effectTag |= Ref; + } + } + + function updateFunctionalComponent(current, workInProgress) { + var fn = workInProgress.type; + var nextProps = workInProgress.pendingProps; + + var memoizedProps = workInProgress.memoizedProps; + if (hasContextChanged()) { + // Normally we can bail out on props equality but if context has changed + // we don't do the bailout and we have to reuse existing props instead. + if (nextProps === null) { + nextProps = memoizedProps; + } + } else { + if (nextProps === null || memoizedProps === nextProps) { + return bailoutOnAlreadyFinishedWork(current, workInProgress); + } + // TODO: consider bringing fn.shouldComponentUpdate() back. + // It used to be here. + } + + var unmaskedContext = getUnmaskedContext(workInProgress); + var context = getMaskedContext(workInProgress, unmaskedContext); + + var nextChildren; + + { + ReactCurrentOwner.current = workInProgress; + ReactDebugCurrentFiber.setCurrentPhase("render"); + nextChildren = fn(nextProps, context); + ReactDebugCurrentFiber.setCurrentPhase(null); + } + // React DevTools reads this flag. + workInProgress.effectTag |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren); + memoizeProps(workInProgress, nextProps); + return workInProgress.child; + } + + function updateClassComponent(current, workInProgress, renderExpirationTime) { + // Push context providers early to prevent context stack mismatches. + // During mounting we don't know the child context yet as the instance doesn't exist. + // We will invalidate the child context in finishClassComponent() right after rendering. + var hasContext = pushContextProvider(workInProgress); + + var shouldUpdate = void 0; + if (current === null) { + if (!workInProgress.stateNode) { + // In the initial pass we might need to construct the instance. + constructClassInstance(workInProgress, workInProgress.pendingProps); + mountClassInstance(workInProgress, renderExpirationTime); + shouldUpdate = true; + } else { + invariant(false, "Resuming work not yet implemented."); + // In a resume, we'll already have an instance we can reuse. + // shouldUpdate = resumeMountClassInstance(workInProgress, renderExpirationTime); + } + } else { + shouldUpdate = updateClassInstance( + current, + workInProgress, + renderExpirationTime + ); + } + return finishClassComponent( + current, + workInProgress, + shouldUpdate, + hasContext + ); + } + + function finishClassComponent( + current, + workInProgress, + shouldUpdate, + hasContext + ) { + // Refs should update even if shouldComponentUpdate returns false + markRef(current, workInProgress); + + if (!shouldUpdate) { + // Context providers should defer to sCU for rendering + if (hasContext) { + invalidateContextProvider(workInProgress, false); + } + + return bailoutOnAlreadyFinishedWork(current, workInProgress); + } + + var instance = workInProgress.stateNode; + + // Rerender + ReactCurrentOwner.current = workInProgress; + var nextChildren = void 0; + { + ReactDebugCurrentFiber.setCurrentPhase("render"); + nextChildren = instance.render(); + ReactDebugCurrentFiber.setCurrentPhase(null); + } + // React DevTools reads this flag. + workInProgress.effectTag |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren); + // Memoize props and state using the values we just used to render. + // TODO: Restructure so we never read values from the instance. + memoizeState(workInProgress, instance.state); + memoizeProps(workInProgress, instance.props); + + // The context might have changed so we need to recalculate it. + if (hasContext) { + invalidateContextProvider(workInProgress, true); + } + + return workInProgress.child; + } + + function pushHostRootContext(workInProgress) { + var root = workInProgress.stateNode; + if (root.pendingContext) { + pushTopLevelContextObject( + workInProgress, + root.pendingContext, + root.pendingContext !== root.context + ); + } else if (root.context) { + // Should always be set + pushTopLevelContextObject(workInProgress, root.context, false); + } + pushHostContainer(workInProgress, root.containerInfo); + } + + function updateHostRoot(current, workInProgress, renderExpirationTime) { + pushHostRootContext(workInProgress); + var updateQueue = workInProgress.updateQueue; + if (updateQueue !== null) { + var prevState = workInProgress.memoizedState; + var state = processUpdateQueue( + current, + workInProgress, + updateQueue, + null, + null, + renderExpirationTime + ); + if (prevState === state) { + // If the state is the same as before, that's a bailout because we had + // no work that expires at this time. + resetHydrationState(); + return bailoutOnAlreadyFinishedWork(current, workInProgress); + } + var element = state.element; + var root = workInProgress.stateNode; + if ( + (current === null || current.child === null) && + root.hydrate && + enterHydrationState(workInProgress) + ) { + // If we don't have any current children this might be the first pass. + // We always try to hydrate. If this isn't a hydration pass there won't + // be any children to hydrate which is effectively the same thing as + // not hydrating. + + // This is a bit of a hack. We track the host root as a placement to + // know that we're currently in a mounting state. That way isMounted + // works as expected. We must reset this before committing. + // TODO: Delete this when we delete isMounted and findDOMNode. + workInProgress.effectTag |= Placement; + + // Ensure that children mount into this root without tracking + // side-effects. This ensures that we don't store Placement effects on + // nodes that will be hydrated. + workInProgress.child = mountChildFibersInPlace( + workInProgress, + workInProgress.child, + element, + renderExpirationTime + ); + } else { + // Otherwise reset hydration state in case we aborted and resumed another + // root. + resetHydrationState(); + reconcileChildren(current, workInProgress, element); + } + memoizeState(workInProgress, state); + return workInProgress.child; + } + resetHydrationState(); + // If there is no update queue, that's a bailout because the root has no props. + return bailoutOnAlreadyFinishedWork(current, workInProgress); + } + + function updateHostComponent(current, workInProgress, renderExpirationTime) { + pushHostContext(workInProgress); + + if (current === null) { + tryToClaimNextHydratableInstance(workInProgress); + } + + var type = workInProgress.type; + var memoizedProps = workInProgress.memoizedProps; + var nextProps = workInProgress.pendingProps; + if (nextProps === null) { + nextProps = memoizedProps; + invariant( + nextProps !== null, + "We should always have pending or current props. This error is " + + "likely caused by a bug in React. Please file an issue." + ); + } + var prevProps = current !== null ? current.memoizedProps : null; + + if (hasContextChanged()) { + // Normally we can bail out on props equality but if context has changed + // we don't do the bailout and we have to reuse existing props instead. + } else if (nextProps === null || memoizedProps === nextProps) { + return bailoutOnAlreadyFinishedWork(current, workInProgress); + } + + var nextChildren = nextProps.children; + var isDirectTextChild = shouldSetTextContent(type, nextProps); + + if (isDirectTextChild) { + // We special case a direct text child of a host node. This is a common + // case. We won't handle it as a reified child. We will instead handle + // this in the host environment that also have access to this prop. That + // avoids allocating another HostText fiber and traversing it. + nextChildren = null; + } else if (prevProps && shouldSetTextContent(type, prevProps)) { + // If we're switching from a direct text child to a normal child, or to + // empty, we need to schedule the text content to be reset. + workInProgress.effectTag |= ContentReset; + } + + markRef(current, workInProgress); + + // Check the host config to see if the children are offscreen/hidden. + if ( + renderExpirationTime !== Never && + !useSyncScheduling && + shouldDeprioritizeSubtree(type, nextProps) + ) { + // Down-prioritize the children. + workInProgress.expirationTime = Never; + // Bailout and come back to this fiber later. + return null; + } + + reconcileChildren(current, workInProgress, nextChildren); + memoizeProps(workInProgress, nextProps); + return workInProgress.child; + } + + function updateHostText(current, workInProgress) { + if (current === null) { + tryToClaimNextHydratableInstance(workInProgress); + } + var nextProps = workInProgress.pendingProps; + if (nextProps === null) { + nextProps = workInProgress.memoizedProps; + } + memoizeProps(workInProgress, nextProps); + // Nothing to do here. This is terminal. We'll do the completion step + // immediately after. + return null; + } + + function mountIndeterminateComponent( + current, + workInProgress, + renderExpirationTime + ) { + invariant( + current === null, + "An indeterminate component should never have mounted. This error is " + + "likely caused by a bug in React. Please file an issue." + ); + var fn = workInProgress.type; + var props = workInProgress.pendingProps; + var unmaskedContext = getUnmaskedContext(workInProgress); + var context = getMaskedContext(workInProgress, unmaskedContext); + + var value; + + { + if (fn.prototype && typeof fn.prototype.render === "function") { + var componentName = getComponentName(workInProgress); + warning( + false, + "The <%s /> component appears to have a render method, but doesn't extend React.Component. " + + "This is likely to cause errors. Change %s to extend React.Component instead.", + componentName, + componentName + ); + } + ReactCurrentOwner.current = workInProgress; + value = fn(props, context); + } + // React DevTools reads this flag. + workInProgress.effectTag |= PerformedWork; + + if ( + typeof value === "object" && + value !== null && + typeof value.render === "function" + ) { + // Proceed under the assumption that this is a class instance + workInProgress.tag = ClassComponent; + + // Push context providers early to prevent context stack mismatches. + // During mounting we don't know the child context yet as the instance doesn't exist. + // We will invalidate the child context in finishClassComponent() right after rendering. + var hasContext = pushContextProvider(workInProgress); + adoptClassInstance(workInProgress, value); + mountClassInstance(workInProgress, renderExpirationTime); + return finishClassComponent(current, workInProgress, true, hasContext); + } else { + // Proceed under the assumption that this is a functional component + workInProgress.tag = FunctionalComponent; + { + var Component = workInProgress.type; + + if (Component) { + warning( + !Component.childContextTypes, + "%s(...): childContextTypes cannot be defined on a functional component.", + Component.displayName || Component.name || "Component" + ); + } + if (workInProgress.ref !== null) { + var info = ""; + var ownerName = ReactDebugCurrentFiber.getCurrentFiberOwnerName(); + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } + + var warningKey = ownerName || workInProgress._debugID || ""; + var debugSource = workInProgress._debugSource; + if (debugSource) { + warningKey = debugSource.fileName + ":" + debugSource.lineNumber; + } + if (!warnedAboutStatelessRefs[warningKey]) { + warnedAboutStatelessRefs[warningKey] = true; + warning( + false, + "Stateless function components cannot be given refs. " + + "Attempts to access this ref will fail.%s%s", + info, + ReactDebugCurrentFiber.getCurrentFiberStackAddendum() + ); + } + } + } + reconcileChildren(current, workInProgress, value); + memoizeProps(workInProgress, props); + return workInProgress.child; + } + } + + function updateCallComponent(current, workInProgress, renderExpirationTime) { + var nextCall = workInProgress.pendingProps; + if (hasContextChanged()) { + // Normally we can bail out on props equality but if context has changed + // we don't do the bailout and we have to reuse existing props instead. + if (nextCall === null) { + nextCall = current && current.memoizedProps; + invariant( + nextCall !== null, + "We should always have pending or current props. This error is " + + "likely caused by a bug in React. Please file an issue." + ); + } + } else if (nextCall === null || workInProgress.memoizedProps === nextCall) { + nextCall = workInProgress.memoizedProps; + // TODO: When bailing out, we might need to return the stateNode instead + // of the child. To check it for work. + // return bailoutOnAlreadyFinishedWork(current, workInProgress); + } + + var nextChildren = nextCall.children; + + // The following is a fork of reconcileChildrenAtExpirationTime but using + // stateNode to store the child. + if (current === null) { + workInProgress.stateNode = mountChildFibersInPlace( + workInProgress, + workInProgress.stateNode, + nextChildren, + renderExpirationTime + ); + } else if (current.child === workInProgress.child) { + workInProgress.stateNode = reconcileChildFibers( + workInProgress, + workInProgress.stateNode, + nextChildren, + renderExpirationTime + ); + } else { + workInProgress.stateNode = reconcileChildFibersInPlace( + workInProgress, + workInProgress.stateNode, + nextChildren, + renderExpirationTime + ); + } + + memoizeProps(workInProgress, nextCall); + // This doesn't take arbitrary time so we could synchronously just begin + // eagerly do the work of workInProgress.child as an optimization. + return workInProgress.stateNode; + } + + function updatePortalComponent( + current, + workInProgress, + renderExpirationTime + ) { + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + var nextChildren = workInProgress.pendingProps; + if (hasContextChanged()) { + // Normally we can bail out on props equality but if context has changed + // we don't do the bailout and we have to reuse existing props instead. + if (nextChildren === null) { + nextChildren = current && current.memoizedProps; + invariant( + nextChildren != null, + "We should always have pending or current props. This error is " + + "likely caused by a bug in React. Please file an issue." + ); + } + } else if ( + nextChildren === null || + workInProgress.memoizedProps === nextChildren + ) { + return bailoutOnAlreadyFinishedWork(current, workInProgress); + } + + if (current === null) { + // Portals are special because we don't append the children during mount + // but at commit. Therefore we need to track insertions which the normal + // flow doesn't do during mount. This doesn't happen at the root because + // the root always starts with a "current" with a null child. + // TODO: Consider unifying this with how the root works. + workInProgress.child = reconcileChildFibersInPlace( + workInProgress, + workInProgress.child, + nextChildren, + renderExpirationTime + ); + memoizeProps(workInProgress, nextChildren); + } else { + reconcileChildren(current, workInProgress, nextChildren); + memoizeProps(workInProgress, nextChildren); + } + return workInProgress.child; + } + + /* + function reuseChildrenEffects(returnFiber : Fiber, firstChild : Fiber) { + let child = firstChild; + do { + // Ensure that the first and last effect of the parent corresponds + // to the children's first and last effect. + if (!returnFiber.firstEffect) { + returnFiber.firstEffect = child.firstEffect; + } + if (child.lastEffect) { + if (returnFiber.lastEffect) { + returnFiber.lastEffect.nextEffect = child.firstEffect; + } + returnFiber.lastEffect = child.lastEffect; + } + } while (child = child.sibling); + } + */ + + function bailoutOnAlreadyFinishedWork(current, workInProgress) { + cancelWorkTimer(workInProgress); + + // TODO: We should ideally be able to bail out early if the children have no + // more work to do. However, since we don't have a separation of this + // Fiber's priority and its children yet - we don't know without doing lots + // of the same work we do anyway. Once we have that separation we can just + // bail out here if the children has no more work at this priority level. + // if (workInProgress.priorityOfChildren <= priorityLevel) { + // // If there are side-effects in these children that have not yet been + // // committed we need to ensure that they get properly transferred up. + // if (current && current.child !== workInProgress.child) { + // reuseChildrenEffects(workInProgress, child); + // } + // return null; + // } + + cloneChildFibers(current, workInProgress); + return workInProgress.child; + } + + function bailoutOnLowPriority(current, workInProgress) { + cancelWorkTimer(workInProgress); + + // TODO: Handle HostComponent tags here as well and call pushHostContext()? + // See PR 8590 discussion for context + switch (workInProgress.tag) { + case HostRoot: + pushHostRootContext(workInProgress); + break; + case ClassComponent: + pushContextProvider(workInProgress); + break; + case HostPortal: + pushHostContainer( + workInProgress, + workInProgress.stateNode.containerInfo + ); + break; + } + // TODO: What if this is currently in progress? + // How can that happen? How is this not being cloned? + return null; + } + + // TODO: Delete memoizeProps/State and move to reconcile/bailout instead + function memoizeProps(workInProgress, nextProps) { + workInProgress.memoizedProps = nextProps; + } + + function memoizeState(workInProgress, nextState) { + workInProgress.memoizedState = nextState; + // Don't reset the updateQueue, in case there are pending updates. Resetting + // is handled by processUpdateQueue. + } + + function beginWork(current, workInProgress, renderExpirationTime) { + if ( + workInProgress.expirationTime === NoWork || + workInProgress.expirationTime > renderExpirationTime + ) { + return bailoutOnLowPriority(current, workInProgress); + } + + switch (workInProgress.tag) { + case IndeterminateComponent: + return mountIndeterminateComponent( + current, + workInProgress, + renderExpirationTime + ); + case FunctionalComponent: + return updateFunctionalComponent(current, workInProgress); + case ClassComponent: + return updateClassComponent( + current, + workInProgress, + renderExpirationTime + ); + case HostRoot: + return updateHostRoot(current, workInProgress, renderExpirationTime); + case HostComponent: + return updateHostComponent( + current, + workInProgress, + renderExpirationTime + ); + case HostText: + return updateHostText(current, workInProgress); + case CallHandlerPhase: + // This is a restart. Reset the tag to the initial phase. + workInProgress.tag = CallComponent; + // Intentionally fall through since this is now the same. + case CallComponent: + return updateCallComponent( + current, + workInProgress, + renderExpirationTime + ); + case ReturnComponent: + // A return component is just a placeholder, we can just run through the + // next one immediately. + return null; + case HostPortal: + return updatePortalComponent( + current, + workInProgress, + renderExpirationTime + ); + case Fragment: + return updateFragment(current, workInProgress); + default: + invariant( + false, + "Unknown unit of work tag. This error is likely caused by a bug in " + + "React. Please file an issue." + ); + } + } + + function beginFailedWork(current, workInProgress, renderExpirationTime) { + // Push context providers here to avoid a push/pop context mismatch. + switch (workInProgress.tag) { + case ClassComponent: + pushContextProvider(workInProgress); + break; + case HostRoot: + pushHostRootContext(workInProgress); + break; + default: + invariant( + false, + "Invalid type of work. This error is likely caused by a bug in React. " + + "Please file an issue." + ); + } + + // Add an error effect so we can handle the error during the commit phase + workInProgress.effectTag |= Err; + + // This is a weird case where we do "resume" work — work that failed on + // our first attempt. Because we no longer have a notion of "progressed + // deletions," reset the child to the current child to make sure we delete + // it again. TODO: Find a better way to handle this, perhaps during a more + // general overhaul of error handling. + if (current === null) { + workInProgress.child = null; + } else if (workInProgress.child !== current.child) { + workInProgress.child = current.child; + } + + if ( + workInProgress.expirationTime === NoWork || + workInProgress.expirationTime > renderExpirationTime + ) { + return bailoutOnLowPriority(current, workInProgress); + } + + // If we don't bail out, we're going be recomputing our children so we need + // to drop our effect list. + workInProgress.firstEffect = null; + workInProgress.lastEffect = null; + + // Unmount the current children as if the component rendered null + var nextChildren = null; + reconcileChildrenAtExpirationTime( + current, + workInProgress, + nextChildren, + renderExpirationTime + ); + + if (workInProgress.tag === ClassComponent) { + var instance = workInProgress.stateNode; + workInProgress.memoizedProps = instance.props; + workInProgress.memoizedState = instance.state; + } + + return workInProgress.child; + } + + return { + beginWork: beginWork, + beginFailedWork: beginFailedWork + }; +}; + +var ReactFiberCompleteWork = function(config, hostContext, hydrationContext) { + var createInstance = config.createInstance, + createTextInstance = config.createTextInstance, + appendInitialChild = config.appendInitialChild, + finalizeInitialChildren = config.finalizeInitialChildren, + prepareUpdate = config.prepareUpdate, + mutation = config.mutation, + persistence = config.persistence; + var getRootHostContainer = hostContext.getRootHostContainer, + popHostContext = hostContext.popHostContext, + getHostContext = hostContext.getHostContext, + popHostContainer = hostContext.popHostContainer; + var prepareToHydrateHostInstance = + hydrationContext.prepareToHydrateHostInstance, + prepareToHydrateHostTextInstance = + hydrationContext.prepareToHydrateHostTextInstance, + popHydrationState = hydrationContext.popHydrationState; + + function markUpdate(workInProgress) { + // Tag the fiber with an update effect. This turns a Placement into + // an UpdateAndPlacement. + workInProgress.effectTag |= Update; + } + + function markRef(workInProgress) { + workInProgress.effectTag |= Ref; + } + + function appendAllReturns(returns, workInProgress) { + var node = workInProgress.stateNode; + if (node) { + node["return"] = workInProgress; + } + while (node !== null) { + if ( + node.tag === HostComponent || + node.tag === HostText || + node.tag === HostPortal + ) { + invariant(false, "A call cannot have host component children."); + } else if (node.tag === ReturnComponent) { + returns.push(node.type); + } else if (node.child !== null) { + node.child["return"] = node; + node = node.child; + continue; + } + while (node.sibling === null) { + if (node["return"] === null || node["return"] === workInProgress) { + return; + } + node = node["return"]; + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } + } + + function moveCallToHandlerPhase( + current, + workInProgress, + renderExpirationTime + ) { + var call = workInProgress.memoizedProps; + invariant( + call, + "Should be resolved by now. This error is likely caused by a bug in " + + "React. Please file an issue." + ); + + // First step of the call has completed. Now we need to do the second. + // TODO: It would be nice to have a multi stage call represented by a + // single component, or at least tail call optimize nested ones. Currently + // that requires additional fields that we don't want to add to the fiber. + // So this requires nested handlers. + // Note: This doesn't mutate the alternate node. I don't think it needs to + // since this stage is reset for every pass. + workInProgress.tag = CallHandlerPhase; + + // Build up the returns. + // TODO: Compare this to a generator or opaque helpers like Children. + var returns = []; + appendAllReturns(returns, workInProgress); + var fn = call.handler; + var props = call.props; + var nextChildren = fn(props, returns); + + var currentFirstChild = current !== null ? current.child : null; + workInProgress.child = reconcileChildFibers( + workInProgress, + currentFirstChild, + nextChildren, + renderExpirationTime + ); + return workInProgress.child; + } + + function appendAllChildren(parent, workInProgress) { + // We only have the top Fiber that was created but we need recurse down its + // children to find all the terminal nodes. + var node = workInProgress.child; + while (node !== null) { + if (node.tag === HostComponent || node.tag === HostText) { + appendInitialChild(parent, node.stateNode); + } else if (node.tag === HostPortal) { + // If we have a portal child, then we don't want to traverse + // down its children. Instead, we'll get insertions from each child in + // the portal directly. + } else if (node.child !== null) { + node.child["return"] = node; + node = node.child; + continue; + } + if (node === workInProgress) { + return; + } + while (node.sibling === null) { + if (node["return"] === null || node["return"] === workInProgress) { + return; + } + node = node["return"]; + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } + } + + var updateHostContainer = void 0; + var updateHostComponent = void 0; + var updateHostText = void 0; + if (mutation) { + if (enableMutatingReconciler) { + // Mutation mode + updateHostContainer = function(workInProgress) { + // Noop + }; + updateHostComponent = function( + current, + workInProgress, + updatePayload, + type, + oldProps, + newProps, + rootContainerInstance + ) { + // TODO: Type this specific to this type of component. + workInProgress.updateQueue = updatePayload; + // If the update payload indicates that there is a change or if there + // is a new ref we mark this as an update. All the work is done in commitWork. + if (updatePayload) { + markUpdate(workInProgress); + } + }; + updateHostText = function(current, workInProgress, oldText, newText) { + // If the text differs, mark it as an update. All the work in done in commitWork. + if (oldText !== newText) { + markUpdate(workInProgress); + } + }; + } else { + invariant(false, "Mutating reconciler is disabled."); + } + } else if (persistence) { + if (enablePersistentReconciler) { + // Persistent host tree mode + var cloneInstance = persistence.cloneInstance, + createContainerChildSet = persistence.createContainerChildSet, + appendChildToContainerChildSet = + persistence.appendChildToContainerChildSet, + finalizeContainerChildren = persistence.finalizeContainerChildren; + + // An unfortunate fork of appendAllChildren because we have two different parent types. + + var appendAllChildrenToContainer = function( + containerChildSet, + workInProgress + ) { + // We only have the top Fiber that was created but we need recurse down its + // children to find all the terminal nodes. + var node = workInProgress.child; + while (node !== null) { + if (node.tag === HostComponent || node.tag === HostText) { + appendChildToContainerChildSet(containerChildSet, node.stateNode); + } else if (node.tag === HostPortal) { + // If we have a portal child, then we don't want to traverse + // down its children. Instead, we'll get insertions from each child in + // the portal directly. + } else if (node.child !== null) { + node.child["return"] = node; + node = node.child; + continue; + } + if (node === workInProgress) { + return; + } + while (node.sibling === null) { + if (node["return"] === null || node["return"] === workInProgress) { + return; + } + node = node["return"]; + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } + }; + updateHostContainer = function(workInProgress) { + var portalOrRoot = workInProgress.stateNode; + var childrenUnchanged = workInProgress.firstEffect === null; + if (childrenUnchanged) { + // No changes, just reuse the existing instance. + } else { + var container = portalOrRoot.containerInfo; + var newChildSet = createContainerChildSet(container); + if (finalizeContainerChildren(container, newChildSet)) { + markUpdate(workInProgress); + } + portalOrRoot.pendingChildren = newChildSet; + // If children might have changed, we have to add them all to the set. + appendAllChildrenToContainer(newChildSet, workInProgress); + // Schedule an update on the container to swap out the container. + markUpdate(workInProgress); + } + }; + updateHostComponent = function( + current, + workInProgress, + updatePayload, + type, + oldProps, + newProps, + rootContainerInstance + ) { + // If there are no effects associated with this node, then none of our children had any updates. + // This guarantees that we can reuse all of them. + var childrenUnchanged = workInProgress.firstEffect === null; + var currentInstance = current.stateNode; + if (childrenUnchanged && updatePayload === null) { + // No changes, just reuse the existing instance. + // Note that this might release a previous clone. + workInProgress.stateNode = currentInstance; + } else { + var recyclableInstance = workInProgress.stateNode; + var newInstance = cloneInstance( + currentInstance, + updatePayload, + type, + oldProps, + newProps, + workInProgress, + childrenUnchanged, + recyclableInstance + ); + if ( + finalizeInitialChildren( + newInstance, + type, + newProps, + rootContainerInstance + ) + ) { + markUpdate(workInProgress); + } + workInProgress.stateNode = newInstance; + if (childrenUnchanged) { + // If there are no other effects in this tree, we need to flag this node as having one. + // Even though we're not going to use it for anything. + // Otherwise parents won't know that there are new children to propagate upwards. + markUpdate(workInProgress); + } else { + // If children might have changed, we have to add them all to the set. + appendAllChildren(newInstance, workInProgress); + } + } + }; + updateHostText = function(current, workInProgress, oldText, newText) { + if (oldText !== newText) { + // If the text content differs, we'll create a new text instance for it. + var rootContainerInstance = getRootHostContainer(); + var currentHostContext = getHostContext(); + workInProgress.stateNode = createTextInstance( + newText, + rootContainerInstance, + currentHostContext, + workInProgress + ); + // We'll have to mark it as having an effect, even though we won't use the effect for anything. + // This lets the parents know that at least one of their children has changed. + markUpdate(workInProgress); + } + }; + } else { + invariant(false, "Persistent reconciler is disabled."); + } + } else { + if (enableNoopReconciler) { + // No host operations + updateHostContainer = function(workInProgress) { + // Noop + }; + updateHostComponent = function( + current, + workInProgress, + updatePayload, + type, + oldProps, + newProps, + rootContainerInstance + ) { + // Noop + }; + updateHostText = function(current, workInProgress, oldText, newText) { + // Noop + }; + } else { + invariant(false, "Noop reconciler is disabled."); + } + } + + function completeWork(current, workInProgress, renderExpirationTime) { + // Get the latest props. + var newProps = workInProgress.pendingProps; + if (newProps === null) { + newProps = workInProgress.memoizedProps; + } else if ( + workInProgress.expirationTime !== Never || + renderExpirationTime === Never + ) { + // Reset the pending props, unless this was a down-prioritization. + workInProgress.pendingProps = null; + } + + switch (workInProgress.tag) { + case FunctionalComponent: + return null; + case ClassComponent: { + // We are leaving this subtree, so pop context if any. + popContextProvider(workInProgress); + return null; + } + case HostRoot: { + popHostContainer(workInProgress); + popTopLevelContextObject(workInProgress); + var fiberRoot = workInProgress.stateNode; + if (fiberRoot.pendingContext) { + fiberRoot.context = fiberRoot.pendingContext; + fiberRoot.pendingContext = null; + } + + if (current === null || current.child === null) { + // If we hydrated, pop so that we can delete any remaining children + // that weren't hydrated. + popHydrationState(workInProgress); + // This resets the hacky state to fix isMounted before committing. + // TODO: Delete this when we delete isMounted and findDOMNode. + workInProgress.effectTag &= ~Placement; + } + updateHostContainer(workInProgress); + return null; + } + case HostComponent: { + popHostContext(workInProgress); + var rootContainerInstance = getRootHostContainer(); + var type = workInProgress.type; + if (current !== null && workInProgress.stateNode != null) { + // If we have an alternate, that means this is an update and we need to + // schedule a side-effect to do the updates. + var oldProps = current.memoizedProps; + // If we get updated because one of our children updated, we don't + // have newProps so we'll have to reuse them. + // TODO: Split the update API as separate for the props vs. children. + // Even better would be if children weren't special cased at all tho. + var instance = workInProgress.stateNode; + var currentHostContext = getHostContext(); + var updatePayload = prepareUpdate( + instance, + type, + oldProps, + newProps, + rootContainerInstance, + currentHostContext + ); + + updateHostComponent( + current, + workInProgress, + updatePayload, + type, + oldProps, + newProps, + rootContainerInstance + ); + + if (current.ref !== workInProgress.ref) { + markRef(workInProgress); + } + } else { + if (!newProps) { + invariant( + workInProgress.stateNode !== null, + "We must have new props for new mounts. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + // This can happen when we abort work. + return null; + } + + var _currentHostContext = getHostContext(); + // TODO: Move createInstance to beginWork and keep it on a context + // "stack" as the parent. Then append children as we go in beginWork + // or completeWork depending on we want to add then top->down or + // bottom->up. Top->down is faster in IE11. + var wasHydrated = popHydrationState(workInProgress); + if (wasHydrated) { + // TODO: Move this and createInstance step into the beginPhase + // to consolidate. + if ( + prepareToHydrateHostInstance( + workInProgress, + rootContainerInstance, + _currentHostContext + ) + ) { + // If changes to the hydrated node needs to be applied at the + // commit-phase we mark this as such. + markUpdate(workInProgress); + } + } else { + var _instance = createInstance( + type, + newProps, + rootContainerInstance, + _currentHostContext, + workInProgress + ); + + appendAllChildren(_instance, workInProgress); + + // Certain renderers require commit-time effects for initial mount. + // (eg DOM renderer supports auto-focus for certain elements). + // Make sure such renderers get scheduled for later work. + if ( + finalizeInitialChildren( + _instance, + type, + newProps, + rootContainerInstance + ) + ) { + markUpdate(workInProgress); + } + workInProgress.stateNode = _instance; + } + + if (workInProgress.ref !== null) { + // If there is a ref on a host node we need to schedule a callback + markRef(workInProgress); + } + } + return null; + } + case HostText: { + var newText = newProps; + if (current && workInProgress.stateNode != null) { + var oldText = current.memoizedProps; + // If we have an alternate, that means this is an update and we need + // to schedule a side-effect to do the updates. + updateHostText(current, workInProgress, oldText, newText); + } else { + if (typeof newText !== "string") { + invariant( + workInProgress.stateNode !== null, + "We must have new props for new mounts. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + // This can happen when we abort work. + return null; + } + var _rootContainerInstance = getRootHostContainer(); + var _currentHostContext2 = getHostContext(); + var _wasHydrated = popHydrationState(workInProgress); + if (_wasHydrated) { + if (prepareToHydrateHostTextInstance(workInProgress)) { + markUpdate(workInProgress); + } + } else { + workInProgress.stateNode = createTextInstance( + newText, + _rootContainerInstance, + _currentHostContext2, + workInProgress + ); + } + } + return null; + } + case CallComponent: + return moveCallToHandlerPhase( + current, + workInProgress, + renderExpirationTime + ); + case CallHandlerPhase: + // Reset the tag to now be a first phase call. + workInProgress.tag = CallComponent; + return null; + case ReturnComponent: + // Does nothing. + return null; + case Fragment: + return null; + case HostPortal: + popHostContainer(workInProgress); + updateHostContainer(workInProgress); + return null; + // Error cases + case IndeterminateComponent: + invariant( + false, + "An indeterminate component should have become determinate before " + + "completing. This error is likely caused by a bug in React. Please " + + "file an issue." + ); + // eslint-disable-next-line no-fallthrough + default: + invariant( + false, + "Unknown unit of work tag. This error is likely caused by a bug in " + + "React. Please file an issue." + ); + } + } + + return { + completeWork: completeWork + }; +}; + +var invokeGuardedCallback$2 = ReactErrorUtils.invokeGuardedCallback; +var hasCaughtError$1 = ReactErrorUtils.hasCaughtError; +var clearCaughtError$1 = ReactErrorUtils.clearCaughtError; + +var ReactFiberCommitWork = function(config, captureError) { + var getPublicInstance = config.getPublicInstance, + mutation = config.mutation, + persistence = config.persistence; + + var callComponentWillUnmountWithTimer = function(current, instance) { + startPhaseTimer(current, "componentWillUnmount"); + instance.props = current.memoizedProps; + instance.state = current.memoizedState; + instance.componentWillUnmount(); + stopPhaseTimer(); + }; + + // Capture errors so they don't interrupt unmounting. + function safelyCallComponentWillUnmount(current, instance) { + { + invokeGuardedCallback$2( + null, + callComponentWillUnmountWithTimer, + null, + current, + instance + ); + if (hasCaughtError$1()) { + var unmountError = clearCaughtError$1(); + captureError(current, unmountError); + } + } + } + + function safelyDetachRef(current) { + var ref = current.ref; + if (ref !== null) { + { + invokeGuardedCallback$2(null, ref, null, null); + if (hasCaughtError$1()) { + var refError = clearCaughtError$1(); + captureError(current, refError); + } + } + } + } + + function commitLifeCycles(current, finishedWork) { + switch (finishedWork.tag) { + case ClassComponent: { + var instance = finishedWork.stateNode; + if (finishedWork.effectTag & Update) { + if (current === null) { + startPhaseTimer(finishedWork, "componentDidMount"); + instance.props = finishedWork.memoizedProps; + instance.state = finishedWork.memoizedState; + instance.componentDidMount(); + stopPhaseTimer(); + } else { + var prevProps = current.memoizedProps; + var prevState = current.memoizedState; + startPhaseTimer(finishedWork, "componentDidUpdate"); + instance.props = finishedWork.memoizedProps; + instance.state = finishedWork.memoizedState; + instance.componentDidUpdate(prevProps, prevState); + stopPhaseTimer(); + } + } + var updateQueue = finishedWork.updateQueue; + if (updateQueue !== null) { + commitCallbacks(updateQueue, instance); + } + return; + } + case HostRoot: { + var _updateQueue = finishedWork.updateQueue; + if (_updateQueue !== null) { + var _instance = + finishedWork.child !== null ? finishedWork.child.stateNode : null; + commitCallbacks(_updateQueue, _instance); + } + return; + } + case HostComponent: { + var _instance2 = finishedWork.stateNode; + + // Renderers may schedule work to be done after host components are mounted + // (eg DOM renderer may schedule auto-focus for inputs and form controls). + // These effects should only be committed when components are first mounted, + // aka when there is no current/alternate. + if (current === null && finishedWork.effectTag & Update) { + var type = finishedWork.type; + var props = finishedWork.memoizedProps; + commitMount(_instance2, type, props, finishedWork); + } + + return; + } + case HostText: { + // We have no life-cycles associated with text. + return; + } + case HostPortal: { + // We have no life-cycles associated with portals. + return; + } + default: { + invariant( + false, + "This unit of work tag should not have side-effects. This error is " + + "likely caused by a bug in React. Please file an issue." + ); + } + } + } + + function commitAttachRef(finishedWork) { + var ref = finishedWork.ref; + if (ref !== null) { + var instance = finishedWork.stateNode; + switch (finishedWork.tag) { + case HostComponent: + ref(getPublicInstance(instance)); + break; + default: + ref(instance); + } + } + } + + function commitDetachRef(current) { + var currentRef = current.ref; + if (currentRef !== null) { + currentRef(null); + } + } + + // User-originating errors (lifecycles and refs) should not interrupt + // deletion, so don't let them throw. Host-originating errors should + // interrupt deletion, so it's okay + function commitUnmount(current) { + if (typeof onCommitUnmount === "function") { + onCommitUnmount(current); + } + + switch (current.tag) { + case ClassComponent: { + safelyDetachRef(current); + var instance = current.stateNode; + if (typeof instance.componentWillUnmount === "function") { + safelyCallComponentWillUnmount(current, instance); + } + return; + } + case HostComponent: { + safelyDetachRef(current); + return; + } + case CallComponent: { + commitNestedUnmounts(current.stateNode); + return; + } + case HostPortal: { + // TODO: this is recursive. + // We are also not using this parent because + // the portal will get pushed immediately. + if (enableMutatingReconciler && mutation) { + unmountHostComponents(current); + } else if (enablePersistentReconciler && persistence) { + emptyPortalContainer(current); + } + return; + } + } + } + + function commitNestedUnmounts(root) { + // While we're inside a removed host node we don't want to call + // removeChild on the inner nodes because they're removed by the top + // call anyway. We also want to call componentWillUnmount on all + // composites before this host node is removed from the tree. Therefore + var node = root; + while (true) { + commitUnmount(node); + // Visit children because they may contain more composite or host nodes. + // Skip portals because commitUnmount() currently visits them recursively. + if ( + node.child !== null && + // If we use mutation we drill down into portals using commitUnmount above. + // If we don't use mutation we drill down into portals here instead. + (!mutation || node.tag !== HostPortal) + ) { + node.child["return"] = node; + node = node.child; + continue; + } + if (node === root) { + return; + } + while (node.sibling === null) { + if (node["return"] === null || node["return"] === root) { + return; + } + node = node["return"]; + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } + } + + function detachFiber(current) { + // Cut off the return pointers to disconnect it from the tree. Ideally, we + // should clear the child pointer of the parent alternate to let this + // get GC:ed but we don't know which for sure which parent is the current + // one so we'll settle for GC:ing the subtree of this child. This child + // itself will be GC:ed when the parent updates the next time. + current["return"] = null; + current.child = null; + if (current.alternate) { + current.alternate.child = null; + current.alternate["return"] = null; + } + } + + if (!mutation) { + var commitContainer = void 0; + if (persistence) { + var replaceContainerChildren = persistence.replaceContainerChildren, + createContainerChildSet = persistence.createContainerChildSet; + + var emptyPortalContainer = function(current) { + var portal = current.stateNode; + var containerInfo = portal.containerInfo; + + var emptyChildSet = createContainerChildSet(containerInfo); + replaceContainerChildren(containerInfo, emptyChildSet); + }; + commitContainer = function(finishedWork) { + switch (finishedWork.tag) { + case ClassComponent: { + return; + } + case HostComponent: { + return; + } + case HostText: { + return; + } + case HostRoot: + case HostPortal: { + var portalOrRoot = finishedWork.stateNode; + var containerInfo = portalOrRoot.containerInfo, + _pendingChildren = portalOrRoot.pendingChildren; + + replaceContainerChildren(containerInfo, _pendingChildren); + return; + } + default: { + invariant( + false, + "This unit of work tag should not have side-effects. This error is " + + "likely caused by a bug in React. Please file an issue." + ); + } + } + }; + } else { + commitContainer = function(finishedWork) { + // Noop + }; + } + if (enablePersistentReconciler || enableNoopReconciler) { + return { + commitResetTextContent: function(finishedWork) {}, + commitPlacement: function(finishedWork) {}, + commitDeletion: function(current) { + // Detach refs and call componentWillUnmount() on the whole subtree. + commitNestedUnmounts(current); + detachFiber(current); + }, + commitWork: function(current, finishedWork) { + commitContainer(finishedWork); + }, + + commitLifeCycles: commitLifeCycles, + commitAttachRef: commitAttachRef, + commitDetachRef: commitDetachRef + }; + } else if (persistence) { + invariant(false, "Persistent reconciler is disabled."); + } else { + invariant(false, "Noop reconciler is disabled."); + } + } + var commitMount = mutation.commitMount, + commitUpdate = mutation.commitUpdate, + resetTextContent = mutation.resetTextContent, + commitTextUpdate = mutation.commitTextUpdate, + appendChild = mutation.appendChild, + appendChildToContainer = mutation.appendChildToContainer, + insertBefore = mutation.insertBefore, + insertInContainerBefore = mutation.insertInContainerBefore, + removeChild = mutation.removeChild, + removeChildFromContainer = mutation.removeChildFromContainer; + + function getHostParentFiber(fiber) { + var parent = fiber["return"]; + while (parent !== null) { + if (isHostParent(parent)) { + return parent; + } + parent = parent["return"]; + } + invariant( + false, + "Expected to find a host parent. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + } + + function isHostParent(fiber) { + return ( + fiber.tag === HostComponent || + fiber.tag === HostRoot || + fiber.tag === HostPortal + ); + } + + function getHostSibling(fiber) { + // We're going to search forward into the tree until we find a sibling host + // node. Unfortunately, if multiple insertions are done in a row we have to + // search past them. This leads to exponential search for the next sibling. + var node = fiber; + siblings: while (true) { + // If we didn't find anything, let's try the next sibling. + while (node.sibling === null) { + if (node["return"] === null || isHostParent(node["return"])) { + // If we pop out of the root or hit the parent the fiber we are the + // last sibling. + return null; + } + node = node["return"]; + } + node.sibling["return"] = node["return"]; + node = node.sibling; + while (node.tag !== HostComponent && node.tag !== HostText) { + // If it is not host node and, we might have a host node inside it. + // Try to search down until we find one. + if (node.effectTag & Placement) { + // If we don't have a child, try the siblings instead. + continue siblings; + } + // If we don't have a child, try the siblings instead. + // We also skip portals because they are not part of this host tree. + if (node.child === null || node.tag === HostPortal) { + continue siblings; + } else { + node.child["return"] = node; + node = node.child; + } + } + // Check if this host node is stable or about to be placed. + if (!(node.effectTag & Placement)) { + // Found it! + return node.stateNode; + } + } + } + + function commitPlacement(finishedWork) { + // Recursively insert all host nodes into the parent. + var parentFiber = getHostParentFiber(finishedWork); + var parent = void 0; + var isContainer = void 0; + switch (parentFiber.tag) { + case HostComponent: + parent = parentFiber.stateNode; + isContainer = false; + break; + case HostRoot: + parent = parentFiber.stateNode.containerInfo; + isContainer = true; + break; + case HostPortal: + parent = parentFiber.stateNode.containerInfo; + isContainer = true; + break; + default: + invariant( + false, + "Invalid host parent fiber. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + } + if (parentFiber.effectTag & ContentReset) { + // Reset the text content of the parent before doing any insertions + resetTextContent(parent); + // Clear ContentReset from the effect tag + parentFiber.effectTag &= ~ContentReset; + } + + var before = getHostSibling(finishedWork); + // We only have the top Fiber that was inserted but we need recurse down its + // children to find all the terminal nodes. + var node = finishedWork; + while (true) { + if (node.tag === HostComponent || node.tag === HostText) { + if (before) { + if (isContainer) { + insertInContainerBefore(parent, node.stateNode, before); + } else { + insertBefore(parent, node.stateNode, before); + } + } else { + if (isContainer) { + appendChildToContainer(parent, node.stateNode); + } else { + appendChild(parent, node.stateNode); + } + } + } else if (node.tag === HostPortal) { + // If the insertion itself is a portal, then we don't want to traverse + // down its children. Instead, we'll get insertions from each child in + // the portal directly. + } else if (node.child !== null) { + node.child["return"] = node; + node = node.child; + continue; + } + if (node === finishedWork) { + return; + } + while (node.sibling === null) { + if (node["return"] === null || node["return"] === finishedWork) { + return; + } + node = node["return"]; + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } + } + + function unmountHostComponents(current) { + // We only have the top Fiber that was inserted but we need recurse down its + var node = current; + + // Each iteration, currentParent is populated with node's host parent if not + // currentParentIsValid. + var currentParentIsValid = false; + var currentParent = void 0; + var currentParentIsContainer = void 0; + + while (true) { + if (!currentParentIsValid) { + var parent = node["return"]; + findParent: while (true) { + invariant( + parent !== null, + "Expected to find a host parent. This error is likely caused by " + + "a bug in React. Please file an issue." + ); + switch (parent.tag) { + case HostComponent: + currentParent = parent.stateNode; + currentParentIsContainer = false; + break findParent; + case HostRoot: + currentParent = parent.stateNode.containerInfo; + currentParentIsContainer = true; + break findParent; + case HostPortal: + currentParent = parent.stateNode.containerInfo; + currentParentIsContainer = true; + break findParent; + } + parent = parent["return"]; + } + currentParentIsValid = true; + } + + if (node.tag === HostComponent || node.tag === HostText) { + commitNestedUnmounts(node); + // After all the children have unmounted, it is now safe to remove the + // node from the tree. + if (currentParentIsContainer) { + removeChildFromContainer(currentParent, node.stateNode); + } else { + removeChild(currentParent, node.stateNode); + } + // Don't visit children because we already visited them. + } else if (node.tag === HostPortal) { + // When we go into a portal, it becomes the parent to remove from. + // We will reassign it back when we pop the portal on the way up. + currentParent = node.stateNode.containerInfo; + // Visit children because portals might contain host components. + if (node.child !== null) { + node.child["return"] = node; + node = node.child; + continue; + } + } else { + commitUnmount(node); + // Visit children because we may find more host components below. + if (node.child !== null) { + node.child["return"] = node; + node = node.child; + continue; + } + } + if (node === current) { + return; + } + while (node.sibling === null) { + if (node["return"] === null || node["return"] === current) { + return; + } + node = node["return"]; + if (node.tag === HostPortal) { + // When we go out of the portal, we need to restore the parent. + // Since we don't keep a stack of them, we will search for it. + currentParentIsValid = false; + } + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } + } + + function commitDeletion(current) { + // Recursively delete all host nodes from the parent. + // Detach refs and call componentWillUnmount() on the whole subtree. + unmountHostComponents(current); + detachFiber(current); + } + + function commitWork(current, finishedWork) { + switch (finishedWork.tag) { + case ClassComponent: { + return; + } + case HostComponent: { + var instance = finishedWork.stateNode; + if (instance != null) { + // Commit the work prepared earlier. + var newProps = finishedWork.memoizedProps; + // For hydration we reuse the update path but we treat the oldProps + // as the newProps. The updatePayload will contain the real change in + // this case. + var oldProps = current !== null ? current.memoizedProps : newProps; + var type = finishedWork.type; + // TODO: Type the updateQueue to be specific to host components. + var updatePayload = finishedWork.updateQueue; + finishedWork.updateQueue = null; + if (updatePayload !== null) { + commitUpdate( + instance, + updatePayload, + type, + oldProps, + newProps, + finishedWork + ); + } + } + return; + } + case HostText: { + invariant( + finishedWork.stateNode !== null, + "This should have a text node initialized. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + var textInstance = finishedWork.stateNode; + var newText = finishedWork.memoizedProps; + // For hydration we reuse the update path but we treat the oldProps + // as the newProps. The updatePayload will contain the real change in + // this case. + var oldText = current !== null ? current.memoizedProps : newText; + commitTextUpdate(textInstance, oldText, newText); + return; + } + case HostRoot: { + return; + } + default: { + invariant( + false, + "This unit of work tag should not have side-effects. This error is " + + "likely caused by a bug in React. Please file an issue." + ); + } + } + } + + function commitResetTextContent(current) { + resetTextContent(current.stateNode); + } + + if (enableMutatingReconciler) { + return { + commitResetTextContent: commitResetTextContent, + commitPlacement: commitPlacement, + commitDeletion: commitDeletion, + commitWork: commitWork, + commitLifeCycles: commitLifeCycles, + commitAttachRef: commitAttachRef, + commitDetachRef: commitDetachRef + }; + } else { + invariant(false, "Mutating reconciler is disabled."); + } +}; + +var NO_CONTEXT = {}; + +var ReactFiberHostContext = function(config) { + var getChildHostContext = config.getChildHostContext, + getRootHostContext = config.getRootHostContext; + + var contextStackCursor = createCursor(NO_CONTEXT); + var contextFiberStackCursor = createCursor(NO_CONTEXT); + var rootInstanceStackCursor = createCursor(NO_CONTEXT); + + function requiredContext(c) { + invariant( + c !== NO_CONTEXT, + "Expected host context to exist. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + return c; + } + + function getRootHostContainer() { + var rootInstance = requiredContext(rootInstanceStackCursor.current); + return rootInstance; + } + + function pushHostContainer(fiber, nextRootInstance) { + // Push current root instance onto the stack; + // This allows us to reset root when portals are popped. + push(rootInstanceStackCursor, nextRootInstance, fiber); + + var nextRootContext = getRootHostContext(nextRootInstance); + + // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. + push(contextFiberStackCursor, fiber, fiber); + push(contextStackCursor, nextRootContext, fiber); + } + + function popHostContainer(fiber) { + pop(contextStackCursor, fiber); + pop(contextFiberStackCursor, fiber); + pop(rootInstanceStackCursor, fiber); + } + + function getHostContext() { + var context = requiredContext(contextStackCursor.current); + return context; + } + + function pushHostContext(fiber) { + var rootInstance = requiredContext(rootInstanceStackCursor.current); + var context = requiredContext(contextStackCursor.current); + var nextContext = getChildHostContext(context, fiber.type, rootInstance); + + // Don't push this Fiber's context unless it's unique. + if (context === nextContext) { + return; + } + + // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. + push(contextFiberStackCursor, fiber, fiber); + push(contextStackCursor, nextContext, fiber); + } + + function popHostContext(fiber) { + // Do not pop unless this Fiber provided the current context. + // pushHostContext() only pushes Fibers that provide unique contexts. + if (contextFiberStackCursor.current !== fiber) { + return; + } + + pop(contextStackCursor, fiber); + pop(contextFiberStackCursor, fiber); + } + + function resetHostContainer() { + contextStackCursor.current = NO_CONTEXT; + rootInstanceStackCursor.current = NO_CONTEXT; + } + + return { + getHostContext: getHostContext, + getRootHostContainer: getRootHostContainer, + popHostContainer: popHostContainer, + popHostContext: popHostContext, + pushHostContainer: pushHostContainer, + pushHostContext: pushHostContext, + resetHostContainer: resetHostContainer + }; +}; + +var ReactFiberHydrationContext = function(config) { + var shouldSetTextContent = config.shouldSetTextContent, + hydration = config.hydration; + + // If this doesn't have hydration mode. + + if (!hydration) { + return { + enterHydrationState: function() { + return false; + }, + resetHydrationState: function() {}, + tryToClaimNextHydratableInstance: function() {}, + prepareToHydrateHostInstance: function() { + invariant( + false, + "Expected prepareToHydrateHostInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + }, + prepareToHydrateHostTextInstance: function() { + invariant( + false, + "Expected prepareToHydrateHostTextInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + }, + popHydrationState: function(fiber) { + return false; + } + }; + } + + var canHydrateInstance = hydration.canHydrateInstance, + canHydrateTextInstance = hydration.canHydrateTextInstance, + getNextHydratableSibling = hydration.getNextHydratableSibling, + getFirstHydratableChild = hydration.getFirstHydratableChild, + hydrateInstance = hydration.hydrateInstance, + hydrateTextInstance = hydration.hydrateTextInstance, + didNotMatchHydratedContainerTextInstance = + hydration.didNotMatchHydratedContainerTextInstance, + didNotMatchHydratedTextInstance = hydration.didNotMatchHydratedTextInstance, + didNotHydrateContainerInstance = hydration.didNotHydrateContainerInstance, + didNotHydrateInstance = hydration.didNotHydrateInstance, + didNotFindHydratableContainerInstance = + hydration.didNotFindHydratableContainerInstance, + didNotFindHydratableContainerTextInstance = + hydration.didNotFindHydratableContainerTextInstance, + didNotFindHydratableInstance = hydration.didNotFindHydratableInstance, + didNotFindHydratableTextInstance = + hydration.didNotFindHydratableTextInstance; + + // The deepest Fiber on the stack involved in a hydration context. + // This may have been an insertion or a hydration. + + var hydrationParentFiber = null; + var nextHydratableInstance = null; + var isHydrating = false; + + function enterHydrationState(fiber) { + var parentInstance = fiber.stateNode.containerInfo; + nextHydratableInstance = getFirstHydratableChild(parentInstance); + hydrationParentFiber = fiber; + isHydrating = true; + return true; + } + + function deleteHydratableInstance(returnFiber, instance) { + { + switch (returnFiber.tag) { + case HostRoot: + didNotHydrateContainerInstance( + returnFiber.stateNode.containerInfo, + instance + ); + break; + case HostComponent: + didNotHydrateInstance( + returnFiber.type, + returnFiber.memoizedProps, + returnFiber.stateNode, + instance + ); + break; + } + } + + var childToDelete = createFiberFromHostInstanceForDeletion(); + childToDelete.stateNode = instance; + childToDelete["return"] = returnFiber; + childToDelete.effectTag = Deletion; + + // This might seem like it belongs on progressedFirstDeletion. However, + // these children are not part of the reconciliation list of children. + // Even if we abort and rereconcile the children, that will try to hydrate + // again and the nodes are still in the host tree so these will be + // recreated. + if (returnFiber.lastEffect !== null) { + returnFiber.lastEffect.nextEffect = childToDelete; + returnFiber.lastEffect = childToDelete; + } else { + returnFiber.firstEffect = returnFiber.lastEffect = childToDelete; + } + } + + function insertNonHydratedInstance(returnFiber, fiber) { + fiber.effectTag |= Placement; + { + switch (returnFiber.tag) { + case HostRoot: { + var parentContainer = returnFiber.stateNode.containerInfo; + switch (fiber.tag) { + case HostComponent: + var type = fiber.type; + var props = fiber.pendingProps; + didNotFindHydratableContainerInstance( + parentContainer, + type, + props + ); + break; + case HostText: + var text = fiber.pendingProps; + didNotFindHydratableContainerTextInstance(parentContainer, text); + break; + } + break; + } + case HostComponent: { + var parentType = returnFiber.type; + var parentProps = returnFiber.memoizedProps; + var parentInstance = returnFiber.stateNode; + switch (fiber.tag) { + case HostComponent: + var _type = fiber.type; + var _props = fiber.pendingProps; + didNotFindHydratableInstance( + parentType, + parentProps, + parentInstance, + _type, + _props + ); + break; + case HostText: + var _text = fiber.pendingProps; + didNotFindHydratableTextInstance( + parentType, + parentProps, + parentInstance, + _text + ); + break; + } + break; + } + default: + return; + } + } + } + + function tryHydrate(fiber, nextInstance) { + switch (fiber.tag) { + case HostComponent: { + var type = fiber.type; + var props = fiber.pendingProps; + var instance = canHydrateInstance(nextInstance, type, props); + if (instance !== null) { + fiber.stateNode = instance; + return true; + } + return false; + } + case HostText: { + var text = fiber.pendingProps; + var textInstance = canHydrateTextInstance(nextInstance, text); + if (textInstance !== null) { + fiber.stateNode = textInstance; + return true; + } + return false; + } + default: + return false; + } + } + + function tryToClaimNextHydratableInstance(fiber) { + if (!isHydrating) { + return; + } + var nextInstance = nextHydratableInstance; + if (!nextInstance) { + // Nothing to hydrate. Make it an insertion. + insertNonHydratedInstance(hydrationParentFiber, fiber); + isHydrating = false; + hydrationParentFiber = fiber; + return; + } + if (!tryHydrate(fiber, nextInstance)) { + // If we can't hydrate this instance let's try the next one. + // We use this as a heuristic. It's based on intuition and not data so it + // might be flawed or unnecessary. + nextInstance = getNextHydratableSibling(nextInstance); + if (!nextInstance || !tryHydrate(fiber, nextInstance)) { + // Nothing to hydrate. Make it an insertion. + insertNonHydratedInstance(hydrationParentFiber, fiber); + isHydrating = false; + hydrationParentFiber = fiber; + return; + } + // We matched the next one, we'll now assume that the first one was + // superfluous and we'll delete it. Since we can't eagerly delete it + // we'll have to schedule a deletion. To do that, this node needs a dummy + // fiber associated with it. + deleteHydratableInstance(hydrationParentFiber, nextHydratableInstance); + } + hydrationParentFiber = fiber; + nextHydratableInstance = getFirstHydratableChild(nextInstance); + } + + function prepareToHydrateHostInstance( + fiber, + rootContainerInstance, + hostContext + ) { + var instance = fiber.stateNode; + var updatePayload = hydrateInstance( + instance, + fiber.type, + fiber.memoizedProps, + rootContainerInstance, + hostContext, + fiber + ); + // TODO: Type this specific to this type of component. + fiber.updateQueue = updatePayload; + // If the update payload indicates that there is a change or if there + // is a new ref we mark this as an update. + if (updatePayload !== null) { + return true; + } + return false; + } + + function prepareToHydrateHostTextInstance(fiber) { + var textInstance = fiber.stateNode; + var textContent = fiber.memoizedProps; + var shouldUpdate = hydrateTextInstance(textInstance, textContent, fiber); + { + if (shouldUpdate) { + // We assume that prepareToHydrateHostTextInstance is called in a context where the + // hydration parent is the parent host component of this host text. + var returnFiber = hydrationParentFiber; + if (returnFiber !== null) { + switch (returnFiber.tag) { + case HostRoot: { + var parentContainer = returnFiber.stateNode.containerInfo; + didNotMatchHydratedContainerTextInstance( + parentContainer, + textInstance, + textContent + ); + break; + } + case HostComponent: { + var parentType = returnFiber.type; + var parentProps = returnFiber.memoizedProps; + var parentInstance = returnFiber.stateNode; + didNotMatchHydratedTextInstance( + parentType, + parentProps, + parentInstance, + textInstance, + textContent + ); + break; + } + } + } + } + } + return shouldUpdate; + } + + function popToNextHostParent(fiber) { + var parent = fiber["return"]; + while ( + parent !== null && + parent.tag !== HostComponent && + parent.tag !== HostRoot + ) { + parent = parent["return"]; + } + hydrationParentFiber = parent; + } + + function popHydrationState(fiber) { + if (fiber !== hydrationParentFiber) { + // We're deeper than the current hydration context, inside an inserted + // tree. + return false; + } + if (!isHydrating) { + // If we're not currently hydrating but we're in a hydration context, then + // we were an insertion and now need to pop up reenter hydration of our + // siblings. + popToNextHostParent(fiber); + isHydrating = true; + return false; + } + + var type = fiber.type; + + // If we have any remaining hydratable nodes, we need to delete them now. + // We only do this deeper than head and body since they tend to have random + // other nodes in them. We also ignore components with pure text content in + // side of them. + // TODO: Better heuristic. + if ( + fiber.tag !== HostComponent || + (type !== "head" && + type !== "body" && + !shouldSetTextContent(type, fiber.memoizedProps)) + ) { + var nextInstance = nextHydratableInstance; + while (nextInstance) { + deleteHydratableInstance(fiber, nextInstance); + nextInstance = getNextHydratableSibling(nextInstance); + } + } + + popToNextHostParent(fiber); + nextHydratableInstance = hydrationParentFiber + ? getNextHydratableSibling(fiber.stateNode) + : null; + return true; + } + + function resetHydrationState() { + hydrationParentFiber = null; + nextHydratableInstance = null; + isHydrating = false; + } + + return { + enterHydrationState: enterHydrationState, + resetHydrationState: resetHydrationState, + tryToClaimNextHydratableInstance: tryToClaimNextHydratableInstance, + prepareToHydrateHostInstance: prepareToHydrateHostInstance, + prepareToHydrateHostTextInstance: prepareToHydrateHostTextInstance, + popHydrationState: popHydrationState + }; +}; + +// This lets us hook into Fiber to debug what it's doing. +// See https://github.com/facebook/react/pull/8033. +// This is not part of the public API, not even for React DevTools. +// You may only inject a debugTool if you work on React Fiber itself. +var ReactFiberInstrumentation = { + debugTool: null +}; + +var ReactFiberInstrumentation_1 = ReactFiberInstrumentation; + +var invokeGuardedCallback$1 = ReactErrorUtils.invokeGuardedCallback; +var hasCaughtError = ReactErrorUtils.hasCaughtError; +var clearCaughtError = ReactErrorUtils.clearCaughtError; + +{ + var didWarnAboutStateTransition = false; + var didWarnSetStateChildContext = false; + var didWarnStateUpdateForUnmountedComponent = {}; + + var warnAboutUpdateOnUnmounted = function(fiber) { + var componentName = getComponentName(fiber) || "ReactClass"; + if (didWarnStateUpdateForUnmountedComponent[componentName]) { + return; + } + warning( + false, + "Can only update a mounted or mounting " + + "component. This usually means you called setState, replaceState, " + + "or forceUpdate on an unmounted component. This is a no-op.\n\nPlease " + + "check the code for the %s component.", + componentName + ); + didWarnStateUpdateForUnmountedComponent[componentName] = true; + }; + + var warnAboutInvalidUpdates = function(instance) { + switch (ReactDebugCurrentFiber.phase) { + case "getChildContext": + if (didWarnSetStateChildContext) { + return; + } + warning( + false, + "setState(...): Cannot call setState() inside getChildContext()" + ); + didWarnSetStateChildContext = true; + break; + case "render": + if (didWarnAboutStateTransition) { + return; + } + warning( + false, + "Cannot update during an existing state transition (such as within " + + "`render` or another component's constructor). Render methods should " + + "be a pure function of props and state; constructor side-effects are " + + "an anti-pattern, but can be moved to `componentWillMount`." + ); + didWarnAboutStateTransition = true; + break; + } + }; +} + +var ReactFiberScheduler = function(config) { + var hostContext = ReactFiberHostContext(config); + var hydrationContext = ReactFiberHydrationContext(config); + var popHostContainer = hostContext.popHostContainer, + popHostContext = hostContext.popHostContext, + resetHostContainer = hostContext.resetHostContainer; + + var _ReactFiberBeginWork = ReactFiberBeginWork( + config, + hostContext, + hydrationContext, + scheduleWork, + computeExpirationForFiber + ), + beginWork = _ReactFiberBeginWork.beginWork, + beginFailedWork = _ReactFiberBeginWork.beginFailedWork; + + var _ReactFiberCompleteWo = ReactFiberCompleteWork( + config, + hostContext, + hydrationContext + ), + completeWork = _ReactFiberCompleteWo.completeWork; + + var _ReactFiberCommitWork = ReactFiberCommitWork(config, captureError), + commitResetTextContent = _ReactFiberCommitWork.commitResetTextContent, + commitPlacement = _ReactFiberCommitWork.commitPlacement, + commitDeletion = _ReactFiberCommitWork.commitDeletion, + commitWork = _ReactFiberCommitWork.commitWork, + commitLifeCycles = _ReactFiberCommitWork.commitLifeCycles, + commitAttachRef = _ReactFiberCommitWork.commitAttachRef, + commitDetachRef = _ReactFiberCommitWork.commitDetachRef; + + var now = config.now, + scheduleDeferredCallback = config.scheduleDeferredCallback, + useSyncScheduling = config.useSyncScheduling, + prepareForCommit = config.prepareForCommit, + resetAfterCommit = config.resetAfterCommit; + + // Represents the current time in ms. + + var startTime = now(); + var mostRecentCurrentTime = msToExpirationTime(0); + + // Represents the expiration time that incoming updates should use. (If this + // is NoWork, use the default strategy: async updates in async mode, sync + // updates in sync mode.) + var expirationContext = NoWork; + + var isWorking = false; + + // The next work in progress fiber that we're currently working on. + var nextUnitOfWork = null; + var nextRoot = null; + // The time at which we're currently rendering work. + var nextRenderExpirationTime = NoWork; + + // The next fiber with an effect that we're currently committing. + var nextEffect = null; + + // Keep track of which fibers have captured an error that need to be handled. + // Work is removed from this collection after componentDidCatch is called. + var capturedErrors = null; + // Keep track of which fibers have failed during the current batch of work. + // This is a different set than capturedErrors, because it is not reset until + // the end of the batch. This is needed to propagate errors correctly if a + // subtree fails more than once. + var failedBoundaries = null; + // Error boundaries that captured an error during the current commit. + var commitPhaseBoundaries = null; + var firstUncaughtError = null; + var didFatal = false; + + var isCommitting = false; + var isUnmounting = false; + + // Used for performance tracking. + var interruptedBy = null; + + function resetContextStack() { + // Reset the stack + reset(); + // Reset the cursors + resetContext(); + resetHostContainer(); + } + + function commitAllHostEffects() { + while (nextEffect !== null) { + { + ReactDebugCurrentFiber.setCurrentFiber(nextEffect); + } + recordEffect(); + + var effectTag = nextEffect.effectTag; + if (effectTag & ContentReset) { + commitResetTextContent(nextEffect); + } + + if (effectTag & Ref) { + var current = nextEffect.alternate; + if (current !== null) { + commitDetachRef(current); + } + } + + // The following switch statement is only concerned about placement, + // updates, and deletions. To avoid needing to add a case for every + // possible bitmap value, we remove the secondary effects from the + // effect tag and switch on that value. + var primaryEffectTag = + effectTag & ~(Callback | Err | ContentReset | Ref | PerformedWork); + switch (primaryEffectTag) { + case Placement: { + commitPlacement(nextEffect); + // Clear the "placement" from effect tag so that we know that this is inserted, before + // any life-cycles like componentDidMount gets called. + // TODO: findDOMNode doesn't rely on this any more but isMounted + // does and isMounted is deprecated anyway so we should be able + // to kill this. + nextEffect.effectTag &= ~Placement; + break; + } + case PlacementAndUpdate: { + // Placement + commitPlacement(nextEffect); + // Clear the "placement" from effect tag so that we know that this is inserted, before + // any life-cycles like componentDidMount gets called. + nextEffect.effectTag &= ~Placement; + + // Update + var _current = nextEffect.alternate; + commitWork(_current, nextEffect); + break; + } + case Update: { + var _current2 = nextEffect.alternate; + commitWork(_current2, nextEffect); + break; + } + case Deletion: { + isUnmounting = true; + commitDeletion(nextEffect); + isUnmounting = false; + break; + } + } + nextEffect = nextEffect.nextEffect; + } + + { + ReactDebugCurrentFiber.resetCurrentFiber(); + } + } + + function commitAllLifeCycles() { + while (nextEffect !== null) { + var effectTag = nextEffect.effectTag; + + if (effectTag & (Update | Callback)) { + recordEffect(); + var current = nextEffect.alternate; + commitLifeCycles(current, nextEffect); + } + + if (effectTag & Ref) { + recordEffect(); + commitAttachRef(nextEffect); + } + + if (effectTag & Err) { + recordEffect(); + commitErrorHandling(nextEffect); + } + + var next = nextEffect.nextEffect; + // Ensure that we clean these up so that we don't accidentally keep them. + // I'm not actually sure this matters because we can't reset firstEffect + // and lastEffect since they're on every node, not just the effectful + // ones. So we have to clean everything as we reuse nodes anyway. + nextEffect.nextEffect = null; + // Ensure that we reset the effectTag here so that we can rely on effect + // tags to reason about the current life-cycle. + nextEffect = next; + } + } + + function commitRoot(finishedWork) { + // We keep track of this so that captureError can collect any boundaries + // that capture an error during the commit phase. The reason these aren't + // local to this function is because errors that occur during cWU are + // captured elsewhere, to prevent the unmount from being interrupted. + isWorking = true; + isCommitting = true; + startCommitTimer(); + + var root = finishedWork.stateNode; + invariant( + root.current !== finishedWork, + "Cannot commit the same tree as before. This is probably a bug " + + "related to the return field. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + root.isReadyForCommit = false; + + // Reset this to null before calling lifecycles + ReactCurrentOwner.current = null; + + var firstEffect = void 0; + if (finishedWork.effectTag > PerformedWork) { + // A fiber's effect list consists only of its children, not itself. So if + // the root has an effect, we need to add it to the end of the list. The + // resulting list is the set that would belong to the root's parent, if + // it had one; that is, all the effects in the tree including the root. + if (finishedWork.lastEffect !== null) { + finishedWork.lastEffect.nextEffect = finishedWork; + firstEffect = finishedWork.firstEffect; + } else { + firstEffect = finishedWork; + } + } else { + // There is no effect on the root. + firstEffect = finishedWork.firstEffect; + } + + prepareForCommit(); + + // Commit all the side-effects within a tree. We'll do this in two passes. + // The first pass performs all the host insertions, updates, deletions and + // ref unmounts. + nextEffect = firstEffect; + startCommitHostEffectsTimer(); + while (nextEffect !== null) { + var didError = false; + var _error = void 0; + { + invokeGuardedCallback$1(null, commitAllHostEffects, null); + if (hasCaughtError()) { + didError = true; + _error = clearCaughtError(); + } + } + if (didError) { + invariant( + nextEffect !== null, + "Should have next effect. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + captureError(nextEffect, _error); + // Clean-up + if (nextEffect !== null) { + nextEffect = nextEffect.nextEffect; + } + } + } + stopCommitHostEffectsTimer(); + + resetAfterCommit(); + + // The work-in-progress tree is now the current tree. This must come after + // the first pass of the commit phase, so that the previous tree is still + // current during componentWillUnmount, but before the second pass, so that + // the finished work is current during componentDidMount/Update. + root.current = finishedWork; + + // In the second pass we'll perform all life-cycles and ref callbacks. + // Life-cycles happen as a separate pass so that all placements, updates, + // and deletions in the entire tree have already been invoked. + // This pass also triggers any renderer-specific initial effects. + nextEffect = firstEffect; + startCommitLifeCyclesTimer(); + while (nextEffect !== null) { + var _didError = false; + var _error2 = void 0; + { + invokeGuardedCallback$1(null, commitAllLifeCycles, null); + if (hasCaughtError()) { + _didError = true; + _error2 = clearCaughtError(); + } + } + if (_didError) { + invariant( + nextEffect !== null, + "Should have next effect. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + captureError(nextEffect, _error2); + if (nextEffect !== null) { + nextEffect = nextEffect.nextEffect; + } + } + } + + isCommitting = false; + isWorking = false; + stopCommitLifeCyclesTimer(); + stopCommitTimer(); + if (typeof onCommitRoot === "function") { + onCommitRoot(finishedWork.stateNode); + } + if (true && ReactFiberInstrumentation_1.debugTool) { + ReactFiberInstrumentation_1.debugTool.onCommitWork(finishedWork); + } + + // If we caught any errors during this commit, schedule their boundaries + // to update. + if (commitPhaseBoundaries) { + commitPhaseBoundaries.forEach(scheduleErrorRecovery); + commitPhaseBoundaries = null; + } + + if (firstUncaughtError !== null) { + var _error3 = firstUncaughtError; + firstUncaughtError = null; + onUncaughtError(_error3); + } + + var remainingTime = root.current.expirationTime; + + if (remainingTime === NoWork) { + capturedErrors = null; + failedBoundaries = null; + } + + return remainingTime; + } + + function resetExpirationTime(workInProgress, renderTime) { + if (renderTime !== Never && workInProgress.expirationTime === Never) { + // The children of this component are hidden. Don't bubble their + // expiration times. + return; + } + + // Check for pending updates. + var newExpirationTime = getUpdateExpirationTime(workInProgress); + + // TODO: Calls need to visit stateNode + + // Bubble up the earliest expiration time. + var child = workInProgress.child; + while (child !== null) { + if ( + child.expirationTime !== NoWork && + (newExpirationTime === NoWork || + newExpirationTime > child.expirationTime) + ) { + newExpirationTime = child.expirationTime; + } + child = child.sibling; + } + workInProgress.expirationTime = newExpirationTime; + } + + function completeUnitOfWork(workInProgress) { + while (true) { + // The current, flushed, state of this fiber is the alternate. + // Ideally nothing should rely on this, but relying on it here + // means that we don't need an additional field on the work in + // progress. + var current = workInProgress.alternate; + { + ReactDebugCurrentFiber.setCurrentFiber(workInProgress); + } + var next = completeWork( + current, + workInProgress, + nextRenderExpirationTime + ); + { + ReactDebugCurrentFiber.resetCurrentFiber(); + } + + var returnFiber = workInProgress["return"]; + var siblingFiber = workInProgress.sibling; + + resetExpirationTime(workInProgress, nextRenderExpirationTime); + + if (next !== null) { + stopWorkTimer(workInProgress); + if (true && ReactFiberInstrumentation_1.debugTool) { + ReactFiberInstrumentation_1.debugTool.onCompleteWork(workInProgress); + } + // If completing this work spawned new work, do that next. We'll come + // back here again. + return next; + } + + if (returnFiber !== null) { + // Append all the effects of the subtree and this fiber onto the effect + // list of the parent. The completion order of the children affects the + // side-effect order. + if (returnFiber.firstEffect === null) { + returnFiber.firstEffect = workInProgress.firstEffect; + } + if (workInProgress.lastEffect !== null) { + if (returnFiber.lastEffect !== null) { + returnFiber.lastEffect.nextEffect = workInProgress.firstEffect; + } + returnFiber.lastEffect = workInProgress.lastEffect; + } + + // If this fiber had side-effects, we append it AFTER the children's + // side-effects. We can perform certain side-effects earlier if + // needed, by doing multiple passes over the effect list. We don't want + // to schedule our own side-effect on our own list because if end up + // reusing children we'll schedule this effect onto itself since we're + // at the end. + var effectTag = workInProgress.effectTag; + // Skip both NoWork and PerformedWork tags when creating the effect list. + // PerformedWork effect is read by React DevTools but shouldn't be committed. + if (effectTag > PerformedWork) { + if (returnFiber.lastEffect !== null) { + returnFiber.lastEffect.nextEffect = workInProgress; + } else { + returnFiber.firstEffect = workInProgress; + } + returnFiber.lastEffect = workInProgress; + } + } + + stopWorkTimer(workInProgress); + if (true && ReactFiberInstrumentation_1.debugTool) { + ReactFiberInstrumentation_1.debugTool.onCompleteWork(workInProgress); + } + + if (siblingFiber !== null) { + // If there is more work to do in this returnFiber, do that next. + return siblingFiber; + } else if (returnFiber !== null) { + // If there's no more work in this returnFiber. Complete the returnFiber. + workInProgress = returnFiber; + continue; + } else { + // We've reached the root. + var root = workInProgress.stateNode; + root.isReadyForCommit = true; + return null; + } + } + + // Without this explicit null return Flow complains of invalid return type + // TODO Remove the above while(true) loop + // eslint-disable-next-line no-unreachable + return null; + } + + function performUnitOfWork(workInProgress) { + // The current, flushed, state of this fiber is the alternate. + // Ideally nothing should rely on this, but relying on it here + // means that we don't need an additional field on the work in + // progress. + var current = workInProgress.alternate; + + // See if beginning this work spawns more work. + startWorkTimer(workInProgress); + { + ReactDebugCurrentFiber.setCurrentFiber(workInProgress); + } + var next = beginWork(current, workInProgress, nextRenderExpirationTime); + { + ReactDebugCurrentFiber.resetCurrentFiber(); + } + if (true && ReactFiberInstrumentation_1.debugTool) { + ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress); + } + + if (next === null) { + // If this doesn't spawn new work, complete the current work. + next = completeUnitOfWork(workInProgress); + } + + ReactCurrentOwner.current = null; + + return next; + } + + function performFailedUnitOfWork(workInProgress) { + // The current, flushed, state of this fiber is the alternate. + // Ideally nothing should rely on this, but relying on it here + // means that we don't need an additional field on the work in + // progress. + var current = workInProgress.alternate; + + // See if beginning this work spawns more work. + startWorkTimer(workInProgress); + { + ReactDebugCurrentFiber.setCurrentFiber(workInProgress); + } + var next = beginFailedWork( + current, + workInProgress, + nextRenderExpirationTime + ); + { + ReactDebugCurrentFiber.resetCurrentFiber(); + } + if (true && ReactFiberInstrumentation_1.debugTool) { + ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress); + } + + if (next === null) { + // If this doesn't spawn new work, complete the current work. + next = completeUnitOfWork(workInProgress); + } + + ReactCurrentOwner.current = null; + + return next; + } + + function workLoop(expirationTime) { + if (capturedErrors !== null) { + // If there are unhandled errors, switch to the slow work loop. + // TODO: How to avoid this check in the fast path? Maybe the renderer + // could keep track of which roots have unhandled errors and call a + // forked version of renderRoot. + slowWorkLoopThatChecksForFailedWork(expirationTime); + return; + } + if ( + nextRenderExpirationTime === NoWork || + nextRenderExpirationTime > expirationTime + ) { + return; + } + + if (nextRenderExpirationTime <= mostRecentCurrentTime) { + // Flush all expired work. + while (nextUnitOfWork !== null) { + nextUnitOfWork = performUnitOfWork(nextUnitOfWork); + } + } else { + // Flush asynchronous work until the deadline runs out of time. + while (nextUnitOfWork !== null && !shouldYield()) { + nextUnitOfWork = performUnitOfWork(nextUnitOfWork); + } + } + } + + function slowWorkLoopThatChecksForFailedWork(expirationTime) { + if ( + nextRenderExpirationTime === NoWork || + nextRenderExpirationTime > expirationTime + ) { + return; + } + + if (nextRenderExpirationTime <= mostRecentCurrentTime) { + // Flush all expired work. + while (nextUnitOfWork !== null) { + if (hasCapturedError(nextUnitOfWork)) { + // Use a forked version of performUnitOfWork + nextUnitOfWork = performFailedUnitOfWork(nextUnitOfWork); + } else { + nextUnitOfWork = performUnitOfWork(nextUnitOfWork); + } + } + } else { + // Flush asynchronous work until the deadline runs out of time. + while (nextUnitOfWork !== null && !shouldYield()) { + if (hasCapturedError(nextUnitOfWork)) { + // Use a forked version of performUnitOfWork + nextUnitOfWork = performFailedUnitOfWork(nextUnitOfWork); + } else { + nextUnitOfWork = performUnitOfWork(nextUnitOfWork); + } + } + } + } + + function renderRootCatchBlock(root, failedWork, boundary, expirationTime) { + // We're going to restart the error boundary that captured the error. + // Conceptually, we're unwinding the stack. We need to unwind the + // context stack, too. + unwindContexts(failedWork, boundary); + + // Restart the error boundary using a forked version of + // performUnitOfWork that deletes the boundary's children. The entire + // failed subree will be unmounted. During the commit phase, a special + // lifecycle method is called on the error boundary, which triggers + // a re-render. + nextUnitOfWork = performFailedUnitOfWork(boundary); + + // Continue working. + workLoop(expirationTime); + } + + function renderRoot(root, expirationTime) { + invariant( + !isWorking, + "renderRoot was called recursively. This error is likely caused " + + "by a bug in React. Please file an issue." + ); + isWorking = true; + + // We're about to mutate the work-in-progress tree. If the root was pending + // commit, it no longer is: we'll need to complete it again. + root.isReadyForCommit = false; + + // Check if we're starting from a fresh stack, or if we're resuming from + // previously yielded work. + if ( + root !== nextRoot || + expirationTime !== nextRenderExpirationTime || + nextUnitOfWork === null + ) { + // Reset the stack and start working from the root. + resetContextStack(); + nextRoot = root; + nextRenderExpirationTime = expirationTime; + nextUnitOfWork = createWorkInProgress( + nextRoot.current, + null, + expirationTime + ); + } + + startWorkLoopTimer(nextUnitOfWork); + + var didError = false; + var error = null; + { + invokeGuardedCallback$1(null, workLoop, null, expirationTime); + if (hasCaughtError()) { + didError = true; + error = clearCaughtError(); + } + } + + // An error was thrown during the render phase. + while (didError) { + if (didFatal) { + // This was a fatal error. Don't attempt to recover from it. + firstUncaughtError = error; + break; + } + + var failedWork = nextUnitOfWork; + if (failedWork === null) { + // An error was thrown but there's no current unit of work. This can + // happen during the commit phase if there's a bug in the renderer. + didFatal = true; + continue; + } + + // "Capture" the error by finding the nearest boundary. If there is no + // error boundary, we use the root. + var boundary = captureError(failedWork, error); + invariant( + boundary !== null, + "Should have found an error boundary. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + + if (didFatal) { + // The error we just captured was a fatal error. This happens + // when the error propagates to the root more than once. + continue; + } + + didError = false; + error = null; + { + invokeGuardedCallback$1( + null, + renderRootCatchBlock, + null, + root, + failedWork, + boundary, + expirationTime + ); + if (hasCaughtError()) { + didError = true; + error = clearCaughtError(); + continue; + } + } + // We're finished working. Exit the error loop. + break; + } + + var uncaughtError = firstUncaughtError; + + // We're done performing work. Time to clean up. + stopWorkLoopTimer(interruptedBy); + interruptedBy = null; + isWorking = false; + didFatal = false; + firstUncaughtError = null; + + if (uncaughtError !== null) { + onUncaughtError(uncaughtError); + } + + return root.isReadyForCommit ? root.current.alternate : null; + } + + // Returns the boundary that captured the error, or null if the error is ignored + function captureError(failedWork, error) { + // It is no longer valid because we exited the user code. + ReactCurrentOwner.current = null; + { + ReactDebugCurrentFiber.resetCurrentFiber(); + } + + // Search for the nearest error boundary. + var boundary = null; + + // Passed to logCapturedError() + var errorBoundaryFound = false; + var willRetry = false; + var errorBoundaryName = null; + + // Host containers are a special case. If the failed work itself is a host + // container, then it acts as its own boundary. In all other cases, we + // ignore the work itself and only search through the parents. + if (failedWork.tag === HostRoot) { + boundary = failedWork; + + if (isFailedBoundary(failedWork)) { + // If this root already failed, there must have been an error when + // attempting to unmount it. This is a worst-case scenario and + // should only be possible if there's a bug in the renderer. + didFatal = true; + } + } else { + var node = failedWork["return"]; + while (node !== null && boundary === null) { + if (node.tag === ClassComponent) { + var instance = node.stateNode; + if (typeof instance.componentDidCatch === "function") { + errorBoundaryFound = true; + errorBoundaryName = getComponentName(node); + + // Found an error boundary! + boundary = node; + willRetry = true; + } + } else if (node.tag === HostRoot) { + // Treat the root like a no-op error boundary + boundary = node; + } + + if (isFailedBoundary(node)) { + // This boundary is already in a failed state. + + // If we're currently unmounting, that means this error was + // thrown while unmounting a failed subtree. We should ignore + // the error. + if (isUnmounting) { + return null; + } + + // If we're in the commit phase, we should check to see if + // this boundary already captured an error during this commit. + // This case exists because multiple errors can be thrown during + // a single commit without interruption. + if ( + commitPhaseBoundaries !== null && + (commitPhaseBoundaries.has(node) || + (node.alternate !== null && + commitPhaseBoundaries.has(node.alternate))) + ) { + // If so, we should ignore this error. + return null; + } + + // The error should propagate to the next boundary -— we keep looking. + boundary = null; + willRetry = false; + } + + node = node["return"]; + } + } + + if (boundary !== null) { + // Add to the collection of failed boundaries. This lets us know that + // subsequent errors in this subtree should propagate to the next boundary. + if (failedBoundaries === null) { + failedBoundaries = new Set(); + } + failedBoundaries.add(boundary); + + // This method is unsafe outside of the begin and complete phases. + // We might be in the commit phase when an error is captured. + // The risk is that the return path from this Fiber may not be accurate. + // That risk is acceptable given the benefit of providing users more context. + var _componentStack = getStackAddendumByWorkInProgressFiber(failedWork); + var _componentName = getComponentName(failedWork); + + // Add to the collection of captured errors. This is stored as a global + // map of errors and their component stack location keyed by the boundaries + // that capture them. We mostly use this Map as a Set; it's a Map only to + // avoid adding a field to Fiber to store the error. + if (capturedErrors === null) { + capturedErrors = new Map(); + } + + var capturedError = { + componentName: _componentName, + componentStack: _componentStack, + error: error, + errorBoundary: errorBoundaryFound ? boundary.stateNode : null, + errorBoundaryFound: errorBoundaryFound, + errorBoundaryName: errorBoundaryName, + willRetry: willRetry + }; + + capturedErrors.set(boundary, capturedError); + + try { + logCapturedError(capturedError); + } catch (e) { + // Prevent cycle if logCapturedError() throws. + // A cycle may still occur if logCapturedError renders a component that throws. + console.error(e); + } + + // If we're in the commit phase, defer scheduling an update on the + // boundary until after the commit is complete + if (isCommitting) { + if (commitPhaseBoundaries === null) { + commitPhaseBoundaries = new Set(); + } + commitPhaseBoundaries.add(boundary); + } else { + // Otherwise, schedule an update now. + // TODO: Is this actually necessary during the render phase? Is it + // possible to unwind and continue rendering at the same priority, + // without corrupting internal state? + scheduleErrorRecovery(boundary); + } + return boundary; + } else if (firstUncaughtError === null) { + // If no boundary is found, we'll need to throw the error + firstUncaughtError = error; + } + return null; + } + + function hasCapturedError(fiber) { + // TODO: capturedErrors should store the boundary instance, to avoid needing + // to check the alternate. + return ( + capturedErrors !== null && + (capturedErrors.has(fiber) || + (fiber.alternate !== null && capturedErrors.has(fiber.alternate))) + ); + } + + function isFailedBoundary(fiber) { + // TODO: failedBoundaries should store the boundary instance, to avoid + // needing to check the alternate. + return ( + failedBoundaries !== null && + (failedBoundaries.has(fiber) || + (fiber.alternate !== null && failedBoundaries.has(fiber.alternate))) + ); + } + + function commitErrorHandling(effectfulFiber) { + var capturedError = void 0; + if (capturedErrors !== null) { + capturedError = capturedErrors.get(effectfulFiber); + capturedErrors["delete"](effectfulFiber); + if (capturedError == null) { + if (effectfulFiber.alternate !== null) { + effectfulFiber = effectfulFiber.alternate; + capturedError = capturedErrors.get(effectfulFiber); + capturedErrors["delete"](effectfulFiber); + } + } + } + + invariant( + capturedError != null, + "No error for given unit of work. This error is likely caused by a " + + "bug in React. Please file an issue." + ); + + switch (effectfulFiber.tag) { + case ClassComponent: + var instance = effectfulFiber.stateNode; + + var info = { + componentStack: capturedError.componentStack + }; + + // Allow the boundary to handle the error, usually by scheduling + // an update to itself + instance.componentDidCatch(capturedError.error, info); + return; + case HostRoot: + if (firstUncaughtError === null) { + firstUncaughtError = capturedError.error; + } + return; + default: + invariant( + false, + "Invalid type of work. This error is likely caused by a bug in " + + "React. Please file an issue." + ); + } + } + + function unwindContexts(from, to) { + var node = from; + while (node !== null) { + switch (node.tag) { + case ClassComponent: + popContextProvider(node); + break; + case HostComponent: + popHostContext(node); + break; + case HostRoot: + popHostContainer(node); + break; + case HostPortal: + popHostContainer(node); + break; + } + if (node === to || node.alternate === to) { + stopFailedWorkTimer(node); + break; + } else { + stopWorkTimer(node); + } + node = node["return"]; + } + } + + function computeAsyncExpiration() { + // Given the current clock time, returns an expiration time. We use rounding + // to batch like updates together. + // Should complete within ~1000ms. 1200ms max. + var currentTime = recalculateCurrentTime(); + var expirationMs = 1000; + var bucketSizeMs = 200; + return computeExpirationBucket(currentTime, expirationMs, bucketSizeMs); + } + + function computeExpirationForFiber(fiber) { + var expirationTime = void 0; + if (expirationContext !== NoWork) { + // An explicit expiration context was set; + expirationTime = expirationContext; + } else if (isWorking) { + if (isCommitting) { + // Updates that occur during the commit phase should have sync priority + // by default. + expirationTime = Sync; + } else { + // Updates during the render phase should expire at the same time as + // the work that is being rendered. + expirationTime = nextRenderExpirationTime; + } + } else { + // No explicit expiration context was set, and we're not currently + // performing work. Calculate a new expiration time. + if (useSyncScheduling && !(fiber.internalContextTag & AsyncUpdates)) { + // This is a sync update + expirationTime = Sync; + } else { + // This is an async update + expirationTime = computeAsyncExpiration(); + } + } + return expirationTime; + } + + function scheduleWork(fiber, expirationTime) { + return scheduleWorkImpl(fiber, expirationTime, false); + } + + function scheduleWorkImpl(fiber, expirationTime, isErrorRecovery) { + recordScheduleUpdate(); + + { + if (!isErrorRecovery && fiber.tag === ClassComponent) { + var instance = fiber.stateNode; + warnAboutInvalidUpdates(instance); + } + } + + var node = fiber; + while (node !== null) { + // Walk the parent path to the root and update each node's + // expiration time. + if ( + node.expirationTime === NoWork || + node.expirationTime > expirationTime + ) { + node.expirationTime = expirationTime; + } + if (node.alternate !== null) { + if ( + node.alternate.expirationTime === NoWork || + node.alternate.expirationTime > expirationTime + ) { + node.alternate.expirationTime = expirationTime; + } + } + if (node["return"] === null) { + if (node.tag === HostRoot) { + var root = node.stateNode; + if ( + !isWorking && + root === nextRoot && + expirationTime <= nextRenderExpirationTime + ) { + // Restart the root from the top. + if (nextUnitOfWork !== null) { + // This is an interruption. (Used for performance tracking.) + interruptedBy = fiber; + } + nextRoot = null; + nextUnitOfWork = null; + nextRenderExpirationTime = NoWork; + } + requestWork(root, expirationTime); + } else { + { + if (!isErrorRecovery && fiber.tag === ClassComponent) { + warnAboutUpdateOnUnmounted(fiber); + } + } + return; + } + } + node = node["return"]; + } + } + + function scheduleErrorRecovery(fiber) { + scheduleWorkImpl(fiber, Sync, true); + } + + function recalculateCurrentTime() { + // Subtract initial time so it fits inside 32bits + var ms = now() - startTime; + mostRecentCurrentTime = msToExpirationTime(ms); + return mostRecentCurrentTime; + } + + function deferredUpdates(fn) { + var previousExpirationContext = expirationContext; + expirationContext = computeAsyncExpiration(); + try { + return fn(); + } finally { + expirationContext = previousExpirationContext; + } + } + + function syncUpdates(fn) { + var previousExpirationContext = expirationContext; + expirationContext = Sync; + try { + return fn(); + } finally { + expirationContext = previousExpirationContext; + } + } + + // TODO: Everything below this is written as if it has been lifted to the + // renderers. I'll do this in a follow-up. + + // Linked-list of roots + var firstScheduledRoot = null; + var lastScheduledRoot = null; + + var isCallbackScheduled = false; + var isRendering = false; + var nextFlushedRoot = null; + var nextFlushedExpirationTime = NoWork; + var deadlineDidExpire = false; + var hasUnhandledError = false; + var unhandledError = null; + var deadline = null; + + var isBatchingUpdates = false; + var isUnbatchingUpdates = false; + + // Use these to prevent an infinite loop of nested updates + var NESTED_UPDATE_LIMIT = 1000; + var nestedUpdateCount = 0; + + var timeHeuristicForUnitOfWork = 1; + + // requestWork is called by the scheduler whenever a root receives an update. + // It's up to the renderer to call renderRoot at some point in the future. + function requestWork(root, expirationTime) { + if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { + invariant( + false, + "Maximum update depth exceeded. This can happen when a " + + "component repeatedly calls setState inside componentWillUpdate or " + + "componentDidUpdate. React limits the number of nested updates to " + + "prevent infinite loops." + ); + } + + // Add the root to the schedule. + // Check if this root is already part of the schedule. + if (root.nextScheduledRoot === null) { + // This root is not already scheduled. Add it. + root.remainingExpirationTime = expirationTime; + if (lastScheduledRoot === null) { + firstScheduledRoot = lastScheduledRoot = root; + root.nextScheduledRoot = root; + } else { + lastScheduledRoot.nextScheduledRoot = root; + lastScheduledRoot = root; + lastScheduledRoot.nextScheduledRoot = firstScheduledRoot; + } + } else { + // This root is already scheduled, but its priority may have increased. + var remainingExpirationTime = root.remainingExpirationTime; + if ( + remainingExpirationTime === NoWork || + expirationTime < remainingExpirationTime + ) { + // Update the priority. + root.remainingExpirationTime = expirationTime; + } + } + + if (isRendering) { + // Prevent reentrancy. Remaining work will be scheduled at the end of + // the currently rendering batch. + return; + } + + if (isBatchingUpdates) { + // Flush work at the end of the batch. + if (isUnbatchingUpdates) { + // ...unless we're inside unbatchedUpdates, in which case we should + // flush it now. + performWorkOnRoot(root, Sync); + } + return; + } + + // TODO: Get rid of Sync and use current time? + if (expirationTime === Sync) { + performWork(Sync, null); + } else if (!isCallbackScheduled) { + isCallbackScheduled = true; + startRequestCallbackTimer(); + scheduleDeferredCallback(performAsyncWork); + } + } + + function findHighestPriorityRoot() { + var highestPriorityWork = NoWork; + var highestPriorityRoot = null; + + if (lastScheduledRoot !== null) { + var previousScheduledRoot = lastScheduledRoot; + var root = firstScheduledRoot; + while (root !== null) { + var remainingExpirationTime = root.remainingExpirationTime; + if (remainingExpirationTime === NoWork) { + // This root no longer has work. Remove it from the scheduler. + + // TODO: This check is redudant, but Flow is confused by the branch + // below where we set lastScheduledRoot to null, even though we break + // from the loop right after. + invariant( + previousScheduledRoot !== null && lastScheduledRoot !== null, + "Should have a previous and last root. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + if (root === root.nextScheduledRoot) { + // This is the only root in the list. + root.nextScheduledRoot = null; + firstScheduledRoot = lastScheduledRoot = null; + break; + } else if (root === firstScheduledRoot) { + // This is the first root in the list. + var next = root.nextScheduledRoot; + firstScheduledRoot = next; + lastScheduledRoot.nextScheduledRoot = next; + root.nextScheduledRoot = null; + } else if (root === lastScheduledRoot) { + // This is the last root in the list. + lastScheduledRoot = previousScheduledRoot; + lastScheduledRoot.nextScheduledRoot = firstScheduledRoot; + root.nextScheduledRoot = null; + break; + } else { + previousScheduledRoot.nextScheduledRoot = root.nextScheduledRoot; + root.nextScheduledRoot = null; + } + root = previousScheduledRoot.nextScheduledRoot; + } else { + if ( + highestPriorityWork === NoWork || + remainingExpirationTime < highestPriorityWork + ) { + // Update the priority, if it's higher + highestPriorityWork = remainingExpirationTime; + highestPriorityRoot = root; + } + if (root === lastScheduledRoot) { + break; + } + previousScheduledRoot = root; + root = root.nextScheduledRoot; + } + } + } + + // If the next root is the same as the previous root, this is a nested + // update. To prevent an infinite loop, increment the nested update count. + var previousFlushedRoot = nextFlushedRoot; + if ( + previousFlushedRoot !== null && + previousFlushedRoot === highestPriorityRoot + ) { + nestedUpdateCount++; + } else { + // Reset whenever we switch roots. + nestedUpdateCount = 0; + } + nextFlushedRoot = highestPriorityRoot; + nextFlushedExpirationTime = highestPriorityWork; + } + + function performAsyncWork(dl) { + performWork(NoWork, dl); + } + + function performWork(minExpirationTime, dl) { + deadline = dl; + + // Keep working on roots until there's no more work, or until the we reach + // the deadline. + findHighestPriorityRoot(); + + if (enableUserTimingAPI && deadline !== null) { + var didExpire = nextFlushedExpirationTime < recalculateCurrentTime(); + stopRequestCallbackTimer(didExpire); + } + + while ( + nextFlushedRoot !== null && + nextFlushedExpirationTime !== NoWork && + (minExpirationTime === NoWork || + nextFlushedExpirationTime <= minExpirationTime) && + !deadlineDidExpire + ) { + performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime); + // Find the next highest priority work. + findHighestPriorityRoot(); + } + + // We're done flushing work. Either we ran out of time in this callback, + // or there's no more work left with sufficient priority. + + // If we're inside a callback, set this to false since we just completed it. + if (deadline !== null) { + isCallbackScheduled = false; + } + // If there's work left over, schedule a new callback. + if (nextFlushedRoot !== null && !isCallbackScheduled) { + isCallbackScheduled = true; + startRequestCallbackTimer(); + scheduleDeferredCallback(performAsyncWork); + } + + // Clean-up. + deadline = null; + deadlineDidExpire = false; + nestedUpdateCount = 0; + + if (hasUnhandledError) { + var _error4 = unhandledError; + unhandledError = null; + hasUnhandledError = false; + throw _error4; + } + } + + function performWorkOnRoot(root, expirationTime) { + invariant( + !isRendering, + "performWorkOnRoot was called recursively. This error is likely caused " + + "by a bug in React. Please file an issue." + ); + + isRendering = true; + + // Check if this is async work or sync/expired work. + // TODO: Pass current time as argument to renderRoot, commitRoot + if (expirationTime <= recalculateCurrentTime()) { + // Flush sync work. + var finishedWork = root.finishedWork; + if (finishedWork !== null) { + // This root is already complete. We can commit it. + root.finishedWork = null; + root.remainingExpirationTime = commitRoot(finishedWork); + } else { + root.finishedWork = null; + finishedWork = renderRoot(root, expirationTime); + if (finishedWork !== null) { + // We've completed the root. Commit it. + root.remainingExpirationTime = commitRoot(finishedWork); + } + } + } else { + // Flush async work. + var _finishedWork = root.finishedWork; + if (_finishedWork !== null) { + // This root is already complete. We can commit it. + root.finishedWork = null; + root.remainingExpirationTime = commitRoot(_finishedWork); + } else { + root.finishedWork = null; + _finishedWork = renderRoot(root, expirationTime); + if (_finishedWork !== null) { + // We've completed the root. Check the deadline one more time + // before committing. + if (!shouldYield()) { + // Still time left. Commit the root. + root.remainingExpirationTime = commitRoot(_finishedWork); + } else { + // There's no time left. Mark this root as complete. We'll come + // back and commit it later. + root.finishedWork = _finishedWork; + } + } + } + } + + isRendering = false; + } + + // When working on async work, the reconciler asks the renderer if it should + // yield execution. For DOM, we implement this with requestIdleCallback. + function shouldYield() { + if (deadline === null) { + return false; + } + if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) { + return false; + } + deadlineDidExpire = true; + return true; + } + + // TODO: Not happy about this hook. Conceptually, renderRoot should return a + // tuple of (isReadyForCommit, didError, error) + function onUncaughtError(error) { + invariant( + nextFlushedRoot !== null, + "Should be working on a root. This error is likely caused by a bug in " + + "React. Please file an issue." + ); + // Unschedule this root so we don't work on it again until there's + // another update. + nextFlushedRoot.remainingExpirationTime = NoWork; + if (!hasUnhandledError) { + hasUnhandledError = true; + unhandledError = error; + } + } + + // TODO: Batching should be implemented at the renderer level, not inside + // the reconciler. + function batchedUpdates(fn, a) { + var previousIsBatchingUpdates = isBatchingUpdates; + isBatchingUpdates = true; + try { + return fn(a); + } finally { + isBatchingUpdates = previousIsBatchingUpdates; + if (!isBatchingUpdates && !isRendering) { + performWork(Sync, null); + } + } + } + + // TODO: Batching should be implemented at the renderer level, not inside + // the reconciler. + function unbatchedUpdates(fn) { + if (isBatchingUpdates && !isUnbatchingUpdates) { + isUnbatchingUpdates = true; + try { + return fn(); + } finally { + isUnbatchingUpdates = false; + } + } + return fn(); + } + + // TODO: Batching should be implemented at the renderer level, not within + // the reconciler. + function flushSync(fn) { + var previousIsBatchingUpdates = isBatchingUpdates; + isBatchingUpdates = true; + try { + return syncUpdates(fn); + } finally { + isBatchingUpdates = previousIsBatchingUpdates; + invariant( + !isRendering, + "flushSync was called from inside a lifecycle method. It cannot be " + + "called when React is already rendering." + ); + performWork(Sync, null); + } + } + + return { + computeAsyncExpiration: computeAsyncExpiration, + computeExpirationForFiber: computeExpirationForFiber, + scheduleWork: scheduleWork, + batchedUpdates: batchedUpdates, + unbatchedUpdates: unbatchedUpdates, + flushSync: flushSync, + deferredUpdates: deferredUpdates + }; +}; + +{ + var didWarnAboutNestedUpdates = false; +} + +// 0 is PROD, 1 is DEV. +// Might add PROFILE later. + +function getContextForSubtree(parentComponent) { + if (!parentComponent) { + return emptyObject; + } + + var fiber = get(parentComponent); + var parentContext = findCurrentUnmaskedContext(fiber); + return isContextProvider(fiber) + ? processChildContext(fiber, parentContext) + : parentContext; +} + +var ReactFiberReconciler$1 = function(config) { + var getPublicInstance = config.getPublicInstance; + + var _ReactFiberScheduler = ReactFiberScheduler(config), + computeAsyncExpiration = _ReactFiberScheduler.computeAsyncExpiration, + computeExpirationForFiber = _ReactFiberScheduler.computeExpirationForFiber, + scheduleWork = _ReactFiberScheduler.scheduleWork, + batchedUpdates = _ReactFiberScheduler.batchedUpdates, + unbatchedUpdates = _ReactFiberScheduler.unbatchedUpdates, + flushSync = _ReactFiberScheduler.flushSync, + deferredUpdates = _ReactFiberScheduler.deferredUpdates; + + function scheduleTopLevelUpdate(current, element, callback) { + { + if ( + ReactDebugCurrentFiber.phase === "render" && + ReactDebugCurrentFiber.current !== null && + !didWarnAboutNestedUpdates + ) { + didWarnAboutNestedUpdates = true; + warning( + false, + "Render methods should be a pure function of props and state; " + + "triggering nested component updates from render is not allowed. " + + "If necessary, trigger nested updates in componentDidUpdate.\n\n" + + "Check the render method of %s.", + getComponentName(ReactDebugCurrentFiber.current) || "Unknown" + ); + } + } + + callback = callback === undefined ? null : callback; + { + warning( + callback === null || typeof callback === "function", + "render(...): Expected the last optional `callback` argument to be a " + + "function. Instead received: %s.", + callback + ); + } + + var expirationTime = void 0; + // Check if the top-level element is an async wrapper component. If so, + // treat updates to the root as async. This is a bit weird but lets us + // avoid a separate `renderAsync` API. + if ( + enableAsyncSubtreeAPI && + element != null && + element.type != null && + element.type.prototype != null && + element.type.prototype.unstable_isAsyncReactComponent === true + ) { + expirationTime = computeAsyncExpiration(); + } else { + expirationTime = computeExpirationForFiber(current); + } + + var update = { + expirationTime: expirationTime, + partialState: { element: element }, + callback: callback, + isReplace: false, + isForced: false, + nextCallback: null, + next: null + }; + insertUpdateIntoFiber(current, update); + scheduleWork(current, expirationTime); + } + + function findHostInstance(fiber) { + var hostFiber = findCurrentHostFiber(fiber); + if (hostFiber === null) { + return null; + } + return hostFiber.stateNode; + } + + return { + createContainer: function(containerInfo, hydrate) { + return createFiberRoot(containerInfo, hydrate); + }, + updateContainer: function(element, container, parentComponent, callback) { + // TODO: If this is a nested container, this won't be the root. + var current = container.current; + + { + if (ReactFiberInstrumentation_1.debugTool) { + if (current.alternate === null) { + ReactFiberInstrumentation_1.debugTool.onMountContainer(container); + } else if (element === null) { + ReactFiberInstrumentation_1.debugTool.onUnmountContainer(container); + } else { + ReactFiberInstrumentation_1.debugTool.onUpdateContainer(container); + } + } + } + + var context = getContextForSubtree(parentComponent); + if (container.context === null) { + container.context = context; + } else { + container.pendingContext = context; + } + + scheduleTopLevelUpdate(current, element, callback); + }, + + batchedUpdates: batchedUpdates, + + unbatchedUpdates: unbatchedUpdates, + + deferredUpdates: deferredUpdates, + + flushSync: flushSync, + + getPublicRootInstance: function(container) { + var containerFiber = container.current; + if (!containerFiber.child) { + return null; + } + switch (containerFiber.child.tag) { + case HostComponent: + return getPublicInstance(containerFiber.child.stateNode); + default: + return containerFiber.child.stateNode; + } + }, + + findHostInstance: findHostInstance, + + findHostInstanceWithNoPortals: function(fiber) { + var hostFiber = findCurrentHostFiberWithNoPortals(fiber); + if (hostFiber === null) { + return null; + } + return hostFiber.stateNode; + }, + injectIntoDevTools: function(devToolsConfig) { + var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; + + return injectInternals( + Object.assign({}, devToolsConfig, { + findHostInstanceByFiber: function(fiber) { + return findHostInstance(fiber); + }, + findFiberByHostInstance: function(instance) { + if (!findFiberByHostInstance) { + // Might not be implemented by the renderer. + return null; + } + return findFiberByHostInstance(instance); + } + }) + ); + } + }; +}; + +var ReactFiberReconciler$2 = Object.freeze({ + default: ReactFiberReconciler$1 +}); + +var ReactFiberReconciler$3 = + (ReactFiberReconciler$2 && ReactFiberReconciler$1) || ReactFiberReconciler$2; + +// TODO: bundle Flow types with the package. + +// TODO: decide on the top-level export form. +// This is hacky but makes it work with both Rollup and Jest. +var reactReconciler = ReactFiberReconciler$3["default"] + ? ReactFiberReconciler$3["default"] + : ReactFiberReconciler$3; + +var viewConfigCallbacks = new Map(); +var viewConfigs = new Map(); + +/** + * Registers a native view/component by name. + * A callback is provided to load the view config from UIManager. + * The callback is deferred until the view is actually rendered. + * This is done to avoid causing Prepack deopts. + */ +function register(name, callback) { + invariant( + !viewConfigCallbacks.has(name), + "Tried to register two views with the same name %s", + name + ); + viewConfigCallbacks.set(name, callback); + return name; +} + +/** + * Retrieves a config for the specified view. + * If this is the first time the view has been used, + * This configuration will be lazy-loaded from UIManager. + */ +function get$1(name) { + var viewConfig = void 0; + if (!viewConfigs.has(name)) { + var callback = viewConfigCallbacks.get(name); + invariant( + typeof callback === "function", + "View config not found for name %s", + name + ); + viewConfigCallbacks.set(name, null); + viewConfig = callback(); + viewConfigs.set(name, viewConfig); + } else { + viewConfig = viewConfigs.get(name); + } + invariant(viewConfig, "View config not found for name %s", name); + return viewConfig; +} + +function _classCallCheck$1(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} + +// Modules provided by RN: +/** + * This component defines the same methods as NativeMethodsMixin but without the + * findNodeHandle wrapper. This wrapper is unnecessary for HostComponent views + * and would also result in a circular require.js dependency (since + * ReactNativeFiber depends on this component and NativeMethodsMixin depends on + * ReactNativeFiber). + */ + +var ReactNativeFiberHostComponent = (function() { + function ReactNativeFiberHostComponent(tag, viewConfig) { + _classCallCheck$1(this, ReactNativeFiberHostComponent); + + this._nativeTag = tag; + this._children = []; + this.viewConfig = viewConfig; + } + + ReactNativeFiberHostComponent.prototype.blur = function blur() { + TextInputState.blurTextInput(this._nativeTag); + }; + + ReactNativeFiberHostComponent.prototype.focus = function focus() { + TextInputState.focusTextInput(this._nativeTag); + }; + + ReactNativeFiberHostComponent.prototype.measure = function measure(callback) { + UIManager.measure(this._nativeTag, mountSafeCallback(this, callback)); + }; + + ReactNativeFiberHostComponent.prototype.measureInWindow = function measureInWindow( + callback + ) { + UIManager.measureInWindow( + this._nativeTag, + mountSafeCallback(this, callback) + ); + }; + + ReactNativeFiberHostComponent.prototype.measureLayout = function measureLayout( + relativeToNativeNode, + onSuccess, + onFail /* currently unused */ + ) { + UIManager.measureLayout( + this._nativeTag, + relativeToNativeNode, + mountSafeCallback(this, onFail), + mountSafeCallback(this, onSuccess) + ); + }; + + ReactNativeFiberHostComponent.prototype.setNativeProps = function setNativeProps( + nativeProps + ) { + { + warnForStyleProps(nativeProps, this.viewConfig.validAttributes); + } + + var updatePayload = create(nativeProps, this.viewConfig.validAttributes); + + // Avoid the overhead of bridge calls if there's no update. + // This is an expensive no-op for Android, and causes an unnecessary + // view invalidation for certain components (eg RCTTextInput) on iOS. + if (updatePayload != null) { + UIManager.updateView( + this._nativeTag, + this.viewConfig.uiViewClassName, + updatePayload + ); + } + }; + + return ReactNativeFiberHostComponent; +})(); + +// eslint-disable-next-line no-unused-expressions + +ReactNativeFiberHostComponent.prototype; + +var hasNativePerformanceNow = + typeof performance === "object" && typeof performance.now === "function"; + +var now = hasNativePerformanceNow + ? function() { + return performance.now(); + } + : function() { + return Date.now(); + }; + +var isCallbackScheduled = false; +var scheduledCallback = null; +var frameDeadline = 0; + +var frameDeadlineObject = { + timeRemaining: function() { + return frameDeadline - now(); + } +}; + +function setTimeoutCallback() { + isCallbackScheduled = false; + + // TODO (bvaughn) Hard-coded 5ms unblocks initial async testing. + // React API probably changing to boolean rather than time remaining. + // Longer-term plan is to rewrite this using shared memory, + // And just return the value of the bit as the boolean. + frameDeadline = now() + 5; + + var callback = scheduledCallback; + scheduledCallback = null; + if (callback !== null) { + callback(frameDeadlineObject); + } +} + +// RN has a poor polyfill for requestIdleCallback so we aren't using it. +// This implementation is only intended for short-term use anyway. +// We also don't implement cancel functionality b'c Fiber doesn't currently need it. +function scheduleDeferredCallback(callback) { + // We assume only one callback is scheduled at a time b'c that's how Fiber works. + scheduledCallback = callback; + + if (!isCallbackScheduled) { + isCallbackScheduled = true; + setTimeout(setTimeoutCallback, 1); + } + + return 0; +} + +// Modules provided by RN: +function recursivelyUncacheFiberNode(node) { + if (typeof node === "number") { + // Leaf node (eg text) + uncacheFiberNode(node); + } else { + uncacheFiberNode(node._nativeTag); + + node._children.forEach(recursivelyUncacheFiberNode); + } +} + +var NativeRenderer = reactReconciler({ + appendInitialChild: function(parentInstance, child) { + parentInstance._children.push(child); + }, + createInstance: function( + type, + props, + rootContainerInstance, + hostContext, + internalInstanceHandle + ) { + var tag = ReactNativeTagHandles.allocateTag(); + var viewConfig = get$1(type); + + { + for (var key in viewConfig.validAttributes) { + if (props.hasOwnProperty(key)) { + deepFreezeAndThrowOnMutationInDev(props[key]); + } + } + } + + var updatePayload = create(props, viewConfig.validAttributes); + + UIManager.createView( + tag, // reactTag + viewConfig.uiViewClassName, // viewName + rootContainerInstance, // rootTag + updatePayload + ); + + var component = new ReactNativeFiberHostComponent(tag, viewConfig); + + precacheFiberNode(internalInstanceHandle, tag); + updateFiberProps(tag, props); + + // Not sure how to avoid this cast. Flow is okay if the component is defined + // in the same file but if it's external it can't see the types. + return component; + }, + createTextInstance: function( + text, + rootContainerInstance, + hostContext, + internalInstanceHandle + ) { + var tag = ReactNativeTagHandles.allocateTag(); + + UIManager.createView( + tag, // reactTag + "RCTRawText", // viewName + rootContainerInstance, // rootTag + { text: text } + ); + + precacheFiberNode(internalInstanceHandle, tag); + + return tag; + }, + finalizeInitialChildren: function( + parentInstance, + type, + props, + rootContainerInstance + ) { + // Don't send a no-op message over the bridge. + if (parentInstance._children.length === 0) { + return false; + } + + // Map from child objects to native tags. + // Either way we need to pass a copy of the Array to prevent it from being frozen. + var nativeTags = parentInstance._children.map(function(child) { + return typeof child === "number" + ? child // Leaf node (eg text) + : child._nativeTag; + }); + + UIManager.setChildren( + parentInstance._nativeTag, // containerTag + nativeTags + ); + + return false; + }, + getRootHostContext: function() { + return emptyObject; + }, + getChildHostContext: function() { + return emptyObject; + }, + getPublicInstance: function(instance) { + return instance; + }, + + now: now, + + prepareForCommit: function() { + // Noop + }, + prepareUpdate: function( + instance, + type, + oldProps, + newProps, + rootContainerInstance, + hostContext + ) { + return emptyObject; + }, + resetAfterCommit: function() { + // Noop + }, + + scheduleDeferredCallback: scheduleDeferredCallback, + + shouldDeprioritizeSubtree: function(type, props) { + return false; + }, + shouldSetTextContent: function(type, props) { + // TODO (bvaughn) Revisit this decision. + // Always returning false simplifies the createInstance() implementation, + // But creates an additional child Fiber for raw text children. + // No additional native views are created though. + // It's not clear to me which is better so I'm deferring for now. + // More context @ github.com/facebook/react/pull/8560#discussion_r92111303 + return false; + }, + + useSyncScheduling: true, + + mutation: { + appendChild: function(parentInstance, child) { + var childTag = typeof child === "number" ? child : child._nativeTag; + var children = parentInstance._children; + var index = children.indexOf(child); + + if (index >= 0) { + children.splice(index, 1); + children.push(child); + + UIManager.manageChildren( + parentInstance._nativeTag, // containerTag + [index], // moveFromIndices + [children.length - 1], // moveToIndices + [], // addChildReactTags + [], // addAtIndices + [] + ); + } else { + children.push(child); + + UIManager.manageChildren( + parentInstance._nativeTag, // containerTag + [], // moveFromIndices + [], // moveToIndices + [childTag], // addChildReactTags + [children.length - 1], // addAtIndices + [] + ); + } + }, + appendChildToContainer: function(parentInstance, child) { + var childTag = typeof child === "number" ? child : child._nativeTag; + UIManager.setChildren( + parentInstance, // containerTag + [childTag] + ); + }, + commitTextUpdate: function(textInstance, oldText, newText) { + UIManager.updateView( + textInstance, // reactTag + "RCTRawText", // viewName + { text: newText } + ); + }, + commitMount: function(instance, type, newProps, internalInstanceHandle) { + // Noop + }, + commitUpdate: function( + instance, + updatePayloadTODO, + type, + oldProps, + newProps, + internalInstanceHandle + ) { + var viewConfig = instance.viewConfig; + + updateFiberProps(instance._nativeTag, newProps); + + var updatePayload = diff(oldProps, newProps, viewConfig.validAttributes); + + // Avoid the overhead of bridge calls if there's no update. + // This is an expensive no-op for Android, and causes an unnecessary + // view invalidation for certain components (eg RCTTextInput) on iOS. + if (updatePayload != null) { + UIManager.updateView( + instance._nativeTag, // reactTag + viewConfig.uiViewClassName, // viewName + updatePayload + ); + } + }, + insertBefore: function(parentInstance, child, beforeChild) { + var children = parentInstance._children; + var index = children.indexOf(child); + + // Move existing child or add new child? + if (index >= 0) { + children.splice(index, 1); + var beforeChildIndex = children.indexOf(beforeChild); + children.splice(beforeChildIndex, 0, child); + + UIManager.manageChildren( + parentInstance._nativeTag, // containerID + [index], // moveFromIndices + [beforeChildIndex], // moveToIndices + [], // addChildReactTags + [], // addAtIndices + [] + ); + } else { + var _beforeChildIndex = children.indexOf(beforeChild); + children.splice(_beforeChildIndex, 0, child); + + var childTag = typeof child === "number" ? child : child._nativeTag; + + UIManager.manageChildren( + parentInstance._nativeTag, // containerID + [], // moveFromIndices + [], // moveToIndices + [childTag], // addChildReactTags + [_beforeChildIndex], // addAtIndices + [] + ); + } + }, + insertInContainerBefore: function(parentInstance, child, beforeChild) { + // TODO (bvaughn): Remove this check when... + // We create a wrapper object for the container in ReactNative render() + // Or we refactor to remove wrapper objects entirely. + // For more info on pros/cons see PR #8560 description. + invariant( + typeof parentInstance !== "number", + "Container does not support insertBefore operation" + ); + }, + removeChild: function(parentInstance, child) { + recursivelyUncacheFiberNode(child); + var children = parentInstance._children; + var index = children.indexOf(child); + + children.splice(index, 1); + + UIManager.manageChildren( + parentInstance._nativeTag, // containerID + [], // moveFromIndices + [], // moveToIndices + [], // addChildReactTags + [], // addAtIndices + [index] + ); + }, + removeChildFromContainer: function(parentInstance, child) { + recursivelyUncacheFiberNode(child); + UIManager.manageChildren( + parentInstance, // containerID + [], // moveFromIndices + [], // moveToIndices + [], // addChildReactTags + [], // addAtIndices + [0] + ); + }, + resetTextContent: function(instance) { + // Noop + } + } +}); + +/** + * ReactNative vs ReactWeb + * ----------------------- + * React treats some pieces of data opaquely. This means that the information + * is first class (it can be passed around), but cannot be inspected. This + * allows us to build infrastructure that reasons about resources, without + * making assumptions about the nature of those resources, and this allows that + * infra to be shared across multiple platforms, where the resources are very + * different. General infra (such as `ReactMultiChild`) reasons opaquely about + * the data, but platform specific code (such as `ReactNativeBaseComponent`) can + * make assumptions about the data. + * + * + * `rootNodeID`, uniquely identifies a position in the generated native view + * tree. Many layers of composite components (created with `React.createClass`) + * can all share the same `rootNodeID`. + * + * `nodeHandle`: A sufficiently unambiguous way to refer to a lower level + * resource (dom node, native view etc). The `rootNodeID` is sufficient for web + * `nodeHandle`s, because the position in a tree is always enough to uniquely + * identify a DOM node (we never have nodes in some bank outside of the + * document). The same would be true for `ReactNative`, but we must maintain a + * mapping that we can send efficiently serializable + * strings across native boundaries. + * + * Opaque name TodaysWebReact FutureWebWorkerReact ReactNative + * ---------------------------------------------------------------------------- + * nodeHandle N/A rootNodeID tag + */ + +// TODO (bvaughn) Rename the findNodeHandle module to something more descriptive +// eg findInternalHostInstance. This will reduce the likelihood of someone +// accidentally deep-requiring this version. +function findNodeHandle(componentOrHandle) { + { + var owner = ReactCurrentOwner.current; + if (owner !== null && owner.stateNode !== null) { + warning( + owner.stateNode._warnedAboutRefsInRender, + "%s is accessing findNodeHandle inside its render(). " + + "render() should be a pure function of props and state. It should " + + "never access something that requires stale data from the previous " + + "render, such as refs. Move this logic to componentDidMount and " + + "componentDidUpdate instead.", + getComponentName(owner) || "A component" + ); + + owner.stateNode._warnedAboutRefsInRender = true; + } + } + if (componentOrHandle == null) { + return null; + } + if (typeof componentOrHandle === "number") { + // Already a node handle + return componentOrHandle; + } + + var component = componentOrHandle; + + // TODO (balpert): Wrap iOS native components in a composite wrapper, then + // ReactInstanceMap.get here will always succeed for mounted components + var internalInstance = get(component); + if (internalInstance) { + return NativeRenderer.findHostInstance(internalInstance); + } else { + if (component) { + return component; + } else { + invariant( + // Native + (typeof component === "object" && "_nativeTag" in component) || + // Composite + (component.render != null && typeof component.render === "function"), + "findNodeHandle(...): Argument is not a component " + + "(type: %s, keys: %s)", + typeof component, + Object.keys(component) + ); + invariant( + false, + "findNodeHandle(...): Unable to find node handle for unmounted " + + "component." + ); + } + } +} + +/** + * External users of findNodeHandle() expect the host tag number return type. + * The injected findNodeHandle() strategy returns the instance wrapper though. + * See NativeMethodsMixin#setNativeProps for more info on why this is done. + */ +function findNumericNodeHandleFiber(componentOrHandle) { + var instance = findNodeHandle(componentOrHandle); + if (instance == null || typeof instance === "number") { + return instance; + } + return instance._nativeTag; +} + +// Modules provided by RN: +/** + * `NativeMethodsMixin` provides methods to access the underlying native + * component directly. This can be useful in cases when you want to focus + * a view or measure its on-screen dimensions, for example. + * + * The methods described here are available on most of the default components + * provided by React Native. Note, however, that they are *not* available on + * composite components that aren't directly backed by a native view. This will + * generally include most components that you define in your own app. For more + * information, see [Direct + * Manipulation](docs/direct-manipulation.html). + * + * Note the Flow $Exact<> syntax is required to support mixins. + * React createClass mixins can only be used with exact types. + */ +var NativeMethodsMixin = { + /** + * Determines the location on screen, width, and height of the given view and + * returns the values via an async callback. If successful, the callback will + * be called with the following arguments: + * + * - x + * - y + * - width + * - height + * - pageX + * - pageY + * + * Note that these measurements are not available until after the rendering + * has been completed in native. If you need the measurements as soon as + * possible, consider using the [`onLayout` + * prop](docs/view.html#onlayout) instead. + */ + measure: function(callback) { + UIManager.measure( + findNumericNodeHandleFiber(this), + mountSafeCallback(this, callback) + ); + }, + + /** + * Determines the location of the given view in the window and returns the + * values via an async callback. If the React root view is embedded in + * another native view, this will give you the absolute coordinates. If + * successful, the callback will be called with the following + * arguments: + * + * - x + * - y + * - width + * - height + * + * Note that these measurements are not available until after the rendering + * has been completed in native. + */ + measureInWindow: function(callback) { + UIManager.measureInWindow( + findNumericNodeHandleFiber(this), + mountSafeCallback(this, callback) + ); + }, + + /** + * Like [`measure()`](#measure), but measures the view relative an ancestor, + * specified as `relativeToNativeNode`. This means that the returned x, y + * are relative to the origin x, y of the ancestor view. + * + * As always, to obtain a native node handle for a component, you can use + * `findNumericNodeHandle(component)`. + */ + measureLayout: function( + relativeToNativeNode, + onSuccess, + onFail /* currently unused */ + ) { + UIManager.measureLayout( + findNumericNodeHandleFiber(this), + relativeToNativeNode, + mountSafeCallback(this, onFail), + mountSafeCallback(this, onSuccess) + ); + }, + + /** + * This function sends props straight to native. They will not participate in + * future diff process - this means that if you do not include them in the + * next render, they will remain active (see [Direct + * Manipulation](docs/direct-manipulation.html)). + */ + setNativeProps: function(nativeProps) { + // Class components don't have viewConfig -> validateAttributes. + // Nor does it make sense to set native props on a non-native component. + // Instead, find the nearest host component and set props on it. + // Use findNodeHandle() rather than findNumericNodeHandle() because + // We want the instance/wrapper (not the native tag). + var maybeInstance = void 0; + + // Fiber errors if findNodeHandle is called for an umounted component. + // Tests using ReactTestRenderer will trigger this case indirectly. + // Mimicking stack behavior, we should silently ignore this case. + // TODO Fix ReactTestRenderer so we can remove this try/catch. + try { + maybeInstance = findNodeHandle(this); + } catch (error) {} + + // If there is no host component beneath this we should fail silently. + // This is not an error; it could mean a class component rendered null. + if (maybeInstance == null) { + return; + } + + var viewConfig = maybeInstance.viewConfig; + + { + warnForStyleProps(nativeProps, viewConfig.validAttributes); + } + + var updatePayload = create(nativeProps, viewConfig.validAttributes); + + // Avoid the overhead of bridge calls if there's no update. + // This is an expensive no-op for Android, and causes an unnecessary + // view invalidation for certain components (eg RCTTextInput) on iOS. + if (updatePayload != null) { + UIManager.updateView( + maybeInstance._nativeTag, + viewConfig.uiViewClassName, + updatePayload + ); + } + }, + + /** + * Requests focus for the given input or view. The exact behavior triggered + * will depend on the platform and type of view. + */ + focus: function() { + TextInputState.focusTextInput(findNumericNodeHandleFiber(this)); + }, + + /** + * Removes focus from an input or view. This is the opposite of `focus()`. + */ + blur: function() { + TextInputState.blurTextInput(findNumericNodeHandleFiber(this)); + } +}; + +{ + // hide this from Flow since we can't define these properties outside of + // true without actually implementing them (setting them to undefined + // isn't allowed by ReactClass) + var NativeMethodsMixin_DEV = NativeMethodsMixin; + invariant( + !NativeMethodsMixin_DEV.componentWillMount && + !NativeMethodsMixin_DEV.componentWillReceiveProps, + "Do not override existing functions." + ); + NativeMethodsMixin_DEV.componentWillMount = function() { + throwOnStylesProp(this, this.props); + }; + NativeMethodsMixin_DEV.componentWillReceiveProps = function(newProps) { + throwOnStylesProp(this, newProps); + }; +} + +function _classCallCheck$2(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} + +function _possibleConstructorReturn(self, call) { + if (!self) { + throw new ReferenceError( + "this hasn't been initialised - super() hasn't been called" + ); + } + return call && (typeof call === "object" || typeof call === "function") + ? call + : self; +} + +function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError( + "Super expression must either be null or a function, not " + + typeof superClass + ); + } + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) + Object.setPrototypeOf + ? Object.setPrototypeOf(subClass, superClass) + : (subClass.__proto__ = superClass); +} + +// Modules provided by RN: +/** + * Superclass that provides methods to access the underlying native component. + * This can be useful when you want to focus a view or measure its dimensions. + * + * Methods implemented by this class are available on most default components + * provided by React Native. However, they are *not* available on composite + * components that are not directly backed by a native view. For more + * information, see [Direct Manipulation](docs/direct-manipulation.html). + * + * @abstract + */ + +var ReactNativeComponent = (function(_React$Component) { + _inherits(ReactNativeComponent, _React$Component); + + function ReactNativeComponent() { + _classCallCheck$2(this, ReactNativeComponent); + + return _possibleConstructorReturn( + this, + _React$Component.apply(this, arguments) + ); + } + + /** + * Removes focus. This is the opposite of `focus()`. + */ + ReactNativeComponent.prototype.blur = function blur() { + TextInputState.blurTextInput(findNumericNodeHandleFiber(this)); + }; + + /** + * Requests focus. The exact behavior depends on the platform and view. + */ + + ReactNativeComponent.prototype.focus = function focus() { + TextInputState.focusTextInput(findNumericNodeHandleFiber(this)); + }; + + /** + * Measures the on-screen location and dimensions. If successful, the callback + * will be called asynchronously with the following arguments: + * + * - x + * - y + * - width + * - height + * - pageX + * - pageY + * + * These values are not available until after natives rendering completes. If + * you need the measurements as soon as possible, consider using the + * [`onLayout` prop](docs/view.html#onlayout) instead. + */ + + ReactNativeComponent.prototype.measure = function measure(callback) { + UIManager.measure( + findNumericNodeHandleFiber(this), + mountSafeCallback(this, callback) + ); + }; + + /** + * Measures the on-screen location and dimensions. Even if the React Native + * root view is embedded within another native view, this method will give you + * the absolute coordinates measured from the window. If successful, the + * callback will be called asynchronously with the following arguments: + * + * - x + * - y + * - width + * - height + * + * These values are not available until after natives rendering completes. + */ + + ReactNativeComponent.prototype.measureInWindow = function measureInWindow( + callback + ) { + UIManager.measureInWindow( + findNumericNodeHandleFiber(this), + mountSafeCallback(this, callback) + ); + }; + + /** + * Similar to [`measure()`](#measure), but the resulting location will be + * relative to the supplied ancestor's location. + * + * Obtain a native node handle with `ReactNative.findNodeHandle(component)`. + */ + + ReactNativeComponent.prototype.measureLayout = function measureLayout( + relativeToNativeNode, + onSuccess, + onFail /* currently unused */ + ) { + UIManager.measureLayout( + findNumericNodeHandleFiber(this), + relativeToNativeNode, + mountSafeCallback(this, onFail), + mountSafeCallback(this, onSuccess) + ); + }; + + /** + * This function sends props straight to native. They will not participate in + * future diff process - this means that if you do not include them in the + * next render, they will remain active (see [Direct + * Manipulation](docs/direct-manipulation.html)). + */ + + ReactNativeComponent.prototype.setNativeProps = function setNativeProps( + nativeProps + ) { + // Class components don't have viewConfig -> validateAttributes. + // Nor does it make sense to set native props on a non-native component. + // Instead, find the nearest host component and set props on it. + // Use findNodeHandle() rather than ReactNative.findNodeHandle() because + // We want the instance/wrapper (not the native tag). + var maybeInstance = void 0; + + // Fiber errors if findNodeHandle is called for an umounted component. + // Tests using ReactTestRenderer will trigger this case indirectly. + // Mimicking stack behavior, we should silently ignore this case. + // TODO Fix ReactTestRenderer so we can remove this try/catch. + try { + maybeInstance = findNodeHandle(this); + } catch (error) {} + + // If there is no host component beneath this we should fail silently. + // This is not an error; it could mean a class component rendered null. + if (maybeInstance == null) { + return; + } + + var viewConfig = maybeInstance.viewConfig; + + var updatePayload = create(nativeProps, viewConfig.validAttributes); + + // Avoid the overhead of bridge calls if there's no update. + // This is an expensive no-op for Android, and causes an unnecessary + // view invalidation for certain components (eg RCTTextInput) on iOS. + if (updatePayload != null) { + UIManager.updateView( + maybeInstance._nativeTag, + viewConfig.uiViewClassName, + updatePayload + ); + } + }; + + return ReactNativeComponent; +})(React.Component); + +// eslint-disable-next-line no-unused-expressions + +ReactNativeComponent.prototype; + +// Module provided by RN: +var getInspectorDataForViewTag = void 0; + +{ + var traverseOwnerTreeUp = function(hierarchy, instance) { + if (instance) { + hierarchy.unshift(instance); + traverseOwnerTreeUp(hierarchy, instance._debugOwner); + } + }; + + var getOwnerHierarchy = function(instance) { + var hierarchy = []; + traverseOwnerTreeUp(hierarchy, instance); + return hierarchy; + }; + + var lastNonHostInstance = function(hierarchy) { + for (var i = hierarchy.length - 1; i > 1; i--) { + var instance = hierarchy[i]; + + if (instance.tag !== HostComponent) { + return instance; + } + } + return hierarchy[0]; + }; + + var getHostProps = function(fiber) { + var host = findCurrentHostFiber(fiber); + if (host) { + return host.memoizedProps || emptyObject; + } + return emptyObject; + }; + + var getHostNode = function(fiber, findNodeHandle) { + var hostNode = void 0; + // look for children first for the hostNode + // as composite fibers do not have a hostNode + while (fiber) { + if (fiber.stateNode !== null && fiber.tag === HostComponent) { + hostNode = findNodeHandle(fiber.stateNode); + } + if (hostNode) { + return hostNode; + } + fiber = fiber.child; + } + return null; + }; + + var createHierarchy = function(fiberHierarchy) { + return fiberHierarchy.map(function(fiber) { + return { + name: getComponentName(fiber), + getInspectorData: function(findNodeHandle) { + return { + measure: function(callback) { + return UIManager.measure( + getHostNode(fiber, findNodeHandle), + callback + ); + }, + props: getHostProps(fiber), + source: fiber._debugSource + }; + } + }; + }); + }; + + getInspectorDataForViewTag = function(viewTag) { + var closestInstance = getInstanceFromTag(viewTag); + + // Handle case where user clicks outside of ReactNative + if (!closestInstance) { + return { + hierarchy: [], + props: emptyObject, + selection: null, + source: null + }; + } + + var fiber = findCurrentFiberUsingSlowPath(closestInstance); + var fiberHierarchy = getOwnerHierarchy(fiber); + var instance = lastNonHostInstance(fiberHierarchy); + var hierarchy = createHierarchy(fiberHierarchy); + var props = getHostProps(instance); + var source = instance._debugSource; + var selection = fiberHierarchy.indexOf(instance); + + return { + hierarchy: hierarchy, + props: props, + selection: selection, + source: source + }; + }; +} + +/** + * Creates a renderable ReactNative host component. + * Use this method for view configs that are loaded from UIManager. + * Use createReactNativeComponentClass() for view configs defined within JavaScript. + * + * @param {string} config iOS View configuration. + * @private + */ +var createReactNativeComponentClass = function(name, callback) { + return register(name, callback); +}; + +// Module provided by RN: +/** + * Capture an image of the screen, window or an individual view. The image + * will be stored in a temporary file that will only exist for as long as the + * app is running. + * + * The `view` argument can be the literal string `window` if you want to + * capture the entire window, or it can be a reference to a specific + * React Native component. + * + * The `options` argument may include: + * - width/height (number) - the width and height of the image to capture. + * - format (string) - either 'png' or 'jpeg'. Defaults to 'png'. + * - quality (number) - the quality when using jpeg. 0.0 - 1.0 (default). + * + * Returns a Promise. + * @platform ios + */ +function takeSnapshot(view, options) { + if (typeof view !== "number" && view !== "window") { + view = findNumericNodeHandleFiber(view) || "window"; + } + + // Call the hidden '__takeSnapshot' method; the main one throws an error to + // prevent accidental backwards-incompatible usage. + return UIManager.__takeSnapshot(view, options); +} + +// TODO: direct imports like some-package/src/* are bad. Fix me. +// Module provided by RN: +injection$2.injectFiberBatchedUpdates(NativeRenderer.batchedUpdates); + +var roots = new Map(); + +// Intercept lifecycle errors and ensure they are shown with the correct stack +// trace within the native redbox component. +injection$4.injectDialog(showDialog$1); + +var ReactNativeRenderer = { + NativeComponent: ReactNativeComponent, + + findNodeHandle: findNumericNodeHandleFiber, + + render: function(element, containerTag, callback) { + var root = roots.get(containerTag); + + if (!root) { + // TODO (bvaughn): If we decide to keep the wrapper component, + // We could create a wrapper for containerTag as well to reduce special casing. + root = NativeRenderer.createContainer(containerTag, false); + roots.set(containerTag, root); + } + NativeRenderer.updateContainer(element, root, null, callback); + + return NativeRenderer.getPublicRootInstance(root); + }, + unmountComponentAtNode: function(containerTag) { + var root = roots.get(containerTag); + if (root) { + // TODO: Is it safe to reset this now or should I wait since this unmount could be deferred? + NativeRenderer.updateContainer(null, root, null, function() { + roots["delete"](containerTag); + }); + } + }, + unmountComponentAtNodeAndRemoveContainer: function(containerTag) { + ReactNativeRenderer.unmountComponentAtNode(containerTag); + + // Call back into native to remove all of the subviews from this container + UIManager.removeRootView(containerTag); + }, + createPortal: function(children, containerTag) { + var key = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + + return createPortal(children, containerTag, null, key); + }, + + unstable_batchedUpdates: batchedUpdates, + + flushSync: NativeRenderer.flushSync, + + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: { + // Used as a mixin in many createClass-based components + NativeMethodsMixin: NativeMethodsMixin, + // Used by react-native-github/Libraries/ components + ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin, // requireNativeComponent + ReactGlobalSharedState: ReactGlobalSharedState, // Systrace + ReactNativeComponentTree: ReactNativeComponentTree, // InspectorUtils, ScrollResponder + ReactNativePropRegistry: ReactNativePropRegistry, // flattenStyle, Stylesheet + TouchHistoryMath: TouchHistoryMath, // PanResponder + createReactNativeComponentClass: createReactNativeComponentClass, // RCTText, RCTView, ReactNativeART + takeSnapshot: takeSnapshot + } +}; + +{ + // $FlowFixMe + Object.assign( + ReactNativeRenderer.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + { + // TODO: none of these work since Fiber. Remove these dependencies. + // Used by RCTRenderingPerf, Systrace: + ReactDebugTool: { + addHook: function() {}, + removeHook: function() {} + }, + // Used by ReactPerfStallHandler, RCTRenderingPerf: + ReactPerf: { + start: function() {}, + stop: function() {}, + printInclusive: function() {}, + printWasted: function() {} + } + } + ); +} + +NativeRenderer.injectIntoDevTools({ + findFiberByHostInstance: getInstanceFromTag, + getInspectorDataForViewTag: getInspectorDataForViewTag, + bundleType: 1, + version: ReactVersion, + rendererPackageName: "react-native-renderer" +}); + +var ReactNativeRenderer$2 = Object.freeze({ + default: ReactNativeRenderer +}); + +var ReactNativeRenderer$3 = + (ReactNativeRenderer$2 && ReactNativeRenderer) || ReactNativeRenderer$2; + +// TODO: decide on the top-level export form. +// This is hacky but makes it work with both Rollup and Jest. +var reactNativeRenderer = ReactNativeRenderer$3["default"] + ? ReactNativeRenderer$3["default"] + : ReactNativeRenderer$3; + +module.exports = reactNativeRenderer; + + })(); +} diff --git a/Libraries/Renderer/ReactNativeRenderer-prod.js b/Libraries/Renderer/ReactNativeRenderer-prod.js new file mode 100644 index 00000000000000..936be82520828c --- /dev/null +++ b/Libraries/Renderer/ReactNativeRenderer-prod.js @@ -0,0 +1,5806 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @noflow + * @providesModule ReactNativeRenderer-prod + * @preventMunge + */ + +"use strict"; +require("InitializeCore"); +var invariant = require("fbjs/lib/invariant"), + emptyFunction = require("fbjs/lib/emptyFunction"), + RCTEventEmitter = require("RCTEventEmitter"), + UIManager = require("UIManager"), + React = require("react"), + ExceptionsManager = require("ExceptionsManager"), + TextInputState = require("TextInputState"), + deepDiffer = require("deepDiffer"), + flattenStyle = require("flattenStyle"), + emptyObject = require("fbjs/lib/emptyObject"), + shallowEqual = require("fbjs/lib/shallowEqual"), + ReactErrorUtils = { + _caughtError: null, + _hasCaughtError: !1, + _rethrowError: null, + _hasRethrowError: !1, + injection: { + injectErrorUtils: function(injectedErrorUtils) { + invariant( + "function" === typeof injectedErrorUtils.invokeGuardedCallback, + "Injected invokeGuardedCallback() must be a function." + ); + invokeGuardedCallback = injectedErrorUtils.invokeGuardedCallback; + } + }, + invokeGuardedCallback: function(name, func, context, a, b, c, d, e, f) { + invokeGuardedCallback.apply(ReactErrorUtils, arguments); + }, + invokeGuardedCallbackAndCatchFirstError: function( + name, + func, + context, + a, + b, + c, + d, + e, + f + ) { + ReactErrorUtils.invokeGuardedCallback.apply(this, arguments); + if (ReactErrorUtils.hasCaughtError()) { + var error = ReactErrorUtils.clearCaughtError(); + ReactErrorUtils._hasRethrowError || + ((ReactErrorUtils._hasRethrowError = !0), + (ReactErrorUtils._rethrowError = error)); + } + }, + rethrowCaughtError: function() { + return rethrowCaughtError.apply(ReactErrorUtils, arguments); + }, + hasCaughtError: function() { + return ReactErrorUtils._hasCaughtError; + }, + clearCaughtError: function() { + if (ReactErrorUtils._hasCaughtError) { + var error = ReactErrorUtils._caughtError; + ReactErrorUtils._caughtError = null; + ReactErrorUtils._hasCaughtError = !1; + return error; + } + invariant( + !1, + "clearCaughtError was called but no error was captured. This error is likely caused by a bug in React. Please file an issue." + ); + } + }; +function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) { + ReactErrorUtils._hasCaughtError = !1; + ReactErrorUtils._caughtError = null; + var funcArgs = Array.prototype.slice.call(arguments, 3); + try { + func.apply(context, funcArgs); + } catch (error) { + (ReactErrorUtils._caughtError = error), + (ReactErrorUtils._hasCaughtError = !0); + } +} +function rethrowCaughtError() { + if (ReactErrorUtils._hasRethrowError) { + var error = ReactErrorUtils._rethrowError; + ReactErrorUtils._rethrowError = null; + ReactErrorUtils._hasRethrowError = !1; + throw error; + } +} +var eventPluginOrder = null, + namesToPlugins = {}; +function recomputePluginOrdering() { + if (eventPluginOrder) + for (var pluginName in namesToPlugins) { + var pluginModule = namesToPlugins[pluginName], + pluginIndex = eventPluginOrder.indexOf(pluginName); + invariant( + -1 < pluginIndex, + "EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `%s`.", + pluginName + ); + if (!plugins[pluginIndex]) { + invariant( + pluginModule.extractEvents, + "EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `%s` does not.", + pluginName + ); + plugins[pluginIndex] = pluginModule; + pluginIndex = pluginModule.eventTypes; + for (var eventName in pluginIndex) { + var JSCompiler_inline_result = void 0; + var dispatchConfig = pluginIndex[eventName], + pluginModule$jscomp$0 = pluginModule, + eventName$jscomp$0 = eventName; + invariant( + !eventNameDispatchConfigs.hasOwnProperty(eventName$jscomp$0), + "EventPluginHub: More than one plugin attempted to publish the same event name, `%s`.", + eventName$jscomp$0 + ); + eventNameDispatchConfigs[eventName$jscomp$0] = dispatchConfig; + var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; + if (phasedRegistrationNames) { + for (JSCompiler_inline_result in phasedRegistrationNames) + phasedRegistrationNames.hasOwnProperty( + JSCompiler_inline_result + ) && + publishRegistrationName( + phasedRegistrationNames[JSCompiler_inline_result], + pluginModule$jscomp$0, + eventName$jscomp$0 + ); + JSCompiler_inline_result = !0; + } else + dispatchConfig.registrationName + ? (publishRegistrationName( + dispatchConfig.registrationName, + pluginModule$jscomp$0, + eventName$jscomp$0 + ), + (JSCompiler_inline_result = !0)) + : (JSCompiler_inline_result = !1); + invariant( + JSCompiler_inline_result, + "EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.", + eventName, + pluginName + ); + } + } + } +} +function publishRegistrationName(registrationName, pluginModule) { + invariant( + !registrationNameModules[registrationName], + "EventPluginHub: More than one plugin attempted to publish the same registration name, `%s`.", + registrationName + ); + registrationNameModules[registrationName] = pluginModule; +} +var plugins = [], + eventNameDispatchConfigs = {}, + registrationNameModules = {}, + getFiberCurrentPropsFromNode = null, + getInstanceFromNode = null, + getNodeFromInstance = null; +function isEndish(topLevelType) { + return ( + "topMouseUp" === topLevelType || + "topTouchEnd" === topLevelType || + "topTouchCancel" === topLevelType + ); +} +function isMoveish(topLevelType) { + return "topMouseMove" === topLevelType || "topTouchMove" === topLevelType; +} +function isStartish(topLevelType) { + return "topMouseDown" === topLevelType || "topTouchStart" === topLevelType; +} +function executeDispatch(event, simulated, listener, inst) { + simulated = event.type || "unknown-event"; + event.currentTarget = getNodeFromInstance(inst); + ReactErrorUtils.invokeGuardedCallbackAndCatchFirstError( + simulated, + listener, + void 0, + event + ); + event.currentTarget = null; +} +function executeDirectDispatch(event) { + var dispatchListener = event._dispatchListeners, + dispatchInstance = event._dispatchInstances; + invariant( + !Array.isArray(dispatchListener), + "executeDirectDispatch(...): Invalid `event`." + ); + event.currentTarget = dispatchListener + ? getNodeFromInstance(dispatchInstance) + : null; + dispatchListener = dispatchListener ? dispatchListener(event) : null; + event.currentTarget = null; + event._dispatchListeners = null; + event._dispatchInstances = null; + return dispatchListener; +} +function accumulateInto(current, next) { + invariant( + null != next, + "accumulateInto(...): Accumulated items must not be null or undefined." + ); + if (null == current) return next; + if (Array.isArray(current)) { + if (Array.isArray(next)) return current.push.apply(current, next), current; + current.push(next); + return current; + } + return Array.isArray(next) ? [current].concat(next) : [current, next]; +} +function forEachAccumulated(arr, cb, scope) { + Array.isArray(arr) ? arr.forEach(cb, scope) : arr && cb.call(scope, arr); +} +var eventQueue = null; +function executeDispatchesAndReleaseTopLevel(e) { + if (e) { + var dispatchListeners = e._dispatchListeners, + dispatchInstances = e._dispatchInstances; + if (Array.isArray(dispatchListeners)) + for ( + var i = 0; + i < dispatchListeners.length && !e.isPropagationStopped(); + i++ + ) + executeDispatch(e, !1, dispatchListeners[i], dispatchInstances[i]); + else + dispatchListeners && + executeDispatch(e, !1, dispatchListeners, dispatchInstances); + e._dispatchListeners = null; + e._dispatchInstances = null; + e.isPersistent() || e.constructor.release(e); + } +} +var injection = { + injectEventPluginOrder: function(injectedEventPluginOrder) { + invariant( + !eventPluginOrder, + "EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React." + ); + eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder); + recomputePluginOrdering(); + }, + injectEventPluginsByName: function(injectedNamesToPlugins) { + var isOrderingDirty = !1, + pluginName; + for (pluginName in injectedNamesToPlugins) + if (injectedNamesToPlugins.hasOwnProperty(pluginName)) { + var pluginModule = injectedNamesToPlugins[pluginName]; + (namesToPlugins.hasOwnProperty(pluginName) && + namesToPlugins[pluginName] === pluginModule) || + (invariant( + !namesToPlugins[pluginName], + "EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.", + pluginName + ), + (namesToPlugins[pluginName] = pluginModule), + (isOrderingDirty = !0)); + } + isOrderingDirty && recomputePluginOrdering(); + } +}; +function getListener(inst, registrationName) { + var listener = inst.stateNode; + if (!listener) return null; + var props = getFiberCurrentPropsFromNode(listener); + if (!props) return null; + listener = props[registrationName]; + a: switch (registrationName) { + case "onClick": + case "onClickCapture": + case "onDoubleClick": + case "onDoubleClickCapture": + case "onMouseDown": + case "onMouseDownCapture": + case "onMouseMove": + case "onMouseMoveCapture": + case "onMouseUp": + case "onMouseUpCapture": + (props = !props.disabled) || + ((inst = inst.type), + (props = !( + "button" === inst || + "input" === inst || + "select" === inst || + "textarea" === inst + ))); + inst = !props; + break a; + default: + inst = !1; + } + if (inst) return null; + invariant( + !listener || "function" === typeof listener, + "Expected `%s` listener to be a function, instead got a value of `%s` type.", + registrationName, + typeof listener + ); + return listener; +} +function getParent(inst) { + do inst = inst["return"]; + while (inst && 5 !== inst.tag); + return inst ? inst : null; +} +function traverseTwoPhase(inst, fn, arg) { + for (var path = []; inst; ) path.push(inst), (inst = getParent(inst)); + for (inst = path.length; 0 < inst--; ) fn(path[inst], "captured", arg); + for (inst = 0; inst < path.length; inst++) fn(path[inst], "bubbled", arg); +} +function accumulateDirectionalDispatches(inst, phase, event) { + if ( + (phase = getListener( + inst, + event.dispatchConfig.phasedRegistrationNames[phase] + )) + ) + (event._dispatchListeners = accumulateInto( + event._dispatchListeners, + phase + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + )); +} +function accumulateTwoPhaseDispatchesSingle(event) { + event && + event.dispatchConfig.phasedRegistrationNames && + traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); +} +function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + var targetInst = event._targetInst; + targetInst = targetInst ? getParent(targetInst) : null; + traverseTwoPhase(targetInst, accumulateDirectionalDispatches, event); + } +} +function accumulateDirectDispatchesSingle(event) { + if (event && event.dispatchConfig.registrationName) { + var inst = event._targetInst; + if (inst && event && event.dispatchConfig.registrationName) { + var listener = getListener(inst, event.dispatchConfig.registrationName); + listener && + ((event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + ))); + } + } +} +var shouldBeReleasedProperties = "dispatchConfig _targetInst nativeEvent isDefaultPrevented isPropagationStopped _dispatchListeners _dispatchInstances".split( + " " + ), + EventInterface = { + type: null, + target: null, + currentTarget: emptyFunction.thatReturnsNull, + eventPhase: null, + bubbles: null, + cancelable: null, + timeStamp: function(event) { + return event.timeStamp || Date.now(); + }, + defaultPrevented: null, + isTrusted: null + }; +function SyntheticEvent( + dispatchConfig, + targetInst, + nativeEvent, + nativeEventTarget +) { + this.dispatchConfig = dispatchConfig; + this._targetInst = targetInst; + this.nativeEvent = nativeEvent; + dispatchConfig = this.constructor.Interface; + for (var propName in dispatchConfig) + dispatchConfig.hasOwnProperty(propName) && + ((targetInst = dispatchConfig[propName]) + ? (this[propName] = targetInst(nativeEvent)) + : "target" === propName + ? (this.target = nativeEventTarget) + : (this[propName] = nativeEvent[propName])); + this.isDefaultPrevented = (null != nativeEvent.defaultPrevented + ? nativeEvent.defaultPrevented + : !1 === nativeEvent.returnValue) + ? emptyFunction.thatReturnsTrue + : emptyFunction.thatReturnsFalse; + this.isPropagationStopped = emptyFunction.thatReturnsFalse; + return this; +} +Object.assign(SyntheticEvent.prototype, { + preventDefault: function() { + this.defaultPrevented = !0; + var event = this.nativeEvent; + event && + (event.preventDefault + ? event.preventDefault() + : "unknown" !== typeof event.returnValue && (event.returnValue = !1), + (this.isDefaultPrevented = emptyFunction.thatReturnsTrue)); + }, + stopPropagation: function() { + var event = this.nativeEvent; + event && + (event.stopPropagation + ? event.stopPropagation() + : "unknown" !== typeof event.cancelBubble && (event.cancelBubble = !0), + (this.isPropagationStopped = emptyFunction.thatReturnsTrue)); + }, + persist: function() { + this.isPersistent = emptyFunction.thatReturnsTrue; + }, + isPersistent: emptyFunction.thatReturnsFalse, + destructor: function() { + var Interface = this.constructor.Interface, + propName; + for (propName in Interface) this[propName] = null; + for ( + Interface = 0; + Interface < shouldBeReleasedProperties.length; + Interface++ + ) + this[shouldBeReleasedProperties[Interface]] = null; + } +}); +SyntheticEvent.Interface = EventInterface; +SyntheticEvent.augmentClass = function(Class, Interface) { + function E() {} + E.prototype = this.prototype; + var prototype = new E(); + Object.assign(prototype, Class.prototype); + Class.prototype = prototype; + Class.prototype.constructor = Class; + Class.Interface = Object.assign({}, this.Interface, Interface); + Class.augmentClass = this.augmentClass; + addEventPoolingTo(Class); +}; +addEventPoolingTo(SyntheticEvent); +function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) { + if (this.eventPool.length) { + var instance = this.eventPool.pop(); + this.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst); + return instance; + } + return new this(dispatchConfig, targetInst, nativeEvent, nativeInst); +} +function releasePooledEvent(event) { + invariant( + event instanceof this, + "Trying to release an event instance into a pool of a different type." + ); + event.destructor(); + 10 > this.eventPool.length && this.eventPool.push(event); +} +function addEventPoolingTo(EventConstructor) { + EventConstructor.eventPool = []; + EventConstructor.getPooled = getPooledEvent; + EventConstructor.release = releasePooledEvent; +} +function ResponderSyntheticEvent( + dispatchConfig, + dispatchMarker, + nativeEvent, + nativeEventTarget +) { + return SyntheticEvent.call( + this, + dispatchConfig, + dispatchMarker, + nativeEvent, + nativeEventTarget + ); +} +SyntheticEvent.augmentClass(ResponderSyntheticEvent, { + touchHistory: function() { + return null; + } +}); +var touchBank = [], + touchHistory = { + touchBank: touchBank, + numberActiveTouches: 0, + indexOfSingleActiveTouch: -1, + mostRecentTimeStamp: 0 + }; +function timestampForTouch(touch) { + return touch.timeStamp || touch.timestamp; +} +function getTouchIdentifier(_ref) { + _ref = _ref.identifier; + invariant(null != _ref, "Touch object is missing identifier."); + return _ref; +} +function recordTouchStart(touch) { + var identifier = getTouchIdentifier(touch), + touchRecord = touchBank[identifier]; + touchRecord + ? ((touchRecord.touchActive = !0), + (touchRecord.startPageX = touch.pageX), + (touchRecord.startPageY = touch.pageY), + (touchRecord.startTimeStamp = timestampForTouch(touch)), + (touchRecord.currentPageX = touch.pageX), + (touchRecord.currentPageY = touch.pageY), + (touchRecord.currentTimeStamp = timestampForTouch(touch)), + (touchRecord.previousPageX = touch.pageX), + (touchRecord.previousPageY = touch.pageY), + (touchRecord.previousTimeStamp = timestampForTouch(touch))) + : ((touchRecord = { + touchActive: !0, + startPageX: touch.pageX, + startPageY: touch.pageY, + startTimeStamp: timestampForTouch(touch), + currentPageX: touch.pageX, + currentPageY: touch.pageY, + currentTimeStamp: timestampForTouch(touch), + previousPageX: touch.pageX, + previousPageY: touch.pageY, + previousTimeStamp: timestampForTouch(touch) + }), + (touchBank[identifier] = touchRecord)); + touchHistory.mostRecentTimeStamp = timestampForTouch(touch); +} +function recordTouchMove(touch) { + var touchRecord = touchBank[getTouchIdentifier(touch)]; + touchRecord + ? ((touchRecord.touchActive = !0), + (touchRecord.previousPageX = touchRecord.currentPageX), + (touchRecord.previousPageY = touchRecord.currentPageY), + (touchRecord.previousTimeStamp = touchRecord.currentTimeStamp), + (touchRecord.currentPageX = touch.pageX), + (touchRecord.currentPageY = touch.pageY), + (touchRecord.currentTimeStamp = timestampForTouch(touch)), + (touchHistory.mostRecentTimeStamp = timestampForTouch(touch))) + : console.error( + "Cannot record touch move without a touch start.\nTouch Move: %s\n", + "Touch Bank: %s", + printTouch(touch), + printTouchBank() + ); +} +function recordTouchEnd(touch) { + var touchRecord = touchBank[getTouchIdentifier(touch)]; + touchRecord + ? ((touchRecord.touchActive = !1), + (touchRecord.previousPageX = touchRecord.currentPageX), + (touchRecord.previousPageY = touchRecord.currentPageY), + (touchRecord.previousTimeStamp = touchRecord.currentTimeStamp), + (touchRecord.currentPageX = touch.pageX), + (touchRecord.currentPageY = touch.pageY), + (touchRecord.currentTimeStamp = timestampForTouch(touch)), + (touchHistory.mostRecentTimeStamp = timestampForTouch(touch))) + : console.error( + "Cannot record touch end without a touch start.\nTouch End: %s\n", + "Touch Bank: %s", + printTouch(touch), + printTouchBank() + ); +} +function printTouch(touch) { + return JSON.stringify({ + identifier: touch.identifier, + pageX: touch.pageX, + pageY: touch.pageY, + timestamp: timestampForTouch(touch) + }); +} +function printTouchBank() { + var printed = JSON.stringify(touchBank.slice(0, 20)); + 20 < touchBank.length && + (printed += " (original size: " + touchBank.length + ")"); + return printed; +} +var ResponderTouchHistoryStore = { + recordTouchTrack: function(topLevelType, nativeEvent) { + if (isMoveish(topLevelType)) + nativeEvent.changedTouches.forEach(recordTouchMove); + else if (isStartish(topLevelType)) + nativeEvent.changedTouches.forEach(recordTouchStart), + (touchHistory.numberActiveTouches = nativeEvent.touches.length), + 1 === touchHistory.numberActiveTouches && + (touchHistory.indexOfSingleActiveTouch = + nativeEvent.touches[0].identifier); + else if ( + isEndish(topLevelType) && + (nativeEvent.changedTouches.forEach(recordTouchEnd), + (touchHistory.numberActiveTouches = nativeEvent.touches.length), + 1 === touchHistory.numberActiveTouches) + ) + for (topLevelType = 0; topLevelType < touchBank.length; topLevelType++) + if ( + ((nativeEvent = touchBank[topLevelType]), + null != nativeEvent && nativeEvent.touchActive) + ) { + touchHistory.indexOfSingleActiveTouch = topLevelType; + break; + } + }, + touchHistory: touchHistory +}; +function accumulate(current, next) { + invariant( + null != next, + "accumulate(...): Accumulated items must be not be null or undefined." + ); + return null == current + ? next + : Array.isArray(current) + ? current.concat(next) + : Array.isArray(next) ? [current].concat(next) : [current, next]; +} +var responderInst = null, + trackedTouchCount = 0, + previousActiveTouches = 0; +function changeResponder(nextResponderInst, blockHostResponder) { + var oldResponderInst = responderInst; + responderInst = nextResponderInst; + if (null !== ResponderEventPlugin.GlobalResponderHandler) + ResponderEventPlugin.GlobalResponderHandler.onChange( + oldResponderInst, + nextResponderInst, + blockHostResponder + ); +} +var eventTypes = { + startShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onStartShouldSetResponder", + captured: "onStartShouldSetResponderCapture" + } + }, + scrollShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onScrollShouldSetResponder", + captured: "onScrollShouldSetResponderCapture" + } + }, + selectionChangeShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onSelectionChangeShouldSetResponder", + captured: "onSelectionChangeShouldSetResponderCapture" + } + }, + moveShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onMoveShouldSetResponder", + captured: "onMoveShouldSetResponderCapture" + } + }, + responderStart: { registrationName: "onResponderStart" }, + responderMove: { registrationName: "onResponderMove" }, + responderEnd: { registrationName: "onResponderEnd" }, + responderRelease: { registrationName: "onResponderRelease" }, + responderTerminationRequest: { + registrationName: "onResponderTerminationRequest" + }, + responderGrant: { registrationName: "onResponderGrant" }, + responderReject: { registrationName: "onResponderReject" }, + responderTerminate: { registrationName: "onResponderTerminate" } + }, + ResponderEventPlugin = { + _getResponder: function() { + return responderInst; + }, + eventTypes: eventTypes, + extractEvents: function( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + if (isStartish(topLevelType)) trackedTouchCount += 1; + else if (isEndish(topLevelType)) + if (0 <= trackedTouchCount) --trackedTouchCount; + else + return ( + console.error( + "Ended a touch event which was not counted in `trackedTouchCount`." + ), + null + ); + ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent); + if ( + targetInst && + (("topScroll" === topLevelType && !nativeEvent.responderIgnoreScroll) || + (0 < trackedTouchCount && "topSelectionChange" === topLevelType) || + isStartish(topLevelType) || + isMoveish(topLevelType)) + ) { + var shouldSetEventType = isStartish(topLevelType) + ? eventTypes.startShouldSetResponder + : isMoveish(topLevelType) + ? eventTypes.moveShouldSetResponder + : "topSelectionChange" === topLevelType + ? eventTypes.selectionChangeShouldSetResponder + : eventTypes.scrollShouldSetResponder; + if (responderInst) + b: { + var JSCompiler_temp = responderInst; + for ( + var depthA = 0, tempA = JSCompiler_temp; + tempA; + tempA = getParent(tempA) + ) + depthA++; + tempA = 0; + for (var tempB = targetInst; tempB; tempB = getParent(tempB)) + tempA++; + for (; 0 < depthA - tempA; ) + (JSCompiler_temp = getParent(JSCompiler_temp)), depthA--; + for (; 0 < tempA - depthA; ) + (targetInst = getParent(targetInst)), tempA--; + for (; depthA--; ) { + if ( + JSCompiler_temp === targetInst || + JSCompiler_temp === targetInst.alternate + ) + break b; + JSCompiler_temp = getParent(JSCompiler_temp); + targetInst = getParent(targetInst); + } + JSCompiler_temp = null; + } + else JSCompiler_temp = targetInst; + targetInst = JSCompiler_temp === responderInst; + JSCompiler_temp = ResponderSyntheticEvent.getPooled( + shouldSetEventType, + JSCompiler_temp, + nativeEvent, + nativeEventTarget + ); + JSCompiler_temp.touchHistory = ResponderTouchHistoryStore.touchHistory; + targetInst + ? forEachAccumulated( + JSCompiler_temp, + accumulateTwoPhaseDispatchesSingleSkipTarget + ) + : forEachAccumulated( + JSCompiler_temp, + accumulateTwoPhaseDispatchesSingle + ); + b: { + shouldSetEventType = JSCompiler_temp._dispatchListeners; + targetInst = JSCompiler_temp._dispatchInstances; + if (Array.isArray(shouldSetEventType)) + for ( + depthA = 0; + depthA < shouldSetEventType.length && + !JSCompiler_temp.isPropagationStopped(); + depthA++ + ) { + if ( + shouldSetEventType[depthA](JSCompiler_temp, targetInst[depthA]) + ) { + shouldSetEventType = targetInst[depthA]; + break b; + } + } + else if ( + shouldSetEventType && + shouldSetEventType(JSCompiler_temp, targetInst) + ) { + shouldSetEventType = targetInst; + break b; + } + shouldSetEventType = null; + } + JSCompiler_temp._dispatchInstances = null; + JSCompiler_temp._dispatchListeners = null; + JSCompiler_temp.isPersistent() || + JSCompiler_temp.constructor.release(JSCompiler_temp); + if (shouldSetEventType && shouldSetEventType !== responderInst) + if ( + ((JSCompiler_temp = ResponderSyntheticEvent.getPooled( + eventTypes.responderGrant, + shouldSetEventType, + nativeEvent, + nativeEventTarget + )), + (JSCompiler_temp.touchHistory = + ResponderTouchHistoryStore.touchHistory), + forEachAccumulated( + JSCompiler_temp, + accumulateDirectDispatchesSingle + ), + (targetInst = !0 === executeDirectDispatch(JSCompiler_temp)), + responderInst) + ) + if ( + ((depthA = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminationRequest, + responderInst, + nativeEvent, + nativeEventTarget + )), + (depthA.touchHistory = ResponderTouchHistoryStore.touchHistory), + forEachAccumulated(depthA, accumulateDirectDispatchesSingle), + (tempA = + !depthA._dispatchListeners || executeDirectDispatch(depthA)), + depthA.isPersistent() || depthA.constructor.release(depthA), + tempA) + ) { + depthA = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminate, + responderInst, + nativeEvent, + nativeEventTarget + ); + depthA.touchHistory = ResponderTouchHistoryStore.touchHistory; + forEachAccumulated(depthA, accumulateDirectDispatchesSingle); + var JSCompiler_temp$jscomp$0 = accumulate( + JSCompiler_temp$jscomp$0, + [JSCompiler_temp, depthA] + ); + changeResponder(shouldSetEventType, targetInst); + } else + (shouldSetEventType = ResponderSyntheticEvent.getPooled( + eventTypes.responderReject, + shouldSetEventType, + nativeEvent, + nativeEventTarget + )), + (shouldSetEventType.touchHistory = + ResponderTouchHistoryStore.touchHistory), + forEachAccumulated( + shouldSetEventType, + accumulateDirectDispatchesSingle + ), + (JSCompiler_temp$jscomp$0 = accumulate( + JSCompiler_temp$jscomp$0, + shouldSetEventType + )); + else + (JSCompiler_temp$jscomp$0 = accumulate( + JSCompiler_temp$jscomp$0, + JSCompiler_temp + )), + changeResponder(shouldSetEventType, targetInst); + else JSCompiler_temp$jscomp$0 = null; + } else JSCompiler_temp$jscomp$0 = null; + shouldSetEventType = responderInst && isStartish(topLevelType); + JSCompiler_temp = responderInst && isMoveish(topLevelType); + targetInst = responderInst && isEndish(topLevelType); + if ( + (shouldSetEventType = shouldSetEventType + ? eventTypes.responderStart + : JSCompiler_temp + ? eventTypes.responderMove + : targetInst ? eventTypes.responderEnd : null) + ) + (shouldSetEventType = ResponderSyntheticEvent.getPooled( + shouldSetEventType, + responderInst, + nativeEvent, + nativeEventTarget + )), + (shouldSetEventType.touchHistory = + ResponderTouchHistoryStore.touchHistory), + forEachAccumulated( + shouldSetEventType, + accumulateDirectDispatchesSingle + ), + (JSCompiler_temp$jscomp$0 = accumulate( + JSCompiler_temp$jscomp$0, + shouldSetEventType + )); + shouldSetEventType = responderInst && "topTouchCancel" === topLevelType; + if ( + (topLevelType = + responderInst && !shouldSetEventType && isEndish(topLevelType)) + ) + a: { + if ((topLevelType = nativeEvent.touches) && 0 !== topLevelType.length) + for ( + JSCompiler_temp = 0; + JSCompiler_temp < topLevelType.length; + JSCompiler_temp++ + ) + if ( + ((targetInst = topLevelType[JSCompiler_temp].target), + null !== targetInst && + void 0 !== targetInst && + 0 !== targetInst) + ) { + depthA = getInstanceFromNode(targetInst); + b: { + for (targetInst = responderInst; depthA; ) { + if ( + targetInst === depthA || + targetInst === depthA.alternate + ) { + targetInst = !0; + break b; + } + depthA = getParent(depthA); + } + targetInst = !1; + } + if (targetInst) { + topLevelType = !1; + break a; + } + } + topLevelType = !0; + } + if ( + (topLevelType = shouldSetEventType + ? eventTypes.responderTerminate + : topLevelType ? eventTypes.responderRelease : null) + ) + (nativeEvent = ResponderSyntheticEvent.getPooled( + topLevelType, + responderInst, + nativeEvent, + nativeEventTarget + )), + (nativeEvent.touchHistory = ResponderTouchHistoryStore.touchHistory), + forEachAccumulated(nativeEvent, accumulateDirectDispatchesSingle), + (JSCompiler_temp$jscomp$0 = accumulate( + JSCompiler_temp$jscomp$0, + nativeEvent + )), + changeResponder(null); + nativeEvent = ResponderTouchHistoryStore.touchHistory.numberActiveTouches; + if ( + ResponderEventPlugin.GlobalInteractionHandler && + nativeEvent !== previousActiveTouches + ) + ResponderEventPlugin.GlobalInteractionHandler.onChange(nativeEvent); + previousActiveTouches = nativeEvent; + return JSCompiler_temp$jscomp$0; + }, + GlobalResponderHandler: null, + GlobalInteractionHandler: null, + injection: { + injectGlobalResponderHandler: function(GlobalResponderHandler) { + ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; + }, + injectGlobalInteractionHandler: function(GlobalInteractionHandler) { + ResponderEventPlugin.GlobalInteractionHandler = GlobalInteractionHandler; + } + } + }, + customBubblingEventTypes = {}, + customDirectEventTypes = {}, + ReactNativeBridgeEventPlugin = { + eventTypes: {}, + extractEvents: function( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + var bubbleDispatchConfig = customBubblingEventTypes[topLevelType], + directDispatchConfig = customDirectEventTypes[topLevelType]; + invariant( + bubbleDispatchConfig || directDispatchConfig, + 'Unsupported top level event type "%s" dispatched', + topLevelType + ); + topLevelType = SyntheticEvent.getPooled( + bubbleDispatchConfig || directDispatchConfig, + targetInst, + nativeEvent, + nativeEventTarget + ); + if (bubbleDispatchConfig) + forEachAccumulated(topLevelType, accumulateTwoPhaseDispatchesSingle); + else if (directDispatchConfig) + forEachAccumulated(topLevelType, accumulateDirectDispatchesSingle); + else return null; + return topLevelType; + }, + processEventTypes: function(viewConfig) { + var bubblingEventTypes = viewConfig.bubblingEventTypes; + viewConfig = viewConfig.directEventTypes; + if (null != bubblingEventTypes) + for (var _topLevelType in bubblingEventTypes) + null == customBubblingEventTypes[_topLevelType] && + (ReactNativeBridgeEventPlugin.eventTypes[ + _topLevelType + ] = customBubblingEventTypes[_topLevelType] = + bubblingEventTypes[_topLevelType]); + if (null != viewConfig) + for (var _topLevelType2 in viewConfig) + null == customDirectEventTypes[_topLevelType2] && + (ReactNativeBridgeEventPlugin.eventTypes[ + _topLevelType2 + ] = customDirectEventTypes[_topLevelType2] = + viewConfig[_topLevelType2]); + } + }, + instanceCache = {}, + instanceProps = {}; +function uncacheFiberNode(tag) { + delete instanceCache[tag]; + delete instanceProps[tag]; +} +function getInstanceFromTag(tag) { + return instanceCache[tag] || null; +} +var ReactNativeComponentTree = Object.freeze({ + precacheFiberNode: function(hostInst, tag) { + instanceCache[tag] = hostInst; + }, + uncacheFiberNode: uncacheFiberNode, + getClosestInstanceFromNode: getInstanceFromTag, + getInstanceFromNode: getInstanceFromTag, + getNodeFromInstance: function(inst) { + inst = inst.stateNode._nativeTag; + invariant(inst, "All native instances should have a tag."); + return inst; + }, + getFiberCurrentPropsFromNode: function(stateNode) { + return instanceProps[stateNode._nativeTag] || null; + }, + updateFiberProps: function(tag, props) { + instanceProps[tag] = props; + } + }), + restoreTarget = null, + restoreQueue = null; +function restoreStateOfTarget(target) { + if ((target = getInstanceFromNode(target))) { + invariant( + null, + "Fiber needs to be injected to handle a fiber target for controlled events. This error is likely caused by a bug in React. Please file an issue." + ); + var props = getFiberCurrentPropsFromNode(target.stateNode); + null.restoreControlledState(target.stateNode, target.type, props); + } +} +function fiberBatchedUpdates(fn, bookkeeping) { + return fn(bookkeeping); +} +var isNestingBatched = !1; +function batchedUpdates(fn, bookkeeping) { + if (isNestingBatched) return fiberBatchedUpdates(fn, bookkeeping); + isNestingBatched = !0; + try { + return fiberBatchedUpdates(fn, bookkeeping); + } finally { + if ( + ((isNestingBatched = !1), + restoreTarget && + ((bookkeeping = restoreTarget), + (fn = restoreQueue), + (restoreQueue = restoreTarget = null), + restoreStateOfTarget(bookkeeping), + fn)) + ) + for (bookkeeping = 0; bookkeeping < fn.length; bookkeeping++) + restoreStateOfTarget(fn[bookkeeping]); + } +} +function handleTopLevel( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget +) { + for (var events, i = 0; i < plugins.length; i++) { + var possiblePlugin = plugins[i]; + possiblePlugin && + (possiblePlugin = possiblePlugin.extractEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + )) && + (events = accumulateInto(events, possiblePlugin)); + } + events && (eventQueue = accumulateInto(eventQueue, events)); + topLevelType = eventQueue; + eventQueue = null; + forEachAccumulated(topLevelType, executeDispatchesAndReleaseTopLevel); + invariant( + !eventQueue, + "processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented." + ); + ReactErrorUtils.rethrowCaughtError(); +} +var ReactNativeTagHandles = { + tagsStartAt: 1, + tagCount: 1, + allocateTag: function() { + for (; this.reactTagIsNativeTopRootID(ReactNativeTagHandles.tagCount); ) + ReactNativeTagHandles.tagCount++; + var tag = ReactNativeTagHandles.tagCount; + ReactNativeTagHandles.tagCount++; + return tag; + }, + assertRootTag: function(tag) { + invariant( + this.reactTagIsNativeTopRootID(tag), + "Expect a native root tag, instead got %s", + tag + ); + }, + reactTagIsNativeTopRootID: function(reactTag) { + return 1 === reactTag % 10; + } + }, + EMPTY_NATIVE_EVENT = {}; +function _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam) { + var nativeEvent = nativeEventParam || EMPTY_NATIVE_EVENT, + inst = getInstanceFromTag(rootNodeID); + batchedUpdates(function() { + handleTopLevel(topLevelType, inst, nativeEvent, nativeEvent.target); + }); +} +var ReactNativeEventEmitter = Object.freeze({ + getListener: getListener, + registrationNames: registrationNameModules, + _receiveRootNodeIDEvent: _receiveRootNodeIDEvent, + receiveEvent: function(rootNodeID, topLevelType, nativeEventParam) { + _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam); + }, + receiveTouches: function(eventTopLevelType, touches, changedIndices) { + if ( + "topTouchEnd" === eventTopLevelType || + "topTouchCancel" === eventTopLevelType + ) { + var JSCompiler_temp = []; + for (var i = 0; i < changedIndices.length; i++) { + var index = changedIndices[i]; + JSCompiler_temp.push(touches[index]); + touches[index] = null; + } + for (i = changedIndices = 0; i < touches.length; i++) + (index = touches[i]), + null !== index && (touches[changedIndices++] = index); + touches.length = changedIndices; + } else + for (JSCompiler_temp = [], i = 0; i < changedIndices.length; i++) + JSCompiler_temp.push(touches[changedIndices[i]]); + for ( + changedIndices = 0; + changedIndices < JSCompiler_temp.length; + changedIndices++ + ) { + i = JSCompiler_temp[changedIndices]; + i.changedTouches = JSCompiler_temp; + i.touches = touches; + index = null; + var target = i.target; + null === target || + void 0 === target || + target < ReactNativeTagHandles.tagsStartAt || + (index = target); + _receiveRootNodeIDEvent(index, eventTopLevelType, i); + } + }, + handleTopLevel: handleTopLevel +}); +RCTEventEmitter.register(ReactNativeEventEmitter); +injection.injectEventPluginOrder([ + "ResponderEventPlugin", + "ReactNativeBridgeEventPlugin" +]); +getFiberCurrentPropsFromNode = + ReactNativeComponentTree.getFiberCurrentPropsFromNode; +getInstanceFromNode = ReactNativeComponentTree.getInstanceFromNode; +getNodeFromInstance = ReactNativeComponentTree.getNodeFromInstance; +ResponderEventPlugin.injection.injectGlobalResponderHandler({ + onChange: function(from, to, blockNativeResponder) { + null !== to + ? UIManager.setJSResponder(to.stateNode._nativeTag, blockNativeResponder) + : UIManager.clearJSResponder(); + } +}); +injection.injectEventPluginsByName({ + ResponderEventPlugin: ResponderEventPlugin, + ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin +}); +function defaultShowDialog() { + return !0; +} +var showDialog = defaultShowDialog, + REACT_PORTAL_TYPE = + ("function" === typeof Symbol && + Symbol["for"] && + Symbol["for"]("react.portal")) || + 60106; +function createPortal(children, containerInfo, implementation) { + var key = + 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null; + return { + $$typeof: REACT_PORTAL_TYPE, + key: null == key ? null : "" + key, + children: children, + containerInfo: containerInfo, + implementation: implementation + }; +} +var TouchHistoryMath = { + centroidDimension: function( + touchHistory, + touchesChangedAfter, + isXAxis, + ofCurrent + ) { + var touchBank = touchHistory.touchBank, + total = 0, + count = 0; + touchHistory = + 1 === touchHistory.numberActiveTouches + ? touchHistory.touchBank[touchHistory.indexOfSingleActiveTouch] + : null; + if (null !== touchHistory) + touchHistory.touchActive && + touchHistory.currentTimeStamp > touchesChangedAfter && + ((total += + ofCurrent && isXAxis + ? touchHistory.currentPageX + : ofCurrent && !isXAxis + ? touchHistory.currentPageY + : !ofCurrent && isXAxis + ? touchHistory.previousPageX + : touchHistory.previousPageY), + (count = 1)); + else + for ( + touchHistory = 0; + touchHistory < touchBank.length; + touchHistory++ + ) { + var touchTrack = touchBank[touchHistory]; + null !== touchTrack && + void 0 !== touchTrack && + touchTrack.touchActive && + touchTrack.currentTimeStamp >= touchesChangedAfter && + ((total += + ofCurrent && isXAxis + ? touchTrack.currentPageX + : ofCurrent && !isXAxis + ? touchTrack.currentPageY + : !ofCurrent && isXAxis + ? touchTrack.previousPageX + : touchTrack.previousPageY), + count++); + } + return 0 < count ? total / count : TouchHistoryMath.noCentroid; + }, + currentCentroidXOfTouchesChangedAfter: function( + touchHistory, + touchesChangedAfter + ) { + return TouchHistoryMath.centroidDimension( + touchHistory, + touchesChangedAfter, + !0, + !0 + ); + }, + currentCentroidYOfTouchesChangedAfter: function( + touchHistory, + touchesChangedAfter + ) { + return TouchHistoryMath.centroidDimension( + touchHistory, + touchesChangedAfter, + !1, + !0 + ); + }, + previousCentroidXOfTouchesChangedAfter: function( + touchHistory, + touchesChangedAfter + ) { + return TouchHistoryMath.centroidDimension( + touchHistory, + touchesChangedAfter, + !0, + !1 + ); + }, + previousCentroidYOfTouchesChangedAfter: function( + touchHistory, + touchesChangedAfter + ) { + return TouchHistoryMath.centroidDimension( + touchHistory, + touchesChangedAfter, + !1, + !1 + ); + }, + currentCentroidX: function(touchHistory) { + return TouchHistoryMath.centroidDimension(touchHistory, 0, !0, !0); + }, + currentCentroidY: function(touchHistory) { + return TouchHistoryMath.centroidDimension(touchHistory, 0, !1, !0); + }, + noCentroid: -1 + }, + ReactCurrentOwner = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner, + ReactGlobalSharedState = Object.freeze({ + ReactCurrentOwner: ReactCurrentOwner, + ReactDebugCurrentFrame: null + }), + objects = {}, + uniqueID = 1, + emptyObject$2 = {}, + ReactNativePropRegistry = (function() { + function ReactNativePropRegistry() { + if (!(this instanceof ReactNativePropRegistry)) + throw new TypeError("Cannot call a class as a function"); + } + ReactNativePropRegistry.register = function(object) { + var id = ++uniqueID; + objects[id] = object; + return id; + }; + ReactNativePropRegistry.getByID = function(id) { + if (!id) return emptyObject$2; + var object = objects[id]; + return object + ? object + : (console.warn("Invalid style with id `" + id + "`. Skipping ..."), + emptyObject$2); + }; + return ReactNativePropRegistry; + })(), + emptyObject$1 = {}, + removedKeys = null, + removedKeyCount = 0; +function resolveObject(idOrObject) { + return "number" === typeof idOrObject + ? ReactNativePropRegistry.getByID(idOrObject) + : idOrObject; +} +function restoreDeletedValuesInNestedArray( + updatePayload, + node, + validAttributes +) { + if (Array.isArray(node)) + for (var i = node.length; i-- && 0 < removedKeyCount; ) + restoreDeletedValuesInNestedArray( + updatePayload, + node[i], + validAttributes + ); + else if (node && 0 < removedKeyCount) + for (i in ((node = resolveObject(node)), removedKeys)) + if (removedKeys[i]) { + var nextProp = node[i]; + if (void 0 !== nextProp) { + var attributeConfig = validAttributes[i]; + if (attributeConfig) { + "function" === typeof nextProp && (nextProp = !0); + "undefined" === typeof nextProp && (nextProp = null); + if ("object" !== typeof attributeConfig) + updatePayload[i] = nextProp; + else if ( + "function" === typeof attributeConfig.diff || + "function" === typeof attributeConfig.process + ) + (nextProp = + "function" === typeof attributeConfig.process + ? attributeConfig.process(nextProp) + : nextProp), + (updatePayload[i] = nextProp); + removedKeys[i] = !1; + removedKeyCount--; + } + } + } +} +function diffNestedProperty( + updatePayload, + prevProp, + nextProp, + validAttributes +) { + if (!updatePayload && prevProp === nextProp) return updatePayload; + if (!prevProp || !nextProp) + return nextProp + ? addNestedProperty(updatePayload, nextProp, validAttributes) + : prevProp + ? clearNestedProperty(updatePayload, prevProp, validAttributes) + : updatePayload; + if (!Array.isArray(prevProp) && !Array.isArray(nextProp)) + return diffProperties( + updatePayload, + resolveObject(prevProp), + resolveObject(nextProp), + validAttributes + ); + if (Array.isArray(prevProp) && Array.isArray(nextProp)) { + var minLength = + prevProp.length < nextProp.length ? prevProp.length : nextProp.length, + i; + for (i = 0; i < minLength; i++) + updatePayload = diffNestedProperty( + updatePayload, + prevProp[i], + nextProp[i], + validAttributes + ); + for (; i < prevProp.length; i++) + updatePayload = clearNestedProperty( + updatePayload, + prevProp[i], + validAttributes + ); + for (; i < nextProp.length; i++) + updatePayload = addNestedProperty( + updatePayload, + nextProp[i], + validAttributes + ); + return updatePayload; + } + return Array.isArray(prevProp) + ? diffProperties( + updatePayload, + flattenStyle(prevProp), + resolveObject(nextProp), + validAttributes + ) + : diffProperties( + updatePayload, + resolveObject(prevProp), + flattenStyle(nextProp), + validAttributes + ); +} +function addNestedProperty(updatePayload, nextProp, validAttributes) { + if (!nextProp) return updatePayload; + if (!Array.isArray(nextProp)) + return ( + (nextProp = resolveObject(nextProp)), + diffProperties(updatePayload, emptyObject$1, nextProp, validAttributes) + ); + for (var i = 0; i < nextProp.length; i++) + updatePayload = addNestedProperty( + updatePayload, + nextProp[i], + validAttributes + ); + return updatePayload; +} +function clearNestedProperty(updatePayload, prevProp, validAttributes) { + if (!prevProp) return updatePayload; + if (!Array.isArray(prevProp)) + return ( + (prevProp = resolveObject(prevProp)), + diffProperties(updatePayload, prevProp, emptyObject$1, validAttributes) + ); + for (var i = 0; i < prevProp.length; i++) + updatePayload = clearNestedProperty( + updatePayload, + prevProp[i], + validAttributes + ); + return updatePayload; +} +function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { + var attributeConfig, propKey; + for (propKey in nextProps) + if ((attributeConfig = validAttributes[propKey])) { + var prevProp = prevProps[propKey]; + var nextProp = nextProps[propKey]; + "function" === typeof nextProp && + ((nextProp = !0), "function" === typeof prevProp && (prevProp = !0)); + "undefined" === typeof nextProp && + ((nextProp = null), + "undefined" === typeof prevProp && (prevProp = null)); + removedKeys && (removedKeys[propKey] = !1); + if (updatePayload && void 0 !== updatePayload[propKey]) + if ("object" !== typeof attributeConfig) + updatePayload[propKey] = nextProp; + else { + if ( + "function" === typeof attributeConfig.diff || + "function" === typeof attributeConfig.process + ) + (attributeConfig = + "function" === typeof attributeConfig.process + ? attributeConfig.process(nextProp) + : nextProp), + (updatePayload[propKey] = attributeConfig); + } + else if (prevProp !== nextProp) + if ("object" !== typeof attributeConfig) + ("object" !== typeof nextProp || + null === nextProp || + deepDiffer(prevProp, nextProp)) && + ((updatePayload || (updatePayload = {}))[propKey] = nextProp); + else if ( + "function" === typeof attributeConfig.diff || + "function" === typeof attributeConfig.process + ) { + if ( + void 0 === prevProp || + ("function" === typeof attributeConfig.diff + ? attributeConfig.diff(prevProp, nextProp) + : "object" !== typeof nextProp || + null === nextProp || + deepDiffer(prevProp, nextProp)) + ) + (attributeConfig = + "function" === typeof attributeConfig.process + ? attributeConfig.process(nextProp) + : nextProp), + ((updatePayload || (updatePayload = {}))[ + propKey + ] = attributeConfig); + } else + (removedKeys = null), + (removedKeyCount = 0), + (updatePayload = diffNestedProperty( + updatePayload, + prevProp, + nextProp, + attributeConfig + )), + 0 < removedKeyCount && + updatePayload && + (restoreDeletedValuesInNestedArray( + updatePayload, + nextProp, + attributeConfig + ), + (removedKeys = null)); + } + for (propKey in prevProps) + void 0 === nextProps[propKey] && + (!(attributeConfig = validAttributes[propKey]) || + (updatePayload && void 0 !== updatePayload[propKey]) || + ((prevProp = prevProps[propKey]), + void 0 !== prevProp && + ("object" !== typeof attributeConfig || + "function" === typeof attributeConfig.diff || + "function" === typeof attributeConfig.process + ? (((updatePayload || (updatePayload = {}))[propKey] = null), + removedKeys || (removedKeys = {}), + removedKeys[propKey] || + ((removedKeys[propKey] = !0), removedKeyCount++)) + : (updatePayload = clearNestedProperty( + updatePayload, + prevProp, + attributeConfig + ))))); + return updatePayload; +} +function mountSafeCallback(context, callback) { + return function() { + if (callback) { + if ("boolean" === typeof context.__isMounted) { + if (!context.__isMounted) return; + } else if ( + "function" === typeof context.isMounted && + !context.isMounted() + ) + return; + return callback.apply(context, arguments); + } + }; +} +function getComponentName(fiber) { + fiber = fiber.type; + return "string" === typeof fiber + ? fiber + : "function" === typeof fiber ? fiber.displayName || fiber.name : null; +} +function isFiberMountedImpl(fiber) { + var node = fiber; + if (fiber.alternate) for (; node["return"]; ) node = node["return"]; + else { + if (0 !== (node.effectTag & 2)) return 1; + for (; node["return"]; ) + if (((node = node["return"]), 0 !== (node.effectTag & 2))) return 1; + } + return 3 === node.tag ? 2 : 3; +} +function isMounted(component) { + return (component = component._reactInternalFiber) + ? 2 === isFiberMountedImpl(component) + : !1; +} +function assertIsMounted(fiber) { + invariant( + 2 === isFiberMountedImpl(fiber), + "Unable to find node on an unmounted component." + ); +} +function findCurrentFiberUsingSlowPath(fiber) { + var alternate = fiber.alternate; + if (!alternate) + return ( + (alternate = isFiberMountedImpl(fiber)), + invariant( + 3 !== alternate, + "Unable to find node on an unmounted component." + ), + 1 === alternate ? null : fiber + ); + for (var a = fiber, b = alternate; ; ) { + var parentA = a["return"], + parentB = parentA ? parentA.alternate : null; + if (!parentA || !parentB) break; + if (parentA.child === parentB.child) { + for (var child = parentA.child; child; ) { + if (child === a) return assertIsMounted(parentA), fiber; + if (child === b) return assertIsMounted(parentA), alternate; + child = child.sibling; + } + invariant(!1, "Unable to find node on an unmounted component."); + } + if (a["return"] !== b["return"]) (a = parentA), (b = parentB); + else { + child = !1; + for (var _child = parentA.child; _child; ) { + if (_child === a) { + child = !0; + a = parentA; + b = parentB; + break; + } + if (_child === b) { + child = !0; + b = parentA; + a = parentB; + break; + } + _child = _child.sibling; + } + if (!child) { + for (_child = parentB.child; _child; ) { + if (_child === a) { + child = !0; + a = parentB; + b = parentA; + break; + } + if (_child === b) { + child = !0; + b = parentB; + a = parentA; + break; + } + _child = _child.sibling; + } + invariant( + child, + "Child was not found in either parent set. This indicates a bug in React related to the return pointer. Please file an issue." + ); + } + } + invariant( + a.alternate === b, + "Return fibers should always be each others' alternates. This error is likely caused by a bug in React. Please file an issue." + ); + } + invariant(3 === a.tag, "Unable to find node on an unmounted component."); + return a.stateNode.current === a ? fiber : alternate; +} +function findCurrentHostFiber(parent) { + parent = findCurrentFiberUsingSlowPath(parent); + if (!parent) return null; + for (var node = parent; ; ) { + if (5 === node.tag || 6 === node.tag) return node; + if (node.child) (node.child["return"] = node), (node = node.child); + else { + if (node === parent) break; + for (; !node.sibling; ) { + if (!node["return"] || node["return"] === parent) return null; + node = node["return"]; + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } + } + return null; +} +function findCurrentHostFiberWithNoPortals(parent) { + parent = findCurrentFiberUsingSlowPath(parent); + if (!parent) return null; + for (var node = parent; ; ) { + if (5 === node.tag || 6 === node.tag) return node; + if (node.child && 4 !== node.tag) + (node.child["return"] = node), (node = node.child); + else { + if (node === parent) break; + for (; !node.sibling; ) { + if (!node["return"] || node["return"] === parent) return null; + node = node["return"]; + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } + } + return null; +} +var valueStack = [], + index = -1; +function pop(cursor) { + 0 > index || + ((cursor.current = valueStack[index]), (valueStack[index] = null), index--); +} +function push(cursor, value) { + index++; + valueStack[index] = cursor.current; + cursor.current = value; +} +new Set(); +var contextStackCursor = { current: emptyObject }, + didPerformWorkStackCursor = { current: !1 }, + previousContext = emptyObject; +function getUnmaskedContext(workInProgress) { + return isContextProvider(workInProgress) + ? previousContext + : contextStackCursor.current; +} +function getMaskedContext(workInProgress, unmaskedContext) { + var contextTypes = workInProgress.type.contextTypes; + if (!contextTypes) return emptyObject; + var instance = workInProgress.stateNode; + if ( + instance && + instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext + ) + return instance.__reactInternalMemoizedMaskedChildContext; + var context = {}, + key; + for (key in contextTypes) context[key] = unmaskedContext[key]; + instance && + ((workInProgress = workInProgress.stateNode), + (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), + (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); + return context; +} +function isContextProvider(fiber) { + return 2 === fiber.tag && null != fiber.type.childContextTypes; +} +function popContextProvider(fiber) { + isContextProvider(fiber) && + (pop(didPerformWorkStackCursor, fiber), pop(contextStackCursor, fiber)); +} +function pushTopLevelContextObject(fiber, context, didChange) { + invariant( + null == contextStackCursor.cursor, + "Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue." + ); + push(contextStackCursor, context, fiber); + push(didPerformWorkStackCursor, didChange, fiber); +} +function processChildContext(fiber, parentContext) { + var instance = fiber.stateNode, + childContextTypes = fiber.type.childContextTypes; + if ("function" !== typeof instance.getChildContext) return parentContext; + instance = instance.getChildContext(); + for (var contextKey in instance) + invariant( + contextKey in childContextTypes, + '%s.getChildContext(): key "%s" is not defined in childContextTypes.', + getComponentName(fiber) || "Unknown", + contextKey + ); + return Object.assign({}, parentContext, instance); +} +function pushContextProvider(workInProgress) { + if (!isContextProvider(workInProgress)) return !1; + var instance = workInProgress.stateNode; + instance = + (instance && instance.__reactInternalMemoizedMergedChildContext) || + emptyObject; + previousContext = contextStackCursor.current; + push(contextStackCursor, instance, workInProgress); + push( + didPerformWorkStackCursor, + didPerformWorkStackCursor.current, + workInProgress + ); + return !0; +} +function invalidateContextProvider(workInProgress, didChange) { + var instance = workInProgress.stateNode; + invariant( + instance, + "Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue." + ); + if (didChange) { + var mergedContext = processChildContext(workInProgress, previousContext); + instance.__reactInternalMemoizedMergedChildContext = mergedContext; + pop(didPerformWorkStackCursor, workInProgress); + pop(contextStackCursor, workInProgress); + push(contextStackCursor, mergedContext, workInProgress); + } else pop(didPerformWorkStackCursor, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); +} +function FiberNode(tag, key, internalContextTag) { + this.tag = tag; + this.key = key; + this.stateNode = this.type = null; + this.sibling = this.child = this["return"] = null; + this.index = 0; + this.memoizedState = this.updateQueue = this.memoizedProps = this.pendingProps = this.ref = null; + this.internalContextTag = internalContextTag; + this.effectTag = 0; + this.lastEffect = this.firstEffect = this.nextEffect = null; + this.expirationTime = 0; + this.alternate = null; +} +function createWorkInProgress(current, pendingProps, expirationTime) { + var workInProgress = current.alternate; + null === workInProgress + ? ((workInProgress = new FiberNode( + current.tag, + current.key, + current.internalContextTag + )), + (workInProgress.type = current.type), + (workInProgress.stateNode = current.stateNode), + (workInProgress.alternate = current), + (current.alternate = workInProgress)) + : ((workInProgress.effectTag = 0), + (workInProgress.nextEffect = null), + (workInProgress.firstEffect = null), + (workInProgress.lastEffect = null)); + workInProgress.expirationTime = expirationTime; + workInProgress.pendingProps = pendingProps; + workInProgress.child = current.child; + workInProgress.memoizedProps = current.memoizedProps; + workInProgress.memoizedState = current.memoizedState; + workInProgress.updateQueue = current.updateQueue; + workInProgress.sibling = current.sibling; + workInProgress.index = current.index; + workInProgress.ref = current.ref; + return workInProgress; +} +function createFiberFromElement(element, internalContextTag, expirationTime) { + var fiber = void 0, + type = element.type, + key = element.key; + "function" === typeof type + ? ((fiber = + type.prototype && type.prototype.isReactComponent + ? new FiberNode(2, key, internalContextTag) + : new FiberNode(0, key, internalContextTag)), + (fiber.type = type), + (fiber.pendingProps = element.props)) + : "string" === typeof type + ? ((fiber = new FiberNode(5, key, internalContextTag)), + (fiber.type = type), + (fiber.pendingProps = element.props)) + : "object" === typeof type && + null !== type && + "number" === typeof type.tag + ? ((fiber = type), (fiber.pendingProps = element.props)) + : invariant( + !1, + "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s", + null == type ? type : typeof type, + "" + ); + fiber.expirationTime = expirationTime; + return fiber; +} +function createFiberFromFragment( + elements, + internalContextTag, + expirationTime, + key +) { + internalContextTag = new FiberNode(10, key, internalContextTag); + internalContextTag.pendingProps = elements; + internalContextTag.expirationTime = expirationTime; + return internalContextTag; +} +function createFiberFromText(content, internalContextTag, expirationTime) { + internalContextTag = new FiberNode(6, null, internalContextTag); + internalContextTag.pendingProps = content; + internalContextTag.expirationTime = expirationTime; + return internalContextTag; +} +function createFiberFromCall(call, internalContextTag, expirationTime) { + internalContextTag = new FiberNode(7, call.key, internalContextTag); + internalContextTag.type = call.handler; + internalContextTag.pendingProps = call; + internalContextTag.expirationTime = expirationTime; + return internalContextTag; +} +function createFiberFromReturn(returnNode, internalContextTag, expirationTime) { + returnNode = new FiberNode(9, null, internalContextTag); + returnNode.expirationTime = expirationTime; + return returnNode; +} +function createFiberFromPortal(portal, internalContextTag, expirationTime) { + internalContextTag = new FiberNode(4, portal.key, internalContextTag); + internalContextTag.pendingProps = portal.children || []; + internalContextTag.expirationTime = expirationTime; + internalContextTag.stateNode = { + containerInfo: portal.containerInfo, + pendingChildren: null, + implementation: portal.implementation + }; + return internalContextTag; +} +var onCommitFiberRoot = null, + onCommitFiberUnmount = null; +function catchErrors(fn) { + return function(arg) { + try { + return fn(arg); + } catch (err) {} + }; +} +function injectInternals(internals) { + if ("undefined" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) return !1; + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if (hook.isDisabled || !hook.supportsFiber) return !0; + try { + var rendererID = hook.inject(internals); + onCommitFiberRoot = catchErrors(function(root) { + return hook.onCommitFiberRoot(rendererID, root); + }); + onCommitFiberUnmount = catchErrors(function(fiber) { + return hook.onCommitFiberUnmount(rendererID, fiber); + }); + } catch (err) {} + return !0; +} +function onCommitRoot(root) { + "function" === typeof onCommitFiberRoot && onCommitFiberRoot(root); +} +function onCommitUnmount(fiber) { + "function" === typeof onCommitFiberUnmount && onCommitFiberUnmount(fiber); +} +function createUpdateQueue(baseState) { + return { + baseState: baseState, + expirationTime: 0, + first: null, + last: null, + callbackList: null, + hasForceUpdate: !1, + isInitialized: !1 + }; +} +function insertUpdateIntoQueue(queue, update) { + null === queue.last + ? (queue.first = queue.last = update) + : ((queue.last.next = update), (queue.last = update)); + if ( + 0 === queue.expirationTime || + queue.expirationTime > update.expirationTime + ) + queue.expirationTime = update.expirationTime; +} +function insertUpdateIntoFiber(fiber, update) { + var alternateFiber = fiber.alternate, + queue1 = fiber.updateQueue; + null === queue1 && (queue1 = fiber.updateQueue = createUpdateQueue(null)); + null !== alternateFiber + ? ((fiber = alternateFiber.updateQueue), + null === fiber && + (fiber = alternateFiber.updateQueue = createUpdateQueue(null))) + : (fiber = null); + fiber = fiber !== queue1 ? fiber : null; + null === fiber + ? insertUpdateIntoQueue(queue1, update) + : null === queue1.last || null === fiber.last + ? (insertUpdateIntoQueue(queue1, update), + insertUpdateIntoQueue(fiber, update)) + : (insertUpdateIntoQueue(queue1, update), (fiber.last = update)); +} +function getStateFromUpdate(update, instance, prevState, props) { + update = update.partialState; + return "function" === typeof update + ? update.call(instance, prevState, props) + : update; +} +function processUpdateQueue( + current, + workInProgress, + queue, + instance, + props, + renderExpirationTime +) { + null !== current && + current.updateQueue === queue && + (queue = workInProgress.updateQueue = { + baseState: queue.baseState, + expirationTime: queue.expirationTime, + first: queue.first, + last: queue.last, + isInitialized: queue.isInitialized, + callbackList: null, + hasForceUpdate: !1 + }); + queue.expirationTime = 0; + queue.isInitialized + ? (current = queue.baseState) + : ((current = queue.baseState = workInProgress.memoizedState), + (queue.isInitialized = !0)); + for ( + var dontMutatePrevState = !0, update = queue.first, didSkip = !1; + null !== update; + + ) { + var updateExpirationTime = update.expirationTime; + if (updateExpirationTime > renderExpirationTime) { + var remainingExpirationTime = queue.expirationTime; + if ( + 0 === remainingExpirationTime || + remainingExpirationTime > updateExpirationTime + ) + queue.expirationTime = updateExpirationTime; + didSkip || ((didSkip = !0), (queue.baseState = current)); + } else { + didSkip || + ((queue.first = update.next), + null === queue.first && (queue.last = null)); + if (update.isReplace) + (current = getStateFromUpdate(update, instance, current, props)), + (dontMutatePrevState = !0); + else if ( + (updateExpirationTime = getStateFromUpdate( + update, + instance, + current, + props + )) + ) + (current = dontMutatePrevState + ? Object.assign({}, current, updateExpirationTime) + : Object.assign(current, updateExpirationTime)), + (dontMutatePrevState = !1); + update.isForced && (queue.hasForceUpdate = !0); + null !== update.callback && + ((updateExpirationTime = queue.callbackList), + null === updateExpirationTime && + (updateExpirationTime = queue.callbackList = []), + updateExpirationTime.push(update)); + } + update = update.next; + } + null !== queue.callbackList + ? (workInProgress.effectTag |= 32) + : null !== queue.first || + queue.hasForceUpdate || + (workInProgress.updateQueue = null); + didSkip || (queue.baseState = current); + return current; +} +function commitCallbacks(queue, context) { + var callbackList = queue.callbackList; + if (null !== callbackList) + for ( + queue.callbackList = null, queue = 0; + queue < callbackList.length; + queue++ + ) { + var update = callbackList[queue], + _callback = update.callback; + update.callback = null; + invariant( + "function" === typeof _callback, + "Invalid argument passed as callback. Expected a function. Instead received: %s", + _callback + ); + _callback.call(context); + } +} +function ReactFiberClassComponent( + scheduleWork, + computeExpirationForFiber, + memoizeProps, + memoizeState +) { + function adoptClassInstance(workInProgress, instance) { + instance.updater = updater; + workInProgress.stateNode = instance; + instance._reactInternalFiber = workInProgress; + } + var updater = { + isMounted: isMounted, + enqueueSetState: function(instance, partialState, callback) { + instance = instance._reactInternalFiber; + callback = void 0 === callback ? null : callback; + var expirationTime = computeExpirationForFiber(instance); + insertUpdateIntoFiber(instance, { + expirationTime: expirationTime, + partialState: partialState, + callback: callback, + isReplace: !1, + isForced: !1, + nextCallback: null, + next: null + }); + scheduleWork(instance, expirationTime); + }, + enqueueReplaceState: function(instance, state, callback) { + instance = instance._reactInternalFiber; + callback = void 0 === callback ? null : callback; + var expirationTime = computeExpirationForFiber(instance); + insertUpdateIntoFiber(instance, { + expirationTime: expirationTime, + partialState: state, + callback: callback, + isReplace: !0, + isForced: !1, + nextCallback: null, + next: null + }); + scheduleWork(instance, expirationTime); + }, + enqueueForceUpdate: function(instance, callback) { + instance = instance._reactInternalFiber; + callback = void 0 === callback ? null : callback; + var expirationTime = computeExpirationForFiber(instance); + insertUpdateIntoFiber(instance, { + expirationTime: expirationTime, + partialState: null, + callback: callback, + isReplace: !1, + isForced: !0, + nextCallback: null, + next: null + }); + scheduleWork(instance, expirationTime); + } + }; + return { + adoptClassInstance: adoptClassInstance, + constructClassInstance: function(workInProgress, props) { + var ctor = workInProgress.type, + unmaskedContext = getUnmaskedContext(workInProgress), + needsContext = + 2 === workInProgress.tag && null != workInProgress.type.contextTypes, + context = needsContext + ? getMaskedContext(workInProgress, unmaskedContext) + : emptyObject; + props = new ctor(props, context); + adoptClassInstance(workInProgress, props); + needsContext && + ((workInProgress = workInProgress.stateNode), + (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), + (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); + return props; + }, + mountClassInstance: function(workInProgress, renderExpirationTime) { + var current = workInProgress.alternate, + instance = workInProgress.stateNode, + state = instance.state || null, + props = workInProgress.pendingProps; + invariant( + props, + "There must be pending props for an initial mount. This error is likely caused by a bug in React. Please file an issue." + ); + var unmaskedContext = getUnmaskedContext(workInProgress); + instance.props = props; + instance.state = workInProgress.memoizedState = state; + instance.refs = emptyObject; + instance.context = getMaskedContext(workInProgress, unmaskedContext); + null != workInProgress.type && + null != workInProgress.type.prototype && + !0 === workInProgress.type.prototype.unstable_isAsyncReactComponent && + (workInProgress.internalContextTag |= 1); + "function" === typeof instance.componentWillMount && + ((state = instance.state), + instance.componentWillMount(), + state !== instance.state && + updater.enqueueReplaceState(instance, instance.state, null), + (state = workInProgress.updateQueue), + null !== state && + (instance.state = processUpdateQueue( + current, + workInProgress, + state, + instance, + props, + renderExpirationTime + ))); + "function" === typeof instance.componentDidMount && + (workInProgress.effectTag |= 4); + }, + updateClassInstance: function( + current, + workInProgress, + renderExpirationTime + ) { + var instance = workInProgress.stateNode; + instance.props = workInProgress.memoizedProps; + instance.state = workInProgress.memoizedState; + var oldProps = workInProgress.memoizedProps, + newProps = workInProgress.pendingProps; + newProps || + ((newProps = oldProps), + invariant( + null != newProps, + "There should always be pending or memoized props. This error is likely caused by a bug in React. Please file an issue." + )); + var oldContext = instance.context, + newUnmaskedContext = getUnmaskedContext(workInProgress); + newUnmaskedContext = getMaskedContext(workInProgress, newUnmaskedContext); + "function" !== typeof instance.componentWillReceiveProps || + (oldProps === newProps && oldContext === newUnmaskedContext) || + ((oldContext = instance.state), + instance.componentWillReceiveProps(newProps, newUnmaskedContext), + instance.state !== oldContext && + updater.enqueueReplaceState(instance, instance.state, null)); + oldContext = workInProgress.memoizedState; + renderExpirationTime = + null !== workInProgress.updateQueue + ? processUpdateQueue( + current, + workInProgress, + workInProgress.updateQueue, + instance, + newProps, + renderExpirationTime + ) + : oldContext; + if ( + !( + oldProps !== newProps || + oldContext !== renderExpirationTime || + didPerformWorkStackCursor.current || + (null !== workInProgress.updateQueue && + workInProgress.updateQueue.hasForceUpdate) + ) + ) + return ( + "function" !== typeof instance.componentDidUpdate || + (oldProps === current.memoizedProps && + oldContext === current.memoizedState) || + (workInProgress.effectTag |= 4), + !1 + ); + var shouldUpdate = newProps; + if ( + null === oldProps || + (null !== workInProgress.updateQueue && + workInProgress.updateQueue.hasForceUpdate) + ) + shouldUpdate = !0; + else { + var instance$jscomp$0 = workInProgress.stateNode, + type = workInProgress.type; + shouldUpdate = + "function" === typeof instance$jscomp$0.shouldComponentUpdate + ? instance$jscomp$0.shouldComponentUpdate( + shouldUpdate, + renderExpirationTime, + newUnmaskedContext + ) + : type.prototype && type.prototype.isPureReactComponent + ? !shallowEqual(oldProps, shouldUpdate) || + !shallowEqual(oldContext, renderExpirationTime) + : !0; + } + shouldUpdate + ? ("function" === typeof instance.componentWillUpdate && + instance.componentWillUpdate( + newProps, + renderExpirationTime, + newUnmaskedContext + ), + "function" === typeof instance.componentDidUpdate && + (workInProgress.effectTag |= 4)) + : ("function" !== typeof instance.componentDidUpdate || + (oldProps === current.memoizedProps && + oldContext === current.memoizedState) || + (workInProgress.effectTag |= 4), + memoizeProps(workInProgress, newProps), + memoizeState(workInProgress, renderExpirationTime)); + instance.props = newProps; + instance.state = renderExpirationTime; + instance.context = newUnmaskedContext; + return shouldUpdate; + } + }; +} +var isArray$1 = Array.isArray, + ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator, + REACT_ELEMENT_TYPE, + REACT_CALL_TYPE, + REACT_RETURN_TYPE, + REACT_FRAGMENT_TYPE; +"function" === typeof Symbol && Symbol["for"] + ? ((REACT_ELEMENT_TYPE = Symbol["for"]("react.element")), + (REACT_CALL_TYPE = Symbol["for"]("react.call")), + (REACT_RETURN_TYPE = Symbol["for"]("react.return")), + (REACT_FRAGMENT_TYPE = Symbol["for"]("react.fragment"))) + : ((REACT_ELEMENT_TYPE = 60103), + (REACT_CALL_TYPE = 60104), + (REACT_RETURN_TYPE = 60105), + (REACT_FRAGMENT_TYPE = 60107)); +function getIteratorFn(maybeIterable) { + if (null === maybeIterable || "undefined" === typeof maybeIterable) + return null; + maybeIterable = + (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL]) || + maybeIterable["@@iterator"]; + return "function" === typeof maybeIterable ? maybeIterable : null; +} +function coerceRef(current, element) { + var mixedRef = element.ref; + if (null !== mixedRef && "function" !== typeof mixedRef) { + if (element._owner) { + element = element._owner; + var inst = void 0; + element && + (invariant( + 2 === element.tag, + "Stateless function components cannot have refs." + ), + (inst = element.stateNode)); + invariant( + inst, + "Missing owner for string ref %s. This error is likely caused by a bug in React. Please file an issue.", + mixedRef + ); + var stringRef = "" + mixedRef; + if ( + null !== current && + null !== current.ref && + current.ref._stringRef === stringRef + ) + return current.ref; + current = function(value) { + var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs; + null === value ? delete refs[stringRef] : (refs[stringRef] = value); + }; + current._stringRef = stringRef; + return current; + } + invariant( + "string" === typeof mixedRef, + "Expected ref to be a function or a string." + ); + invariant( + element._owner, + "Element ref was specified as a string (%s) but no owner was set. You may have multiple copies of React loaded. (details: https://fb.me/react-refs-must-have-owner).", + mixedRef + ); + } + return mixedRef; +} +function throwOnInvalidObjectType(returnFiber, newChild) { + "textarea" !== returnFiber.type && + invariant( + !1, + "Objects are not valid as a React child (found: %s).%s", + "[object Object]" === Object.prototype.toString.call(newChild) + ? "object with keys {" + Object.keys(newChild).join(", ") + "}" + : newChild, + "" + ); +} +function ChildReconciler(shouldClone, shouldTrackSideEffects) { + function deleteChild(returnFiber, childToDelete) { + if (shouldTrackSideEffects) { + if (!shouldClone) { + if (null === childToDelete.alternate) return; + childToDelete = childToDelete.alternate; + } + var last = returnFiber.lastEffect; + null !== last + ? ((last.nextEffect = childToDelete), + (returnFiber.lastEffect = childToDelete)) + : (returnFiber.firstEffect = returnFiber.lastEffect = childToDelete); + childToDelete.nextEffect = null; + childToDelete.effectTag = 8; + } + } + function deleteRemainingChildren(returnFiber, currentFirstChild) { + if (!shouldTrackSideEffects) return null; + for (; null !== currentFirstChild; ) + deleteChild(returnFiber, currentFirstChild), + (currentFirstChild = currentFirstChild.sibling); + return null; + } + function mapRemainingChildren(returnFiber, currentFirstChild) { + for (returnFiber = new Map(); null !== currentFirstChild; ) + null !== currentFirstChild.key + ? returnFiber.set(currentFirstChild.key, currentFirstChild) + : returnFiber.set(currentFirstChild.index, currentFirstChild), + (currentFirstChild = currentFirstChild.sibling); + return returnFiber; + } + function useFiber(fiber, pendingProps, expirationTime) { + if (shouldClone) + return ( + (fiber = createWorkInProgress(fiber, pendingProps, expirationTime)), + (fiber.index = 0), + (fiber.sibling = null), + fiber + ); + fiber.expirationTime = expirationTime; + fiber.effectTag = 0; + fiber.index = 0; + fiber.sibling = null; + fiber.pendingProps = pendingProps; + return fiber; + } + function placeChild(newFiber, lastPlacedIndex, newIndex) { + newFiber.index = newIndex; + if (!shouldTrackSideEffects) return lastPlacedIndex; + newIndex = newFiber.alternate; + if (null !== newIndex) + return ( + (newIndex = newIndex.index), + newIndex < lastPlacedIndex + ? ((newFiber.effectTag = 2), lastPlacedIndex) + : newIndex + ); + newFiber.effectTag = 2; + return lastPlacedIndex; + } + function placeSingleChild(newFiber) { + shouldTrackSideEffects && + null === newFiber.alternate && + (newFiber.effectTag = 2); + return newFiber; + } + function updateTextNode(returnFiber, current, textContent, expirationTime) { + if (null === current || 6 !== current.tag) + return ( + (current = createFiberFromText( + textContent, + returnFiber.internalContextTag, + expirationTime + )), + (current["return"] = returnFiber), + current + ); + current = useFiber(current, textContent, expirationTime); + current["return"] = returnFiber; + return current; + } + function updateElement(returnFiber, current, element, expirationTime) { + if (null !== current && current.type === element.type) + return ( + (expirationTime = useFiber(current, element.props, expirationTime)), + (expirationTime.ref = coerceRef(current, element)), + (expirationTime["return"] = returnFiber), + expirationTime + ); + expirationTime = createFiberFromElement( + element, + returnFiber.internalContextTag, + expirationTime + ); + expirationTime.ref = coerceRef(current, element); + expirationTime["return"] = returnFiber; + return expirationTime; + } + function updateCall(returnFiber, current, call, expirationTime) { + if (null === current || 7 !== current.tag) + return ( + (current = createFiberFromCall( + call, + returnFiber.internalContextTag, + expirationTime + )), + (current["return"] = returnFiber), + current + ); + current = useFiber(current, call, expirationTime); + current["return"] = returnFiber; + return current; + } + function updateReturn(returnFiber, current, returnNode, expirationTime) { + if (null === current || 9 !== current.tag) + return ( + (current = createFiberFromReturn( + returnNode, + returnFiber.internalContextTag, + expirationTime + )), + (current.type = returnNode.value), + (current["return"] = returnFiber), + current + ); + current = useFiber(current, null, expirationTime); + current.type = returnNode.value; + current["return"] = returnFiber; + return current; + } + function updatePortal(returnFiber, current, portal, expirationTime) { + if ( + null === current || + 4 !== current.tag || + current.stateNode.containerInfo !== portal.containerInfo || + current.stateNode.implementation !== portal.implementation + ) + return ( + (current = createFiberFromPortal( + portal, + returnFiber.internalContextTag, + expirationTime + )), + (current["return"] = returnFiber), + current + ); + current = useFiber(current, portal.children || [], expirationTime); + current["return"] = returnFiber; + return current; + } + function updateFragment(returnFiber, current, fragment, expirationTime, key) { + if (null === current || 10 !== current.tag) + return ( + (current = createFiberFromFragment( + fragment, + returnFiber.internalContextTag, + expirationTime, + key + )), + (current["return"] = returnFiber), + current + ); + current = useFiber(current, fragment, expirationTime); + current["return"] = returnFiber; + return current; + } + function createChild(returnFiber, newChild, expirationTime) { + if ("string" === typeof newChild || "number" === typeof newChild) + return ( + (newChild = createFiberFromText( + "" + newChild, + returnFiber.internalContextTag, + expirationTime + )), + (newChild["return"] = returnFiber), + newChild + ); + if ("object" === typeof newChild && null !== newChild) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + if (newChild.type === REACT_FRAGMENT_TYPE) + return ( + (newChild = createFiberFromFragment( + newChild.props.children, + returnFiber.internalContextTag, + expirationTime, + newChild.key + )), + (newChild["return"] = returnFiber), + newChild + ); + expirationTime = createFiberFromElement( + newChild, + returnFiber.internalContextTag, + expirationTime + ); + expirationTime.ref = coerceRef(null, newChild); + expirationTime["return"] = returnFiber; + return expirationTime; + case REACT_CALL_TYPE: + return ( + (newChild = createFiberFromCall( + newChild, + returnFiber.internalContextTag, + expirationTime + )), + (newChild["return"] = returnFiber), + newChild + ); + case REACT_RETURN_TYPE: + return ( + (expirationTime = createFiberFromReturn( + newChild, + returnFiber.internalContextTag, + expirationTime + )), + (expirationTime.type = newChild.value), + (expirationTime["return"] = returnFiber), + expirationTime + ); + case REACT_PORTAL_TYPE: + return ( + (newChild = createFiberFromPortal( + newChild, + returnFiber.internalContextTag, + expirationTime + )), + (newChild["return"] = returnFiber), + newChild + ); + } + if (isArray$1(newChild) || getIteratorFn(newChild)) + return ( + (newChild = createFiberFromFragment( + newChild, + returnFiber.internalContextTag, + expirationTime, + null + )), + (newChild["return"] = returnFiber), + newChild + ); + throwOnInvalidObjectType(returnFiber, newChild); + } + return null; + } + function updateSlot(returnFiber, oldFiber, newChild, expirationTime) { + var key = null !== oldFiber ? oldFiber.key : null; + if ("string" === typeof newChild || "number" === typeof newChild) + return null !== key + ? null + : updateTextNode(returnFiber, oldFiber, "" + newChild, expirationTime); + if ("object" === typeof newChild && null !== newChild) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + return newChild.key === key + ? newChild.type === REACT_FRAGMENT_TYPE + ? updateFragment( + returnFiber, + oldFiber, + newChild.props.children, + expirationTime, + key + ) + : updateElement(returnFiber, oldFiber, newChild, expirationTime) + : null; + case REACT_CALL_TYPE: + return newChild.key === key + ? updateCall(returnFiber, oldFiber, newChild, expirationTime) + : null; + case REACT_RETURN_TYPE: + return null === key + ? updateReturn(returnFiber, oldFiber, newChild, expirationTime) + : null; + case REACT_PORTAL_TYPE: + return newChild.key === key + ? updatePortal(returnFiber, oldFiber, newChild, expirationTime) + : null; + } + if (isArray$1(newChild) || getIteratorFn(newChild)) + return null !== key + ? null + : updateFragment( + returnFiber, + oldFiber, + newChild, + expirationTime, + null + ); + throwOnInvalidObjectType(returnFiber, newChild); + } + return null; + } + function updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChild, + expirationTime + ) { + if ("string" === typeof newChild || "number" === typeof newChild) + return ( + (existingChildren = existingChildren.get(newIdx) || null), + updateTextNode( + returnFiber, + existingChildren, + "" + newChild, + expirationTime + ) + ); + if ("object" === typeof newChild && null !== newChild) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + return ( + (existingChildren = + existingChildren.get( + null === newChild.key ? newIdx : newChild.key + ) || null), + newChild.type === REACT_FRAGMENT_TYPE + ? updateFragment( + returnFiber, + existingChildren, + newChild.props.children, + expirationTime, + newChild.key + ) + : updateElement( + returnFiber, + existingChildren, + newChild, + expirationTime + ) + ); + case REACT_CALL_TYPE: + return ( + (existingChildren = + existingChildren.get( + null === newChild.key ? newIdx : newChild.key + ) || null), + updateCall(returnFiber, existingChildren, newChild, expirationTime) + ); + case REACT_RETURN_TYPE: + return ( + (existingChildren = existingChildren.get(newIdx) || null), + updateReturn( + returnFiber, + existingChildren, + newChild, + expirationTime + ) + ); + case REACT_PORTAL_TYPE: + return ( + (existingChildren = + existingChildren.get( + null === newChild.key ? newIdx : newChild.key + ) || null), + updatePortal( + returnFiber, + existingChildren, + newChild, + expirationTime + ) + ); + } + if (isArray$1(newChild) || getIteratorFn(newChild)) + return ( + (existingChildren = existingChildren.get(newIdx) || null), + updateFragment( + returnFiber, + existingChildren, + newChild, + expirationTime, + null + ) + ); + throwOnInvalidObjectType(returnFiber, newChild); + } + return null; + } + function reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChildren, + expirationTime + ) { + for ( + var resultingFirstChild = null, + previousNewFiber = null, + oldFiber = currentFirstChild, + newIdx = (currentFirstChild = 0), + nextOldFiber = null; + null !== oldFiber && newIdx < newChildren.length; + newIdx++ + ) { + oldFiber.index > newIdx + ? ((nextOldFiber = oldFiber), (oldFiber = null)) + : (nextOldFiber = oldFiber.sibling); + var newFiber = updateSlot( + returnFiber, + oldFiber, + newChildren[newIdx], + expirationTime + ); + if (null === newFiber) { + null === oldFiber && (oldFiber = nextOldFiber); + break; + } + shouldTrackSideEffects && + oldFiber && + null === newFiber.alternate && + deleteChild(returnFiber, oldFiber); + currentFirstChild = placeChild(newFiber, currentFirstChild, newIdx); + null === previousNewFiber + ? (resultingFirstChild = newFiber) + : (previousNewFiber.sibling = newFiber); + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } + if (newIdx === newChildren.length) + return ( + deleteRemainingChildren(returnFiber, oldFiber), resultingFirstChild + ); + if (null === oldFiber) { + for (; newIdx < newChildren.length; newIdx++) + if ( + (oldFiber = createChild( + returnFiber, + newChildren[newIdx], + expirationTime + )) + ) + (currentFirstChild = placeChild(oldFiber, currentFirstChild, newIdx)), + null === previousNewFiber + ? (resultingFirstChild = oldFiber) + : (previousNewFiber.sibling = oldFiber), + (previousNewFiber = oldFiber); + return resultingFirstChild; + } + for ( + oldFiber = mapRemainingChildren(returnFiber, oldFiber); + newIdx < newChildren.length; + newIdx++ + ) + if ( + (nextOldFiber = updateFromMap( + oldFiber, + returnFiber, + newIdx, + newChildren[newIdx], + expirationTime + )) + ) { + if (shouldTrackSideEffects && null !== nextOldFiber.alternate) + oldFiber["delete"]( + null === nextOldFiber.key ? newIdx : nextOldFiber.key + ); + currentFirstChild = placeChild(nextOldFiber, currentFirstChild, newIdx); + null === previousNewFiber + ? (resultingFirstChild = nextOldFiber) + : (previousNewFiber.sibling = nextOldFiber); + previousNewFiber = nextOldFiber; + } + shouldTrackSideEffects && + oldFiber.forEach(function(child) { + return deleteChild(returnFiber, child); + }); + return resultingFirstChild; + } + function reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChildrenIterable, + expirationTime + ) { + var iteratorFn = getIteratorFn(newChildrenIterable); + invariant( + "function" === typeof iteratorFn, + "An object is not an iterable. This error is likely caused by a bug in React. Please file an issue." + ); + newChildrenIterable = iteratorFn.call(newChildrenIterable); + invariant( + null != newChildrenIterable, + "An iterable object provided no iterator." + ); + for ( + var previousNewFiber = (iteratorFn = null), + oldFiber = currentFirstChild, + newIdx = (currentFirstChild = 0), + nextOldFiber = null, + step = newChildrenIterable.next(); + null !== oldFiber && !step.done; + newIdx++, step = newChildrenIterable.next() + ) { + oldFiber.index > newIdx + ? ((nextOldFiber = oldFiber), (oldFiber = null)) + : (nextOldFiber = oldFiber.sibling); + var newFiber = updateSlot( + returnFiber, + oldFiber, + step.value, + expirationTime + ); + if (null === newFiber) { + oldFiber || (oldFiber = nextOldFiber); + break; + } + shouldTrackSideEffects && + oldFiber && + null === newFiber.alternate && + deleteChild(returnFiber, oldFiber); + currentFirstChild = placeChild(newFiber, currentFirstChild, newIdx); + null === previousNewFiber + ? (iteratorFn = newFiber) + : (previousNewFiber.sibling = newFiber); + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } + if (step.done) + return deleteRemainingChildren(returnFiber, oldFiber), iteratorFn; + if (null === oldFiber) { + for (; !step.done; newIdx++, step = newChildrenIterable.next()) + (step = createChild(returnFiber, step.value, expirationTime)), + null !== step && + ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), + null === previousNewFiber + ? (iteratorFn = step) + : (previousNewFiber.sibling = step), + (previousNewFiber = step)); + return iteratorFn; + } + for ( + oldFiber = mapRemainingChildren(returnFiber, oldFiber); + !step.done; + newIdx++, step = newChildrenIterable.next() + ) + if ( + ((step = updateFromMap( + oldFiber, + returnFiber, + newIdx, + step.value, + expirationTime + )), + null !== step) + ) { + if (shouldTrackSideEffects && null !== step.alternate) + oldFiber["delete"](null === step.key ? newIdx : step.key); + currentFirstChild = placeChild(step, currentFirstChild, newIdx); + null === previousNewFiber + ? (iteratorFn = step) + : (previousNewFiber.sibling = step); + previousNewFiber = step; + } + shouldTrackSideEffects && + oldFiber.forEach(function(child) { + return deleteChild(returnFiber, child); + }); + return iteratorFn; + } + return function(returnFiber, currentFirstChild, newChild, expirationTime) { + var isObject = "object" === typeof newChild && null !== newChild; + if (isObject) + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + a: { + var key = newChild.key; + for (isObject = currentFirstChild; null !== isObject; ) { + if (isObject.key === key) + if ( + 10 === isObject.tag + ? newChild.type === REACT_FRAGMENT_TYPE + : isObject.type === newChild.type + ) { + deleteRemainingChildren(returnFiber, isObject.sibling); + currentFirstChild = useFiber( + isObject, + newChild.type === REACT_FRAGMENT_TYPE + ? newChild.props.children + : newChild.props, + expirationTime + ); + currentFirstChild.ref = coerceRef(isObject, newChild); + currentFirstChild["return"] = returnFiber; + returnFiber = currentFirstChild; + break a; + } else { + deleteRemainingChildren(returnFiber, isObject); + break; + } + else deleteChild(returnFiber, isObject); + isObject = isObject.sibling; + } + newChild.type === REACT_FRAGMENT_TYPE + ? ((newChild = createFiberFromFragment( + newChild.props.children, + returnFiber.internalContextTag, + expirationTime, + newChild.key + )), + (newChild["return"] = returnFiber), + (returnFiber = newChild)) + : ((expirationTime = createFiberFromElement( + newChild, + returnFiber.internalContextTag, + expirationTime + )), + (expirationTime.ref = coerceRef(currentFirstChild, newChild)), + (expirationTime["return"] = returnFiber), + (returnFiber = expirationTime)); + } + return placeSingleChild(returnFiber); + case REACT_CALL_TYPE: + a: { + for (isObject = newChild.key; null !== currentFirstChild; ) { + if (currentFirstChild.key === isObject) + if (7 === currentFirstChild.tag) { + deleteRemainingChildren( + returnFiber, + currentFirstChild.sibling + ); + newChild = useFiber( + currentFirstChild, + newChild, + expirationTime + ); + newChild["return"] = returnFiber; + returnFiber = newChild; + break a; + } else { + deleteRemainingChildren(returnFiber, currentFirstChild); + break; + } + else deleteChild(returnFiber, currentFirstChild); + currentFirstChild = currentFirstChild.sibling; + } + newChild = createFiberFromCall( + newChild, + returnFiber.internalContextTag, + expirationTime + ); + newChild["return"] = returnFiber; + returnFiber = newChild; + } + return placeSingleChild(returnFiber); + case REACT_RETURN_TYPE: + a: { + if (null !== currentFirstChild) + if (9 === currentFirstChild.tag) { + deleteRemainingChildren(returnFiber, currentFirstChild.sibling); + currentFirstChild = useFiber( + currentFirstChild, + null, + expirationTime + ); + currentFirstChild.type = newChild.value; + currentFirstChild["return"] = returnFiber; + returnFiber = currentFirstChild; + break a; + } else deleteRemainingChildren(returnFiber, currentFirstChild); + currentFirstChild = createFiberFromReturn( + newChild, + returnFiber.internalContextTag, + expirationTime + ); + currentFirstChild.type = newChild.value; + currentFirstChild["return"] = returnFiber; + returnFiber = currentFirstChild; + } + return placeSingleChild(returnFiber); + case REACT_PORTAL_TYPE: + a: { + for (isObject = newChild.key; null !== currentFirstChild; ) { + if (currentFirstChild.key === isObject) + if ( + 4 === currentFirstChild.tag && + currentFirstChild.stateNode.containerInfo === + newChild.containerInfo && + currentFirstChild.stateNode.implementation === + newChild.implementation + ) { + deleteRemainingChildren( + returnFiber, + currentFirstChild.sibling + ); + newChild = useFiber( + currentFirstChild, + newChild.children || [], + expirationTime + ); + newChild["return"] = returnFiber; + returnFiber = newChild; + break a; + } else { + deleteRemainingChildren(returnFiber, currentFirstChild); + break; + } + else deleteChild(returnFiber, currentFirstChild); + currentFirstChild = currentFirstChild.sibling; + } + newChild = createFiberFromPortal( + newChild, + returnFiber.internalContextTag, + expirationTime + ); + newChild["return"] = returnFiber; + returnFiber = newChild; + } + return placeSingleChild(returnFiber); + } + if ("string" === typeof newChild || "number" === typeof newChild) + return ( + (newChild = "" + newChild), + null !== currentFirstChild && 6 === currentFirstChild.tag + ? (deleteRemainingChildren(returnFiber, currentFirstChild.sibling), + (newChild = useFiber(currentFirstChild, newChild, expirationTime))) + : (deleteRemainingChildren(returnFiber, currentFirstChild), + (newChild = createFiberFromText( + newChild, + returnFiber.internalContextTag, + expirationTime + ))), + (newChild["return"] = returnFiber), + (returnFiber = newChild), + placeSingleChild(returnFiber) + ); + if (isArray$1(newChild)) + return reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChild, + expirationTime + ); + if (getIteratorFn(newChild)) + return reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChild, + expirationTime + ); + isObject && throwOnInvalidObjectType(returnFiber, newChild); + if ("undefined" === typeof newChild) + switch (returnFiber.tag) { + case 2: + case 1: + (newChild = returnFiber.type), + invariant( + !1, + "%s(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.", + newChild.displayName || newChild.name || "Component" + ); + } + return deleteRemainingChildren(returnFiber, currentFirstChild); + }; +} +var reconcileChildFibers = ChildReconciler(!0, !0), + reconcileChildFibersInPlace = ChildReconciler(!1, !0), + mountChildFibersInPlace = ChildReconciler(!1, !1); +function ReactFiberBeginWork( + config, + hostContext, + hydrationContext, + scheduleWork, + computeExpirationForFiber +) { + function reconcileChildren(current, workInProgress, nextChildren) { + reconcileChildrenAtExpirationTime( + current, + workInProgress, + nextChildren, + workInProgress.expirationTime + ); + } + function reconcileChildrenAtExpirationTime( + current, + workInProgress, + nextChildren, + renderExpirationTime + ) { + workInProgress.child = + null === current + ? mountChildFibersInPlace( + workInProgress, + workInProgress.child, + nextChildren, + renderExpirationTime + ) + : current.child === workInProgress.child + ? reconcileChildFibers( + workInProgress, + workInProgress.child, + nextChildren, + renderExpirationTime + ) + : reconcileChildFibersInPlace( + workInProgress, + workInProgress.child, + nextChildren, + renderExpirationTime + ); + } + function markRef(current, workInProgress) { + var ref = workInProgress.ref; + null === ref || + (current && current.ref === ref) || + (workInProgress.effectTag |= 128); + } + function finishClassComponent( + current, + workInProgress, + shouldUpdate, + hasContext + ) { + markRef(current, workInProgress); + if (!shouldUpdate) + return ( + hasContext && invalidateContextProvider(workInProgress, !1), + bailoutOnAlreadyFinishedWork(current, workInProgress) + ); + shouldUpdate = workInProgress.stateNode; + ReactCurrentOwner.current = workInProgress; + var nextChildren = shouldUpdate.render(); + workInProgress.effectTag |= 1; + reconcileChildren(current, workInProgress, nextChildren); + workInProgress.memoizedState = shouldUpdate.state; + workInProgress.memoizedProps = shouldUpdate.props; + hasContext && invalidateContextProvider(workInProgress, !0); + return workInProgress.child; + } + function pushHostRootContext(workInProgress) { + var root = workInProgress.stateNode; + root.pendingContext + ? pushTopLevelContextObject( + workInProgress, + root.pendingContext, + root.pendingContext !== root.context + ) + : root.context && + pushTopLevelContextObject(workInProgress, root.context, !1); + pushHostContainer(workInProgress, root.containerInfo); + } + function bailoutOnAlreadyFinishedWork(current, workInProgress) { + invariant( + null === current || workInProgress.child === current.child, + "Resuming work not yet implemented." + ); + if (null !== workInProgress.child) { + current = workInProgress.child; + var newChild = createWorkInProgress( + current, + current.pendingProps, + current.expirationTime + ); + workInProgress.child = newChild; + for (newChild["return"] = workInProgress; null !== current.sibling; ) + (current = current.sibling), + (newChild = newChild.sibling = createWorkInProgress( + current, + current.pendingProps, + current.expirationTime + )), + (newChild["return"] = workInProgress); + newChild.sibling = null; + } + return workInProgress.child; + } + function bailoutOnLowPriority(current, workInProgress) { + switch (workInProgress.tag) { + case 3: + pushHostRootContext(workInProgress); + break; + case 2: + pushContextProvider(workInProgress); + break; + case 4: + pushHostContainer( + workInProgress, + workInProgress.stateNode.containerInfo + ); + } + return null; + } + var shouldSetTextContent = config.shouldSetTextContent, + useSyncScheduling = config.useSyncScheduling, + shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree, + pushHostContext = hostContext.pushHostContext, + pushHostContainer = hostContext.pushHostContainer, + enterHydrationState = hydrationContext.enterHydrationState, + resetHydrationState = hydrationContext.resetHydrationState, + tryToClaimNextHydratableInstance = + hydrationContext.tryToClaimNextHydratableInstance; + config = ReactFiberClassComponent( + scheduleWork, + computeExpirationForFiber, + function(workInProgress, nextProps) { + workInProgress.memoizedProps = nextProps; + }, + function(workInProgress, nextState) { + workInProgress.memoizedState = nextState; + } + ); + var adoptClassInstance = config.adoptClassInstance, + constructClassInstance = config.constructClassInstance, + mountClassInstance = config.mountClassInstance, + updateClassInstance = config.updateClassInstance; + return { + beginWork: function(current, workInProgress, renderExpirationTime) { + if ( + 0 === workInProgress.expirationTime || + workInProgress.expirationTime > renderExpirationTime + ) + return bailoutOnLowPriority(current, workInProgress); + switch (workInProgress.tag) { + case 0: + invariant( + null === current, + "An indeterminate component should never have mounted. This error is likely caused by a bug in React. Please file an issue." + ); + var fn = workInProgress.type, + props = workInProgress.pendingProps, + unmaskedContext = getUnmaskedContext(workInProgress); + unmaskedContext = getMaskedContext(workInProgress, unmaskedContext); + fn = fn(props, unmaskedContext); + workInProgress.effectTag |= 1; + "object" === typeof fn && + null !== fn && + "function" === typeof fn.render + ? ((workInProgress.tag = 2), + (props = pushContextProvider(workInProgress)), + adoptClassInstance(workInProgress, fn), + mountClassInstance(workInProgress, renderExpirationTime), + (workInProgress = finishClassComponent( + current, + workInProgress, + !0, + props + ))) + : ((workInProgress.tag = 1), + reconcileChildren(current, workInProgress, fn), + (workInProgress.memoizedProps = props), + (workInProgress = workInProgress.child)); + return workInProgress; + case 1: + a: { + props = workInProgress.type; + renderExpirationTime = workInProgress.pendingProps; + fn = workInProgress.memoizedProps; + if (didPerformWorkStackCursor.current) + null === renderExpirationTime && (renderExpirationTime = fn); + else if ( + null === renderExpirationTime || + fn === renderExpirationTime + ) { + workInProgress = bailoutOnAlreadyFinishedWork( + current, + workInProgress + ); + break a; + } + fn = getUnmaskedContext(workInProgress); + fn = getMaskedContext(workInProgress, fn); + props = props(renderExpirationTime, fn); + workInProgress.effectTag |= 1; + reconcileChildren(current, workInProgress, props); + workInProgress.memoizedProps = renderExpirationTime; + workInProgress = workInProgress.child; + } + return workInProgress; + case 2: + return ( + (props = pushContextProvider(workInProgress)), + (fn = void 0), + null === current + ? workInProgress.stateNode + ? invariant(!1, "Resuming work not yet implemented.") + : (constructClassInstance( + workInProgress, + workInProgress.pendingProps + ), + mountClassInstance(workInProgress, renderExpirationTime), + (fn = !0)) + : (fn = updateClassInstance( + current, + workInProgress, + renderExpirationTime + )), + finishClassComponent(current, workInProgress, fn, props) + ); + case 3: + return ( + pushHostRootContext(workInProgress), + (props = workInProgress.updateQueue), + null !== props + ? ((fn = workInProgress.memoizedState), + (props = processUpdateQueue( + current, + workInProgress, + props, + null, + null, + renderExpirationTime + )), + fn === props + ? (resetHydrationState(), + (workInProgress = bailoutOnAlreadyFinishedWork( + current, + workInProgress + ))) + : ((fn = props.element), + (unmaskedContext = workInProgress.stateNode), + (null === current || null === current.child) && + unmaskedContext.hydrate && + enterHydrationState(workInProgress) + ? ((workInProgress.effectTag |= 2), + (workInProgress.child = mountChildFibersInPlace( + workInProgress, + workInProgress.child, + fn, + renderExpirationTime + ))) + : (resetHydrationState(), + reconcileChildren(current, workInProgress, fn)), + (workInProgress.memoizedState = props), + (workInProgress = workInProgress.child))) + : (resetHydrationState(), + (workInProgress = bailoutOnAlreadyFinishedWork( + current, + workInProgress + ))), + workInProgress + ); + case 5: + pushHostContext(workInProgress); + null === current && tryToClaimNextHydratableInstance(workInProgress); + props = workInProgress.type; + var memoizedProps = workInProgress.memoizedProps; + fn = workInProgress.pendingProps; + null === fn && + ((fn = memoizedProps), + invariant( + null !== fn, + "We should always have pending or current props. This error is likely caused by a bug in React. Please file an issue." + )); + unmaskedContext = null !== current ? current.memoizedProps : null; + didPerformWorkStackCursor.current || + (null !== fn && memoizedProps !== fn) + ? ((memoizedProps = fn.children), + shouldSetTextContent(props, fn) + ? (memoizedProps = null) + : unmaskedContext && + shouldSetTextContent(props, unmaskedContext) && + (workInProgress.effectTag |= 16), + markRef(current, workInProgress), + 2147483647 !== renderExpirationTime && + !useSyncScheduling && + shouldDeprioritizeSubtree(props, fn) + ? ((workInProgress.expirationTime = 2147483647), + (workInProgress = null)) + : (reconcileChildren(current, workInProgress, memoizedProps), + (workInProgress.memoizedProps = fn), + (workInProgress = workInProgress.child))) + : (workInProgress = bailoutOnAlreadyFinishedWork( + current, + workInProgress + )); + return workInProgress; + case 6: + return ( + null === current && + tryToClaimNextHydratableInstance(workInProgress), + (current = workInProgress.pendingProps), + null === current && (current = workInProgress.memoizedProps), + (workInProgress.memoizedProps = current), + null + ); + case 8: + workInProgress.tag = 7; + case 7: + props = workInProgress.pendingProps; + if (didPerformWorkStackCursor.current) + null === props && + ((props = current && current.memoizedProps), + invariant( + null !== props, + "We should always have pending or current props. This error is likely caused by a bug in React. Please file an issue." + )); + else if (null === props || workInProgress.memoizedProps === props) + props = workInProgress.memoizedProps; + fn = props.children; + workInProgress.stateNode = + null === current + ? mountChildFibersInPlace( + workInProgress, + workInProgress.stateNode, + fn, + renderExpirationTime + ) + : current.child === workInProgress.child + ? reconcileChildFibers( + workInProgress, + workInProgress.stateNode, + fn, + renderExpirationTime + ) + : reconcileChildFibersInPlace( + workInProgress, + workInProgress.stateNode, + fn, + renderExpirationTime + ); + workInProgress.memoizedProps = props; + return workInProgress.stateNode; + case 9: + return null; + case 4: + a: { + pushHostContainer( + workInProgress, + workInProgress.stateNode.containerInfo + ); + props = workInProgress.pendingProps; + if (didPerformWorkStackCursor.current) + null === props && + ((props = current && current.memoizedProps), + invariant( + null != props, + "We should always have pending or current props. This error is likely caused by a bug in React. Please file an issue." + )); + else if (null === props || workInProgress.memoizedProps === props) { + workInProgress = bailoutOnAlreadyFinishedWork( + current, + workInProgress + ); + break a; + } + null === current + ? (workInProgress.child = reconcileChildFibersInPlace( + workInProgress, + workInProgress.child, + props, + renderExpirationTime + )) + : reconcileChildren(current, workInProgress, props); + workInProgress.memoizedProps = props; + workInProgress = workInProgress.child; + } + return workInProgress; + case 10: + a: { + renderExpirationTime = workInProgress.pendingProps; + if (didPerformWorkStackCursor.current) + null === renderExpirationTime && + (renderExpirationTime = workInProgress.memoizedProps); + else if ( + null === renderExpirationTime || + workInProgress.memoizedProps === renderExpirationTime + ) { + workInProgress = bailoutOnAlreadyFinishedWork( + current, + workInProgress + ); + break a; + } + reconcileChildren(current, workInProgress, renderExpirationTime); + workInProgress.memoizedProps = renderExpirationTime; + workInProgress = workInProgress.child; + } + return workInProgress; + default: + invariant( + !1, + "Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue." + ); + } + }, + beginFailedWork: function(current, workInProgress, renderExpirationTime) { + switch (workInProgress.tag) { + case 2: + pushContextProvider(workInProgress); + break; + case 3: + pushHostRootContext(workInProgress); + break; + default: + invariant( + !1, + "Invalid type of work. This error is likely caused by a bug in React. Please file an issue." + ); + } + workInProgress.effectTag |= 64; + null === current + ? (workInProgress.child = null) + : workInProgress.child !== current.child && + (workInProgress.child = current.child); + if ( + 0 === workInProgress.expirationTime || + workInProgress.expirationTime > renderExpirationTime + ) + return bailoutOnLowPriority(current, workInProgress); + workInProgress.firstEffect = null; + workInProgress.lastEffect = null; + reconcileChildrenAtExpirationTime( + current, + workInProgress, + null, + renderExpirationTime + ); + 2 === workInProgress.tag && + ((current = workInProgress.stateNode), + (workInProgress.memoizedProps = current.props), + (workInProgress.memoizedState = current.state)); + return workInProgress.child; + } + }; +} +function ReactFiberCompleteWork(config, hostContext, hydrationContext) { + function markUpdate(workInProgress) { + workInProgress.effectTag |= 4; + } + var createInstance = config.createInstance, + createTextInstance = config.createTextInstance, + appendInitialChild = config.appendInitialChild, + finalizeInitialChildren = config.finalizeInitialChildren, + prepareUpdate = config.prepareUpdate, + persistence = config.persistence, + getRootHostContainer = hostContext.getRootHostContainer, + popHostContext = hostContext.popHostContext, + getHostContext = hostContext.getHostContext, + popHostContainer = hostContext.popHostContainer, + prepareToHydrateHostInstance = + hydrationContext.prepareToHydrateHostInstance, + prepareToHydrateHostTextInstance = + hydrationContext.prepareToHydrateHostTextInstance, + popHydrationState = hydrationContext.popHydrationState, + updateHostContainer = void 0, + updateHostComponent = void 0, + updateHostText = void 0; + config.mutation + ? ((updateHostContainer = function() {}), + (updateHostComponent = function(current, workInProgress, updatePayload) { + (workInProgress.updateQueue = updatePayload) && + markUpdate(workInProgress); + }), + (updateHostText = function(current, workInProgress, oldText, newText) { + oldText !== newText && markUpdate(workInProgress); + })) + : persistence + ? invariant(!1, "Persistent reconciler is disabled.") + : invariant(!1, "Noop reconciler is disabled."); + return { + completeWork: function(current, workInProgress, renderExpirationTime) { + var newProps = workInProgress.pendingProps; + if (null === newProps) newProps = workInProgress.memoizedProps; + else if ( + 2147483647 !== workInProgress.expirationTime || + 2147483647 === renderExpirationTime + ) + workInProgress.pendingProps = null; + switch (workInProgress.tag) { + case 1: + return null; + case 2: + return popContextProvider(workInProgress), null; + case 3: + popHostContainer(workInProgress); + pop(didPerformWorkStackCursor, workInProgress); + pop(contextStackCursor, workInProgress); + newProps = workInProgress.stateNode; + newProps.pendingContext && + ((newProps.context = newProps.pendingContext), + (newProps.pendingContext = null)); + if (null === current || null === current.child) + popHydrationState(workInProgress), (workInProgress.effectTag &= -3); + updateHostContainer(workInProgress); + return null; + case 5: + popHostContext(workInProgress); + renderExpirationTime = getRootHostContainer(); + var type = workInProgress.type; + if (null !== current && null != workInProgress.stateNode) { + var oldProps = current.memoizedProps, + instance = workInProgress.stateNode, + currentHostContext = getHostContext(); + instance = prepareUpdate( + instance, + type, + oldProps, + newProps, + renderExpirationTime, + currentHostContext + ); + updateHostComponent( + current, + workInProgress, + instance, + type, + oldProps, + newProps, + renderExpirationTime + ); + current.ref !== workInProgress.ref && + (workInProgress.effectTag |= 128); + } else { + if (!newProps) + return ( + invariant( + null !== workInProgress.stateNode, + "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." + ), + null + ); + current = getHostContext(); + if (popHydrationState(workInProgress)) + prepareToHydrateHostInstance( + workInProgress, + renderExpirationTime, + current + ) && markUpdate(workInProgress); + else { + current = createInstance( + type, + newProps, + renderExpirationTime, + current, + workInProgress + ); + a: for (oldProps = workInProgress.child; null !== oldProps; ) { + if (5 === oldProps.tag || 6 === oldProps.tag) + appendInitialChild(current, oldProps.stateNode); + else if (4 !== oldProps.tag && null !== oldProps.child) { + oldProps.child["return"] = oldProps; + oldProps = oldProps.child; + continue; + } + if (oldProps === workInProgress) break; + for (; null === oldProps.sibling; ) { + if ( + null === oldProps["return"] || + oldProps["return"] === workInProgress + ) + break a; + oldProps = oldProps["return"]; + } + oldProps.sibling["return"] = oldProps["return"]; + oldProps = oldProps.sibling; + } + finalizeInitialChildren( + current, + type, + newProps, + renderExpirationTime + ) && markUpdate(workInProgress); + workInProgress.stateNode = current; + } + null !== workInProgress.ref && (workInProgress.effectTag |= 128); + } + return null; + case 6: + if (current && null != workInProgress.stateNode) + updateHostText( + current, + workInProgress, + current.memoizedProps, + newProps + ); + else { + if ("string" !== typeof newProps) + return ( + invariant( + null !== workInProgress.stateNode, + "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." + ), + null + ); + current = getRootHostContainer(); + renderExpirationTime = getHostContext(); + popHydrationState(workInProgress) + ? prepareToHydrateHostTextInstance(workInProgress) && + markUpdate(workInProgress) + : (workInProgress.stateNode = createTextInstance( + newProps, + current, + renderExpirationTime, + workInProgress + )); + } + return null; + case 7: + newProps = workInProgress.memoizedProps; + invariant( + newProps, + "Should be resolved by now. This error is likely caused by a bug in React. Please file an issue." + ); + workInProgress.tag = 8; + type = []; + a: for ( + (oldProps = workInProgress.stateNode) && + (oldProps["return"] = workInProgress); + null !== oldProps; + + ) { + if (5 === oldProps.tag || 6 === oldProps.tag || 4 === oldProps.tag) + invariant(!1, "A call cannot have host component children."); + else if (9 === oldProps.tag) type.push(oldProps.type); + else if (null !== oldProps.child) { + oldProps.child["return"] = oldProps; + oldProps = oldProps.child; + continue; + } + for (; null === oldProps.sibling; ) { + if ( + null === oldProps["return"] || + oldProps["return"] === workInProgress + ) + break a; + oldProps = oldProps["return"]; + } + oldProps.sibling["return"] = oldProps["return"]; + oldProps = oldProps.sibling; + } + oldProps = newProps.handler; + newProps = oldProps(newProps.props, type); + workInProgress.child = reconcileChildFibers( + workInProgress, + null !== current ? current.child : null, + newProps, + renderExpirationTime + ); + return workInProgress.child; + case 8: + return (workInProgress.tag = 7), null; + case 9: + return null; + case 10: + return null; + case 4: + return ( + popHostContainer(workInProgress), + updateHostContainer(workInProgress), + null + ); + case 0: + invariant( + !1, + "An indeterminate component should have become determinate before completing. This error is likely caused by a bug in React. Please file an issue." + ); + default: + invariant( + !1, + "Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue." + ); + } + } + }; +} +function ReactFiberCommitWork(config, captureError) { + function safelyDetachRef(current) { + var ref = current.ref; + if (null !== ref) + try { + ref(null); + } catch (refError) { + captureError(current, refError); + } + } + function commitUnmount(current) { + "function" === typeof onCommitUnmount && onCommitUnmount(current); + switch (current.tag) { + case 2: + safelyDetachRef(current); + var instance = current.stateNode; + if ("function" === typeof instance.componentWillUnmount) + try { + (instance.props = current.memoizedProps), + (instance.state = current.memoizedState), + instance.componentWillUnmount(); + } catch (unmountError) { + captureError(current, unmountError); + } + break; + case 5: + safelyDetachRef(current); + break; + case 7: + commitNestedUnmounts(current.stateNode); + break; + case 4: + mutation && unmountHostComponents(current); + } + } + function commitNestedUnmounts(root) { + for (var node = root; ; ) + if ( + (commitUnmount(node), + null === node.child || (mutation && 4 === node.tag)) + ) { + if (node === root) break; + for (; null === node.sibling; ) { + if (null === node["return"] || node["return"] === root) return; + node = node["return"]; + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } else (node.child["return"] = node), (node = node.child); + } + function isHostParent(fiber) { + return 5 === fiber.tag || 3 === fiber.tag || 4 === fiber.tag; + } + function unmountHostComponents(current) { + for ( + var node = current, + currentParentIsValid = !1, + currentParent = void 0, + currentParentIsContainer = void 0; + ; + + ) { + if (!currentParentIsValid) { + currentParentIsValid = node["return"]; + a: for (;;) { + invariant( + null !== currentParentIsValid, + "Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue." + ); + switch (currentParentIsValid.tag) { + case 5: + currentParent = currentParentIsValid.stateNode; + currentParentIsContainer = !1; + break a; + case 3: + currentParent = currentParentIsValid.stateNode.containerInfo; + currentParentIsContainer = !0; + break a; + case 4: + currentParent = currentParentIsValid.stateNode.containerInfo; + currentParentIsContainer = !0; + break a; + } + currentParentIsValid = currentParentIsValid["return"]; + } + currentParentIsValid = !0; + } + if (5 === node.tag || 6 === node.tag) + commitNestedUnmounts(node), + currentParentIsContainer + ? removeChildFromContainer(currentParent, node.stateNode) + : removeChild(currentParent, node.stateNode); + else if ( + (4 === node.tag + ? (currentParent = node.stateNode.containerInfo) + : commitUnmount(node), + null !== node.child) + ) { + node.child["return"] = node; + node = node.child; + continue; + } + if (node === current) break; + for (; null === node.sibling; ) { + if (null === node["return"] || node["return"] === current) return; + node = node["return"]; + 4 === node.tag && (currentParentIsValid = !1); + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } + } + var getPublicInstance = config.getPublicInstance, + mutation = config.mutation; + config = config.persistence; + mutation || + (config + ? invariant(!1, "Persistent reconciler is disabled.") + : invariant(!1, "Noop reconciler is disabled.")); + var commitMount = mutation.commitMount, + commitUpdate = mutation.commitUpdate, + resetTextContent = mutation.resetTextContent, + commitTextUpdate = mutation.commitTextUpdate, + appendChild = mutation.appendChild, + appendChildToContainer = mutation.appendChildToContainer, + insertBefore = mutation.insertBefore, + insertInContainerBefore = mutation.insertInContainerBefore, + removeChild = mutation.removeChild, + removeChildFromContainer = mutation.removeChildFromContainer; + return { + commitResetTextContent: function(current) { + resetTextContent(current.stateNode); + }, + commitPlacement: function(finishedWork) { + a: { + for (var parent = finishedWork["return"]; null !== parent; ) { + if (isHostParent(parent)) { + var parentFiber = parent; + break a; + } + parent = parent["return"]; + } + invariant( + !1, + "Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue." + ); + parentFiber = void 0; + } + var isContainer = (parent = void 0); + switch (parentFiber.tag) { + case 5: + parent = parentFiber.stateNode; + isContainer = !1; + break; + case 3: + parent = parentFiber.stateNode.containerInfo; + isContainer = !0; + break; + case 4: + parent = parentFiber.stateNode.containerInfo; + isContainer = !0; + break; + default: + invariant( + !1, + "Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue." + ); + } + parentFiber.effectTag & 16 && + (resetTextContent(parent), (parentFiber.effectTag &= -17)); + a: b: for (parentFiber = finishedWork; ; ) { + for (; null === parentFiber.sibling; ) { + if ( + null === parentFiber["return"] || + isHostParent(parentFiber["return"]) + ) { + parentFiber = null; + break a; + } + parentFiber = parentFiber["return"]; + } + parentFiber.sibling["return"] = parentFiber["return"]; + for ( + parentFiber = parentFiber.sibling; + 5 !== parentFiber.tag && 6 !== parentFiber.tag; + + ) { + if (parentFiber.effectTag & 2) continue b; + if (null === parentFiber.child || 4 === parentFiber.tag) continue b; + else + (parentFiber.child["return"] = parentFiber), + (parentFiber = parentFiber.child); + } + if (!(parentFiber.effectTag & 2)) { + parentFiber = parentFiber.stateNode; + break a; + } + } + for (var node = finishedWork; ; ) { + if (5 === node.tag || 6 === node.tag) + parentFiber + ? isContainer + ? insertInContainerBefore(parent, node.stateNode, parentFiber) + : insertBefore(parent, node.stateNode, parentFiber) + : isContainer + ? appendChildToContainer(parent, node.stateNode) + : appendChild(parent, node.stateNode); + else if (4 !== node.tag && null !== node.child) { + node.child["return"] = node; + node = node.child; + continue; + } + if (node === finishedWork) break; + for (; null === node.sibling; ) { + if (null === node["return"] || node["return"] === finishedWork) + return; + node = node["return"]; + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } + }, + commitDeletion: function(current) { + unmountHostComponents(current); + current["return"] = null; + current.child = null; + current.alternate && + ((current.alternate.child = null), + (current.alternate["return"] = null)); + }, + commitWork: function(current, finishedWork) { + switch (finishedWork.tag) { + case 2: + break; + case 5: + var instance = finishedWork.stateNode; + if (null != instance) { + var newProps = finishedWork.memoizedProps; + current = null !== current ? current.memoizedProps : newProps; + var type = finishedWork.type, + updatePayload = finishedWork.updateQueue; + finishedWork.updateQueue = null; + null !== updatePayload && + commitUpdate( + instance, + updatePayload, + type, + current, + newProps, + finishedWork + ); + } + break; + case 6: + invariant( + null !== finishedWork.stateNode, + "This should have a text node initialized. This error is likely caused by a bug in React. Please file an issue." + ); + instance = finishedWork.memoizedProps; + commitTextUpdate( + finishedWork.stateNode, + null !== current ? current.memoizedProps : instance, + instance + ); + break; + case 3: + break; + default: + invariant( + !1, + "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." + ); + } + }, + commitLifeCycles: function(current, finishedWork) { + switch (finishedWork.tag) { + case 2: + var instance = finishedWork.stateNode; + if (finishedWork.effectTag & 4) + if (null === current) + (instance.props = finishedWork.memoizedProps), + (instance.state = finishedWork.memoizedState), + instance.componentDidMount(); + else { + var prevProps = current.memoizedProps; + current = current.memoizedState; + instance.props = finishedWork.memoizedProps; + instance.state = finishedWork.memoizedState; + instance.componentDidUpdate(prevProps, current); + } + finishedWork = finishedWork.updateQueue; + null !== finishedWork && commitCallbacks(finishedWork, instance); + break; + case 3: + instance = finishedWork.updateQueue; + null !== instance && + commitCallbacks( + instance, + null !== finishedWork.child ? finishedWork.child.stateNode : null + ); + break; + case 5: + instance = finishedWork.stateNode; + null === current && + finishedWork.effectTag & 4 && + commitMount( + instance, + finishedWork.type, + finishedWork.memoizedProps, + finishedWork + ); + break; + case 6: + break; + case 4: + break; + default: + invariant( + !1, + "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." + ); + } + }, + commitAttachRef: function(finishedWork) { + var ref = finishedWork.ref; + if (null !== ref) { + var instance = finishedWork.stateNode; + switch (finishedWork.tag) { + case 5: + ref(getPublicInstance(instance)); + break; + default: + ref(instance); + } + } + }, + commitDetachRef: function(current) { + current = current.ref; + null !== current && current(null); + } + }; +} +var NO_CONTEXT = {}; +function ReactFiberHostContext(config) { + function requiredContext(c) { + invariant( + c !== NO_CONTEXT, + "Expected host context to exist. This error is likely caused by a bug in React. Please file an issue." + ); + return c; + } + var getChildHostContext = config.getChildHostContext, + getRootHostContext = config.getRootHostContext, + contextStackCursor = { current: NO_CONTEXT }, + contextFiberStackCursor = { current: NO_CONTEXT }, + rootInstanceStackCursor = { current: NO_CONTEXT }; + return { + getHostContext: function() { + return requiredContext(contextStackCursor.current); + }, + getRootHostContainer: function() { + return requiredContext(rootInstanceStackCursor.current); + }, + popHostContainer: function(fiber) { + pop(contextStackCursor, fiber); + pop(contextFiberStackCursor, fiber); + pop(rootInstanceStackCursor, fiber); + }, + popHostContext: function(fiber) { + contextFiberStackCursor.current === fiber && + (pop(contextStackCursor, fiber), pop(contextFiberStackCursor, fiber)); + }, + pushHostContainer: function(fiber, nextRootInstance) { + push(rootInstanceStackCursor, nextRootInstance, fiber); + nextRootInstance = getRootHostContext(nextRootInstance); + push(contextFiberStackCursor, fiber, fiber); + push(contextStackCursor, nextRootInstance, fiber); + }, + pushHostContext: function(fiber) { + var rootInstance = requiredContext(rootInstanceStackCursor.current), + context = requiredContext(contextStackCursor.current); + rootInstance = getChildHostContext(context, fiber.type, rootInstance); + context !== rootInstance && + (push(contextFiberStackCursor, fiber, fiber), + push(contextStackCursor, rootInstance, fiber)); + }, + resetHostContainer: function() { + contextStackCursor.current = NO_CONTEXT; + rootInstanceStackCursor.current = NO_CONTEXT; + } + }; +} +function ReactFiberHydrationContext(config) { + function deleteHydratableInstance(returnFiber, instance) { + var fiber = new FiberNode(5, null, 0); + fiber.type = "DELETED"; + fiber.stateNode = instance; + fiber["return"] = returnFiber; + fiber.effectTag = 8; + null !== returnFiber.lastEffect + ? ((returnFiber.lastEffect.nextEffect = fiber), + (returnFiber.lastEffect = fiber)) + : (returnFiber.firstEffect = returnFiber.lastEffect = fiber); + } + function tryHydrate(fiber, nextInstance) { + switch (fiber.tag) { + case 5: + return ( + (nextInstance = canHydrateInstance( + nextInstance, + fiber.type, + fiber.pendingProps + )), + null !== nextInstance ? ((fiber.stateNode = nextInstance), !0) : !1 + ); + case 6: + return ( + (nextInstance = canHydrateTextInstance( + nextInstance, + fiber.pendingProps + )), + null !== nextInstance ? ((fiber.stateNode = nextInstance), !0) : !1 + ); + default: + return !1; + } + } + function popToNextHostParent(fiber) { + for ( + fiber = fiber["return"]; + null !== fiber && 5 !== fiber.tag && 3 !== fiber.tag; + + ) + fiber = fiber["return"]; + hydrationParentFiber = fiber; + } + var shouldSetTextContent = config.shouldSetTextContent; + config = config.hydration; + if (!config) + return { + enterHydrationState: function() { + return !1; + }, + resetHydrationState: function() {}, + tryToClaimNextHydratableInstance: function() {}, + prepareToHydrateHostInstance: function() { + invariant( + !1, + "Expected prepareToHydrateHostInstance() to never be called. This error is likely caused by a bug in React. Please file an issue." + ); + }, + prepareToHydrateHostTextInstance: function() { + invariant( + !1, + "Expected prepareToHydrateHostTextInstance() to never be called. This error is likely caused by a bug in React. Please file an issue." + ); + }, + popHydrationState: function() { + return !1; + } + }; + var canHydrateInstance = config.canHydrateInstance, + canHydrateTextInstance = config.canHydrateTextInstance, + getNextHydratableSibling = config.getNextHydratableSibling, + getFirstHydratableChild = config.getFirstHydratableChild, + hydrateInstance = config.hydrateInstance, + hydrateTextInstance = config.hydrateTextInstance, + hydrationParentFiber = null, + nextHydratableInstance = null, + isHydrating = !1; + return { + enterHydrationState: function(fiber) { + nextHydratableInstance = getFirstHydratableChild( + fiber.stateNode.containerInfo + ); + hydrationParentFiber = fiber; + return (isHydrating = !0); + }, + resetHydrationState: function() { + nextHydratableInstance = hydrationParentFiber = null; + isHydrating = !1; + }, + tryToClaimNextHydratableInstance: function(fiber) { + if (isHydrating) { + var nextInstance = nextHydratableInstance; + if (nextInstance) { + if (!tryHydrate(fiber, nextInstance)) { + nextInstance = getNextHydratableSibling(nextInstance); + if (!nextInstance || !tryHydrate(fiber, nextInstance)) { + fiber.effectTag |= 2; + isHydrating = !1; + hydrationParentFiber = fiber; + return; + } + deleteHydratableInstance( + hydrationParentFiber, + nextHydratableInstance + ); + } + hydrationParentFiber = fiber; + nextHydratableInstance = getFirstHydratableChild(nextInstance); + } else + (fiber.effectTag |= 2), + (isHydrating = !1), + (hydrationParentFiber = fiber); + } + }, + prepareToHydrateHostInstance: function( + fiber, + rootContainerInstance, + hostContext + ) { + rootContainerInstance = hydrateInstance( + fiber.stateNode, + fiber.type, + fiber.memoizedProps, + rootContainerInstance, + hostContext, + fiber + ); + fiber.updateQueue = rootContainerInstance; + return null !== rootContainerInstance ? !0 : !1; + }, + prepareToHydrateHostTextInstance: function(fiber) { + return hydrateTextInstance(fiber.stateNode, fiber.memoizedProps, fiber); + }, + popHydrationState: function(fiber) { + if (fiber !== hydrationParentFiber) return !1; + if (!isHydrating) + return popToNextHostParent(fiber), (isHydrating = !0), !1; + var type = fiber.type; + if ( + 5 !== fiber.tag || + ("head" !== type && + "body" !== type && + !shouldSetTextContent(type, fiber.memoizedProps)) + ) + for (type = nextHydratableInstance; type; ) + deleteHydratableInstance(fiber, type), + (type = getNextHydratableSibling(type)); + popToNextHostParent(fiber); + nextHydratableInstance = hydrationParentFiber + ? getNextHydratableSibling(fiber.stateNode) + : null; + return !0; + } + }; +} +function ReactFiberScheduler(config) { + function commitRoot(finishedWork) { + isCommitting = isWorking = !0; + var root = finishedWork.stateNode; + invariant( + root.current !== finishedWork, + "Cannot commit the same tree as before. This is probably a bug related to the return field. This error is likely caused by a bug in React. Please file an issue." + ); + root.isReadyForCommit = !1; + ReactCurrentOwner.current = null; + if (1 < finishedWork.effectTag) + if (null !== finishedWork.lastEffect) { + finishedWork.lastEffect.nextEffect = finishedWork; + var firstEffect = finishedWork.firstEffect; + } else firstEffect = finishedWork; + else firstEffect = finishedWork.firstEffect; + prepareForCommit(); + for (nextEffect = firstEffect; null !== nextEffect; ) { + var didError = !1, + _error = void 0; + try { + for (; null !== nextEffect; ) { + var effectTag = nextEffect.effectTag; + effectTag & 16 && commitResetTextContent(nextEffect); + if (effectTag & 128) { + var current = nextEffect.alternate; + null !== current && commitDetachRef(current); + } + switch (effectTag & -242) { + case 2: + commitPlacement(nextEffect); + nextEffect.effectTag &= -3; + break; + case 6: + commitPlacement(nextEffect); + nextEffect.effectTag &= -3; + commitWork(nextEffect.alternate, nextEffect); + break; + case 4: + commitWork(nextEffect.alternate, nextEffect); + break; + case 8: + (isUnmounting = !0), + commitDeletion(nextEffect), + (isUnmounting = !1); + } + nextEffect = nextEffect.nextEffect; + } + } catch (e) { + (didError = !0), (_error = e); + } + didError && + (invariant( + null !== nextEffect, + "Should have next effect. This error is likely caused by a bug in React. Please file an issue." + ), + captureError(nextEffect, _error), + null !== nextEffect && (nextEffect = nextEffect.nextEffect)); + } + resetAfterCommit(); + root.current = finishedWork; + for (nextEffect = firstEffect; null !== nextEffect; ) { + firstEffect = !1; + didError = void 0; + try { + for (; null !== nextEffect; ) { + var effectTag$jscomp$0 = nextEffect.effectTag; + effectTag$jscomp$0 & 36 && + commitLifeCycles(nextEffect.alternate, nextEffect); + effectTag$jscomp$0 & 128 && commitAttachRef(nextEffect); + if (effectTag$jscomp$0 & 64) + switch (((_error = nextEffect), + (effectTag = void 0), + null !== capturedErrors && + ((effectTag = capturedErrors.get(_error)), + capturedErrors["delete"](_error), + null == effectTag && + null !== _error.alternate && + ((_error = _error.alternate), + (effectTag = capturedErrors.get(_error)), + capturedErrors["delete"](_error))), + invariant( + null != effectTag, + "No error for given unit of work. This error is likely caused by a bug in React. Please file an issue." + ), + _error.tag)) { + case 2: + _error.stateNode.componentDidCatch(effectTag.error, { + componentStack: effectTag.componentStack + }); + break; + case 3: + null === firstUncaughtError && + (firstUncaughtError = effectTag.error); + break; + default: + invariant( + !1, + "Invalid type of work. This error is likely caused by a bug in React. Please file an issue." + ); + } + var next = nextEffect.nextEffect; + nextEffect.nextEffect = null; + nextEffect = next; + } + } catch (e) { + (firstEffect = !0), (didError = e); + } + firstEffect && + (invariant( + null !== nextEffect, + "Should have next effect. This error is likely caused by a bug in React. Please file an issue." + ), + captureError(nextEffect, didError), + null !== nextEffect && (nextEffect = nextEffect.nextEffect)); + } + isWorking = isCommitting = !1; + "function" === typeof onCommitRoot && onCommitRoot(finishedWork.stateNode); + commitPhaseBoundaries && + (commitPhaseBoundaries.forEach(scheduleErrorRecovery), + (commitPhaseBoundaries = null)); + null !== firstUncaughtError && + ((finishedWork = firstUncaughtError), + (firstUncaughtError = null), + onUncaughtError(finishedWork)); + root = root.current.expirationTime; + 0 === root && (failedBoundaries = capturedErrors = null); + return root; + } + function completeUnitOfWork(workInProgress$jscomp$0) { + for (;;) { + var next = completeWork( + workInProgress$jscomp$0.alternate, + workInProgress$jscomp$0, + nextRenderExpirationTime + ), + returnFiber = workInProgress$jscomp$0["return"], + siblingFiber = workInProgress$jscomp$0.sibling; + var workInProgress = workInProgress$jscomp$0; + if ( + 2147483647 === nextRenderExpirationTime || + 2147483647 !== workInProgress.expirationTime + ) { + if (2 !== workInProgress.tag && 3 !== workInProgress.tag) + var newExpirationTime = 0; + else + (newExpirationTime = workInProgress.updateQueue), + (newExpirationTime = + null === newExpirationTime + ? 0 + : newExpirationTime.expirationTime); + for (var child = workInProgress.child; null !== child; ) + 0 !== child.expirationTime && + (0 === newExpirationTime || + newExpirationTime > child.expirationTime) && + (newExpirationTime = child.expirationTime), + (child = child.sibling); + workInProgress.expirationTime = newExpirationTime; + } + if (null !== next) return next; + null !== returnFiber && + (null === returnFiber.firstEffect && + (returnFiber.firstEffect = workInProgress$jscomp$0.firstEffect), + null !== workInProgress$jscomp$0.lastEffect && + (null !== returnFiber.lastEffect && + (returnFiber.lastEffect.nextEffect = + workInProgress$jscomp$0.firstEffect), + (returnFiber.lastEffect = workInProgress$jscomp$0.lastEffect)), + 1 < workInProgress$jscomp$0.effectTag && + (null !== returnFiber.lastEffect + ? (returnFiber.lastEffect.nextEffect = workInProgress$jscomp$0) + : (returnFiber.firstEffect = workInProgress$jscomp$0), + (returnFiber.lastEffect = workInProgress$jscomp$0))); + if (null !== siblingFiber) return siblingFiber; + if (null !== returnFiber) workInProgress$jscomp$0 = returnFiber; + else { + workInProgress$jscomp$0.stateNode.isReadyForCommit = !0; + break; + } + } + return null; + } + function performUnitOfWork(workInProgress) { + var next = beginWork( + workInProgress.alternate, + workInProgress, + nextRenderExpirationTime + ); + null === next && (next = completeUnitOfWork(workInProgress)); + ReactCurrentOwner.current = null; + return next; + } + function performFailedUnitOfWork(workInProgress) { + var next = beginFailedWork( + workInProgress.alternate, + workInProgress, + nextRenderExpirationTime + ); + null === next && (next = completeUnitOfWork(workInProgress)); + ReactCurrentOwner.current = null; + return next; + } + function workLoop(expirationTime) { + if (null !== capturedErrors) { + if ( + !( + 0 === nextRenderExpirationTime || + nextRenderExpirationTime > expirationTime + ) + ) + if (nextRenderExpirationTime <= mostRecentCurrentTime) + for (; null !== nextUnitOfWork; ) + nextUnitOfWork = hasCapturedError(nextUnitOfWork) + ? performFailedUnitOfWork(nextUnitOfWork) + : performUnitOfWork(nextUnitOfWork); + else + for (; null !== nextUnitOfWork && !shouldYield(); ) + nextUnitOfWork = hasCapturedError(nextUnitOfWork) + ? performFailedUnitOfWork(nextUnitOfWork) + : performUnitOfWork(nextUnitOfWork); + } else if ( + !( + 0 === nextRenderExpirationTime || + nextRenderExpirationTime > expirationTime + ) + ) + if (nextRenderExpirationTime <= mostRecentCurrentTime) + for (; null !== nextUnitOfWork; ) + nextUnitOfWork = performUnitOfWork(nextUnitOfWork); + else + for (; null !== nextUnitOfWork && !shouldYield(); ) + nextUnitOfWork = performUnitOfWork(nextUnitOfWork); + } + function renderRoot(root, expirationTime) { + invariant( + !isWorking, + "renderRoot was called recursively. This error is likely caused by a bug in React. Please file an issue." + ); + isWorking = !0; + root.isReadyForCommit = !1; + if ( + root !== nextRoot || + expirationTime !== nextRenderExpirationTime || + null === nextUnitOfWork + ) { + for (; -1 < index; ) (valueStack[index] = null), index--; + previousContext = emptyObject; + contextStackCursor.current = emptyObject; + didPerformWorkStackCursor.current = !1; + resetHostContainer(); + nextRoot = root; + nextRenderExpirationTime = expirationTime; + nextUnitOfWork = createWorkInProgress( + nextRoot.current, + null, + expirationTime + ); + } + var didError = !1, + error = null; + try { + workLoop(expirationTime); + } catch (e) { + (didError = !0), (error = e); + } + for (; didError; ) { + if (didFatal) { + firstUncaughtError = error; + break; + } + var failedWork = nextUnitOfWork; + if (null === failedWork) didFatal = !0; + else { + var boundary = captureError(failedWork, error); + invariant( + null !== boundary, + "Should have found an error boundary. This error is likely caused by a bug in React. Please file an issue." + ); + if (!didFatal) { + try { + didError = boundary; + error = expirationTime; + for (boundary = didError; null !== failedWork; ) { + switch (failedWork.tag) { + case 2: + popContextProvider(failedWork); + break; + case 5: + popHostContext(failedWork); + break; + case 3: + popHostContainer(failedWork); + break; + case 4: + popHostContainer(failedWork); + } + if (failedWork === boundary || failedWork.alternate === boundary) + break; + failedWork = failedWork["return"]; + } + nextUnitOfWork = performFailedUnitOfWork(didError); + workLoop(error); + } catch (e) { + didError = !0; + error = e; + continue; + } + break; + } + } + } + expirationTime = firstUncaughtError; + didFatal = isWorking = !1; + firstUncaughtError = null; + null !== expirationTime && onUncaughtError(expirationTime); + return root.isReadyForCommit ? root.current.alternate : null; + } + function captureError(failedWork, error) { + var boundary = (ReactCurrentOwner.current = null), + errorBoundaryFound = !1, + willRetry = !1, + errorBoundaryName = null; + if (3 === failedWork.tag) + (boundary = failedWork), isFailedBoundary(failedWork) && (didFatal = !0); + else + for ( + var node = failedWork["return"]; + null !== node && null === boundary; + + ) { + 2 === node.tag + ? "function" === typeof node.stateNode.componentDidCatch && + ((errorBoundaryFound = !0), + (errorBoundaryName = getComponentName(node)), + (boundary = node), + (willRetry = !0)) + : 3 === node.tag && (boundary = node); + if (isFailedBoundary(node)) { + if ( + isUnmounting || + (null !== commitPhaseBoundaries && + (commitPhaseBoundaries.has(node) || + (null !== node.alternate && + commitPhaseBoundaries.has(node.alternate)))) + ) + return null; + boundary = null; + willRetry = !1; + } + node = node["return"]; + } + if (null !== boundary) { + null === failedBoundaries && (failedBoundaries = new Set()); + failedBoundaries.add(boundary); + var info = ""; + node = failedWork; + do { + a: switch (node.tag) { + case 0: + case 1: + case 2: + case 5: + var owner = node._debugOwner, + source = node._debugSource; + var JSCompiler_inline_result = getComponentName(node); + var ownerName = null; + owner && (ownerName = getComponentName(owner)); + owner = source; + JSCompiler_inline_result = + "\n in " + + (JSCompiler_inline_result || "Unknown") + + (owner + ? " (at " + + owner.fileName.replace(/^.*[\\\/]/, "") + + ":" + + owner.lineNumber + + ")" + : ownerName ? " (created by " + ownerName + ")" : ""); + break a; + default: + JSCompiler_inline_result = ""; + } + info += JSCompiler_inline_result; + node = node["return"]; + } while (node); + node = info; + failedWork = getComponentName(failedWork); + null === capturedErrors && (capturedErrors = new Map()); + error = { + componentName: failedWork, + componentStack: node, + error: error, + errorBoundary: errorBoundaryFound ? boundary.stateNode : null, + errorBoundaryFound: errorBoundaryFound, + errorBoundaryName: errorBoundaryName, + willRetry: willRetry + }; + capturedErrors.set(boundary, error); + try { + !1 !== showDialog(error) && console.error(error.error); + } catch (e) { + console.error(e); + } + isCommitting + ? (null === commitPhaseBoundaries && + (commitPhaseBoundaries = new Set()), + commitPhaseBoundaries.add(boundary)) + : scheduleErrorRecovery(boundary); + return boundary; + } + null === firstUncaughtError && (firstUncaughtError = error); + return null; + } + function hasCapturedError(fiber) { + return ( + null !== capturedErrors && + (capturedErrors.has(fiber) || + (null !== fiber.alternate && capturedErrors.has(fiber.alternate))) + ); + } + function isFailedBoundary(fiber) { + return ( + null !== failedBoundaries && + (failedBoundaries.has(fiber) || + (null !== fiber.alternate && failedBoundaries.has(fiber.alternate))) + ); + } + function computeAsyncExpiration() { + return 20 * ((((recalculateCurrentTime() + 100) / 20) | 0) + 1); + } + function computeExpirationForFiber(fiber) { + return 0 !== expirationContext + ? expirationContext + : isWorking + ? isCommitting ? 1 : nextRenderExpirationTime + : !useSyncScheduling || fiber.internalContextTag & 1 + ? computeAsyncExpiration() + : 1; + } + function scheduleWork(fiber, expirationTime) { + return scheduleWorkImpl(fiber, expirationTime, !1); + } + function scheduleWorkImpl(fiber, expirationTime$jscomp$0) { + for (; null !== fiber; ) { + if ( + 0 === fiber.expirationTime || + fiber.expirationTime > expirationTime$jscomp$0 + ) + fiber.expirationTime = expirationTime$jscomp$0; + null !== fiber.alternate && + (0 === fiber.alternate.expirationTime || + fiber.alternate.expirationTime > expirationTime$jscomp$0) && + (fiber.alternate.expirationTime = expirationTime$jscomp$0); + if (null === fiber["return"]) + if (3 === fiber.tag) { + var root = fiber.stateNode; + !isWorking && + root === nextRoot && + expirationTime$jscomp$0 <= nextRenderExpirationTime && + ((nextUnitOfWork = nextRoot = null), + (nextRenderExpirationTime = 0)); + var expirationTime = expirationTime$jscomp$0; + nestedUpdateCount > NESTED_UPDATE_LIMIT && + invariant( + !1, + "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops." + ); + if (null === root.nextScheduledRoot) + (root.remainingExpirationTime = expirationTime), + null === lastScheduledRoot + ? ((firstScheduledRoot = lastScheduledRoot = root), + (root.nextScheduledRoot = root)) + : ((lastScheduledRoot = lastScheduledRoot.nextScheduledRoot = root), + (lastScheduledRoot.nextScheduledRoot = firstScheduledRoot)); + else { + var remainingExpirationTime = root.remainingExpirationTime; + if ( + 0 === remainingExpirationTime || + expirationTime < remainingExpirationTime + ) + root.remainingExpirationTime = expirationTime; + } + isRendering || + (isBatchingUpdates + ? isUnbatchingUpdates && performWorkOnRoot(root, 1) + : 1 === expirationTime + ? performWork(1, null) + : isCallbackScheduled || + ((isCallbackScheduled = !0), + scheduleDeferredCallback(performAsyncWork))); + } else break; + fiber = fiber["return"]; + } + } + function scheduleErrorRecovery(fiber) { + scheduleWorkImpl(fiber, 1, !0); + } + function recalculateCurrentTime() { + return (mostRecentCurrentTime = (((now() - startTime) / 10) | 0) + 2); + } + function findHighestPriorityRoot() { + var highestPriorityWork = 0, + highestPriorityRoot = null; + if (null !== lastScheduledRoot) + for ( + var previousScheduledRoot = lastScheduledRoot, + root = firstScheduledRoot; + null !== root; + + ) { + var remainingExpirationTime = root.remainingExpirationTime; + if (0 === remainingExpirationTime) { + invariant( + null !== previousScheduledRoot && null !== lastScheduledRoot, + "Should have a previous and last root. This error is likely caused by a bug in React. Please file an issue." + ); + if (root === root.nextScheduledRoot) { + firstScheduledRoot = lastScheduledRoot = root.nextScheduledRoot = null; + break; + } else if (root === firstScheduledRoot) + (firstScheduledRoot = remainingExpirationTime = + root.nextScheduledRoot), + (lastScheduledRoot.nextScheduledRoot = remainingExpirationTime), + (root.nextScheduledRoot = null); + else if (root === lastScheduledRoot) { + lastScheduledRoot = previousScheduledRoot; + lastScheduledRoot.nextScheduledRoot = firstScheduledRoot; + root.nextScheduledRoot = null; + break; + } else + (previousScheduledRoot.nextScheduledRoot = root.nextScheduledRoot), + (root.nextScheduledRoot = null); + root = previousScheduledRoot.nextScheduledRoot; + } else { + if ( + 0 === highestPriorityWork || + remainingExpirationTime < highestPriorityWork + ) + (highestPriorityWork = remainingExpirationTime), + (highestPriorityRoot = root); + if (root === lastScheduledRoot) break; + previousScheduledRoot = root; + root = root.nextScheduledRoot; + } + } + previousScheduledRoot = nextFlushedRoot; + null !== previousScheduledRoot && + previousScheduledRoot === highestPriorityRoot + ? nestedUpdateCount++ + : (nestedUpdateCount = 0); + nextFlushedRoot = highestPriorityRoot; + nextFlushedExpirationTime = highestPriorityWork; + } + function performAsyncWork(dl) { + performWork(0, dl); + } + function performWork(minExpirationTime, dl) { + deadline = dl; + for ( + findHighestPriorityRoot(); + null !== nextFlushedRoot && + 0 !== nextFlushedExpirationTime && + (0 === minExpirationTime || + nextFlushedExpirationTime <= minExpirationTime) && + !deadlineDidExpire; + + ) + performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime), + findHighestPriorityRoot(); + null !== deadline && (isCallbackScheduled = !1); + null === nextFlushedRoot || + isCallbackScheduled || + ((isCallbackScheduled = !0), scheduleDeferredCallback(performAsyncWork)); + deadline = null; + deadlineDidExpire = !1; + nestedUpdateCount = 0; + if (hasUnhandledError) + throw ((minExpirationTime = unhandledError), + (unhandledError = null), + (hasUnhandledError = !1), + minExpirationTime); + } + function performWorkOnRoot(root, expirationTime) { + invariant( + !isRendering, + "performWorkOnRoot was called recursively. This error is likely caused by a bug in React. Please file an issue." + ); + isRendering = !0; + if (expirationTime <= recalculateCurrentTime()) { + var finishedWork = root.finishedWork; + null !== finishedWork + ? ((root.finishedWork = null), + (root.remainingExpirationTime = commitRoot(finishedWork))) + : ((root.finishedWork = null), + (finishedWork = renderRoot(root, expirationTime)), + null !== finishedWork && + (root.remainingExpirationTime = commitRoot(finishedWork))); + } else + (finishedWork = root.finishedWork), + null !== finishedWork + ? ((root.finishedWork = null), + (root.remainingExpirationTime = commitRoot(finishedWork))) + : ((root.finishedWork = null), + (finishedWork = renderRoot(root, expirationTime)), + null !== finishedWork && + (shouldYield() + ? (root.finishedWork = finishedWork) + : (root.remainingExpirationTime = commitRoot(finishedWork)))); + isRendering = !1; + } + function shouldYield() { + return null === deadline || + deadline.timeRemaining() > timeHeuristicForUnitOfWork + ? !1 + : (deadlineDidExpire = !0); + } + function onUncaughtError(error) { + invariant( + null !== nextFlushedRoot, + "Should be working on a root. This error is likely caused by a bug in React. Please file an issue." + ); + nextFlushedRoot.remainingExpirationTime = 0; + hasUnhandledError || ((hasUnhandledError = !0), (unhandledError = error)); + } + var hostContext = ReactFiberHostContext(config), + hydrationContext = ReactFiberHydrationContext(config), + popHostContainer = hostContext.popHostContainer, + popHostContext = hostContext.popHostContext, + resetHostContainer = hostContext.resetHostContainer, + _ReactFiberBeginWork = ReactFiberBeginWork( + config, + hostContext, + hydrationContext, + scheduleWork, + computeExpirationForFiber + ), + beginWork = _ReactFiberBeginWork.beginWork, + beginFailedWork = _ReactFiberBeginWork.beginFailedWork, + completeWork = ReactFiberCompleteWork(config, hostContext, hydrationContext) + .completeWork; + hostContext = ReactFiberCommitWork(config, captureError); + var commitResetTextContent = hostContext.commitResetTextContent, + commitPlacement = hostContext.commitPlacement, + commitDeletion = hostContext.commitDeletion, + commitWork = hostContext.commitWork, + commitLifeCycles = hostContext.commitLifeCycles, + commitAttachRef = hostContext.commitAttachRef, + commitDetachRef = hostContext.commitDetachRef, + now = config.now, + scheduleDeferredCallback = config.scheduleDeferredCallback, + useSyncScheduling = config.useSyncScheduling, + prepareForCommit = config.prepareForCommit, + resetAfterCommit = config.resetAfterCommit, + startTime = now(), + mostRecentCurrentTime = 2, + expirationContext = 0, + isWorking = !1, + nextUnitOfWork = null, + nextRoot = null, + nextRenderExpirationTime = 0, + nextEffect = null, + capturedErrors = null, + failedBoundaries = null, + commitPhaseBoundaries = null, + firstUncaughtError = null, + didFatal = !1, + isCommitting = !1, + isUnmounting = !1, + firstScheduledRoot = null, + lastScheduledRoot = null, + isCallbackScheduled = !1, + isRendering = !1, + nextFlushedRoot = null, + nextFlushedExpirationTime = 0, + deadlineDidExpire = !1, + hasUnhandledError = !1, + unhandledError = null, + deadline = null, + isBatchingUpdates = !1, + isUnbatchingUpdates = !1, + NESTED_UPDATE_LIMIT = 1e3, + nestedUpdateCount = 0, + timeHeuristicForUnitOfWork = 1; + return { + computeAsyncExpiration: computeAsyncExpiration, + computeExpirationForFiber: computeExpirationForFiber, + scheduleWork: scheduleWork, + batchedUpdates: function(fn, a) { + var previousIsBatchingUpdates = isBatchingUpdates; + isBatchingUpdates = !0; + try { + return fn(a); + } finally { + (isBatchingUpdates = previousIsBatchingUpdates) || + isRendering || + performWork(1, null); + } + }, + unbatchedUpdates: function(fn) { + if (isBatchingUpdates && !isUnbatchingUpdates) { + isUnbatchingUpdates = !0; + try { + return fn(); + } finally { + isUnbatchingUpdates = !1; + } + } + return fn(); + }, + flushSync: function(fn) { + var previousIsBatchingUpdates = isBatchingUpdates; + isBatchingUpdates = !0; + try { + a: { + var previousExpirationContext = expirationContext; + expirationContext = 1; + try { + var JSCompiler_inline_result = fn(); + break a; + } finally { + expirationContext = previousExpirationContext; + } + JSCompiler_inline_result = void 0; + } + return JSCompiler_inline_result; + } finally { + (isBatchingUpdates = previousIsBatchingUpdates), + invariant( + !isRendering, + "flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering." + ), + performWork(1, null); + } + }, + deferredUpdates: function(fn) { + var previousExpirationContext = expirationContext; + expirationContext = computeAsyncExpiration(); + try { + return fn(); + } finally { + expirationContext = previousExpirationContext; + } + } + }; +} +function ReactFiberReconciler$1(config) { + function findHostInstance(fiber) { + fiber = findCurrentHostFiber(fiber); + return null === fiber ? null : fiber.stateNode; + } + var getPublicInstance = config.getPublicInstance; + config = ReactFiberScheduler(config); + var computeAsyncExpiration = config.computeAsyncExpiration, + computeExpirationForFiber = config.computeExpirationForFiber, + scheduleWork = config.scheduleWork; + return { + createContainer: function(containerInfo, hydrate) { + var uninitializedFiber = new FiberNode(3, null, 0); + containerInfo = { + current: uninitializedFiber, + containerInfo: containerInfo, + pendingChildren: null, + remainingExpirationTime: 0, + isReadyForCommit: !1, + finishedWork: null, + context: null, + pendingContext: null, + hydrate: hydrate, + nextScheduledRoot: null + }; + return (uninitializedFiber.stateNode = containerInfo); + }, + updateContainer: function(element, container, parentComponent, callback) { + var current = container.current; + if (parentComponent) { + parentComponent = parentComponent._reactInternalFiber; + var parentContext; + b: { + invariant( + 2 === isFiberMountedImpl(parentComponent) && + 2 === parentComponent.tag, + "Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue." + ); + for (parentContext = parentComponent; 3 !== parentContext.tag; ) { + if (isContextProvider(parentContext)) { + parentContext = + parentContext.stateNode + .__reactInternalMemoizedMergedChildContext; + break b; + } + parentContext = parentContext["return"]; + invariant( + parentContext, + "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue." + ); + } + parentContext = parentContext.stateNode.context; + } + parentComponent = isContextProvider(parentComponent) + ? processChildContext(parentComponent, parentContext) + : parentContext; + } else parentComponent = emptyObject; + null === container.context + ? (container.context = parentComponent) + : (container.pendingContext = parentComponent); + container = callback; + container = void 0 === container ? null : container; + callback = + null != element && + null != element.type && + null != element.type.prototype && + !0 === element.type.prototype.unstable_isAsyncReactComponent + ? computeAsyncExpiration() + : computeExpirationForFiber(current); + insertUpdateIntoFiber(current, { + expirationTime: callback, + partialState: { element: element }, + callback: container, + isReplace: !1, + isForced: !1, + nextCallback: null, + next: null + }); + scheduleWork(current, callback); + }, + batchedUpdates: config.batchedUpdates, + unbatchedUpdates: config.unbatchedUpdates, + deferredUpdates: config.deferredUpdates, + flushSync: config.flushSync, + getPublicRootInstance: function(container) { + container = container.current; + if (!container.child) return null; + switch (container.child.tag) { + case 5: + return getPublicInstance(container.child.stateNode); + default: + return container.child.stateNode; + } + }, + findHostInstance: findHostInstance, + findHostInstanceWithNoPortals: function(fiber) { + fiber = findCurrentHostFiberWithNoPortals(fiber); + return null === fiber ? null : fiber.stateNode; + }, + injectIntoDevTools: function(devToolsConfig) { + var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; + return injectInternals( + Object.assign({}, devToolsConfig, { + findHostInstanceByFiber: function(fiber) { + return findHostInstance(fiber); + }, + findFiberByHostInstance: function(instance) { + return findFiberByHostInstance + ? findFiberByHostInstance(instance) + : null; + } + }) + ); + } + }; +} +var ReactFiberReconciler$2 = Object.freeze({ default: ReactFiberReconciler$1 }), + ReactFiberReconciler$3 = + (ReactFiberReconciler$2 && ReactFiberReconciler$1) || + ReactFiberReconciler$2, + reactReconciler = ReactFiberReconciler$3["default"] + ? ReactFiberReconciler$3["default"] + : ReactFiberReconciler$3, + viewConfigCallbacks = new Map(), + viewConfigs = new Map(), + ReactNativeFiberHostComponent = (function() { + function ReactNativeFiberHostComponent(tag, viewConfig) { + if (!(this instanceof ReactNativeFiberHostComponent)) + throw new TypeError("Cannot call a class as a function"); + this._nativeTag = tag; + this._children = []; + this.viewConfig = viewConfig; + } + ReactNativeFiberHostComponent.prototype.blur = function() { + TextInputState.blurTextInput(this._nativeTag); + }; + ReactNativeFiberHostComponent.prototype.focus = function() { + TextInputState.focusTextInput(this._nativeTag); + }; + ReactNativeFiberHostComponent.prototype.measure = function(callback) { + UIManager.measure(this._nativeTag, mountSafeCallback(this, callback)); + }; + ReactNativeFiberHostComponent.prototype.measureInWindow = function( + callback + ) { + UIManager.measureInWindow( + this._nativeTag, + mountSafeCallback(this, callback) + ); + }; + ReactNativeFiberHostComponent.prototype.measureLayout = function( + relativeToNativeNode, + onSuccess, + onFail + ) { + UIManager.measureLayout( + this._nativeTag, + relativeToNativeNode, + mountSafeCallback(this, onFail), + mountSafeCallback(this, onSuccess) + ); + }; + ReactNativeFiberHostComponent.prototype.setNativeProps = function( + nativeProps + ) { + nativeProps = diffProperties( + null, + emptyObject$1, + nativeProps, + this.viewConfig.validAttributes + ); + null != nativeProps && + UIManager.updateView( + this._nativeTag, + this.viewConfig.uiViewClassName, + nativeProps + ); + }; + return ReactNativeFiberHostComponent; + })(); +ReactNativeFiberHostComponent.prototype; +var now = + "object" === typeof performance && "function" === typeof performance.now + ? function() { + return performance.now(); + } + : function() { + return Date.now(); + }, + isCallbackScheduled = !1, + scheduledCallback = null, + frameDeadline = 0, + frameDeadlineObject = { + timeRemaining: function() { + return frameDeadline - now(); + } + }; +function setTimeoutCallback() { + isCallbackScheduled = !1; + frameDeadline = now() + 5; + var callback = scheduledCallback; + scheduledCallback = null; + null !== callback && callback(frameDeadlineObject); +} +function recursivelyUncacheFiberNode(node) { + "number" === typeof node + ? uncacheFiberNode(node) + : (uncacheFiberNode(node._nativeTag), + node._children.forEach(recursivelyUncacheFiberNode)); +} +var NativeRenderer = reactReconciler({ + appendInitialChild: function(parentInstance, child) { + parentInstance._children.push(child); + }, + createInstance: function( + type, + props, + rootContainerInstance, + hostContext, + internalInstanceHandle + ) { + hostContext = ReactNativeTagHandles.allocateTag(); + if (viewConfigs.has(type)) var viewConfig = viewConfigs.get(type); + else + (viewConfig = viewConfigCallbacks.get(type)), + invariant( + "function" === typeof viewConfig, + "View config not found for name %s", + type + ), + viewConfigCallbacks.set(type, null), + (viewConfig = viewConfig()), + viewConfigs.set(type, viewConfig); + invariant(viewConfig, "View config not found for name %s", type); + type = viewConfig; + viewConfig = diffProperties( + null, + emptyObject$1, + props, + type.validAttributes + ); + UIManager.createView( + hostContext, + type.uiViewClassName, + rootContainerInstance, + viewConfig + ); + rootContainerInstance = new ReactNativeFiberHostComponent( + hostContext, + type + ); + instanceCache[hostContext] = internalInstanceHandle; + instanceProps[hostContext] = props; + return rootContainerInstance; + }, + createTextInstance: function( + text, + rootContainerInstance, + hostContext, + internalInstanceHandle + ) { + hostContext = ReactNativeTagHandles.allocateTag(); + UIManager.createView(hostContext, "RCTRawText", rootContainerInstance, { + text: text + }); + instanceCache[hostContext] = internalInstanceHandle; + return hostContext; + }, + finalizeInitialChildren: function(parentInstance) { + if (0 === parentInstance._children.length) return !1; + var nativeTags = parentInstance._children.map(function(child) { + return "number" === typeof child ? child : child._nativeTag; + }); + UIManager.setChildren(parentInstance._nativeTag, nativeTags); + return !1; + }, + getRootHostContext: function() { + return emptyObject; + }, + getChildHostContext: function() { + return emptyObject; + }, + getPublicInstance: function(instance) { + return instance; + }, + now: now, + prepareForCommit: function() {}, + prepareUpdate: function() { + return emptyObject; + }, + resetAfterCommit: function() {}, + scheduleDeferredCallback: function(callback) { + scheduledCallback = callback; + isCallbackScheduled || + ((isCallbackScheduled = !0), setTimeout(setTimeoutCallback, 1)); + return 0; + }, + shouldDeprioritizeSubtree: function() { + return !1; + }, + shouldSetTextContent: function() { + return !1; + }, + useSyncScheduling: !0, + mutation: { + appendChild: function(parentInstance, child) { + var childTag = "number" === typeof child ? child : child._nativeTag, + children = parentInstance._children, + index = children.indexOf(child); + 0 <= index + ? (children.splice(index, 1), + children.push(child), + UIManager.manageChildren( + parentInstance._nativeTag, + [index], + [children.length - 1], + [], + [], + [] + )) + : (children.push(child), + UIManager.manageChildren( + parentInstance._nativeTag, + [], + [], + [childTag], + [children.length - 1], + [] + )); + }, + appendChildToContainer: function(parentInstance, child) { + UIManager.setChildren(parentInstance, [ + "number" === typeof child ? child : child._nativeTag + ]); + }, + commitTextUpdate: function(textInstance, oldText, newText) { + UIManager.updateView(textInstance, "RCTRawText", { text: newText }); + }, + commitMount: function() {}, + commitUpdate: function( + instance, + updatePayloadTODO, + type, + oldProps, + newProps + ) { + updatePayloadTODO = instance.viewConfig; + instanceProps[instance._nativeTag] = newProps; + oldProps = diffProperties( + null, + oldProps, + newProps, + updatePayloadTODO.validAttributes + ); + null != oldProps && + UIManager.updateView( + instance._nativeTag, + updatePayloadTODO.uiViewClassName, + oldProps + ); + }, + insertBefore: function(parentInstance, child, beforeChild) { + var children = parentInstance._children, + index = children.indexOf(child); + 0 <= index + ? (children.splice(index, 1), + (beforeChild = children.indexOf(beforeChild)), + children.splice(beforeChild, 0, child), + UIManager.manageChildren( + parentInstance._nativeTag, + [index], + [beforeChild], + [], + [], + [] + )) + : ((index = children.indexOf(beforeChild)), + children.splice(index, 0, child), + UIManager.manageChildren( + parentInstance._nativeTag, + [], + [], + ["number" === typeof child ? child : child._nativeTag], + [index], + [] + )); + }, + insertInContainerBefore: function(parentInstance) { + invariant( + "number" !== typeof parentInstance, + "Container does not support insertBefore operation" + ); + }, + removeChild: function(parentInstance, child) { + recursivelyUncacheFiberNode(child); + var children = parentInstance._children; + child = children.indexOf(child); + children.splice(child, 1); + UIManager.manageChildren( + parentInstance._nativeTag, + [], + [], + [], + [], + [child] + ); + }, + removeChildFromContainer: function(parentInstance, child) { + recursivelyUncacheFiberNode(child); + UIManager.manageChildren(parentInstance, [], [], [], [], [0]); + }, + resetTextContent: function() {} + } +}); +function findNodeHandle(componentOrHandle) { + if (null == componentOrHandle) return null; + if ("number" === typeof componentOrHandle) return componentOrHandle; + var internalInstance = componentOrHandle._reactInternalFiber; + if (internalInstance) + return NativeRenderer.findHostInstance(internalInstance); + if (componentOrHandle) return componentOrHandle; + invariant( + ("object" === typeof componentOrHandle && + "_nativeTag" in componentOrHandle) || + (null != componentOrHandle.render && + "function" === typeof componentOrHandle.render), + "findNodeHandle(...): Argument is not a component (type: %s, keys: %s)", + typeof componentOrHandle, + Object.keys(componentOrHandle) + ); + invariant( + !1, + "findNodeHandle(...): Unable to find node handle for unmounted component." + ); +} +function findNumericNodeHandleFiber(componentOrHandle) { + componentOrHandle = findNodeHandle(componentOrHandle); + return null == componentOrHandle || "number" === typeof componentOrHandle + ? componentOrHandle + : componentOrHandle._nativeTag; +} +function _inherits(subClass, superClass) { + if ("function" !== typeof superClass && null !== superClass) + throw new TypeError( + "Super expression must either be null or a function, not " + + typeof superClass + ); + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: !1, + writable: !0, + configurable: !0 + } + }); + superClass && + (Object.setPrototypeOf + ? Object.setPrototypeOf(subClass, superClass) + : (subClass.__proto__ = superClass)); +} +var ReactNativeComponent = (function(_React$Component) { + function ReactNativeComponent() { + if (!(this instanceof ReactNativeComponent)) + throw new TypeError("Cannot call a class as a function"); + var call = _React$Component.apply(this, arguments); + if (!this) + throw new ReferenceError( + "this hasn't been initialised - super() hasn't been called" + ); + return !call || ("object" !== typeof call && "function" !== typeof call) + ? this + : call; + } + _inherits(ReactNativeComponent, _React$Component); + ReactNativeComponent.prototype.blur = function() { + TextInputState.blurTextInput(findNumericNodeHandleFiber(this)); + }; + ReactNativeComponent.prototype.focus = function() { + TextInputState.focusTextInput(findNumericNodeHandleFiber(this)); + }; + ReactNativeComponent.prototype.measure = function(callback) { + UIManager.measure( + findNumericNodeHandleFiber(this), + mountSafeCallback(this, callback) + ); + }; + ReactNativeComponent.prototype.measureInWindow = function(callback) { + UIManager.measureInWindow( + findNumericNodeHandleFiber(this), + mountSafeCallback(this, callback) + ); + }; + ReactNativeComponent.prototype.measureLayout = function( + relativeToNativeNode, + onSuccess, + onFail + ) { + UIManager.measureLayout( + findNumericNodeHandleFiber(this), + relativeToNativeNode, + mountSafeCallback(this, onFail), + mountSafeCallback(this, onSuccess) + ); + }; + ReactNativeComponent.prototype.setNativeProps = function(nativeProps) { + var maybeInstance = void 0; + try { + maybeInstance = findNodeHandle(this); + } catch (error) {} + if (null != maybeInstance) { + var viewConfig = maybeInstance.viewConfig; + nativeProps = diffProperties( + null, + emptyObject$1, + nativeProps, + viewConfig.validAttributes + ); + null != nativeProps && + UIManager.updateView( + maybeInstance._nativeTag, + viewConfig.uiViewClassName, + nativeProps + ); + } + }; + return ReactNativeComponent; +})(React.Component); +ReactNativeComponent.prototype; +var getInspectorDataForViewTag = void 0; +getInspectorDataForViewTag = function() { + invariant(!1, "getInspectorDataForViewTag() is not available in production"); +}; +fiberBatchedUpdates = NativeRenderer.batchedUpdates; +var roots = new Map(); +function fn$jscomp$inline_601(capturedError) { + var componentStack = capturedError.componentStack, + error = capturedError.error; + if (error instanceof Error) { + capturedError = error.message; + var name = error.name; + try { + error.message = + (capturedError ? name + ": " + capturedError : name) + + "\n\nThis error is located at:" + + componentStack; + } catch (e) {} + } else + error = + "string" === typeof error + ? Error(error + "\n\nThis error is located at:" + componentStack) + : Error("Unspecified error at:" + componentStack); + ExceptionsManager.handleException(error, !1); + return !1; +} +invariant( + showDialog === defaultShowDialog, + "The custom dialog was already injected." +); +invariant( + "function" === typeof fn$jscomp$inline_601, + "Injected showDialog() must be a function." +); +showDialog = fn$jscomp$inline_601; +var ReactNativeRenderer = { + NativeComponent: ReactNativeComponent, + findNodeHandle: findNumericNodeHandleFiber, + render: function(element, containerTag, callback) { + var root = roots.get(containerTag); + root || + ((root = NativeRenderer.createContainer(containerTag, !1)), + roots.set(containerTag, root)); + NativeRenderer.updateContainer(element, root, null, callback); + return NativeRenderer.getPublicRootInstance(root); + }, + unmountComponentAtNode: function(containerTag) { + var root = roots.get(containerTag); + root && + NativeRenderer.updateContainer(null, root, null, function() { + roots["delete"](containerTag); + }); + }, + unmountComponentAtNodeAndRemoveContainer: function(containerTag) { + ReactNativeRenderer.unmountComponentAtNode(containerTag); + UIManager.removeRootView(containerTag); + }, + createPortal: function(children, containerTag) { + return createPortal( + children, + containerTag, + null, + 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : null + ); + }, + unstable_batchedUpdates: batchedUpdates, + flushSync: NativeRenderer.flushSync, + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: { + NativeMethodsMixin: { + measure: function(callback) { + UIManager.measure( + findNumericNodeHandleFiber(this), + mountSafeCallback(this, callback) + ); + }, + measureInWindow: function(callback) { + UIManager.measureInWindow( + findNumericNodeHandleFiber(this), + mountSafeCallback(this, callback) + ); + }, + measureLayout: function(relativeToNativeNode, onSuccess, onFail) { + UIManager.measureLayout( + findNumericNodeHandleFiber(this), + relativeToNativeNode, + mountSafeCallback(this, onFail), + mountSafeCallback(this, onSuccess) + ); + }, + setNativeProps: function(nativeProps) { + var maybeInstance = void 0; + try { + maybeInstance = findNodeHandle(this); + } catch (error) {} + if (null != maybeInstance) { + var viewConfig = maybeInstance.viewConfig; + nativeProps = diffProperties( + null, + emptyObject$1, + nativeProps, + viewConfig.validAttributes + ); + null != nativeProps && + UIManager.updateView( + maybeInstance._nativeTag, + viewConfig.uiViewClassName, + nativeProps + ); + } + }, + focus: function() { + TextInputState.focusTextInput(findNumericNodeHandleFiber(this)); + }, + blur: function() { + TextInputState.blurTextInput(findNumericNodeHandleFiber(this)); + } + }, + ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin, + ReactGlobalSharedState: ReactGlobalSharedState, + ReactNativeComponentTree: ReactNativeComponentTree, + ReactNativePropRegistry: ReactNativePropRegistry, + TouchHistoryMath: TouchHistoryMath, + createReactNativeComponentClass: function(name, callback) { + invariant( + !viewConfigCallbacks.has(name), + "Tried to register two views with the same name %s", + name + ); + viewConfigCallbacks.set(name, callback); + return name; + }, + takeSnapshot: function(view, options) { + "number" !== typeof view && + "window" !== view && + (view = findNumericNodeHandleFiber(view) || "window"); + return UIManager.__takeSnapshot(view, options); + } + } +}; +NativeRenderer.injectIntoDevTools({ + findFiberByHostInstance: getInstanceFromTag, + getInspectorDataForViewTag: getInspectorDataForViewTag, + bundleType: 0, + version: "16.1.1", + rendererPackageName: "react-native-renderer" +}); +var ReactNativeRenderer$2 = Object.freeze({ default: ReactNativeRenderer }), + ReactNativeRenderer$3 = + (ReactNativeRenderer$2 && ReactNativeRenderer) || ReactNativeRenderer$2; +module.exports = ReactNativeRenderer$3["default"] + ? ReactNativeRenderer$3["default"] + : ReactNativeRenderer$3; diff --git a/Libraries/Renderer/shims/ReactNative.js b/Libraries/Renderer/shims/ReactNative.js index 35b7c3909512a3..a648cafbc30c22 100644 --- a/Libraries/Renderer/shims/ReactNative.js +++ b/Libraries/Renderer/shims/ReactNative.js @@ -14,9 +14,9 @@ import type {ReactNativeType} from 'ReactNativeTypes'; let ReactNative; if (__DEV__) { - ReactNative = require('ReactNativeFiber-dev'); + ReactNative = require('ReactNativeRenderer-dev'); } else { - ReactNative = require('ReactNativeFiber-prod'); + ReactNative = require('ReactNativeRenderer-prod'); } module.exports = (ReactNative: ReactNativeType); diff --git a/Libraries/Renderer/shims/ReactNativeTypes.js b/Libraries/Renderer/shims/ReactNativeTypes.js index 5da6886014ffb1..f20bb30faa7938 100644 --- a/Libraries/Renderer/shims/ReactNativeTypes.js +++ b/Libraries/Renderer/shims/ReactNativeTypes.js @@ -4,10 +4,9 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @providesModule ReactNativeTypes * @flow + * @providesModule ReactNativeTypes */ -'use strict'; export type MeasureOnSuccessCallback = ( x: number, diff --git a/Libraries/Renderer/shims/ReactTypes.js b/Libraries/Renderer/shims/ReactTypes.js index 736d1210e1f5c2..900582e5d5ac83 100644 --- a/Libraries/Renderer/shims/ReactTypes.js +++ b/Libraries/Renderer/shims/ReactTypes.js @@ -4,16 +4,14 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @providesModule ReactTypes * @flow + * @providesModule ReactTypes */ -'use strict'; - export type ReactNode = | React$Element - | ReactCoroutine - | ReactYield + | ReactCall + | ReactReturn | ReactPortal | ReactText | ReactFragment; @@ -26,16 +24,16 @@ export type ReactText = string | number; export type ReactEmpty = null | void | boolean; -export type ReactCoroutine = { +export type ReactCall = { $$typeof: Symbol | number, key: null | string, children: any, - // This should be a more specific CoroutineHandler - handler: (props: any, yields: Array) => ReactNodeList, + // This should be a more specific CallHandler + handler: (props: any, returns: Array) => ReactNodeList, props: any, }; -export type ReactYield = { +export type ReactReturn = { $$typeof: Symbol | number, value: mixed, }; diff --git a/Libraries/Share/Share.js b/Libraries/Share/Share.js index 457cf4a9610353..44d7433218bed2 100644 --- a/Libraries/Share/Share.js +++ b/Libraries/Share/Share.js @@ -111,13 +111,13 @@ class Share { /** * The content was successfully shared. */ - static get sharedAction() { return 'sharedAction'; } + static get sharedAction(): string { return 'sharedAction'; } /** * The dialog has been dismissed. * @platform ios */ - static get dismissedAction() { return 'dismissedAction'; } + static get dismissedAction(): string { return 'dismissedAction'; } } diff --git a/Libraries/Storage/AsyncStorage.js b/Libraries/Storage/AsyncStorage.js index 0ba87ed6c18b9c..fb54d6beef95b8 100644 --- a/Libraries/Storage/AsyncStorage.js +++ b/Libraries/Storage/AsyncStorage.js @@ -21,45 +21,11 @@ const RCTAsyncStorage = NativeModules.AsyncRocksDBStorage || NativeModules.AsyncLocalStorage; /** - * @class - * @description - * `AsyncStorage` is a simple, unencrypted, asynchronous, persistent, key-value storage - * system that is global to the app. It should be used instead of LocalStorage. - * - * It is recommended that you use an abstraction on top of `AsyncStorage` - * instead of `AsyncStorage` directly for anything more than light usage since - * it operates globally. - * - * On iOS, `AsyncStorage` is backed by native code that stores small values in a - * serialized dictionary and larger values in separate files. On Android, - * `AsyncStorage` will use either [RocksDB](http://rocksdb.org/) or SQLite - * based on what is available. - * - * The `AsyncStorage` JavaScript code is a simple facade that provides a clear - * JavaScript API, real `Error` objects, and simple non-multi functions. Each - * method in the API returns a `Promise` object. - * - * Persisting data: - * ``` - * try { - * await AsyncStorage.setItem('@MySuperStore:key', 'I like to save it.'); - * } catch (error) { - * // Error saving data - * } - * ``` - * - * Fetching data: - * ``` - * try { - * const value = await AsyncStorage.getItem('@MySuperStore:key'); - * if (value !== null){ - * // We have data!! - * console.log(value); - * } - * } catch (error) { - * // Error retrieving data - * } - * ``` + * `AsyncStorage` is a simple, unencrypted, asynchronous, persistent, key-value + * storage system that is global to the app. It should be used instead of + * LocalStorage. + * + * See http://facebook.github.io/react-native/docs/asyncstorage.html */ var AsyncStorage = { _getRequests: ([]: Array), @@ -68,11 +34,8 @@ var AsyncStorage = { /** * Fetches an item for a `key` and invokes a callback upon completion. - * Returns a `Promise` object. - * @param key Key of the item to fetch. - * @param callback Function that will be called with a result if found or - * any error. - * @returns A `Promise` object. + * + * See http://facebook.github.io/react-native/docs/asyncstorage.html#getitem */ getItem: function( key: string, @@ -95,11 +58,8 @@ var AsyncStorage = { /** * Sets the value for a `key` and invokes a callback upon completion. - * Returns a `Promise` object. - * @param key Key of the item to set. - * @param value Value to set for the `key`. - * @param callback Function that will be called with any error. - * @returns A `Promise` object. + * + * See http://facebook.github.io/react-native/docs/asyncstorage.html#setitem */ setItem: function( key: string, @@ -121,10 +81,8 @@ var AsyncStorage = { /** * Removes an item for a `key` and invokes a callback upon completion. - * Returns a `Promise` object. - * @param key Key of the item to remove. - * @param callback Function that will be called with any error. - * @returns A `Promise` object. + * + * See http://facebook.github.io/react-native/docs/asyncstorage.html#removeitem */ removeItem: function( key: string, @@ -145,38 +103,11 @@ var AsyncStorage = { /** * Merges an existing `key` value with an input value, assuming both values - * are stringified JSON. Returns a `Promise` object. + * are stringified JSON. * * **NOTE:** This is not supported by all native implementations. * - * @param key Key of the item to modify. - * @param value New value to merge for the `key`. - * @param callback Function that will be called with any error. - * @returns A `Promise` object. - * - * @example Example - * let UID123_object = { - * name: 'Chris', - * age: 30, - * traits: {hair: 'brown', eyes: 'brown'}, - * }; - * // You only need to define what will be added or updated - * let UID123_delta = { - * age: 31, - * traits: {eyes: 'blue', shoe_size: 10} - * }; - * - * AsyncStorage.setItem('UID123', JSON.stringify(UID123_object), () => { - * AsyncStorage.mergeItem('UID123', JSON.stringify(UID123_delta), () => { - * AsyncStorage.getItem('UID123', (err, result) => { - * console.log(result); - * }); - * }); - * }); - * - * // Console log result: - * // => {'name':'Chris','age':31,'traits': - * // {'shoe_size':10,'hair':'brown','eyes':'blue'}} + * See http://facebook.github.io/react-native/docs/asyncstorage.html#mergeitem */ mergeItem: function( key: string, @@ -197,11 +128,11 @@ var AsyncStorage = { }, /** - * Erases *all* `AsyncStorage` for all clients, libraries, etc. You probably + * Erases *all* `AsyncStorage` for all clients, libraries, etc. You probably * don't want to call this; use `removeItem` or `multiRemove` to clear only - * your app's keys. Returns a `Promise` object. - * @param callback Function that will be called with any error. - * @returns A `Promise` object. + * your app's keys. + * + * See http://facebook.github.io/react-native/docs/asyncstorage.html#clear */ clear: function(callback?: ?(error: ?Error) => void): Promise { return new Promise((resolve, reject) => { @@ -218,11 +149,8 @@ var AsyncStorage = { /** * Gets *all* keys known to your app; for all callers, libraries, etc. - * Returns a `Promise` object. - * @param callback Function that will be called the keys found and any error. - * @returns A `Promise` object. * - * Example: see the `multiGet` example. + * See http://facebook.github.io/react-native/docs/asyncstorage.html#getallkeys */ getAllKeys: function(callback?: ?(error: ?Error, keys: ?Array) => void): Promise { return new Promise((resolve, reject) => { @@ -247,7 +175,11 @@ var AsyncStorage = { * indicate which key caused the error. */ - /** Flushes any pending requests using a single batch call to get the data. */ + /** + * Flushes any pending requests using a single batch call to get the data. + * + * See http://facebook.github.io/react-native/docs/asyncstorage.html#flushgetrequests + * */ flushGetRequests: function(): void { const getRequests = this._getRequests; const getKeys = this._getKeys; @@ -278,30 +210,9 @@ var AsyncStorage = { /** * This allows you to batch the fetching of items given an array of `key` * inputs. Your callback will be invoked with an array of corresponding - * key-value pairs found: - * - * ``` - * multiGet(['k1', 'k2'], cb) -> cb([['k1', 'val1'], ['k2', 'val2']]) - * ``` - * - * The method returns a `Promise` object. - * - * @param keys Array of key for the items to get. - * @param callback Function that will be called with a key-value array of - * the results, plus an array of any key-specific errors found. - * @returns A `Promise` object. - * - * @example Example - * - * AsyncStorage.getAllKeys((err, keys) => { - * AsyncStorage.multiGet(keys, (err, stores) => { - * stores.map((result, i, store) => { - * // get at each store's key/value so you can work with it - * let key = store[i][0]; - * let value = store[i][1]; - * }); - * }); - * }); + * key-value pairs found. + * + * See http://facebook.github.io/react-native/docs/asyncstorage.html#multiget */ multiGet: function( keys: Array, @@ -341,19 +252,9 @@ var AsyncStorage = { /** * Use this as a batch operation for storing multiple key-value pairs. When - * the operation completes you'll get a single callback with any errors: + * the operation completes you'll get a single callback with any errors. * - * ``` - * multiSet([['k1', 'val1'], ['k2', 'val2']], cb); - * ``` - * - * The method returns a `Promise` object. - * - * @param keyValuePairs Array of key-value array for the items to set. - * @param callback Function that will be called with an array of any - * key-specific errors found. - * @returns A `Promise` object. - * Example: see the `multiMerge` example. + * See http://facebook.github.io/react-native/docs/asyncstorage.html#multiset */ multiSet: function( keyValuePairs: Array>, @@ -373,20 +274,9 @@ var AsyncStorage = { }, /** - * Call this to batch the deletion of all keys in the `keys` array. Returns - * a `Promise` object. - * - * @param keys Array of key for the items to delete. - * @param callback Function that will be called an array of any key-specific - * errors found. - * @returns A `Promise` object. - * - * @example Example - * let keys = ['k1', 'k2']; - * AsyncStorage.multiRemove(keys, (err) => { - * // keys k1 & k2 removed, if they existed - * // do most stuff after removal (if you want) - * }); + * Call this to batch the deletion of all keys in the `keys` array. + * + * See http://facebook.github.io/react-native/docs/asyncstorage.html#multiremove */ multiRemove: function( keys: Array, @@ -407,61 +297,11 @@ var AsyncStorage = { /** * Batch operation to merge in existing and new values for a given set of - * keys. This assumes that the values are stringified JSON. Returns a - * `Promise` object. - * + * keys. This assumes that the values are stringified JSON. + * * **NOTE**: This is not supported by all native implementations. - * - * @param keyValuePairs Array of key-value array for the items to merge. - * @param callback Function that will be called with an array of any - * key-specific errors found. - * @returns A `Promise` object. - * - * @example Example - * // first user, initial values - * let UID234_object = { - * name: 'Chris', - * age: 30, - * traits: {hair: 'brown', eyes: 'brown'}, - * }; - * - * // first user, delta values - * let UID234_delta = { - * age: 31, - * traits: {eyes: 'blue', shoe_size: 10}, - * }; - * - * // second user, initial values - * let UID345_object = { - * name: 'Marge', - * age: 25, - * traits: {hair: 'blonde', eyes: 'blue'}, - * }; - * - * // second user, delta values - * let UID345_delta = { - * age: 26, - * traits: {eyes: 'green', shoe_size: 6}, - * }; - * - * let multi_set_pairs = [['UID234', JSON.stringify(UID234_object)], ['UID345', JSON.stringify(UID345_object)]] - * let multi_merge_pairs = [['UID234', JSON.stringify(UID234_delta)], ['UID345', JSON.stringify(UID345_delta)]] - * - * AsyncStorage.multiSet(multi_set_pairs, (err) => { - * AsyncStorage.multiMerge(multi_merge_pairs, (err) => { - * AsyncStorage.multiGet(['UID234','UID345'], (err, stores) => { - * stores.map( (result, i, store) => { - * let key = store[i][0]; - * let val = store[i][1]; - * console.log(key, val); - * }); - * }); - * }); - * }); - * - * // Console log results: - * // => UID234 {"name":"Chris","age":31,"traits":{"shoe_size":10,"hair":"brown","eyes":"blue"}} - * // => UID345 {"name":"Marge","age":26,"traits":{"shoe_size":6,"hair":"blonde","eyes":"green"}} + * + * See http://facebook.github.io/react-native/docs/asyncstorage.html#multimerge */ multiMerge: function( keyValuePairs: Array>, diff --git a/Libraries/StyleSheet/StyleSheet.js b/Libraries/StyleSheet/StyleSheet.js index 8fd9b1f6cd5141..ae845cab0c6ec5 100644 --- a/Libraries/StyleSheet/StyleSheet.js +++ b/Libraries/StyleSheet/StyleSheet.js @@ -18,10 +18,19 @@ const StyleSheetValidation = require('StyleSheetValidation'); const flatten = require('flattenStyle'); -export type Styles = {[key: string]: Object}; -export type StyleSheet = {[key: $Keys]: number}; -export type StyleValue = {[key: string]: Object} | number | false | null; -export type StyleProp = StyleValue | Array; +import type { + StyleSheetStyle as _StyleSheetStyle, + Styles as _Styles, + StyleSheet as _StyleSheet, + StyleValue as _StyleValue, + StyleObj, +} from 'StyleSheetTypes'; + +export type StyleProp = StyleObj; +export type Styles = _Styles; +export type StyleSheet = _StyleSheet; +export type StyleValue = _StyleValue; +export type StyleSheetStyle = _StyleSheetStyle; let hairlineWidth = PixelRatio.roundToNearestPixel(0.4); if (hairlineWidth === 0) { @@ -29,13 +38,14 @@ if (hairlineWidth === 0) { } const absoluteFillObject = { - position: 'absolute', + position: ('absolute': 'absolute'), left: 0, right: 0, top: 0, bottom: 0, }; -const absoluteFill = ReactNativePropRegistry.register(absoluteFillObject); // This also freezes it +const absoluteFill: typeof absoluteFillObject = + ReactNativePropRegistry.register(absoluteFillObject); // This also freezes it /** * A StyleSheet is an abstraction similar to CSS StyleSheets @@ -197,7 +207,7 @@ module.exports = { * Creates a StyleSheet style reference from the given object. */ create(obj: S): StyleSheet { - const result: StyleSheet = {}; + const result = {}; for (const key in obj) { StyleSheetValidation.validateStyle(key, obj); result[key] = obj[key] && ReactNativePropRegistry.register(obj[key]); diff --git a/Libraries/StyleSheet/StyleSheetTypes.js b/Libraries/StyleSheet/StyleSheetTypes.js index 515d3e6145ea77..da2cac469fd526 100644 --- a/Libraries/StyleSheet/StyleSheetTypes.js +++ b/Libraries/StyleSheet/StyleSheetTypes.js @@ -8,8 +8,241 @@ * * @providesModule StyleSheetTypes * @flow + * @format */ + 'use strict'; -type Atom = number | bool | Object | Array; -export type StyleObj = Atom; +import AnimatedNode from 'AnimatedNode'; + +export opaque type StyleSheetStyle: number = number; + +export type ColorValue = null | string; +export type DimensionValue = null | number | string | AnimatedNode; + +export type LayoutStyle<+Dimension = DimensionValue> = { + +display?: 'none' | 'flex', + +width?: Dimension, + +height?: Dimension, + +top?: Dimension, + +bottom?: Dimension, + +left?: Dimension, + +right?: Dimension, + +minWidth?: Dimension, + +maxWidth?: Dimension, + +minHeight?: Dimension, + +maxHeight?: Dimension, + +margin?: Dimension, + +marginVertical?: Dimension, + +marginHorizontal?: Dimension, + +marginTop?: Dimension, + +marginBottom?: Dimension, + +marginLeft?: Dimension, + +marginRight?: Dimension, + +padding?: Dimension, + +paddingVertical?: Dimension, + +paddingHorizontal?: Dimension, + +paddingTop?: Dimension, + +paddingBottom?: Dimension, + +paddingLeft?: Dimension, + +paddingRight?: Dimension, + +borderWidth?: number, + +borderTopWidth?: number, + +borderBottomWidth?: number, + +borderLeftWidth?: number, + +borderRightWidth?: number, + +position?: 'absolute' | 'relative', + +flexDirection?: 'row' | 'row-reverse' | 'column' | 'column-reverse', + +flexWrap?: 'wrap' | 'nowrap', + +justifyContent?: + | 'flex-start' + | 'flex-end' + | 'center' + | 'space-between' + | 'space-around', + +alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline', + +alignSelf?: + | 'auto' + | 'flex-start' + | 'flex-end' + | 'center' + | 'stretch' + | 'baseline', + +alignContent?: + | 'flex-start' + | 'flex-end' + | 'center' + | 'stretch' + | 'space-between' + | 'space-around', + +overflow?: 'visible' | 'hidden' | 'scroll', + +flex?: number, + +flexGrow?: number, + +flexShrink?: number, + +flexBasis?: number | string, + +aspectRatio?: number, + +zIndex?: number, + +direction?: 'inherit' | 'ltr' | 'rtl', +}; + +export type TransformStyle = { + +transform?: $ReadOnlyArray< + | {+perspective: number | AnimatedNode} + | {+rotate: string} + | {+rotateX: string} + | {+rotateY: string} + | {+rotateZ: string} + | {+scale: number | AnimatedNode} + | {+scaleX: number | AnimatedNode} + | {+scaleY: number | AnimatedNode} + | {+translateX: number | AnimatedNode} + | {+translateY: number | AnimatedNode} + | { + +translate: [number | AnimatedNode, number | AnimatedNode] | AnimatedNode, + } + | {+skewX: string} + | {+skewY: string} + // TODO: what is the actual type it expects? + | {+matrix: $ReadOnlyArray | AnimatedNode}, + >, +}; + +export type ShadowStyle<+Color = ColorValue> = { + +shadowColor?: Color, + +shadowOffset?: { + +width?: number, + +height?: number, + }, + +shadowOpacity?: number | AnimatedNode, + +shadowRadius?: number, +}; + +export type ViewStyle<+Dimension = DimensionValue, +Color = ColorValue> = { + ...$Exact>, + ...$Exact>, + ...$Exact, + +backfaceVisibility?: 'visible' | 'hidden', + +backgroundColor?: Color, + +borderColor?: Color, + +borderTopColor?: Color, + +borderRightColor?: Color, + +borderBottomColor?: Color, + +borderLeftColor?: Color, + +borderRadius?: number, + +borderTopLeftRadius?: number, + +borderTopRightRadius?: number, + +borderBottomLeftRadius?: number, + +borderBottomRightRadius?: number, + +borderStyle?: 'solid' | 'dotted' | 'dashed', + +borderWidth?: number, + +borderTopWidth?: number, + +borderRightWidth?: number, + +borderBottomWidth?: number, + +borderLeftWidth?: number, + +opacity?: number | AnimatedNode, + +elevation?: number, +}; + +export type TextStyle<+Dimension = DimensionValue, +Color = ColorValue> = { + ...$Exact>, + +color?: Color, + +fontFamily?: string, + +fontSize?: number, + +fontStyle?: 'normal' | 'italic', + +fontWeight?: + | 'normal' + | 'bold' + | '100' + | '200' + | '300' + | '400' + | '500' + | '600' + | '700' + | '800' + | '900', + +fontVariant?: $ReadOnlyArray< + | 'small-caps' + | 'oldstyle-nums' + | 'lining-nums' + | 'tabular-nums' + | 'proportional-nums', + >, + +textShadowOffset?: {+width?: number, +height?: number}, + +textShadowRadius?: number, + +textShadowColor?: Color, + +letterSpacing?: number, + +lineHeight?: number, + +textAlign?: 'auto' | 'left' | 'right' | 'center' | 'justify', + +textAlignVertical?: 'auto' | 'top' | 'bottom' | 'center', + +includeFontPadding?: boolean, + +textDecorationLine?: + | 'none' + | 'underline' + | 'line-through' + | 'underline line-through', + +textDecorationStyle?: 'solid' | 'double' | 'dotted' | 'dashed', + +textDecorationColor?: Color, + +writingDirection?: 'auto' | 'ltr' | 'rtl', +}; + +export type ImageStyle<+Dimension = DimensionValue, +Color = ColorValue> = { + ...$Exact>, + +resizeMode?: 'contain' | 'cover' | 'stretch' | 'center' | 'repeat', + +tintColor?: Color, + +overlayColor?: string, +}; + +export type Style<+Dimension = DimensionValue, +Color = ColorValue> = { + ...$Exact>, + +resizeMode?: 'contain' | 'cover' | 'stretch' | 'center' | 'repeat', + +tintColor?: Color, + +overlayColor?: string, +}; + +export type StyleProp<+T> = + | null + | void + | T + | StyleSheetStyle + | number + | false + | '' + | $ReadOnlyArray>; + +// export type ViewStyleProp = StyleProp<$Shape>>; +// export type TextStyleProp = StyleProp< +// $Shape>, +// >; +// export type ImageStyleProp = StyleProp< +// $Shape>, +// >; + +export type StyleObj = StyleProp<$Shape>>; +export type StyleValue = StyleObj; + +export type ViewStyleProp = StyleObj; +export type TextStyleProp = StyleObj; +export type ImageStyleProp = StyleObj; + +export type Styles = { + +[key: string]: $Shape>, +}; +export type StyleSheet<+S: Styles> = $ObjMap StyleSheetStyle>; + +/* +Utility type get non-nullable types for specific style keys. +Useful when a component requires values for certain Style Keys. +So Instead: +``` +type Props = {position: string}; +``` +You should use: +``` +type Props = {position: TypeForStyleKey<'position'>}; +``` + +This will correctly give you the type 'absolute' | 'relative' instead of the +weak type of just string; +*/ +export type TypeForStyleKey<+key: $Keys>> = $ElementType, key>; diff --git a/Libraries/StyleSheet/StyleSheetValidation.js b/Libraries/StyleSheet/StyleSheetValidation.js index c2ee260c89a44b..dadf735dde20e4 100644 --- a/Libraries/StyleSheet/StyleSheetValidation.js +++ b/Libraries/StyleSheet/StyleSheetValidation.js @@ -24,6 +24,10 @@ var invariant = require('fbjs/lib/invariant'); const ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; class StyleSheetValidation { + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an error + * caught by Flow 0.59 which was not caught before. Most likely, this error + * is because an exported function parameter is missing an annotation. + * Without an annotation, these parameters are uncovered by Flow. */ static validateStyleProp(prop, style, caller) { if (!__DEV__) { return; @@ -59,6 +63,10 @@ class StyleSheetValidation { } } + /* $FlowFixMe(>=0.59.0 site=react_native_fb) This comment suppresses an error + * caught by Flow 0.59 which was not caught before. Most likely, this error + * is because an exported function parameter is missing an annotation. + * Without an annotation, these parameters are uncovered by Flow. */ static validateStyle(name, styles) { if (!__DEV__) { return; diff --git a/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponent.h b/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponent.h new file mode 100644 index 00000000000000..49017bda5bdc92 --- /dev/null +++ b/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponent.h @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import +#import +#import + +@class RCTBridge; + +/** + * ComponentKit component represents a React Native Surface created + * (and stored in the state) with given `bridge`, `moduleName`, + * and `properties`. + */ +@interface RCTSurfaceBackedComponent : CKCompositeComponent + ++ (instancetype)newWithBridge:(RCTBridge *)bridge + moduleName:(NSString *)moduleName + properties:(NSDictionary *)properties + options:(RCTSurfaceHostingComponentOptions)options; + +@end diff --git a/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponent.mm b/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponent.mm new file mode 100644 index 00000000000000..74e03c5cf2ca88 --- /dev/null +++ b/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponent.mm @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "RCTSurfaceBackedComponent.h" + +#import + +#import +#import +#import +#import + +#import "RCTSurfaceBackedComponentState.h" + +@implementation RCTSurfaceBackedComponent + ++ (id)initialState +{ + return [RCTSurfaceBackedComponentState new]; +} + ++ (instancetype)newWithBridge:(RCTBridge *)bridge + moduleName:(NSString *)moduleName + properties:(NSDictionary *)properties + options:(RCTSurfaceHostingComponentOptions)options +{ + CKComponentScope scope(self, moduleName); + + RCTSurfaceBackedComponentState *state = scope.state(); + + if (state.surface == nil || state.surface.bridge != bridge || ![state.surface.moduleName isEqualToString:moduleName]) { + RCTSurface *surface = + [[RCTSurface alloc] initWithBridge:bridge + moduleName:moduleName + initialProperties:properties]; + + state = [RCTSurfaceBackedComponentState newWithSurface:surface]; + + CKComponentScope::replaceState(scope, state); + } + else { + if (![state.surface.properties isEqualToDictionary:properties]) { + state.surface.properties = properties; + } + } + + RCTSurfaceHostingComponent *surfaceHostingComponent = + [RCTSurfaceHostingComponent newWithSurface:state.surface + options:options]; + + CKComponent *component; + if (options.activityIndicatorComponentFactory == nil || state.surface.stage & RCTSurfaceStageSurfaceDidInitialLayout) { + component = surfaceHostingComponent; + } else { + component = [CKOverlayLayoutComponent newWithComponent:surfaceHostingComponent + overlay:options.activityIndicatorComponentFactory()]; + } + + return [super newWithComponent:component]; +} + +@end diff --git a/React/DevSupport/RCTSamplingProfilerPackagerMethod.h b/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponentState.h similarity index 54% rename from React/DevSupport/RCTSamplingProfilerPackagerMethod.h rename to Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponentState.h index 8ffff9bdd317c4..819d927d0ea444 100644 --- a/React/DevSupport/RCTSamplingProfilerPackagerMethod.h +++ b/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponentState.h @@ -7,16 +7,14 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import -@protocol RCTJSEnvironment; +@class RCTSurface; -#if RCT_DEV // Only supported in dev mode +@interface RCTSurfaceBackedComponentState: NSObject -@interface RCTSamplingProfilerPackagerMethod : NSObject +@property (atomic, readonly, strong) RCTSurface *surface; -- (instancetype)initWithJSEnvironment:(id)jsEnvironment; ++ (instancetype)newWithSurface:(RCTSurface *)surface; @end - -#endif diff --git a/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponentState.mm b/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponentState.mm new file mode 100644 index 00000000000000..25d1819a552aac --- /dev/null +++ b/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponentState.mm @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "RCTSurfaceBackedComponentState.h" + +#import + +@implementation RCTSurfaceBackedComponentState + ++ (instancetype)newWithSurface:(RCTSurface *)surface +{ + return [[self alloc] initWithSurface:surface]; +} + +- (instancetype)initWithSurface:(RCTSurface *)surface +{ + if (self == [super init]) { + _surface = surface; + } + + return self; +} + +@end diff --git a/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponent+Internal.h b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponent+Internal.h new file mode 100644 index 00000000000000..184ff32a9342c6 --- /dev/null +++ b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponent+Internal.h @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import +#import + +@class RCTSurface; +@class RCTSurfaceHostingComponentState; + +@interface RCTSurfaceHostingComponent () + +@property (nonatomic, strong, readonly) RCTSurface *surface; +@property (nonatomic, retain, readonly) RCTSurfaceHostingComponentState *state; +@property (nonatomic, assign, readonly) RCTSurfaceHostingComponentOptions options; + +@end diff --git a/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponent.h b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponent.h new file mode 100644 index 00000000000000..c1dd823afb5bb7 --- /dev/null +++ b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponent.h @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import +#import + +@class RCTSurface; + +/** + * ComponentKit component represents given Surface instance. + */ +@interface RCTSurfaceHostingComponent : CKComponent + ++ (instancetype)newWithSurface:(RCTSurface *)surface options:(RCTSurfaceHostingComponentOptions)options; + +@end diff --git a/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponent.mm b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponent.mm new file mode 100644 index 00000000000000..010bd961c40530 --- /dev/null +++ b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponent.mm @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "RCTSurfaceHostingComponent.h" +#import "RCTSurfaceHostingComponent+Internal.h" + +#import + +#import +#import +#import + +#import "RCTSurfaceHostingComponentState.h" + +@implementation RCTSurfaceHostingComponent + ++ (id)initialState +{ + return [RCTSurfaceHostingComponentState new]; +} + ++ (instancetype)newWithSurface:(RCTSurface *)surface options:(RCTSurfaceHostingComponentOptions)options +{ + CKComponentScope scope(self, surface); + + RCTSurfaceHostingComponentState *const state = scope.state(); + + RCTSurfaceHostingComponentState *const newState = + [RCTSurfaceHostingComponentState newWithStage:surface.stage + intrinsicSize:surface.intrinsicSize]; + + if (![state isEqual:newState]) { + CKComponentScope::replaceState(scope, newState); + } + + RCTSurfaceHostingComponent *const component = + [super newWithView:{[UIView class]} size:{}]; + + if (component) { + component->_state = scope.state(); + component->_surface = surface; + component->_options = options; + } + + return component; +} + +- (CKComponentLayout)computeLayoutThatFits:(CKSizeRange)constrainedSize +{ + // Optimistically communicating layout constraints to the `_surface`, + // just to provide layout constraints to React Native as early as possible. + // React Native *may* use this info later during applying the own state and + // related laying out in parallel with ComponentKit execution. + // This call will not interfere (or introduce any negative side effects) with + // following invocation of `sizeThatFitsMinimumSize:maximumSize:`. + // A weak point: We assume here that this particular layout will be + // mounted eventually, which is technically not guaranteed by ComponentKit. + // Therefore we also assume that the last layout calculated in a sequence + // will be mounted anyways, which is probably true for all *real* use cases. + // We plan to tackle this problem during the next big step in improving + // interop compatibilities of React Native which will enable us granularly + // control React Native mounting blocks and, as a result, implement + // truly synchronous mounting stage between React Native and ComponentKit. + [_surface setMinimumSize:constrainedSize.min + maximumSize:constrainedSize.max]; + + // Just in case of the very first building pass, we give React Native a chance + // to prepare its internals for coming synchronous measuring. + [_surface synchronouslyWaitForStage:RCTSurfaceStageSurfaceDidInitialLayout + timeout:_options.synchronousLayoutingTimeout]; + + CGSize fittingSize = CGSizeZero; + if (_surface.stage & RCTSurfaceStageSurfaceDidInitialLayout) { + fittingSize = [_surface sizeThatFitsMinimumSize:constrainedSize.min + maximumSize:constrainedSize.max]; + } + else { + fittingSize = _options.activityIndicatorSize; + } + + fittingSize = constrainedSize.clamp(fittingSize); + return {self, fittingSize}; +} + +- (CKComponentBoundsAnimation)boundsAnimationFromPreviousComponent:(RCTSurfaceHostingComponent *)previousComponent +{ + if (_options.boundsAnimations && (previousComponent->_state.stage != _state.stage)) { + return { + .mode = CKComponentBoundsAnimationModeDefault, + .duration = 0.25, + .options = UIViewAnimationOptionCurveEaseInOut, + }; + } + + return {}; +} + +@end diff --git a/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentController.h b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentController.h new file mode 100644 index 00000000000000..04b8fcafa308c8 --- /dev/null +++ b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentController.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +@interface RCTSurfaceHostingComponentController : CKComponentController + +@end diff --git a/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentController.mm b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentController.mm new file mode 100644 index 00000000000000..c44dbcd007e162 --- /dev/null +++ b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentController.mm @@ -0,0 +1,143 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "RCTSurfaceHostingComponentController.h" + +#import +#import +#import +#import +#import + +#import "RCTSurfaceHostingComponent+Internal.h" +#import "RCTSurfaceHostingComponent.h" +#import "RCTSurfaceHostingComponentState.h" + +@interface RCTSurfaceHostingComponentController() +@end + +@implementation RCTSurfaceHostingComponentController { + RCTSurface *_surface; +} + +- (instancetype)initWithComponent:(RCTSurfaceHostingComponent *)component +{ + if (self = [super initWithComponent:component]) { + [self updateSurfaceWithComponent:component]; + } + + return self; +} + +#pragma mark - Lifecycle + +- (void)didMount +{ + [super didMount]; + [self mountSurfaceView]; +} + +- (void)didRemount +{ + [super didRemount]; + [self mountSurfaceView]; +} + +- (void)didUpdateComponent +{ + [super didUpdateComponent]; + [self updateSurfaceWithComponent:(RCTSurfaceHostingComponent *)self.component]; +} + +- (void)didUnmount +{ + [super didUnmount]; + [self unmountSurfaceView]; +} + +#pragma mark - Helpers + +- (void)updateSurfaceWithComponent:(RCTSurfaceHostingComponent *)component +{ + // Updating `surface` + RCTSurface *const surface = component.surface; + if (surface != _surface) { + if (_surface.delegate == self) { + _surface.delegate = nil; + } + + _surface = surface; + _surface.delegate = self; + } +} + +- (void)setIntrinsicSize:(CGSize)intrinsicSize +{ + [self.component updateState:^(RCTSurfaceHostingComponentState *state) { + return [RCTSurfaceHostingComponentState newWithStage:state.stage + intrinsicSize:intrinsicSize]; + } mode:[self suitableStateUpdateMode]]; +} + +- (void)setStage:(RCTSurfaceStage)stage +{ + [self.component updateState:^(RCTSurfaceHostingComponentState *state) { + return [RCTSurfaceHostingComponentState newWithStage:stage + intrinsicSize:state.intrinsicSize]; + } mode:[self suitableStateUpdateMode]]; +} + +- (CKUpdateMode)suitableStateUpdateMode +{ + return ((RCTSurfaceHostingComponent *)self.component).options.synchronousStateUpdates && RCTIsMainQueue() ? CKUpdateModeSynchronous : CKUpdateModeAsynchronous; +} + +- (void)mountSurfaceView +{ + UIView *const surfaceView = _surface.view; + + const CKComponentViewContext &context = [[self component] viewContext]; + + UIView *const superview = context.view; + superview.clipsToBounds = YES; + + RCTAssert([superview.subviews count] <= 1, @"Should never have more than a single stateful subview."); + + UIView *const existingSurfaceView = [superview.subviews lastObject]; + if (existingSurfaceView != surfaceView) { + [existingSurfaceView removeFromSuperview]; + surfaceView.frame = superview.bounds; + surfaceView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [superview addSubview:surfaceView]; + } +} + +- (void)unmountSurfaceView +{ + const CKComponentViewContext &context = [[self component] viewContext]; + + UIView *const superview = context.view; + RCTAssert([superview.subviews count] <= 1, @"Should never have more than a single stateful subview."); + UIView *const existingSurfaceView = [superview.subviews lastObject]; + [existingSurfaceView removeFromSuperview]; +} + +#pragma mark - RCTSurfaceDelegate + +- (void)surface:(RCTSurface *)surface didChangeIntrinsicSize:(CGSize)intrinsicSize +{ + [self setIntrinsicSize:intrinsicSize]; +} + +- (void)surface:(RCTSurface *)surface didChangeStage:(RCTSurfaceStage)stage +{ + [self setStage:stage]; +} + +@end diff --git a/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentOptions.h b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentOptions.h new file mode 100644 index 00000000000000..001cbd84e1f7a7 --- /dev/null +++ b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentOptions.h @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import + +typedef CKComponent *(^RCTSurfaceHostingComponentOptionsActivityIndicatorComponentFactory)(); + +struct RCTSurfaceHostingComponentOptions { + NSTimeInterval synchronousLayoutingTimeout = 0.350; + BOOL synchronousStateUpdates = YES; + CGSize activityIndicatorSize = {44.0, 44.0}; + BOOL boundsAnimations = YES; + RCTSurfaceHostingComponentOptionsActivityIndicatorComponentFactory activityIndicatorComponentFactory = nil; +}; diff --git a/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentState.h b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentState.h new file mode 100644 index 00000000000000..b1279aaa595322 --- /dev/null +++ b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentState.h @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import + +@interface RCTSurfaceHostingComponentState: NSObject + +@property (nonatomic, readonly, assign) CGSize intrinsicSize; +@property (nonatomic, readonly, assign) RCTSurfaceStage stage; + ++ (instancetype)newWithStage:(RCTSurfaceStage)stage + intrinsicSize:(CGSize)intrinsicSize; + +@end diff --git a/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentState.mm b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentState.mm new file mode 100644 index 00000000000000..f5573db67fc50f --- /dev/null +++ b/Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentState.mm @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "RCTSurfaceHostingComponentState.h" + +@implementation RCTSurfaceHostingComponentState + ++ (instancetype)newWithStage:(RCTSurfaceStage)stage + intrinsicSize:(CGSize)intrinsicSize +{ + return [[self alloc] initWithStage:stage intrinsicSize:intrinsicSize]; +} + + +- (instancetype)initWithStage:(RCTSurfaceStage)stage + intrinsicSize:(CGSize)intrinsicSize +{ + if (self = [super init]) { + _stage = stage; + _intrinsicSize = intrinsicSize; + } + + return self; +} + +- (BOOL)isEqual:(RCTSurfaceHostingComponentState *)other +{ + if (other == self) { + return YES; + } + + return + _stage == other->_stage && + CGSizeEqualToSize(_intrinsicSize, other->_intrinsicSize); +} + +@end diff --git a/Libraries/Text/RCTText.xcodeproj/project.pbxproj b/Libraries/Text/RCTText.xcodeproj/project.pbxproj index cb8b92e4f38c7a..0065b050984e6b 100644 --- a/Libraries/Text/RCTText.xcodeproj/project.pbxproj +++ b/Libraries/Text/RCTText.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 2D3B5F3A1D9B106F00451313 /* RCTTextFieldManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1362F0FF1B4D51F400E06D8C /* RCTTextFieldManager.m */; }; 2D3B5F3B1D9B106F00451313 /* RCTTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 131B6ABD1AF0CD0600FFC3E0 /* RCTTextView.m */; }; 2D3B5F3C1D9B106F00451313 /* RCTTextViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 131B6ABF1AF0CD0600FFC3E0 /* RCTTextViewManager.m */; }; + 2DEAB2901F84BA4300FC6B42 /* RCTFontAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = A85C82991F742AA20036C019 /* RCTFontAttributes.m */; }; 58B511CE1A9E6C5C00147676 /* RCTRawTextManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511C71A9E6C5C00147676 /* RCTRawTextManager.m */; }; 58B511CF1A9E6C5C00147676 /* RCTShadowRawText.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511C91A9E6C5C00147676 /* RCTShadowRawText.m */; }; 58B511D01A9E6C5C00147676 /* RCTShadowText.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511CB1A9E6C5C00147676 /* RCTShadowText.m */; }; diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 92c382b9651060..7f9907e76e26ad 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -243,11 +243,13 @@ const viewConfig = { * ```javascript * class MyAppHeaderText extends Component { * render() { - * - * - * {this.props.children} - * - * + * return ( + * + * + * {this.props.children} + * + * + * ); * } * } * ``` diff --git a/Libraries/Utilities/BackHandler.android.js b/Libraries/Utilities/BackHandler.android.js index 21e320c5e457a1..e9ccd1a5809390 100644 --- a/Libraries/Utilities/BackHandler.android.js +++ b/Libraries/Utilities/BackHandler.android.js @@ -74,6 +74,12 @@ var BackHandler = { DeviceEventManager.invokeDefaultBackPressHandler(); }, + /** + * Adds an event handler. Supported events: + * + * - `hardwareBackPress`: Fires when the Android hardware back button is pressed or when the + * tvOS menu button is pressed. + */ addEventListener: function ( eventName: BackPressEventName, handler: Function @@ -84,6 +90,9 @@ var BackHandler = { }; }, + /** + * Removes the event handler. + */ removeEventListener: function( eventName: BackPressEventName, handler: Function diff --git a/Libraries/Utilities/BundleSegments.js b/Libraries/Utilities/BundleSegments.js index b7a2cd9332ff12..5b86b1b8aa8b57 100644 --- a/Libraries/Utilities/BundleSegments.js +++ b/Libraries/Utilities/BundleSegments.js @@ -17,7 +17,7 @@ let segmentLoaders = new Map(); /** * Ensure that a bundle segment is ready for use, for example requiring some of - * its module. We cache load promises so as to avoid calling `fetchBundle` twice + * its module. We cache load promises so as to avoid calling `fetchSegment` twice * for the same bundle. We assume that once a segment is fetched/loaded, it is * never gettting removed during this instance of the JavaScript VM. */ @@ -30,16 +30,16 @@ async function loadForModule(moduleID: number): Promise { if (segmentLoader != null) { return await segmentLoader; } - // FIXME: `fetchBundle` should be renamed `fetchSegment`. - const {fetchBundle} = global; - if (fetchBundle == null) { + + const {fetchSegment} = global; + if (fetchSegment == null) { throw new Error( - 'When bundle splitting is enabled, the `global.fetchBundle` function ' + + 'When bundle splitting is enabled, the `global.fetchSegment` function ' + 'must be provided to be able to load particular bundle segments.', ); } segmentLoader = new Promise((resolve, reject) => { - fetchBundle(segmentId, error => { + fetchSegment(segmentId, error => { if (error != null) { reject(error); return; diff --git a/Libraries/Utilities/HMRClient.js b/Libraries/Utilities/HMRClient.js index c0443b069787e7..f6b9ce0822bc16 100644 --- a/Libraries/Utilities/HMRClient.js +++ b/Libraries/Utilities/HMRClient.js @@ -33,10 +33,12 @@ const HMRClient = { ? `${host}:${port}` : host; + bundleEntry = bundleEntry.replace(/\.(bundle|delta)/, '.js'); + // Build the websocket url const wsUrl = `ws://${wsHostPort}/hot?` + `platform=${platform}&` + - `bundleEntry=${bundleEntry.replace('.bundle', '.js')}`; + `bundleEntry=${bundleEntry}`; const activeWS = new WebSocket(wsUrl); activeWS.onerror = (e) => { diff --git a/Libraries/WebSocket/RCTReconnectingWebSocket.h b/Libraries/WebSocket/RCTReconnectingWebSocket.h index 559fa635095a0e..7eb8fabb736f71 100644 --- a/Libraries/WebSocket/RCTReconnectingWebSocket.h +++ b/Libraries/WebSocket/RCTReconnectingWebSocket.h @@ -11,28 +11,29 @@ #if RCT_DEV // Only supported in dev mode -@class RCTSRWebSocket; - -@protocol RCTWebSocketProtocolDelegate - -- (void)webSocketDidOpen:(RCTSRWebSocket *)webSocket; - -- (void)webSocket:(RCTSRWebSocket *)webSocket didReceiveMessage:(id)message; - -- (void)webSocket:(RCTSRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean; +@class RCTReconnectingWebSocket; +@protocol RCTReconnectingWebSocketDelegate +- (void)reconnectingWebSocketDidOpen:(RCTReconnectingWebSocket *)webSocket; +- (void)reconnectingWebSocket:(RCTReconnectingWebSocket *)webSocket didReceiveMessage:(id)message; +/** Sent when the socket has closed due to error or clean shutdown. An automatic reconnect will start shortly. */ +- (void)reconnectingWebSocketDidClose:(RCTReconnectingWebSocket *)webSocket; @end @interface RCTReconnectingWebSocket : NSObject -- (instancetype)initWithURL:(NSURL *)url; -@property (nonatomic, weak) id delegate; -/** @brief Must be set before -start to have effect */ -@property (nonatomic, strong) dispatch_queue_t delegateDispatchQueue; +/** Delegate will be messaged on the given queue (required). */ +- (instancetype)initWithURL:(NSURL *)url queue:(dispatch_queue_t)queue; + +@property (nonatomic, weak) id delegate; - (void)send:(id)data; - (void)start; - (void)stop; +- (instancetype)initWithURL:(NSURL *)url __deprecated_msg("Use initWithURL:queue: instead"); +/** @brief Must be set before -start to have effect */ +@property (nonatomic, strong) dispatch_queue_t delegateDispatchQueue __deprecated_msg("Use initWithURL:queue: instead"); + @end #endif diff --git a/Libraries/WebSocket/RCTReconnectingWebSocket.m b/Libraries/WebSocket/RCTReconnectingWebSocket.m index f6ab409caece17..899120e8e2b8ae 100644 --- a/Libraries/WebSocket/RCTReconnectingWebSocket.m +++ b/Libraries/WebSocket/RCTReconnectingWebSocket.m @@ -58,8 +58,6 @@ @implementation RCTReconnectingWebSocket { RCTSRWebSocket *_socket; } -@synthesize delegate = _delegate; - + (void)load { static dispatch_once_t onceToken; @@ -75,14 +73,20 @@ + (void)load }); } -- (instancetype)initWithURL:(NSURL *)url +- (instancetype)initWithURL:(NSURL *)url queue:(dispatch_queue_t)queue { if (self = [super init]) { _url = url; + _delegateDispatchQueue = queue; } return self; } +- (instancetype)initWithURL:(NSURL *)url +{ + return [self initWithURL:url queue:dispatch_get_main_queue()]; +} + - (void)send:(id)data { [_socket send:data]; @@ -93,9 +97,7 @@ - (void)start [self stop]; _socket = [[RCTSRWebSocket alloc] initWithURL:_url]; _socket.delegate = self; - if (_delegateDispatchQueue) { - [_socket setDelegateDispatchQueue:_delegateDispatchQueue]; - } + [_socket setDelegateDispatchQueue:_delegateDispatchQueue]; [_socket open]; } @@ -108,9 +110,7 @@ - (void)stop - (void)webSocket:(RCTSRWebSocket *)webSocket didReceiveMessage:(id)message { - if (_delegate) { - [_delegate webSocket:webSocket didReceiveMessage:message]; - } + [_delegate reconnectingWebSocket:self didReceiveMessage:message]; } - (void)reconnect @@ -126,17 +126,18 @@ - (void)reconnect - (void)webSocketDidOpen:(RCTSRWebSocket *)webSocket { - [self.delegate webSocketDidOpen:webSocket]; + [_delegate reconnectingWebSocketDidOpen:self]; } - (void)webSocket:(RCTSRWebSocket *)webSocket didFailWithError:(NSError *)error { + [_delegate reconnectingWebSocketDidClose:self]; [self reconnect]; } - (void)webSocket:(RCTSRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean { - [self.delegate webSocket:webSocket didCloseWithCode:code reason:reason wasClean:wasClean]; + [_delegate reconnectingWebSocketDidClose:self]; [self reconnect]; } diff --git a/Libraries/WebSocket/RCTWebSocket.xcodeproj/project.pbxproj b/Libraries/WebSocket/RCTWebSocket.xcodeproj/project.pbxproj index 8121ed0c108179..efb2609ad37b1a 100644 --- a/Libraries/WebSocket/RCTWebSocket.xcodeproj/project.pbxproj +++ b/Libraries/WebSocket/RCTWebSocket.xcodeproj/project.pbxproj @@ -435,8 +435,8 @@ EXECUTABLE_PREFIX = lib; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", + "RCT_METRO_PORT=${RCT_METRO_PORT}", "$(inherited)", - "RCT_METRO_PORT=${RCT_METRO_PORT}", ); GCC_TREAT_WARNINGS_AS_ERRORS = NO; OTHER_LDFLAGS = "-ObjC"; diff --git a/Libraries/WebSocket/RCTWebSocketExecutor.m b/Libraries/WebSocket/RCTWebSocketExecutor.m index b292c4f9b8ca15..9747730df0d0fc 100644 --- a/Libraries/WebSocket/RCTWebSocketExecutor.m +++ b/Libraries/WebSocket/RCTWebSocketExecutor.m @@ -117,7 +117,7 @@ - (BOOL)prepareJSRuntime initError = error; dispatch_semaphore_signal(s); }]; - long runtimeIsReady = dispatch_semaphore_wait(s, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC)); + long runtimeIsReady = dispatch_semaphore_wait(s, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 5)); if (initError) { RCTLogInfo(@"Websocket runtime setup failed: %@", initError); } diff --git a/Libraries/react-native/react-native-implementation.js b/Libraries/react-native/react-native-implementation.js index 88cd864c1e8869..577a896cd7258d 100644 --- a/Libraries/react-native/react-native-implementation.js +++ b/Libraries/react-native/react-native-implementation.js @@ -103,6 +103,7 @@ const ReactNative = { get unstable_batchedUpdates() { return require('ReactNative').unstable_batchedUpdates; }, get Vibration() { return require('Vibration'); }, get VibrationIOS() { return require('VibrationIOS'); }, + get YellowBox() { return require('YellowBox'); }, // Plugins get DeviceEventEmitter() { return require('RCTDeviceEventEmitter'); }, diff --git a/RNTester/RNTester.xcodeproj/project.pbxproj b/RNTester/RNTester.xcodeproj/project.pbxproj index 039f9c656f2436..18510385e40f69 100644 --- a/RNTester/RNTester.xcodeproj/project.pbxproj +++ b/RNTester/RNTester.xcodeproj/project.pbxproj @@ -21,7 +21,6 @@ 139FDEDB1B0651FB00C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDED91B0651EA00C62182 /* libRCTWebSocket.a */; }; 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; - 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 13B6C1A31C34225900D3FAF5 /* RCTURLUtilsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B6C1A21C34225900D3FAF5 /* RCTURLUtilsTests.m */; }; 13BCE84F1C9C209600DD7AAD /* RCTComponentPropsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BCE84E1C9C209600DD7AAD /* RCTComponentPropsTests.m */; }; @@ -59,7 +58,6 @@ 27F441EC1BEBE5030039B79C /* FlexibleSizeExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */; }; 2D4624FA1DA2EAC300C74D09 /* RCTLoggingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D299BAE1D33EBFA00FA1057 /* RCTLoggingTests.m */; }; 2D4624FB1DA2EAC300C74D09 /* RCTRootViewIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 27B885551BED29AF00008352 /* RCTRootViewIntegrationTests.m */; }; - 2D4624FC1DA2EAC300C74D09 /* RNTesterIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DB99D0B1BA0340600302749 /* RNTesterIntegrationTests.m */; }; 2D4624FD1DA2EAC300C74D09 /* RNTesterSnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 143BC5A01B21E45C00462512 /* RNTesterSnapshotTests.m */; }; 2D4624FE1DA2EAC300C74D09 /* RCTUIManagerScenarioTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */; }; 2D4625351DA2EBBE00C74D09 /* libRCTTest-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323CC1DA2DD8B000FE1B8 /* libRCTTest-tvOS.a */; }; @@ -75,12 +73,9 @@ 2D4BD8DD1DA2E20D005AC8A8 /* RCTImageUtilTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 144D21231B2204C5006DB32B /* RCTImageUtilTests.m */; }; 2D4BD8DE1DA2E20D005AC8A8 /* RCTJSONTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DB03471B5D2ED500C27245 /* RCTJSONTests.m */; }; 2D4BD8DF1DA2E20D005AC8A8 /* RCTMethodArgumentTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DF61B51B67A45000EDB188 /* RCTMethodArgumentTests.m */; }; - 2D4BD8E01DA2E20D005AC8A8 /* RCTModuleInitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 134CB9291C85A38800265FA6 /* RCTModuleInitTests.m */; }; - 2D4BD8E11DA2E20D005AC8A8 /* RCTModuleInitNotificationRaceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13129DD31C85F87C007D611C /* RCTModuleInitNotificationRaceTests.m */; }; 2D4BD8E21DA2E20D005AC8A8 /* RCTModuleMethodTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1393D0371B68CD1300E1B601 /* RCTModuleMethodTests.mm */; }; 2D4BD8E31DA2E20D005AC8A8 /* RCTShadowViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 138D6A161B53CD440074A87E /* RCTShadowViewTests.m */; }; 2D4BD8E41DA2E20D005AC8A8 /* RCTUIManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFAB1B21F5E400C1F8F2 /* RCTUIManagerTests.m */; }; - 2D4BD8E51DA2E20D005AC8A8 /* RCTComponentPropsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BCE84E1C9C209600DD7AAD /* RCTComponentPropsTests.m */; }; 2D4BD8E61DA2E20D005AC8A8 /* RNTesterUnitTestsBundle.js in Resources */ = {isa = PBXBuildFile; fileRef = 3DD981D51D33C6FB007DC7BE /* RNTesterUnitTestsBundle.js */; }; 2D4BD8E71DA2E20D005AC8A8 /* libOCMock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14D6D7101B220EB3001FB087 /* libOCMock.a */; }; 2D66FF8F1ECA406D00F0A767 /* libART.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D66FF651ECA405900F0A767 /* libART.a */; }; @@ -89,7 +84,6 @@ 2DD323DC1DA2DDBF000FE1B8 /* FlexibleSizeExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */; }; 2DD323DD1DA2DDBF000FE1B8 /* UpdatePropertiesExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.m */; }; 2DD323DE1DA2DDBF000FE1B8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; - 2DD323DF1DA2DDBF000FE1B8 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 2DD323E01DA2DDBF000FE1B8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 2DD323E11DA2DDBF000FE1B8 /* legacy_image@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */; }; 2DD323E21DA2DDBF000FE1B8 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB61A68108700A75B9A /* Info.plist */; }; @@ -100,6 +94,18 @@ 2DD323E81DA2DE3F000FE1B8 /* libRCTText-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D01DA2DD8B000FE1B8 /* libRCTText-tvOS.a */; }; 2DD323E91DA2DE3F000FE1B8 /* libRCTWebSocket-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D51DA2DD8B000FE1B8 /* libRCTWebSocket-tvOS.a */; }; 2DD323EA1DA2DE3F000FE1B8 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D91DA2DD8B000FE1B8 /* libReact.a */; }; + 2DDEF0101F84BF7B00DBDF73 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */; }; + 2DE7E7FD1FB2A4F3009E225D /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323B51DA2DD8B000FE1B8 /* libRCTAnimation.a */; }; + 2DE7E7FE1FB2A4F3009E225D /* libRCTBlob-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5281CA531EEAC9A700AC40CD /* libRCTBlob-tvOS.a */; }; + 2DE7E7FF1FB2A4F3009E225D /* libRCTImage-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323BB1DA2DD8B000FE1B8 /* libRCTImage-tvOS.a */; }; + 2DE7E8001FB2A4F3009E225D /* libRCTLinking-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323BF1DA2DD8B000FE1B8 /* libRCTLinking-tvOS.a */; }; + 2DE7E8011FB2A4F3009E225D /* libRCTNetwork-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323C31DA2DD8B000FE1B8 /* libRCTNetwork-tvOS.a */; }; + 2DE7E8021FB2A4F3009E225D /* libRCTPushNotification-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D05746C1DE6008900184BB4 /* libRCTPushNotification-tvOS.a */; }; + 2DE7E8031FB2A4F3009E225D /* libRCTSettings-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323C81DA2DD8B000FE1B8 /* libRCTSettings-tvOS.a */; }; + 2DE7E8041FB2A4F3009E225D /* libRCTTest-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323CC1DA2DD8B000FE1B8 /* libRCTTest-tvOS.a */; }; + 2DE7E8051FB2A4F3009E225D /* libRCTText-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D01DA2DD8B000FE1B8 /* libRCTText-tvOS.a */; }; + 2DE7E8061FB2A4F3009E225D /* libRCTWebSocket-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D51DA2DD8B000FE1B8 /* libRCTWebSocket-tvOS.a */; }; + 2DE7E8071FB2A4F3009E225D /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D91DA2DD8B000FE1B8 /* libReact.a */; }; 3578590A1B28D2CF00341EDB /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 357859011B28D2C500341EDB /* libRCTLinking.a */; }; 39AA31A41DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 39AA31A31DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m */; }; 3D05746D1DE6008900184BB4 /* libRCTPushNotification-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D05746C1DE6008900184BB4 /* libRCTPushNotification-tvOS.a */; }; @@ -210,6 +216,20 @@ remoteGlobalIDString = 2DD3238F1DA2DD8A000FE1B8; remoteInfo = "RNTester-tvOS"; }; + 2D609F0C1F84BD7E00D65B08 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 14AADEFF1AC3DB95002390C9 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 9936F3131F5F2E4B0010BF04; + remoteInfo = privatedata; + }; + 2D609F0E1F84BD7E00D65B08 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 14AADEFF1AC3DB95002390C9 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 9936F32F1F5F2E5B0010BF04; + remoteInfo = "privatedata-tvOS"; + }; 2D66FF641ECA405900F0A767 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 2D66FF5F1ECA405900F0A767 /* ART.xcodeproj */; @@ -238,13 +258,6 @@ remoteGlobalIDString = 3D383D621EBD27B9005632C8; remoteInfo = "double-conversion-tvOS"; }; - 2DD323A61DA2DD8B000FE1B8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 2DD3238F1DA2DD8A000FE1B8; - remoteInfo = "RNTester-tvOS"; - }; 2DD323B41DA2DD8B000FE1B8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 13E5019C1D07A502005F35D8 /* RCTAnimation.xcodeproj */; @@ -454,7 +467,6 @@ 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = RNTester/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = RNTester/AppDelegate.m; sourceTree = ""; }; 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = RNTester/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RNTester/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = RNTester/main.m; sourceTree = ""; }; 13B6C1A21C34225900D3FAF5 /* RCTURLUtilsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTURLUtilsTests.m; sourceTree = ""; }; @@ -499,6 +511,7 @@ 2DD323901DA2DD8A000FE1B8 /* RNTester-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "RNTester-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 2DD323A01DA2DD8B000FE1B8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 2DD323A51DA2DD8B000FE1B8 /* RNTester-tvOSUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "RNTester-tvOSUnitTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = RNTester/Images.xcassets; sourceTree = ""; }; 357858F81B28D2C400341EDB /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = ""; }; 39AA31A31DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUnicodeDecodeTests.m; sourceTree = ""; }; 3D13F83E1D6F6AE000E69E0E /* RNTesterBundle.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RNTesterBundle.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -602,6 +615,17 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 2DE7E7FD1FB2A4F3009E225D /* libRCTAnimation.a in Frameworks */, + 2DE7E7FE1FB2A4F3009E225D /* libRCTBlob-tvOS.a in Frameworks */, + 2DE7E7FF1FB2A4F3009E225D /* libRCTImage-tvOS.a in Frameworks */, + 2DE7E8001FB2A4F3009E225D /* libRCTLinking-tvOS.a in Frameworks */, + 2DE7E8011FB2A4F3009E225D /* libRCTNetwork-tvOS.a in Frameworks */, + 2DE7E8021FB2A4F3009E225D /* libRCTPushNotification-tvOS.a in Frameworks */, + 2DE7E8031FB2A4F3009E225D /* libRCTSettings-tvOS.a in Frameworks */, + 2DE7E8041FB2A4F3009E225D /* libRCTTest-tvOS.a in Frameworks */, + 2DE7E8051FB2A4F3009E225D /* libRCTText-tvOS.a in Frameworks */, + 2DE7E8061FB2A4F3009E225D /* libRCTWebSocket-tvOS.a in Frameworks */, + 2DE7E8071FB2A4F3009E225D /* libReact.a in Frameworks */, 2D4BD8E71DA2E20D005AC8A8 /* libOCMock.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -705,10 +729,10 @@ 13B07FAE1A68108700A75B9A /* RNTester */ = { isa = PBXGroup; children = ( + 2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */, 272E6B3A1BEA846C001FCF37 /* NativeExampleViews */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.m */, - 13B07FB51A68108700A75B9A /* Images.xcassets */, 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, 13B07FB71A68108700A75B9A /* main.m */, 1323F18D1C04ABAC0091BED0 /* Supporting Files */, @@ -806,6 +830,8 @@ 2D66FF8C1ECA405900F0A767 /* libthird-party.a */, 3D507F441EBC88B700B56834 /* libdouble-conversion.a */, 2D66FF8E1ECA405900F0A767 /* libdouble-conversion.a */, + 2D609F0D1F84BD7E00D65B08 /* libprivatedata.a */, + 2D609F0F1F84BD7E00D65B08 /* libprivatedata-tvOS.a */, ); name = Products; sourceTree = ""; @@ -870,6 +896,13 @@ path = "RNTester-tvOS"; sourceTree = ""; }; + 2DE7E7D81FB2A4F3009E225D /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; 357858F91B28D2C400341EDB /* Products */ = { isa = PBXGroup; children = ( @@ -928,6 +961,7 @@ 14D6D6EA1B2205C0001FB087 /* OCMock */, 2DD323911DA2DD8B000FE1B8 /* RNTester-tvOS */, 83CBBA001A601CBA00E9B192 /* Products */, + 2DE7E7D81FB2A4F3009E225D /* Frameworks */, ); indentWidth = 2; sourceTree = ""; @@ -1060,7 +1094,6 @@ buildRules = ( ); dependencies = ( - 2DD323A71DA2DD8B000FE1B8 /* PBXTargetDependency */, ); name = "RNTester-tvOSUnitTests"; productName = "RNTester-tvOSUnitTests"; @@ -1275,6 +1308,20 @@ remoteRef = 14DC67F01AB71876001358AB /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 2D609F0D1F84BD7E00D65B08 /* libprivatedata.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libprivatedata.a; + remoteRef = 2D609F0C1F84BD7E00D65B08 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2D609F0F1F84BD7E00D65B08 /* libprivatedata-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libprivatedata-tvOS.a"; + remoteRef = 2D609F0E1F84BD7E00D65B08 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 2D66FF651ECA405900F0A767 /* libART.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -1500,8 +1547,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 3D56F9F11D6F6E9B00F53A06 /* RNTesterBundle.bundle in Resources */, + 2DDEF0101F84BF7B00DBDF73 /* Images.xcassets in Resources */, 3D2AFAF51D646CF80089D1A3 /* legacy_image@2x.png in Resources */, 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, ); @@ -1525,7 +1572,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2DD323DF1DA2DDBF000FE1B8 /* Images.xcassets in Resources */, 2DD323E11DA2DDBF000FE1B8 /* legacy_image@2x.png in Resources */, 2DD323E21DA2DDBF000FE1B8 /* Info.plist in Resources */, ); @@ -1641,7 +1687,6 @@ buildActionMask = 2147483647; files = ( C654F17E1EB34D24000B7A9A /* RNTesterTestModule.m in Sources */, - 2D4624FC1DA2EAC300C74D09 /* RNTesterIntegrationTests.m in Sources */, 2D4624FA1DA2EAC300C74D09 /* RCTLoggingTests.m in Sources */, 2D4624FE1DA2EAC300C74D09 /* RCTUIManagerScenarioTests.m in Sources */, 2D4624FD1DA2EAC300C74D09 /* RNTesterSnapshotTests.m in Sources */, @@ -1669,10 +1714,8 @@ 2D4BD8D41DA2E20D005AC8A8 /* RCTAllocationTests.m in Sources */, 2D4BD8DA1DA2E20D005AC8A8 /* RCTGzipTests.m in Sources */, 2D4BD8DB1DA2E20D005AC8A8 /* RCTImageLoaderHelpers.m in Sources */, - 2D4BD8E51DA2E20D005AC8A8 /* RCTComponentPropsTests.m in Sources */, 2D4BD8D71DA2E20D005AC8A8 /* RCTConvert_NSURLTests.m in Sources */, 2D4BD8E21DA2E20D005AC8A8 /* RCTModuleMethodTests.mm in Sources */, - 2D4BD8E11DA2E20D005AC8A8 /* RCTModuleInitNotificationRaceTests.m in Sources */, 2D4BD8DF1DA2E20D005AC8A8 /* RCTMethodArgumentTests.m in Sources */, 2D4BD8D31DA2E20D005AC8A8 /* RCTBundleURLProviderTests.m in Sources */, 2D4BD8D21DA2E20D005AC8A8 /* RCTURLUtilsTests.m in Sources */, @@ -1682,7 +1725,6 @@ 2D4BD8D81DA2E20D005AC8A8 /* RCTFontTests.m in Sources */, 2D4BD8DD1DA2E20D005AC8A8 /* RCTImageUtilTests.m in Sources */, 2D4BD8E41DA2E20D005AC8A8 /* RCTUIManagerTests.m in Sources */, - 2D4BD8E01DA2E20D005AC8A8 /* RCTModuleInitTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1706,11 +1748,6 @@ target = 2DD3238F1DA2DD8A000FE1B8 /* RNTester-tvOS */; targetProxy = 2D4624C31DA2EA6900C74D09 /* PBXContainerItemProxy */; }; - 2DD323A71DA2DD8B000FE1B8 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 2DD3238F1DA2DD8A000FE1B8 /* RNTester-tvOS */; - targetProxy = 2DD323A61DA2DD8B000FE1B8 /* PBXContainerItemProxy */; - }; 3D13F84C1D6F6B5F00E69E0E /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 3D13F83D1D6F6AE000E69E0E /* RNTesterBundle */; @@ -1775,6 +1812,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = "$(SRCROOT)/RNTester/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = com.facebook.react.uiapp; PRODUCT_NAME = RNTester; @@ -1788,6 +1826,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = V9WTTPBFK9; INFOPLIST_FILE = "$(SRCROOT)/RNTester/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = com.facebook.react.uiapp; PRODUCT_NAME = RNTester; @@ -1896,7 +1935,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.2; + TVOS_DEPLOYMENT_TARGET = 10.2; }; name = Debug; }; @@ -1916,7 +1955,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.2; + TVOS_DEPLOYMENT_TARGET = 10.2; }; name = Release; }; diff --git a/RNTester/RNTester/Images.xcassets/AppIcon.appiconset/Contents.json b/RNTester/RNTester/Images.xcassets/AppIcon.appiconset/Contents.json index 7accb5223dd5f8..2186a876cf87c8 100644 --- a/RNTester/RNTester/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/RNTester/RNTester/Images.xcassets/AppIcon.appiconset/Contents.json @@ -45,6 +45,11 @@ "idiom" : "iphone", "filename" : "Icon-60@3x.png", "scale" : "3x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" } ], "info" : { diff --git a/RNTester/RNTesterIntegrationTests/RCTRootViewIntegrationTests.m b/RNTester/RNTesterIntegrationTests/RCTRootViewIntegrationTests.m index 364a2b956202d4..fc015278359fdd 100644 --- a/RNTester/RNTesterIntegrationTests/RCTRootViewIntegrationTests.m +++ b/RNTester/RNTesterIntegrationTests/RCTRootViewIntegrationTests.m @@ -117,7 +117,7 @@ @implementation RCTRootViewIntegrationTests - (void)setUp { - _runner = RCTInitRunnerForApp(@"IntegrationTests/RCTRootViewIntegrationTestApp", nil); + _runner = RCTInitRunnerForApp(@"IntegrationTests/RCTRootViewIntegrationTestApp", nil, nil); } #pragma mark Logic Tests diff --git a/RNTester/RNTesterIntegrationTests/RNTesterIntegrationTests.m b/RNTester/RNTesterIntegrationTests/RNTesterIntegrationTests.m index 6a09c5e1ee5930..005d0e899ee371 100644 --- a/RNTester/RNTesterIntegrationTests/RNTesterIntegrationTests.m +++ b/RNTester/RNTesterIntegrationTests/RNTesterIntegrationTests.m @@ -37,7 +37,7 @@ @implementation RNTesterIntegrationTests - (void)setUp { - _runner = RCTInitRunnerForApp(@"IntegrationTests/IntegrationTestsApp", nil); + _runner = RCTInitRunnerForApp(@"IntegrationTests/IntegrationTestsApp", nil, nil); _runner.recordMode = NO; } diff --git a/RNTester/RNTesterIntegrationTests/RNTesterSnapshotTests.m b/RNTester/RNTesterIntegrationTests/RNTesterSnapshotTests.m index 8b369d4c01f7bc..4ba1e184a42422 100644 --- a/RNTester/RNTesterIntegrationTests/RNTesterSnapshotTests.m +++ b/RNTester/RNTesterIntegrationTests/RNTesterSnapshotTests.m @@ -24,7 +24,7 @@ @implementation RNTesterSnapshotTests - (void)setUp { - _runner = RCTInitRunnerForApp(@"RNTester/js/RNTesterApp.ios", nil); + _runner = RCTInitRunnerForApp(@"RNTester/js/RNTesterApp.ios", nil, nil); if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 11) { _runner.testSuffix = @"-iOS11"; } else if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10) { diff --git a/RNTester/js/ListExampleShared.js b/RNTester/js/ListExampleShared.js index cae8519f0aca74..d9569efb0d1c97 100644 --- a/RNTester/js/ListExampleShared.js +++ b/RNTester/js/ListExampleShared.js @@ -201,6 +201,9 @@ function pressItem(context: Object, key: string) { } function renderSmallSwitchOption(context: Object, key: string) { + if(Platform.isTVOS) { + return null; + } return ( {key}: diff --git a/RNTester/js/ModalExample.js b/RNTester/js/ModalExample.js index c57ef54edb67d1..e0c4a55b22c5cb 100644 --- a/RNTester/js/ModalExample.js +++ b/RNTester/js/ModalExample.js @@ -16,6 +16,7 @@ var ReactNative = require('react-native'); var { Modal, Picker, + Platform, StyleSheet, Switch, Text, @@ -91,6 +92,15 @@ class ModalExample extends React.Component<{}, $FlowFixMeState> { this.setState({transparent: !this.state.transparent}); }; + renderSwitch() { + if (Platform.isTVOS) { + return null; + } + return ( + + ); + } + render() { var modalBackgroundStyle = { backgroundColor: this.state.transparent ? 'rgba(0, 0, 0, 0.5)' : '#f5fcff', @@ -140,9 +150,21 @@ class ModalExample extends React.Component<{}, $FlowFixMeState> { Transparent - + {this.renderSwitch()} - + {this.renderPickers()} + + + ); + } + renderPickers() { + if (Platform.isTVOS) { + return null; + } + return ( + Presentation style { - - ); } } + exports.examples = [ { title: 'Modal Presentation', diff --git a/RNTester/js/TextInputExample.ios.js b/RNTester/js/TextInputExample.ios.js index 453bc269b9e89e..efb11653391e4a 100644 --- a/RNTester/js/TextInputExample.ios.js +++ b/RNTester/js/TextInputExample.ios.js @@ -284,7 +284,7 @@ class SelectionExample extends React.Component<$FlowFixMeProps, SelectionExample } selectRandom() { - var positions = [this.getRandomPosition(), this.getRandomPosition()].sort(); + var positions = [this.getRandomPosition(), this.getRandomPosition()].sort((a, b) => a - b); this.select(...positions); } diff --git a/React.podspec b/React.podspec index b4346aa9a403b4..1e790575d270ca 100644 --- a/React.podspec +++ b/React.podspec @@ -43,7 +43,7 @@ Pod::Spec.new do |s| s.subspec "Core" do |ss| ss.dependency "yoga", "#{package["version"]}.React" - ss.source_files = "React/**/*.{c,h,m,mm,S}" + ss.source_files = "React/**/*.{c,h,m,mm,S,cpp}" ss.exclude_files = "**/__tests__/*", "IntegrationTests/*", "React/DevSupport/*", diff --git a/React/Base/RCTAssert.m b/React/Base/RCTAssert.m index 345dae02158fb6..79db51973c46ec 100644 --- a/React/Base/RCTAssert.m +++ b/React/Base/RCTAssert.m @@ -131,7 +131,7 @@ void RCTFatal(NSError *error) #endif NSString *name = [NSString stringWithFormat:@"%@: %@", RCTFatalExceptionName, error.localizedDescription]; NSString *message = RCTFormatError(error.localizedDescription, error.userInfo[RCTJSStackTraceKey], 75); - [NSException raise:name format:@"%@", message]; + @throw [[NSException alloc] initWithName:name reason:message userInfo:nil]; #if DEBUG } @catch (NSException *e) {} #endif diff --git a/React/Base/RCTBridge+Private.h b/React/Base/RCTBridge+Private.h index ec7dde92fa21c8..343d998db4ab52 100644 --- a/React/Base/RCTBridge+Private.h +++ b/React/Base/RCTBridge+Private.h @@ -7,6 +7,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ +#import #import #import @@ -158,6 +159,15 @@ RCT_EXTERN void RCTVerifyAllModulesExported(NSArray *extraModules); @end +@interface RCTBridge (JavaScriptCore) + +/** + * The raw JSGlobalContextRef used by the bridge. + */ +@property (nonatomic, readonly, assign) JSGlobalContextRef jsContextRef; + +@end + @interface RCTBatchedBridge : RCTBridge @property (nonatomic, weak, readonly) RCTBridge *parentBridge; diff --git a/React/Base/RCTBridge.h b/React/Base/RCTBridge.h index 4d61b9e0cdb57f..99ad085225f25a 100644 --- a/React/Base/RCTBridge.h +++ b/React/Base/RCTBridge.h @@ -138,6 +138,13 @@ RCT_EXTERN NSString *RCTBridgeModuleNameForClass(Class bridgeModuleClass); arguments:(NSArray *)arguments error:(NSError **)error; +/** + * This method registers the file path of an additional JS segment by its ID. + * + * @experimental + */ +- (void)registerSegmentWithId:(NSUInteger)segmentId path:(NSString *)path; + /** * Retrieve a bridge module instance by name or class. Note that modules are * lazily instantiated, so calling these methods for the first time with a given @@ -171,6 +178,11 @@ RCT_EXTERN NSString *RCTBridgeModuleNameForClass(Class bridgeModuleClass); */ @property (nonatomic, strong, readonly) NSURL *bundleURL; +/** + * URL of the embedded bundle of the bridge. + */ +@property (nonatomic, strong, readonly) NSURL *embeddedBundleURL; + /** * The class of the executor currently being used. Changes to this value will * take effect after the bridge is reloaded. diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index bdf741008f6a52..13329f272d7f47 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -17,7 +17,6 @@ #if RCT_ENABLE_INSPECTOR #import "RCTInspectorDevServerHelper.h" #endif -#import "RCTJSEnvironment.h" #import "RCTLog.h" #import "RCTModuleData.h" #import "RCTPerformanceLogger.h" @@ -329,6 +328,11 @@ - (void)setUp // Sanitize the bundle URL _bundleURL = [RCTConvert NSURL:_bundleURL.absoluteString]; + if ([self.delegate respondsToSelector:@selector(embeddedBundleURLForBridge:)]) { + _embeddedBundleURL = [self.delegate embeddedBundleURLForBridge:self]; + _embeddedBundleURL = [RCTConvert NSURL:_embeddedBundleURL.absoluteString]; + } + self.batchedBridge = [[bridgeClass alloc] initWithParentBridge:self]; [self.batchedBridge start]; @@ -393,13 +397,9 @@ - (JSValue *)callFunctionOnModule:(NSString *)module return [self.batchedBridge callFunctionOnModule:module method:method arguments:arguments error:error]; } -@end - -@implementation RCTBridge (JavaScriptCore) - -- (JSContext *)jsContext +- (void)registerSegmentWithId:(NSUInteger)segmentId path:(NSString *)path { - return [self.batchedBridge jsContext]; + [self.batchedBridge registerSegmentWithId:segmentId path:path]; } - (JSGlobalContextRef)jsContextRef diff --git a/React/Base/RCTBridgeDelegate.h b/React/Base/RCTBridgeDelegate.h index 631e1825535ec9..1609544a94ff3c 100644 --- a/React/Base/RCTBridgeDelegate.h +++ b/React/Base/RCTBridgeDelegate.h @@ -41,10 +41,10 @@ - (NSArray> *)extraModulesForBridge:(RCTBridge *)bridge; /** - * The location of bundle path, this should be a `file://` url + * The location of embedded bundle path, this should be a `file://` url * pointing to a path inside the bundle resources, e.g. `file://..//main.jsbundle`. */ -- (NSURL *)bundledSourceURLForBridge:(RCTBridge *)bridge; +- (NSURL *)embeddedBundleURLForBridge:(RCTBridge *)bridge; /** * Configure whether the JSCExecutor created should use the system JSC API or @@ -94,11 +94,4 @@ - (void)loadSourceForBridge:(RCTBridge *)bridge withBlock:(RCTSourceLoadBlock)loadCallback; -/** - * Specifies the path to folder where additional bundles are located - * - * @experimental - */ -- (NSURL *)jsBundlesDirectory; - @end diff --git a/React/Base/RCTBundleURLProvider.h b/React/Base/RCTBundleURLProvider.h index efc9be73bac36f..7a2562e415585e 100644 --- a/React/Base/RCTBundleURLProvider.h +++ b/React/Base/RCTBundleURLProvider.h @@ -59,11 +59,6 @@ extern const NSUInteger kRCTBundleURLProviderDefaultPort; resourceExtension:(NSString *)extension offlineBundle:(NSBundle *)offlineBundle; -/** - * Returns the URL of the packager server. - */ -- (NSURL *)packagerServerURL; - /** * The IP address or hostname of the packager. */ diff --git a/React/Base/RCTBundleURLProvider.m b/React/Base/RCTBundleURLProvider.m index 61c286ec4518d6..f6fb3ce8af29fe 100644 --- a/React/Base/RCTBundleURLProvider.m +++ b/React/Base/RCTBundleURLProvider.m @@ -111,12 +111,6 @@ - (NSString *)packagerServerHost return nil; } -- (NSURL *)packagerServerURL -{ - NSString *const host = [self packagerServerHost]; - return host ? serverRootWithHost(host) : nil; -} - - (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot fallbackResource:(NSString *)resourceName fallbackExtension:(NSString *)extension { NSString *packagerServerHost = [self packagerServerHost]; diff --git a/React/Base/RCTDefines.h b/React/Base/RCTDefines.h index f700e0335080fa..1b185ce1908049 100644 --- a/React/Base/RCTDefines.h +++ b/React/Base/RCTDefines.h @@ -8,7 +8,7 @@ */ #if __OBJC__ -# import +#import #endif /** @@ -74,6 +74,23 @@ #define RCT_PROFILE RCT_DEV #endif +/** + * Add the default Metro packager port number + */ +#ifndef RCT_METRO_PORT +#define RCT_METRO_PORT 8081 +#else +// test if RCT_METRO_PORT is empty +#define RCT_METRO_PORT_DO_EXPAND(VAL) VAL##1 +#define RCT_METRO_PORT_EXPAND(VAL) RCT_METRO_PORT_DO_EXPAND(VAL) +#if !defined(RCT_METRO_PORT) || (RCT_METRO_PORT_EXPAND(RCT_METRO_PORT) == 1) +// Only here if RCT_METRO_PORT is not defined +// OR RCT_METRO_PORT is the empty string +#undef RCT_METRO_PORT +#define RCT_METRO_PORT 8081 +#endif +#endif + /** * By default, only raise an NSAssertion in debug mode * (custom assert functions will still be called). @@ -86,23 +103,16 @@ * Concat two literals. Supports macro expansions, * e.g. RCT_CONCAT(foo, __FILE__). */ -#define RCT_CONCAT2(A, B) A ## B +#define RCT_CONCAT2(A, B) A##B #define RCT_CONCAT(A, B) RCT_CONCAT2(A, B) /** * Throw an assertion for unimplemented methods. */ -#define RCT_NOT_IMPLEMENTED(method) \ -_Pragma("clang diagnostic push") \ -_Pragma("clang diagnostic ignored \"-Wmissing-method-return-type\"") \ -_Pragma("clang diagnostic ignored \"-Wunused-parameter\"") \ -RCT_EXTERN NSException *_RCTNotImplementedException(SEL, Class); \ -method NS_UNAVAILABLE { @throw _RCTNotImplementedException(_cmd, [self class]); } \ -_Pragma("clang diagnostic pop") - -/** - * Add the default Metro packager port number - */ -#ifndef RCT_METRO_PORT -#define RCT_METRO_PORT 8081 -#endif +#define RCT_NOT_IMPLEMENTED(method) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wmissing-method-return-type\"") \ + _Pragma("clang diagnostic ignored \"-Wunused-parameter\"") \ + RCT_EXTERN NSException *_RCTNotImplementedException(SEL, Class); \ + method NS_UNAVAILABLE { @throw _RCTNotImplementedException(_cmd, [self class]); } \ + _Pragma("clang diagnostic pop") diff --git a/React/Base/RCTJSEnvironment.h b/React/Base/RCTJSEnvironment.h deleted file mode 100644 index a135f62a575958..00000000000000 --- a/React/Base/RCTJSEnvironment.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import - -@protocol RCTJSEnvironment - -/** - * The JSContext used by the bridge. - */ -@property (nonatomic, readonly, strong) JSContext *jsContext; -/** - * The raw JSGlobalContextRef used by the bridge. - */ -@property (nonatomic, readonly, assign) JSGlobalContextRef jsContextRef; - -@end - -@interface RCTBridge (RCTJSEnvironment) - -@end diff --git a/React/Base/RCTModuleData.mm b/React/Base/RCTModuleData.mm index 340e9a5a7db6ee..e333f0e2f7622a 100644 --- a/React/Base/RCTModuleData.mm +++ b/React/Base/RCTModuleData.mm @@ -65,7 +65,7 @@ - (void)setUp methodName = "init"; } RCTLogWarn(@"Module %@ requires main queue setup since it overrides `%s` but doesn't implement " - "`requiresMainQueueSetup. In a future release React Native will default to initializing all native modules " + "`requiresMainQueueSetup`. In a future release React Native will default to initializing all native modules " "on a background thread unless explicitly opted-out of.", _moduleClass, methodName); } } diff --git a/React/Base/RCTRootView.m b/React/Base/RCTRootView.m index 20525b66093201..4a5e53c650ce51 100644 --- a/React/Base/RCTRootView.m +++ b/React/Base/RCTRootView.m @@ -24,6 +24,7 @@ #import "RCTRootContentView.h" #import "RCTTouchHandler.h" #import "RCTUIManager.h" +#import "RCTUIManagerUtils.h" #import "RCTUtils.h" #import "RCTView.h" #import "UIView+React.h" @@ -90,8 +91,8 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge #if TARGET_OS_TV self.tvRemoteHandler = [RCTTVRemoteHandler new]; - for (UIGestureRecognizer *gr in self.tvRemoteHandler.tvRemoteGestureRecognizers) { - [self addGestureRecognizer:gr]; + for (NSString *key in [self.tvRemoteHandler.tvRemoteGestureRecognizers allKeys]) { + [self addGestureRecognizer:self.tvRemoteHandler.tvRemoteGestureRecognizers[key]]; } #endif @@ -243,7 +244,7 @@ - (NSNumber *)reactTag * NOTE: Since the bridge persists, the RootViews might be reused, so the * react tag must be re-assigned every time a new UIManager is created. */ - self.reactTag = [_bridge.uiManager allocateRootTag]; + self.reactTag = RCTAllocateRootViewTag(); } return super.reactTag; } @@ -396,14 +397,3 @@ - (CGSize)intrinsicSize } @end - -@implementation RCTUIManager (RCTRootView) - -- (NSNumber *)allocateRootTag -{ - NSNumber *rootTag = objc_getAssociatedObject(self, _cmd) ?: @1; - objc_setAssociatedObject(self, _cmd, @(rootTag.integerValue + 10), OBJC_ASSOCIATION_RETAIN_NONATOMIC); - return rootTag; -} - -@end diff --git a/React/Base/RCTTVRemoteHandler.h b/React/Base/RCTTVRemoteHandler.h index 51492a4c9fbb69..aedd9aefe0a93c 100644 --- a/React/Base/RCTTVRemoteHandler.h +++ b/React/Base/RCTTVRemoteHandler.h @@ -9,8 +9,26 @@ #import + +extern NSString *const RCTTVRemoteEventMenu; +extern NSString *const RCTTVRemoteEventPlayPause; +extern NSString *const RCTTVRemoteEventSelect; + +extern NSString *const RCTTVRemoteEventLongPlayPause; +extern NSString *const RCTTVRemoteEventLongSelect; + +extern NSString *const RCTTVRemoteEventLeft; +extern NSString *const RCTTVRemoteEventRight; +extern NSString *const RCTTVRemoteEventUp; +extern NSString *const RCTTVRemoteEventDown; + +extern NSString *const RCTTVRemoteEventSwipeLeft; +extern NSString *const RCTTVRemoteEventSwipeRight; +extern NSString *const RCTTVRemoteEventSwipeUp; +extern NSString *const RCTTVRemoteEventSwipeDown; + @interface RCTTVRemoteHandler : NSObject -@property (nonatomic, copy, readonly) NSArray *tvRemoteGestureRecognizers; +@property (nonatomic, copy, readonly) NSDictionary *tvRemoteGestureRecognizers; @end diff --git a/React/Base/RCTTVRemoteHandler.m b/React/Base/RCTTVRemoteHandler.m index 12d70809d25f23..8b39e8eddd2529 100644 --- a/React/Base/RCTTVRemoteHandler.m +++ b/React/Base/RCTTVRemoteHandler.m @@ -26,71 +26,102 @@ #import "RCTDevMenu.h" #endif +NSString *const RCTTVRemoteEventMenu = @"menu"; +NSString *const RCTTVRemoteEventPlayPause = @"playPause"; +NSString *const RCTTVRemoteEventSelect = @"select"; + +NSString *const RCTTVRemoteEventLongPlayPause = @"longPlayPause"; +NSString *const RCTTVRemoteEventLongSelect = @"longSelect"; + +NSString *const RCTTVRemoteEventLeft = @"left"; +NSString *const RCTTVRemoteEventRight = @"right"; +NSString *const RCTTVRemoteEventUp = @"up"; +NSString *const RCTTVRemoteEventDown = @"down"; + +NSString *const RCTTVRemoteEventSwipeLeft = @"swipeLeft"; +NSString *const RCTTVRemoteEventSwipeRight = @"swipeRight"; +NSString *const RCTTVRemoteEventSwipeUp = @"swipeUp"; +NSString *const RCTTVRemoteEventSwipeDown = @"swipeDown"; + + @implementation RCTTVRemoteHandler { - NSMutableArray *_tvRemoteGestureRecognizers; + NSMutableDictionary *_tvRemoteGestureRecognizers; } - (instancetype)init { if ((self = [super init])) { - _tvRemoteGestureRecognizers = [NSMutableArray array]; + _tvRemoteGestureRecognizers = [NSMutableDictionary dictionary]; // Recognizers for Apple TV remote buttons // Play/Pause [self addTapGestureRecognizerWithSelector:@selector(playPausePressed:) - pressType:UIPressTypePlayPause]; + pressType:UIPressTypePlayPause + name:RCTTVRemoteEventPlayPause]; // Menu [self addTapGestureRecognizerWithSelector:@selector(menuPressed:) - pressType:UIPressTypeMenu]; + pressType:UIPressTypeMenu + name:RCTTVRemoteEventMenu]; // Select [self addTapGestureRecognizerWithSelector:@selector(selectPressed:) - pressType:UIPressTypeSelect]; + pressType:UIPressTypeSelect + name:RCTTVRemoteEventSelect]; // Up [self addTapGestureRecognizerWithSelector:@selector(swipedUp:) - pressType:UIPressTypeUpArrow]; + pressType:UIPressTypeUpArrow + name:RCTTVRemoteEventUp]; // Down [self addTapGestureRecognizerWithSelector:@selector(swipedDown:) - pressType:UIPressTypeDownArrow]; + pressType:UIPressTypeDownArrow + name:RCTTVRemoteEventDown]; // Left [self addTapGestureRecognizerWithSelector:@selector(swipedLeft:) - pressType:UIPressTypeLeftArrow]; + pressType:UIPressTypeLeftArrow + name:RCTTVRemoteEventLeft]; // Right [self addTapGestureRecognizerWithSelector:@selector(swipedRight:) - pressType:UIPressTypeRightArrow]; + pressType:UIPressTypeRightArrow + name:RCTTVRemoteEventRight]; // Recognizers for long button presses // We don't intercept long menu press -- that's used by the system to go to the home screen [self addLongPressGestureRecognizerWithSelector:@selector(longPlayPausePressed:) - pressType:UIPressTypePlayPause]; + pressType:UIPressTypePlayPause + name:RCTTVRemoteEventLongPlayPause]; [self addLongPressGestureRecognizerWithSelector:@selector(longSelectPressed:) - pressType:UIPressTypeSelect]; + pressType:UIPressTypeSelect + name:RCTTVRemoteEventLongSelect]; // Recognizers for Apple TV remote trackpad swipes // Up [self addSwipeGestureRecognizerWithSelector:@selector(swipedUp:) - direction:UISwipeGestureRecognizerDirectionUp]; + direction:UISwipeGestureRecognizerDirectionUp + name:RCTTVRemoteEventSwipeUp]; // Down [self addSwipeGestureRecognizerWithSelector:@selector(swipedDown:) - direction:UISwipeGestureRecognizerDirectionDown]; + direction:UISwipeGestureRecognizerDirectionDown + name:RCTTVRemoteEventSwipeDown]; // Left [self addSwipeGestureRecognizerWithSelector:@selector(swipedLeft:) - direction:UISwipeGestureRecognizerDirectionLeft]; + direction:UISwipeGestureRecognizerDirectionLeft + name:RCTTVRemoteEventSwipeLeft]; // Right [self addSwipeGestureRecognizerWithSelector:@selector(swipedRight:) - direction:UISwipeGestureRecognizerDirectionRight]; + direction:UISwipeGestureRecognizerDirectionRight + name:RCTTVRemoteEventSwipeRight]; } @@ -99,22 +130,22 @@ - (instancetype)init - (void)playPausePressed:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"playPause" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventPlayPause toView:r.view]; } - (void)menuPressed:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"menu" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventMenu toView:r.view]; } - (void)selectPressed:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"select" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventSelect toView:r.view]; } - (void)longPlayPausePressed:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"longPlayPause" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventLongPlayPause toView:r.view]; #if __has_include("RCTDevMenu.h") && RCT_DEV // If shake to show is enabled on device, use long play/pause event to show dev menu @@ -124,53 +155,53 @@ - (void)longPlayPausePressed:(UIGestureRecognizer *)r - (void)longSelectPressed:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"longSelect" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventLongSelect toView:r.view]; } - (void)swipedUp:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"up" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventUp toView:r.view]; } - (void)swipedDown:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"down" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventDown toView:r.view]; } - (void)swipedLeft:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"left" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventLeft toView:r.view]; } - (void)swipedRight:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"right" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventRight toView:r.view]; } #pragma mark - -- (void)addLongPressGestureRecognizerWithSelector:(nonnull SEL)selector pressType:(UIPressType)pressType +- (void)addLongPressGestureRecognizerWithSelector:(nonnull SEL)selector pressType:(UIPressType)pressType name:(NSString *)name { UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:selector]; recognizer.allowedPressTypes = @[@(pressType)]; - [_tvRemoteGestureRecognizers addObject:recognizer]; + _tvRemoteGestureRecognizers[name] = recognizer; } -- (void)addTapGestureRecognizerWithSelector:(nonnull SEL)selector pressType:(UIPressType)pressType +- (void)addTapGestureRecognizerWithSelector:(nonnull SEL)selector pressType:(UIPressType)pressType name:(NSString *)name { UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:selector]; recognizer.allowedPressTypes = @[@(pressType)]; - [_tvRemoteGestureRecognizers addObject:recognizer]; + _tvRemoteGestureRecognizers[name] = recognizer; } -- (void)addSwipeGestureRecognizerWithSelector:(nonnull SEL)selector direction:(UISwipeGestureRecognizerDirection)direction +- (void)addSwipeGestureRecognizerWithSelector:(nonnull SEL)selector direction:(UISwipeGestureRecognizerDirection)direction name:(NSString *)name { UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:selector]; recognizer.direction = direction; - [_tvRemoteGestureRecognizers addObject:recognizer]; + _tvRemoteGestureRecognizers[name] = recognizer; } - (void)sendAppleTVEvent:(NSString *)eventType toView:(__unused UIView *)v diff --git a/React/Base/Surface/RCTSurface.h b/React/Base/Surface/RCTSurface.h new file mode 100644 index 00000000000000..1f6ec2b63fea82 --- /dev/null +++ b/React/Base/Surface/RCTSurface.h @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class RCTBridge; +@class RCTSurfaceView; +@protocol RCTSurfaceDelegate; + +/** + * RCTSurface instance represents React Native-powered piece of a user interface + * which can be a full-screen app, separate modal view controller, + * or even small widget. + * It is called "Surface". + * + * The RCTSurface instance is completely thread-safe by design; + * it can be created on any thread, and any its method can be called from + * any thread (if the opposite is not mentioned explicitly). + * + * The primary goals of the RCTSurface are: + * * ability to measure and layout the surface in a thread-safe + * and synchronous manner; + * * ability to create a UIView instance on demand (later); + * * ability to communicate the current stage of the surface granularly. + */ +@interface RCTSurface : NSObject + +@property (atomic, readonly) RCTSurfaceStage stage; +@property (atomic, readonly) RCTBridge *bridge; +@property (atomic, readonly) NSString *moduleName; +@property (atomic, readonly) NSNumber *rootViewTag; + +@property (atomic, readwrite, weak, nullable) id delegate; + +@property (atomic, copy, readwrite) NSDictionary *properties; + +- (instancetype)initWithBridge:(RCTBridge *)bridge + moduleName:(NSString *)moduleName + initialProperties:(NSDictionary *)initialProperties NS_DESIGNATED_INITIALIZER; + +#pragma mark - Dealing with UIView representation, the Main thread only access + +/** + * Creates (if needed) and returns `UIView` instance which represents the Surface. + * The Surface will cache and *retain* this object. + * Returning the UIView instance does not mean that the Surface is ready + * to execute and layout. It can be just a handler which Surface will use later + * to mount the actual views. + * RCTSurface does not control (or influence in any way) the size or origin + * of this view. Some superview (or another owner) must use other methods + * of this class to setup proper layout and interop interactions with UIKit + * or another UI framework. + * This method must be called only from the main queue. + */ +- (RCTSurfaceView *)view; + +#pragma mark - Layout: Setting the size constrains + +/** + * Sets `minimumSize` and `maximumSize` layout constraints for the Surface. + */ +- (void)setMinimumSize:(CGSize)minimumSize + maximumSize:(CGSize)maximumSize; + +/** + * Previously set `minimumSize` layout constraint. + * Defaults to `{0, 0}`. + */ +@property (atomic, assign, readonly) CGSize minimumSize; + +/** + * Previously set `maximumSize` layout constraint. + * Defaults to `{INFINITY, INFINITY}`. + */ +@property (atomic, assign, readonly) CGSize maximumSize; + + +/** + * Simple shortcut to `-[RCTSurface setMinimumSize:size maximumSize:size]`. + */ +- (void)setSize:(CGSize)size; + +#pragma mark - Layout: Measuring + +/** + * Measures the Surface with given constraints. + * This method does not cause any side effects on the surface object. + */ +- (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize + maximumSize:(CGSize)maximumSize; + +/** + * Return the current size of the root view based on (but not clamp by) current + * size constraints. + */ +@property (atomic, assign, readonly) CGSize intrinsicSize; + +#pragma mark - Synchronous waiting + +/** + * Synchronously blocks the current thread up to given `timeout` until + * the Surface will not have given `stage`. + * Do nothing, if called from the main or `UIManager` queue. + */ +- (BOOL)synchronouslyWaitForStage:(RCTSurfaceStage)stage timeout:(NSTimeInterval)timeout; + +@end + +NS_ASSUME_NONNULL_END diff --git a/React/Base/Surface/RCTSurface.mm b/React/Base/Surface/RCTSurface.mm new file mode 100644 index 00000000000000..5884f84beb4c80 --- /dev/null +++ b/React/Base/Surface/RCTSurface.mm @@ -0,0 +1,482 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "RCTSurface.h" +#import "RCTSurfaceView+Internal.h" + +#import + +#import "RCTAssert.h" +#import "RCTBridge+Private.h" +#import "RCTBridge.h" +#import "RCTSurfaceDelegate.h" +#import "RCTSurfaceRootShadowView.h" +#import "RCTSurfaceRootShadowViewDelegate.h" +#import "RCTSurfaceRootView.h" +#import "RCTSurfaceView.h" +#import "RCTTouchHandler.h" +#import "RCTUIManager.h" +#import "RCTUIManagerUtils.h" + +@interface RCTSurface () +@end + +@implementation RCTSurface { + // Immutable + RCTBridge *_bridge; + NSString *_moduleName; + NSNumber *_rootViewTag; + + // Protected by the `_mutex` + std::mutex _mutex; + RCTBridge *_batchedBridge; + RCTSurfaceStage _stage; + NSDictionary *_properties; + CGSize _minimumSize; + CGSize _maximumSize; + CGSize _intrinsicSize; + + // The Main thread only + RCTSurfaceView *_Nullable _view; + RCTTouchHandler *_Nullable _touchHandler; + + // Semaphores + dispatch_semaphore_t _rootShadowViewDidStartRenderingSemaphore; + dispatch_semaphore_t _rootShadowViewDidStartLayingOutSemaphore; +} + +- (instancetype)initWithBridge:(RCTBridge *)bridge + moduleName:(NSString *)moduleName + initialProperties:(NSDictionary *)initialProperties +{ + RCTAssert(bridge.valid, @"Valid bridge is required to instanciate `RCTSurface`."); + + if (self = [super init]) { + _bridge = bridge; + _batchedBridge = [_bridge batchedBridge] ?: _bridge; + _moduleName = moduleName; + _properties = [initialProperties copy]; + _rootViewTag = RCTAllocateRootViewTag(); + _rootShadowViewDidStartRenderingSemaphore = dispatch_semaphore_create(0); + _rootShadowViewDidStartLayingOutSemaphore = dispatch_semaphore_create(0); + + _minimumSize = CGSizeZero; + _maximumSize = CGSizeMake(INFINITY, INFINITY); + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleBridgeWillLoadJavaScriptNotification:) + name:RCTJavaScriptWillStartLoadingNotification + object:_bridge]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleBridgeDidLoadJavaScriptNotification:) + name:RCTJavaScriptDidLoadNotification + object:_bridge]; + + _stage = RCTSurfaceStageSurfaceDidInitialize; + + if (!bridge.loading) { + _stage = (RCTSurfaceStage)(_stage | RCTSurfaceStageBridgeDidLoad); + } + + [self _registerRootViewTag]; + [self _run]; + } + + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +#pragma mark - Immutable Properties (no need to enforce synchonization) + +- (RCTBridge *)bridge +{ + return _bridge; +} + +- (NSString *)moduleName +{ + return _moduleName; +} + +- (NSNumber *)rootViewTag +{ + return _rootViewTag; +} + +#pragma mark - Convinience Internal Thread-Safe Properties + +- (RCTBridge *)_batchedBridge +{ + std::lock_guard lock(_mutex); + return _batchedBridge; +} + +- (RCTUIManager *)_uiManager +{ + return self._batchedBridge.uiManager; +} + +#pragma mark - Main-Threaded Routines + +- (RCTSurfaceView *)view +{ + RCTAssertMainQueue(); + + if (!_view) { + _view = [[RCTSurfaceView alloc] initWithSurface:self]; + + _touchHandler = [[RCTTouchHandler alloc] initWithBridge:self.bridge]; + [_touchHandler attachToView:_view]; + + [self _mountRootViewIfNeeded]; + } + + return _view; +} + +- (void)_mountRootViewIfNeeded +{ + RCTAssertMainQueue(); + + RCTSurfaceView *view = self->_view; + if (!view) { + return; + } + + RCTSurfaceRootView *rootView = + (RCTSurfaceRootView *)[self._uiManager viewForReactTag:self->_rootViewTag]; + if (!rootView) { + return; + } + + RCTAssert([rootView isKindOfClass:[RCTSurfaceRootView class]], + @"Received root view is not an instanse of `RCTSurfaceRootView`."); + + if (rootView.superview != view) { + view.rootView = rootView; + } +} + +#pragma mark - Bridge Events + +- (void)handleBridgeWillLoadJavaScriptNotification:(NSNotification *)notification +{ + RCTAssertMainQueue(); + + [self _setStage:RCTSurfaceStageBridgeDidLoad]; +} + +- (void)handleBridgeDidLoadJavaScriptNotification:(NSNotification *)notification +{ + RCTAssertMainQueue(); + + [self _setStage:RCTSurfaceStageModuleDidLoad]; + + RCTBridge *bridge = notification.userInfo[@"bridge"]; + + BOOL isRerunNeeded = NO; + + { + std::lock_guard lock(_mutex); + + if (bridge != _batchedBridge) { + _batchedBridge = bridge; + isRerunNeeded = YES; + } + } + + if (isRerunNeeded) { + [self _run]; + } +} + +#pragma mark - Stage management + +- (RCTSurfaceStage)stage +{ + std::lock_guard lock(_mutex); + return _stage; +} + +- (void)_setStage:(RCTSurfaceStage)stage +{ + { + std::lock_guard lock(_mutex); + + if (_stage & stage) { + return; + } + + _stage = (RCTSurfaceStage)(_stage | stage); + } + + [self _propagateStageChange:stage]; +} + +- (void)_propagateStageChange:(RCTSurfaceStage)stage +{ + // Updating the `view` + RCTExecuteOnMainQueue(^{ + self->_view.stage = stage; + }); + + // Notifying the `delegate` + id delegate = self.delegate; + if ([delegate respondsToSelector:@selector(surface:didChangeStage:)]) { + [delegate surface:self didChangeStage:stage]; + } +} + +#pragma mark - Properties Management + +- (NSDictionary *)properties +{ + std::lock_guard lock(_mutex); + return _properties; +} + +- (void)setProperties:(NSDictionary *)properties +{ + { + std::lock_guard lock(_mutex); + + if ([properties isEqualToDictionary:_properties]) { + return; + } + + _properties = [properties copy]; + } + + [self _run]; +} + +#pragma mark - Running + +- (void)_run +{ + RCTBridge *batchedBridge; + NSDictionary *properties; + + { + std::lock_guard lock(_mutex); + + batchedBridge = _batchedBridge; + properties = _properties; + } + + if (!batchedBridge.valid) { + return; + } + + NSDictionary *applicationParameters = + @{ + @"rootTag": _rootViewTag, + @"initialProps": properties, + }; + + RCTLogInfo(@"Running surface %@ (%@)", _moduleName, applicationParameters); + + [batchedBridge enqueueJSCall:@"AppRegistry" + method:@"runApplication" + args:@[_moduleName, applicationParameters] + completion:NULL]; + + [self _setStage:RCTSurfaceStageSurfaceDidRun]; +} + +- (void)_registerRootViewTag +{ + RCTBridge *batchedBridge; + CGSize minimumSize; + CGSize maximumSize; + + { + std::lock_guard lock(_mutex); + batchedBridge = _batchedBridge; + minimumSize = _minimumSize; + maximumSize = _maximumSize; + } + + RCTUIManager *uiManager = batchedBridge.uiManager; + RCTUnsafeExecuteOnUIManagerQueueSync(^{ + [uiManager registerRootViewTag:self->_rootViewTag]; + + RCTSurfaceRootShadowView *rootShadowView = + (RCTSurfaceRootShadowView *)[uiManager shadowViewForReactTag:self->_rootViewTag]; + RCTAssert([rootShadowView isKindOfClass:[RCTSurfaceRootShadowView class]], + @"Received shadow view is not an instanse of `RCTSurfaceRootShadowView`."); + + [rootShadowView setMinimumSize:minimumSize + maximumSize:maximumSize]; + rootShadowView.delegate = self; + }); +} + +#pragma mark - Layout + +- (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize + maximumSize:(CGSize)maximumSize +{ + RCTUIManager *uiManager = self._uiManager; + __block CGSize fittingSize; + + RCTUnsafeExecuteOnUIManagerQueueSync(^{ + RCTSurfaceRootShadowView *rootShadowView = + (RCTSurfaceRootShadowView *)[uiManager shadowViewForReactTag:self->_rootViewTag]; + + RCTAssert([rootShadowView isKindOfClass:[RCTSurfaceRootShadowView class]], + @"Received shadow view is not an instanse of `RCTSurfaceRootShadowView`."); + + fittingSize = [rootShadowView sizeThatFitsMinimumSize:minimumSize + maximumSize:maximumSize]; + }); + + return fittingSize; +} + +#pragma mark - Size Constraints + +- (void)setSize:(CGSize)size +{ + [self setMinimumSize:size maximumSize:size]; +} + +- (void)setMinimumSize:(CGSize)minimumSize + maximumSize:(CGSize)maximumSize +{ + { + std::lock_guard lock(_mutex); + if (CGSizeEqualToSize(minimumSize, _minimumSize) && + CGSizeEqualToSize(maximumSize, _maximumSize)) { + return; + } + + _maximumSize = maximumSize; + _minimumSize = minimumSize; + } + + RCTUIManager *uiManager = self._uiManager; + + RCTUnsafeExecuteOnUIManagerQueueSync(^{ + RCTSurfaceRootShadowView *rootShadowView = + (RCTSurfaceRootShadowView *)[uiManager shadowViewForReactTag:self->_rootViewTag]; + RCTAssert([rootShadowView isKindOfClass:[RCTSurfaceRootShadowView class]], + @"Received shadow view is not an instanse of `RCTSurfaceRootShadowView`."); + + [rootShadowView setMinimumSize:minimumSize maximumSize:maximumSize]; + [uiManager setNeedsLayout]; + }); +} + +- (CGSize)minimumSize +{ + std::lock_guard lock(_mutex); + return _minimumSize; +} + +- (CGSize)maximumSize +{ + std::lock_guard lock(_mutex); + return _maximumSize; +} + +#pragma mark - intrinsicSize + +- (void)setIntrinsicSize:(CGSize)intrinsicSize +{ + { + std::lock_guard lock(_mutex); + if (CGSizeEqualToSize(intrinsicSize, _intrinsicSize)) { + return; + } + + _intrinsicSize = intrinsicSize; + } + + // Notifying `delegate` + id delegate = self.delegate; + if ([delegate respondsToSelector:@selector(surface:didChangeIntrinsicSize:)]) { + [delegate surface:self didChangeIntrinsicSize:intrinsicSize]; + } +} + +- (CGSize)intrinsicSize +{ + std::lock_guard lock(_mutex); + return _intrinsicSize; +} + +#pragma mark - Synchronous Waiting + +- (BOOL)synchronouslyWaitForStage:(RCTSurfaceStage)stage timeout:(NSTimeInterval)timeout +{ + dispatch_semaphore_t semaphore; + switch (stage) { + case RCTSurfaceStageSurfaceDidInitialLayout: + semaphore = _rootShadowViewDidStartLayingOutSemaphore; + break; + case RCTSurfaceStageSurfaceDidInitialRendering: + semaphore = _rootShadowViewDidStartRenderingSemaphore; + break; + default: + RCTAssert(NO, @"Only waiting for `RCTSurfaceStageSurfaceDidInitialRendering` and `RCTSurfaceStageSurfaceDidInitialLayout` stages is supported."); + } + + if (RCTIsMainQueue()) { + RCTLogInfo(@"Synchronous waiting is not supported on the main queue."); + return NO; + } + + if (RCTIsUIManagerQueue()) { + RCTLogInfo(@"Synchronous waiting is not supported on UIManager queue."); + return NO; + } + + BOOL timeoutOccured = dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC)); + if (!timeoutOccured) { + // Balancing the semaphore. + // Note: `dispatch_semaphore_wait` reverts the decrement in case when timeout occured. + dispatch_semaphore_signal(semaphore); + } + + return !timeoutOccured; +} + +#pragma mark - RCTSurfaceRootShadowViewDelegate + +- (void)rootShadowView:(RCTRootShadowView *)rootShadowView didChangeIntrinsicSize:(CGSize)intrinsicSize +{ + self.intrinsicSize = intrinsicSize; +} + +- (void)rootShadowViewDidStartRendering:(RCTSurfaceRootShadowView *)rootShadowView +{ + [self _setStage:RCTSurfaceStageSurfaceDidInitialRendering]; + + dispatch_semaphore_signal(_rootShadowViewDidStartRenderingSemaphore); +} + +- (void)rootShadowViewDidStartLayingOut:(RCTSurfaceRootShadowView *)rootShadowView +{ + [self _setStage:RCTSurfaceStageSurfaceDidInitialLayout]; + + dispatch_semaphore_signal(_rootShadowViewDidStartLayingOutSemaphore); + + RCTExecuteOnMainQueue(^{ + // Rendering is happening, let's mount `rootView` into `view` if we already didn't do this. + [self _mountRootViewIfNeeded]; + }); +} + +@end diff --git a/React/Base/Surface/RCTSurfaceDelegate.h b/React/Base/Surface/RCTSurfaceDelegate.h new file mode 100644 index 00000000000000..5455320feb57af --- /dev/null +++ b/React/Base/Surface/RCTSurfaceDelegate.h @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class RCTSurface; + +@protocol RCTSurfaceDelegate + +@optional + +/** + * Notifies a receiver that a surface transitioned to a new stage. + * See `RCTSurfaceStage` for more details. + */ +- (void)surface:(RCTSurface *)surface didChangeStage:(RCTSurfaceStage)stage; + +/** + * Notifies a receiver that root view got a new (intrinsic) size during the last + * layout pass. + */ +- (void)surface:(RCTSurface *)surface didChangeIntrinsicSize:(CGSize)intrinsicSize; + +@end + +NS_ASSUME_NONNULL_END diff --git a/React/Base/Surface/RCTSurfaceRootShadowView.h b/React/Base/Surface/RCTSurfaceRootShadowView.h new file mode 100644 index 00000000000000..f681e67eb0374d --- /dev/null +++ b/React/Base/Surface/RCTSurfaceRootShadowView.h @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import +#import +#import + +@interface RCTSurfaceRootShadowView : RCTShadowView + +@property (nonatomic, assign, readonly) CGSize minimumSize; +@property (nonatomic, assign, readonly) CGSize maximumSize; + +- (void)setMinimumSize:(CGSize)size maximumSize:(CGSize)maximumSize; + +@property (nonatomic, assign, readonly) CGSize intrinsicSize; + +@property (nonatomic, weak) id delegate; + +- (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize + maximumSize:(CGSize)maximumSize; + +/** + * Layout direction (LTR or RTL) inherited from native environment and + * is using as a base direction value in layout engine. + * Defaults to value inferred from current locale. + */ +@property (nonatomic, assign) YGDirection baseDirection; + +/** + * Calculate all views whose frame needs updating after layout has been calculated. + * Returns a set contains the shadowviews that need updating. + */ +- (NSSet *)collectViewsWithUpdatedFrames; + +@end diff --git a/React/Base/Surface/RCTSurfaceRootShadowView.m b/React/Base/Surface/RCTSurfaceRootShadowView.m new file mode 100644 index 00000000000000..f076c9daeea136 --- /dev/null +++ b/React/Base/Surface/RCTSurfaceRootShadowView.m @@ -0,0 +1,138 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "RCTSurfaceRootShadowView.h" + +#import + +#import "RCTI18nUtil.h" + +@implementation RCTSurfaceRootShadowView { + CGSize _intrinsicSize; + BOOL _isRendered; + BOOL _isLaidOut; +} + +- (instancetype)init +{ + if (self = [super init]) { + self.viewName = @"RCTSurfaceRootView"; + _baseDirection = [[RCTI18nUtil sharedInstance] isRTL] ? YGDirectionRTL : YGDirectionLTR; + _minimumSize = CGSizeZero; + _maximumSize = CGSizeMake(INFINITY, INFINITY); + + self.alignSelf = YGAlignStretch; + self.flex = 1; + } + + return self; +} + +- (void)insertReactSubview:(RCTShadowView *)subview atIndex:(NSInteger)atIndex +{ + [super insertReactSubview:subview atIndex:atIndex]; + if (!_isRendered) { + [_delegate rootShadowViewDidStartRendering:self]; + _isRendered = YES; + } +} + +- (void)calculateLayoutWithMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximimSize +{ + // Treating `INFINITY` as `YGUndefined` (which equals `NAN`). + float availableWidth = isinf(maximimSize.width) ? YGUndefined : maximimSize.width; + float availableHeight = isinf(maximimSize.height) ? YGUndefined : maximimSize.height; + + self.minWidth = (YGValue){isinf(minimumSize.width) ? YGUndefined : minimumSize.width, YGUnitPoint}; + self.minWidth = (YGValue){isinf(minimumSize.height) ? YGUndefined : minimumSize.height, YGUnitPoint}; + + YGNodeCalculateLayout(self.yogaNode, availableWidth, availableHeight, _baseDirection); +} + +- (NSSet *)collectViewsWithUpdatedFrames +{ + [self calculateLayoutWithMinimumSize:_minimumSize + maximumSize:_maximumSize]; + + NSMutableSet *viewsWithNewFrame = [NSMutableSet set]; + [self applyLayoutNode:self.yogaNode viewsWithNewFrame:viewsWithNewFrame absolutePosition:CGPointZero]; + + self.intrinsicSize = self.frame.size; + + if (_isRendered && !_isLaidOut) { + [_delegate rootShadowViewDidStartLayingOut:self]; + _isLaidOut = YES; + } + + return viewsWithNewFrame; +} + +- (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize + maximumSize:(CGSize)maximumSize +{ + // Positive case where requested constraind are aready enforced. + if (CGSizeEqualToSize(minimumSize, _minimumSize) && + CGSizeEqualToSize(maximumSize, _maximumSize)) { + // We stil need to call `calculateLayoutWithMinimumSize:maximumSize` + // mehtod though. + [self calculateLayoutWithMinimumSize:_minimumSize + maximumSize:_maximumSize]; + + YGNodeRef yogaNode = self.yogaNode; + return CGSizeMake(YGNodeLayoutGetWidth(yogaNode), YGNodeLayoutGetHeight(yogaNode)); + } + + // Generic case, where requested constraind are different from enforced. + + // Applying given size constraints. + [self calculateLayoutWithMinimumSize:minimumSize + maximumSize:maximumSize]; + + YGNodeRef yogaNode = self.yogaNode; + CGSize fittingSize = + CGSizeMake(YGNodeLayoutGetWidth(yogaNode), YGNodeLayoutGetHeight(yogaNode)); + + // Reverting size constraints. + [self calculateLayoutWithMinimumSize:_minimumSize + maximumSize:_maximumSize]; + + return CGSizeMake( + MAX(minimumSize.width, MIN(maximumSize.width, fittingSize.width)), + MAX(minimumSize.height, MIN(maximumSize.height, fittingSize.height)) + ); +} + +- (void)setMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize +{ + if (CGSizeEqualToSize(minimumSize, _minimumSize) && + CGSizeEqualToSize(maximumSize, _maximumSize)) { + return; + } + + _maximumSize = maximumSize; + _minimumSize = minimumSize; +} + +- (void)setIntrinsicSize:(CGSize)intrinsicSize +{ + if (CGSizeEqualToSize(_intrinsicSize, intrinsicSize)) { + return; + } + + _intrinsicSize = intrinsicSize; + + [_delegate rootShadowView:self didChangeIntrinsicSize:intrinsicSize]; +} + +- (CGSize)intrinsicSize +{ + return _intrinsicSize; +} + +@end diff --git a/React/Base/Surface/RCTSurfaceRootShadowViewDelegate.h b/React/Base/Surface/RCTSurfaceRootShadowViewDelegate.h new file mode 100644 index 00000000000000..1cfa6aecbcd587 --- /dev/null +++ b/React/Base/Surface/RCTSurfaceRootShadowViewDelegate.h @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class RCTSurfaceRootShadowView; + +@protocol RCTSurfaceRootShadowViewDelegate + +- (void)rootShadowView:(RCTSurfaceRootShadowView *)rootShadowView didChangeIntrinsicSize:(CGSize)instrinsicSize; +- (void)rootShadowViewDidStartRendering:(RCTSurfaceRootShadowView *)rootShadowView; +- (void)rootShadowViewDidStartLayingOut:(RCTSurfaceRootShadowView *)rootShadowView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/React/DevSupport/RCTPackagerConnectionBridgeConfig.h b/React/Base/Surface/RCTSurfaceRootView.h similarity index 59% rename from React/DevSupport/RCTPackagerConnectionBridgeConfig.h rename to React/Base/Surface/RCTSurfaceRootView.h index afd02d51c3e020..927563a51f9718 100644 --- a/React/DevSupport/RCTPackagerConnectionBridgeConfig.h +++ b/React/Base/Surface/RCTSurfaceRootView.h @@ -7,20 +7,17 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import "RCTPackagerConnectionConfig.h" +#import -#if RCT_DEV // Only supported in dev mode +#import NS_ASSUME_NONNULL_BEGIN -@class RCTBridge; - -@interface RCTPackagerConnectionBridgeConfig : NSObject - -- (instancetype)initWithBridge:(RCTBridge *)bridge; +/** + * Internal class represents Surface's root view. + */ +@interface RCTSurfaceRootView : RCTView @end NS_ASSUME_NONNULL_END - -#endif diff --git a/React/Base/Surface/RCTSurfaceRootView.mm b/React/Base/Surface/RCTSurfaceRootView.mm new file mode 100644 index 00000000000000..5888b18867a6c8 --- /dev/null +++ b/React/Base/Surface/RCTSurfaceRootView.mm @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "RCTSurfaceRootView.h" + +#import "RCTDefines.h" + +@implementation RCTSurfaceRootView + +RCT_NOT_IMPLEMENTED(- (nullable instancetype)initWithCoder:(NSCoder *)coder) + +@end diff --git a/React/Base/Surface/RCTSurfaceStage.h b/React/Base/Surface/RCTSurfaceStage.h new file mode 100644 index 00000000000000..a02ebc36d80db8 --- /dev/null +++ b/React/Base/Surface/RCTSurfaceStage.h @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +/** + * The stage of the Surface + */ +typedef NS_OPTIONS(NSInteger, RCTSurfaceStage) { + RCTSurfaceStageSurfaceDidInitialize = 1 << 0, // Surface object was created + RCTSurfaceStageBridgeDidLoad = 1 << 1, // Bridge was loaded + RCTSurfaceStageModuleDidLoad = 1 << 2, // Module (JavaScript code) was loaded + RCTSurfaceStageSurfaceDidRun = 1 << 3, // Module (JavaScript code) was run + RCTSurfaceStageSurfaceDidInitialRendering = 1 << 4, // UIManager created the first shadow views + RCTSurfaceStageSurfaceDidInitialLayout = 1 << 5, // UIManager completed the first layout pass + RCTSurfaceStageSurfaceDidInitialMounting = 1 << 6, // UIManager completed the first mounting pass + RCTSurfaceStageSurfaceDidInvalidate = 1 << 7, // Surface received `invalidate` message +}; diff --git a/React/DevSupport/RCTPackagerConnectionConfig.h b/React/Base/Surface/RCTSurfaceView+Internal.h similarity index 52% rename from React/DevSupport/RCTPackagerConnectionConfig.h rename to React/Base/Surface/RCTSurfaceView+Internal.h index 090bede5ffb046..b41bd3a34a2fe5 100644 --- a/React/DevSupport/RCTPackagerConnectionConfig.h +++ b/React/Base/Surface/RCTSurfaceView+Internal.h @@ -7,21 +7,20 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import -#if RCT_DEV // Only supported in dev mode +#import +#import -NS_ASSUME_NONNULL_BEGIN +@class RCTSurfaceRootView; -@protocol RCTPackagerClientMethod; +NS_ASSUME_NONNULL_BEGIN -@protocol RCTPackagerConnectionConfig +@interface RCTSurfaceView (Internal) -@property (nonatomic, copy, readonly) NSURL *packagerURL; -@property (nonatomic, copy, readonly) NSDictionary> *defaultPackagerMethods; +@property (nonatomic, strong) RCTSurfaceRootView *rootView; +@property (nonatomic, assign) RCTSurfaceStage stage; @end NS_ASSUME_NONNULL_END - -#endif diff --git a/React/Base/Surface/RCTSurfaceView.h b/React/Base/Surface/RCTSurfaceView.h new file mode 100644 index 00000000000000..7f90e188e68daa --- /dev/null +++ b/React/Base/Surface/RCTSurfaceView.h @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class RCTSurface; + +typedef UIView *(^RCTSurfaceActivityIndicatorViewFactory)(); + +/** + * UIView instance which represents the Surface + */ +@interface RCTSurfaceView : UIView + +- (instancetype)initWithSurface:(RCTSurface *)surface NS_DESIGNATED_INITIALIZER; + +@property (nonatomic, copy, nullable) RCTSurfaceActivityIndicatorViewFactory activityIndicatorViewFactory; +@property (nonatomic, weak, readonly, nullable) RCTSurface *surface; + +@end + +NS_ASSUME_NONNULL_END diff --git a/React/Base/Surface/RCTSurfaceView.mm b/React/Base/Surface/RCTSurfaceView.mm new file mode 100644 index 00000000000000..ce3b59645c4514 --- /dev/null +++ b/React/Base/Surface/RCTSurfaceView.mm @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "RCTSurfaceView.h" +#import "RCTSurfaceView+Internal.h" + +#import "RCTDefines.h" +#import "RCTSurface.h" +#import "RCTSurfaceRootView.h" + +@implementation RCTSurfaceView { + RCTSurfaceRootView *_Nullable _rootView; + UIView *_Nullable _activityIndicatorView; + RCTSurfaceStage _stage; +} + +RCT_NOT_IMPLEMENTED(- (instancetype)init) +RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame) +RCT_NOT_IMPLEMENTED(- (nullable instancetype)initWithCoder:(NSCoder *)coder) + +- (instancetype)initWithSurface:(RCTSurface *)surface +{ + if (self = [super initWithFrame:CGRectZero]) { + _stage = surface.stage; + _surface = surface; + } + + return self; +} + +#pragma mark - Internal Interface + +- (void)setRootView:(RCTSurfaceRootView *)rootView +{ + if (_rootView == rootView) { + return; + } + + [_rootView removeFromSuperview]; + _rootView = rootView; + [self updateStage]; +} + +- (RCTSurfaceRootView *)rootView +{ + return _rootView; +} + +#pragma mark - activityIndicatorView + +- (void)setActivityIndicatorView:(UIView *)view +{ + [_activityIndicatorView removeFromSuperview]; + _activityIndicatorView = view; + _activityIndicatorView.frame = self.bounds; + _activityIndicatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self addSubview:_activityIndicatorView]; +} + +- (UIView *)activityIndicatorView +{ + return _activityIndicatorView; +} + +#pragma mark - stage + +- (void)setStage:(RCTSurfaceStage)stage +{ + if (stage == _stage) { + return; + } + + _stage = stage; + + [self updateStage]; +} + +- (RCTSurfaceStage)stage +{ + return _stage; +} + +#pragma mark - Visibility + +- (void)updateStage +{ + BOOL displayRootView = _stage & RCTSurfaceStageSurfaceDidInitialLayout; + BOOL displayActivityIndicator = !displayRootView; + + if (displayRootView) { + if (_rootView.superview != self) { + [self addSubview:_rootView]; + } + } + else { + [_rootView removeFromSuperview]; + } + + if (displayActivityIndicator) { + if (!_activityIndicatorView && self.activityIndicatorViewFactory != nil) { + self.activityIndicatorView = self.activityIndicatorViewFactory(); + } + } + else { + [_activityIndicatorView removeFromSuperview]; + } +} + +@end diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index 24cf7f6c111095..937c0997acefd6 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -35,8 +35,8 @@ #import #import #import -#include #import +#import #import #import "NSDataBigString.h" @@ -175,10 +175,11 @@ @implementation RCTCxxBridge std::shared_ptr _reactInstance; } +@synthesize bridgeDescription = _bridgeDescription; +@synthesize embeddedBundleURL = _embeddedBundleURL; @synthesize loading = _loading; -@synthesize valid = _valid; @synthesize performanceLogger = _performanceLogger; -@synthesize bridgeDescription = _bridgeDescription; +@synthesize valid = _valid; + (void)initialize { @@ -187,11 +188,6 @@ + (void)initialize } } -- (JSContext *)jsContext -{ - return contextForGlobalContextRef([self jsContextRef]); -} - - (JSGlobalContextRef)jsContextRef { return (JSGlobalContextRef)(self->_reactInstance ? self->_reactInstance->getJavaScriptContext() : nullptr); @@ -207,6 +203,9 @@ - (instancetype)initWithParentBridge:(RCTBridge *)bridge launchOptions:bridge.launchOptions])) { _parentBridge = bridge; _performanceLogger = [bridge performanceLogger]; + if ([bridge.delegate respondsToSelector:@selector(embeddedBundleURLForBridge:)]) { + _embeddedBundleURL = [bridge.delegate embeddedBundleURLForBridge:bridge]; + } registerPerformanceLoggerHooks(_performanceLogger); @@ -1144,12 +1143,7 @@ - (void)executeApplicationScript:(NSData *)script [self->_performanceLogger markStopForTag:RCTPLRAMBundleLoad]; [self->_performanceLogger setValue:scriptStr->size() forTag:RCTPLRAMStartupCodeSize]; if (self->_reactInstance) { - NSString *jsBundlesDirectory = [self.delegate respondsToSelector:@selector(jsBundlesDirectory)] - ? [[self.delegate jsBundlesDirectory].path stringByAppendingString:@"/"] - : nil; - auto registry = jsBundlesDirectory != nil - ? std::make_unique(std::move(ramBundle), jsBundlesDirectory.UTF8String) - : std::make_unique(std::move(ramBundle)); + auto registry = RAMBundleRegistry::multipleBundlesRegistry(std::move(ramBundle), JSIndexedRAMBundle::buildFactory()); self->_reactInstance->loadRAMBundle(std::move(registry), std::move(scriptStr), sourceUrlStr.UTF8String, !async); } @@ -1210,6 +1204,13 @@ - (JSValue *)callFunctionOnModule:(NSString *)module return ret; } +- (void)registerSegmentWithId:(NSUInteger)segmentId path:(NSString *)path +{ + if (_reactInstance) { + _reactInstance->registerBundle(static_cast(segmentId), path.UTF8String); + } +} + #pragma mark - Payload Processing - (void)partialBatchDidFlush diff --git a/React/CxxBridge/RCTObjcExecutor.mm b/React/CxxBridge/RCTObjcExecutor.mm index 53c32368d5b15e..476bcff9b40709 100644 --- a/React/CxxBridge/RCTObjcExecutor.mm +++ b/React/CxxBridge/RCTObjcExecutor.mm @@ -95,6 +95,10 @@ void setBundleRegistry(std::unique_ptr) override { RCTAssert(NO, @"RAM bundles are not supported in RCTObjcExecutor"); } + void registerBundle(uint32_t bundleId, const std::string &bundlePath) override { + RCTAssert(NO, @"RAM bundles are not supported in RCTObjcExecutor"); + } + void callFunction(const std::string &module, const std::string &method, const folly::dynamic &arguments) override { [m_jse callFunctionOnModule:@(module.c_str()) diff --git a/React/CxxModule/RCTNativeModule.mm b/React/CxxModule/RCTNativeModule.mm index 4fbe0a14128da0..25e62cb330c7f2 100644 --- a/React/CxxModule/RCTNativeModule.mm +++ b/React/CxxModule/RCTNativeModule.mm @@ -112,6 +112,8 @@ static MethodCallResult invokeInner(RCTBridge *bridge, RCTModuleData *moduleData exception, method.JSMethodName, moduleData.name, objcParams, exception.callStackSymbols]; RCTFatal(RCTErrorWithMessage(message)); } + + return folly::none; } } diff --git a/React/DevSupport/RCTPackagerClient.h b/React/DevSupport/RCTPackagerClient.h index 4b070aa9b77878..3b5e38c8766d3d 100644 --- a/React/DevSupport/RCTPackagerClient.h +++ b/React/DevSupport/RCTPackagerClient.h @@ -12,14 +12,14 @@ #if RCT_DEV // Only supported in dev mode @class RCTPackagerClientResponder; -@class RCTSRWebSocket; +@class RCTReconnectingWebSocket; extern const int RCT_PACKAGER_CLIENT_PROTOCOL_VERSION; @protocol RCTPackagerClientMethod -- (void)handleRequest:(id)params withResponder:(RCTPackagerClientResponder *)responder; -- (void)handleNotification:(id)params; +- (void)handleRequest:(NSDictionary *)params withResponder:(RCTPackagerClientResponder *)responder; +- (void)handleNotification:(NSDictionary *)params; @optional @@ -30,7 +30,7 @@ extern const int RCT_PACKAGER_CLIENT_PROTOCOL_VERSION; @interface RCTPackagerClientResponder : NSObject -- (instancetype)initWithId:(id)msgId socket:(RCTSRWebSocket *)socket; +- (instancetype)initWithId:(id)msgId socket:(RCTReconnectingWebSocket *)socket; - (void)respondWithResult:(id)result; - (void)respondWithError:(id)error; diff --git a/React/DevSupport/RCTPackagerClient.m b/React/DevSupport/RCTPackagerClient.m index f38617bd0151f3..e0befe33da8395 100644 --- a/React/DevSupport/RCTPackagerClient.m +++ b/React/DevSupport/RCTPackagerClient.m @@ -10,7 +10,7 @@ #import "RCTPackagerClient.h" #import -#import +#import #import #if RCT_DEV // Only supported in dev mode @@ -19,10 +19,10 @@ @implementation RCTPackagerClientResponder { id _msgId; - __weak RCTSRWebSocket *_socket; + __weak RCTReconnectingWebSocket *_socket; } -- (instancetype)initWithId:(id)msgId socket:(RCTSRWebSocket *)socket +- (instancetype)initWithId:(id)msgId socket:(RCTReconnectingWebSocket *)socket { if (self = [super init]) { _msgId = msgId; diff --git a/React/DevSupport/RCTPackagerConnection.h b/React/DevSupport/RCTPackagerConnection.h index ed8c951bb36580..155dd45153aba6 100644 --- a/React/DevSupport/RCTPackagerConnection.h +++ b/React/DevSupport/RCTPackagerConnection.h @@ -15,27 +15,62 @@ NS_ASSUME_NONNULL_BEGIN -@class RCTBridge; @protocol RCTPackagerClientMethod; -@protocol RCTPackagerConnectionConfig; +@class RCTPackagerClientResponder; + +typedef uint32_t RCTHandlerToken; +typedef void (^RCTNotificationHandler)(NSDictionary *); +typedef void (^RCTRequestHandler)(NSDictionary *, RCTPackagerClientResponder *); +typedef void (^RCTConnectedHandler)(void); + +/** Encapsulates singleton connection to React Native packager. */ +@interface RCTPackagerConnection : NSObject + ++ (instancetype)sharedPackagerConnection; /** - * Encapsulates connection to React Native packager. - * Dispatches messages from websocket to message handlers that must implement - * protocol. - * Message dispatch is performed on the main queue, unless message handler - * provides its own queue by overriding "methodQueue" method. + * Registers a handler for a notification broadcast from the packager. An + * example is "reload" - an instruction to reload from the packager. + * If multiple notification handlers are registered for the same method, they + * will all be invoked sequentially. */ -@interface RCTPackagerConnection : NSObject +- (RCTHandlerToken)addNotificationHandler:(RCTNotificationHandler)handler + queue:(dispatch_queue_t)queue + forMethod:(NSString *)method; + +/** + * Registers a handler for a request from the packager. An example is + * pokeSamplingProfiler; it asks for profile data from the client. + * Only one handler can be registered for a given method; calling this + * displaces any previous request handler registered for that method. + */ +- (RCTHandlerToken)addRequestHandler:(RCTRequestHandler)handler + queue:(dispatch_queue_t)queue + forMethod:(NSString *)method; + +/** + * Registers a handler that runs at most once, when the connection to the + * packager has been established. The handler will be dispatched immediately + * if the connection is already established. + */ +- (RCTHandlerToken)addConnectedHandler:(RCTConnectedHandler)handler + queue:(dispatch_queue_t)queue; -+ (void)checkDefaultConnectionWithCallback:(void (^)(BOOL isRunning))callback - queue:(dispatch_queue_t)queue; +/** Removes a handler. Silently does nothing if the token is not valid. */ +- (void)removeHandler:(RCTHandlerToken)token; -+ (instancetype)connectionForBridge:(RCTBridge *)bridge; -- (instancetype)initWithConfig:(id)config; -- (void)addHandler:(id)handler forMethod:(NSString *)name; +/** Disconnects and removes all handlers. */ - (void)stop; +/** + * Historically no distinction was made between notification and request + * handlers. If you use this method, it will be registered as *both* a + * notification handler *and* a request handler. You should migrate to the + * new block-based API instead. + */ +- (void)addHandler:(id)handler + forMethod:(NSString *)method __deprecated_msg("Use addRequestHandler or addNotificationHandler instead"); + @end NS_ASSUME_NONNULL_END diff --git a/React/DevSupport/RCTPackagerConnection.m b/React/DevSupport/RCTPackagerConnection.m deleted file mode 100644 index 5b16bb9a2d19bf..00000000000000 --- a/React/DevSupport/RCTPackagerConnection.m +++ /dev/null @@ -1,196 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "RCTPackagerConnection.h" - -#import - -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "RCTPackagerConnectionBridgeConfig.h" -#import "RCTReloadPackagerMethod.h" -#import "RCTSamplingProfilerPackagerMethod.h" - -#if RCT_DEV - -static dispatch_queue_t RCTPackagerConnectionQueue() -{ - static dispatch_queue_t queue; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - queue = dispatch_queue_create("com.facebook.RCTPackagerConnectionQueue", DISPATCH_QUEUE_SERIAL); - }); - return queue; -}; - -@interface RCTPackagerConnection () -@end - -@implementation RCTPackagerConnection { - NSURL *_packagerURL; - RCTReconnectingWebSocket *_socket; - NSMutableDictionary> *_handlers; -} - -+ (void)checkDefaultConnectionWithCallback:(void (^)(BOOL isRunning))callback - queue:(dispatch_queue_t)queue -{ - RCTBundleURLProvider *const settings = [RCTBundleURLProvider sharedSettings]; - NSURLComponents *components = [NSURLComponents new]; - components.scheme = @"http"; - components.host = settings.jsLocation ?: @"localhost"; - components.port = @(kRCTBundleURLProviderDefaultPort); - components.path = @"/status"; - [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:components.URL] - queue:[NSOperationQueue mainQueue] - completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { - NSString *const status = data != nil - ? [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] - : nil; - BOOL isRunning = [status isEqualToString:@"packager-status:running"]; - - dispatch_async(queue, ^{ - callback(isRunning); - }); - }]; -} - -+ (instancetype)connectionForBridge:(RCTBridge *)bridge -{ - RCTPackagerConnectionBridgeConfig *config = [[RCTPackagerConnectionBridgeConfig alloc] initWithBridge:bridge]; - return [[[self class] alloc] initWithConfig:config]; -} - -- (instancetype)initWithConfig:(id)config -{ - if (self = [super init]) { - _packagerURL = [config packagerURL]; - _handlers = [[config defaultPackagerMethods] mutableCopy]; - [self connect]; - } - return self; -} - -- (void)connect -{ - RCTAssertMainQueue(); - - NSURL *url = _packagerURL; - if (!url) { - return; - } - - // The jsPackagerClient is a static map that holds different packager clients per the packagerURL - // In case many instances of DevMenu are created, the latest instance that use the same URL as - // previous instances will override given packager client's method handlers - static NSMutableDictionary *socketConnections = nil; - if (socketConnections == nil) { - socketConnections = [NSMutableDictionary new]; - } - - NSString *key = [url absoluteString]; - _socket = socketConnections[key]; - if (!_socket) { - _socket = [[RCTReconnectingWebSocket alloc] initWithURL:url]; - _socket.delegateDispatchQueue = RCTPackagerConnectionQueue(); - [_socket start]; - socketConnections[key] = _socket; - } - - _socket.delegate = self; -} - -- (void)stop -{ - [_socket stop]; -} - - -- (void)addHandler:(id)handler forMethod:(NSString *)name -{ - @synchronized(self) { - _handlers[name] = handler; - } -} - -- (id)handlerForMethod:(NSString *)name -{ - @synchronized(self) { - return _handlers[name]; - } -} - -static BOOL isSupportedVersion(NSNumber *version) -{ - NSArray *const kSupportedVersions = @[ @(RCT_PACKAGER_CLIENT_PROTOCOL_VERSION) ]; - return [kSupportedVersions containsObject:version]; -} - -#pragma mark - RCTWebSocketProtocolDelegate - -- (void)webSocket:(RCTSRWebSocket *)webSocket didReceiveMessage:(id)message -{ - NSError *error = nil; - NSDictionary *msg = RCTJSONParse(message, &error); - - if (error) { - RCTLogError(@"%@ failed to parse message with error %@\n\n%@\n", [self class], error, msg); - return; - } - - if (!isSupportedVersion(msg[@"version"])) { - RCTLogError(@"%@ received message with not supported version %@", [self class], msg[@"version"]); - return; - } - - id methodHandler = [self handlerForMethod:msg[@"method"]]; - if (!methodHandler) { - if (msg[@"id"]) { - NSString *errorMsg = [NSString stringWithFormat:@"%@ no handler found for method %@", [self class], msg[@"method"]]; - RCTLogError(errorMsg, msg[@"method"]); - [[[RCTPackagerClientResponder alloc] initWithId:msg[@"id"] - socket:webSocket] respondWithError:errorMsg]; - } - return; // If it was a broadcast then we ignore it gracefully - } - - dispatch_queue_t methodQueue = [methodHandler respondsToSelector:@selector(methodQueue)] - ? [methodHandler methodQueue] - : dispatch_get_main_queue(); - - dispatch_async(methodQueue, ^{ - if (msg[@"id"]) { - [methodHandler handleRequest:msg[@"params"] - withResponder:[[RCTPackagerClientResponder alloc] initWithId:msg[@"id"] - socket:webSocket]]; - } else { - [methodHandler handleNotification:msg[@"params"]]; - } - }); -} - -- (void)webSocketDidOpen:(RCTSRWebSocket *)webSocket -{ -} - -- (void)webSocket:(RCTSRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean -{ -} - -@end - -#endif diff --git a/React/DevSupport/RCTPackagerConnection.mm b/React/DevSupport/RCTPackagerConnection.mm new file mode 100644 index 00000000000000..572c14faa25849 --- /dev/null +++ b/React/DevSupport/RCTPackagerConnection.mm @@ -0,0 +1,285 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "RCTPackagerConnection.h" + +#import +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#if RCT_DEV +@interface RCTPackagerConnection () +@end + +template +struct Registration { + NSString *method; + Handler handler; + dispatch_queue_t queue; + uint32_t token; +}; + +@implementation RCTPackagerConnection { + std::mutex _mutex; // protects all ivars + RCTReconnectingWebSocket *_socket; + BOOL _socketConnected; + NSString *_jsLocationForSocket; + id _bundleURLChangeObserver; + uint32_t _nextToken; + std::vector> _notificationRegistrations; + std::vector> _requestRegistrations; + std::vector> _connectedRegistrations; +} + ++ (instancetype)sharedPackagerConnection +{ + static RCTPackagerConnection *connection; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + connection = [RCTPackagerConnection new]; + }); + return connection; +} + +- (instancetype)init +{ + if (self = [super init]) { + _nextToken = 1; // Prevent randomly erasing a handler if you pass a bogus 0 token + _jsLocationForSocket = [RCTBundleURLProvider sharedSettings].jsLocation; + _socket = socketForLocation(_jsLocationForSocket); + _socket.delegate = self; + [_socket start]; + + RCTPackagerConnection *const __weak weakSelf = self; + _bundleURLChangeObserver = + [[NSNotificationCenter defaultCenter] + addObserverForName:RCTBundleURLProviderUpdatedNotification + object:nil + queue:[NSOperationQueue mainQueue] + usingBlock:^(NSNotification *_Nonnull note) { + [weakSelf bundleURLSettingsChanged]; + }]; + } + return self; +} + +static RCTReconnectingWebSocket *socketForLocation(NSString *const jsLocation) +{ + NSURLComponents *const components = [NSURLComponents new]; + components.host = jsLocation ?: @"localhost"; + components.scheme = @"http"; + components.port = @(kRCTBundleURLProviderDefaultPort); + components.path = @"/message"; + components.queryItems = @[[NSURLQueryItem queryItemWithName:@"role" value:@"ios"]]; + static dispatch_queue_t queue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + queue = dispatch_queue_create("com.facebook.RCTPackagerConnectionQueue", DISPATCH_QUEUE_SERIAL); + }); + return [[RCTReconnectingWebSocket alloc] initWithURL:components.URL queue:queue]; +} + +- (void)stop +{ + std::lock_guard l(_mutex); + if (_socket == nil) { + // Already stopped + return; + } + [[NSNotificationCenter defaultCenter] removeObserver:_bundleURLChangeObserver]; + _bundleURLChangeObserver = nil; + _socketConnected = NO; + [_socket stop]; + _socket = nil; + _notificationRegistrations.clear(); + _requestRegistrations.clear(); +} + +- (void)bundleURLSettingsChanged +{ + std::lock_guard l(_mutex); + if (_socket == nil) { + return; // already stopped + } + + NSString *const jsLocation = [RCTBundleURLProvider sharedSettings].jsLocation; + if ([jsLocation isEqual:_jsLocationForSocket]) { + return; // unchanged + } + + _socket.delegate = nil; + [_socket stop]; + _jsLocationForSocket = jsLocation; + _socket = socketForLocation(jsLocation); + _socket.delegate = self; + [_socket start]; +} + +- (RCTHandlerToken)addNotificationHandler:(RCTNotificationHandler)handler queue:(dispatch_queue_t)queue forMethod:(NSString *)method +{ + std::lock_guard l(_mutex); + const auto token = _nextToken++; + _notificationRegistrations.push_back({method, handler, queue, token}); + return token; +} + +- (RCTHandlerToken)addRequestHandler:(RCTRequestHandler)handler queue:(dispatch_queue_t)queue forMethod:(NSString *)method +{ + std::lock_guard l(_mutex); + const auto token = _nextToken++; + _requestRegistrations.push_back({method, handler, queue, token}); + return token; +} + +- (RCTHandlerToken)addConnectedHandler:(RCTConnectedHandler)handler queue:(dispatch_queue_t)queue +{ + std::lock_guard l(_mutex); + if (_socketConnected) { + dispatch_async(queue, ^{ + handler(); + }); + return 0; // _nextToken starts at 1, so 0 is a no-op token + } else { + const auto token = _nextToken++; + _connectedRegistrations.push_back({nil, handler, queue, token}); + return token; + } +} + +- (void)removeHandler:(RCTHandlerToken)token +{ + std::lock_guard l(_mutex); + eraseRegistrationsWithToken(_notificationRegistrations, token); + eraseRegistrationsWithToken(_requestRegistrations, token); + eraseRegistrationsWithToken(_connectedRegistrations, token); +} + +template +static void eraseRegistrationsWithToken(std::vector> ®istrations, RCTHandlerToken token) +{ + registrations.erase(std::remove_if(registrations.begin(), registrations.end(), + [&token](const auto ®) { return reg.token == token; }), + registrations.end()); +} + +- (void)addHandler:(id)handler forMethod:(NSString *)method +{ + dispatch_queue_t queue = [handler respondsToSelector:@selector(methodQueue)] + ? [handler methodQueue] : dispatch_get_main_queue(); + + [self addNotificationHandler:^(NSDictionary *notification) { + [handler handleNotification:notification]; + } queue:queue forMethod:method]; + [self addRequestHandler:^(NSDictionary *request, RCTPackagerClientResponder *responder) { + [handler handleRequest:request withResponder:responder]; + } queue:queue forMethod:method]; +} + +static BOOL isSupportedVersion(NSNumber *version) +{ + NSArray *const kSupportedVersions = @[ @(RCT_PACKAGER_CLIENT_PROTOCOL_VERSION) ]; + return [kSupportedVersions containsObject:version]; +} + +#pragma mark - RCTReconnectingWebSocketDelegate + +- (void)reconnectingWebSocketDidOpen:(RCTReconnectingWebSocket *)webSocket +{ + std::vector> registrations; + { + std::lock_guard l(_mutex); + _socketConnected = YES; + registrations = _connectedRegistrations; + _connectedRegistrations.clear(); + } + for (const auto ®istration : registrations) { + // Beware: don't capture the reference to handler in a dispatched block! + RCTConnectedHandler handler = registration.handler; + dispatch_async(registration.queue, ^{ handler(); }); + } +} + +- (void)reconnectingWebSocket:(RCTReconnectingWebSocket *)webSocket didReceiveMessage:(id)message +{ + NSError *error = nil; + NSDictionary *msg = RCTJSONParse(message, &error); + + if (error) { + RCTLogError(@"%@ failed to parse message with error %@\n\n%@\n", [self class], error, msg); + return; + } + + if (!isSupportedVersion(msg[@"version"])) { + RCTLogError(@"%@ received message with not supported version %@", [self class], msg[@"version"]); + return; + } + + NSString *const method = msg[@"method"]; + NSDictionary *const params = msg[@"params"]; + id messageId = msg[@"id"]; + + if (messageId) { // Request + const std::vector> registrations(registrationsWithMethod(_mutex, _requestRegistrations, method)); + if (registrations.empty()) { + RCTLogError(@"No handler found for packager method %@", msg[@"method"]); + [[[RCTPackagerClientResponder alloc] initWithId:messageId + socket:webSocket] + respondWithError: + [NSString stringWithFormat:@"No handler found for packager method %@", msg[@"method"]]]; + } else { + // If there are multiple matching request registrations, only one can win; + // otherwise the packager would get multiple responses. Choose the last one. + RCTRequestHandler handler = registrations.back().handler; + dispatch_async(registrations.back().queue, ^{ + handler(params, [[RCTPackagerClientResponder alloc] initWithId:messageId socket:webSocket]); + }); + } + } else { // Notification + const std::vector> registrations(registrationsWithMethod(_mutex, _notificationRegistrations, method)); + for (const auto ®istration : registrations) { + // Beware: don't capture the reference to handler in a dispatched block! + RCTNotificationHandler handler = registration.handler; + dispatch_async(registration.queue, ^{ handler(params); }); + } + } +} + +- (void)reconnectingWebSocketDidClose:(RCTReconnectingWebSocket *)webSocket +{ + std::lock_guard l(_mutex); + _socketConnected = NO; +} + +template +static std::vector> registrationsWithMethod(std::mutex &mutex, const std::vector> ®istrations, NSString *method) +{ + std::lock_guard l(mutex); // Scope lock acquisition to prevent deadlock when calling out + std::vector> matches; + for (const auto ® : registrations) { + if ([reg.method isEqual:method]) { + matches.push_back(reg); + } + } + return matches; +} + +@end + +#endif diff --git a/React/DevSupport/RCTPackagerConnectionBridgeConfig.m b/React/DevSupport/RCTPackagerConnectionBridgeConfig.m deleted file mode 100644 index 97d78f00b8fd87..00000000000000 --- a/React/DevSupport/RCTPackagerConnectionBridgeConfig.m +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "RCTPackagerConnectionBridgeConfig.h" - -#import - -#import -#import - -#import "RCTJSEnvironment.h" -#import "RCTReloadPackagerMethod.h" -#import "RCTSamplingProfilerPackagerMethod.h" - -#if RCT_DEV // Only supported in dev mode - -@implementation RCTPackagerConnectionBridgeConfig { - id _jsEnvironment; - RCTReloadPackagerMethodBlock _reloadCommand; - NSURL *_sourceURL; -} - -- (instancetype)initWithBridge:(RCTBridge *)bridge -{ - if (self = [super init]) { - _jsEnvironment = bridge; - _sourceURL = [bridge.bundleURL copy]; - __weak RCTBridge *weakBridge = bridge; - _reloadCommand = ^(id params) { - if (params != (id)kCFNull && [params[@"debug"] boolValue]) { - weakBridge.executorClass = objc_lookUpClass("RCTWebSocketExecutor"); - } - [weakBridge reload]; - }; - } - return self; -} - -- (NSURL *)packagerURL -{ - NSURLComponents *components = [NSURLComponents new]; - NSString *host = [_sourceURL host]; - components.host = host ?: @"localhost"; - components.scheme = host ? [_sourceURL scheme] : @"http"; - components.port = [_sourceURL port] ?: @(kRCTBundleURLProviderDefaultPort); - components.path = @"/message"; - components.queryItems = @[[NSURLQueryItem queryItemWithName:@"role" value:@"ios-rn-rctdevmenu"]]; - return components.URL; -} - -- (NSDictionary> *)defaultPackagerMethods -{ - return @{ - @"reload": [[RCTReloadPackagerMethod alloc] initWithReloadCommand:_reloadCommand callbackQueue:dispatch_get_main_queue()], - @"pokeSamplingProfiler": [[RCTSamplingProfilerPackagerMethod alloc] initWithJSEnvironment:_jsEnvironment] - }; -} - -@end - -#endif diff --git a/React/DevSupport/RCTReloadPackagerMethod.h b/React/DevSupport/RCTReloadPackagerMethod.h deleted file mode 100644 index d19fa6553fb532..00000000000000 --- a/React/DevSupport/RCTReloadPackagerMethod.h +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -@class RCTBridge; - -#if RCT_DEV // Only supported in dev mode - -NS_ASSUME_NONNULL_BEGIN - -typedef void (^RCTReloadPackagerMethodBlock)(id); - -@interface RCTReloadPackagerMethod : NSObject - -- (instancetype)initWithReloadCommand:(RCTReloadPackagerMethodBlock)block callbackQueue:(dispatch_queue_t)callbackQueue; - -@end - -NS_ASSUME_NONNULL_END - -#endif diff --git a/React/DevSupport/RCTReloadPackagerMethod.m b/React/DevSupport/RCTReloadPackagerMethod.m deleted file mode 100644 index 317daec420bfd3..00000000000000 --- a/React/DevSupport/RCTReloadPackagerMethod.m +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "RCTReloadPackagerMethod.h" - -#import "RCTBridge.h" - -#if RCT_DEV // Only supported in dev mode - -@implementation RCTReloadPackagerMethod { - RCTReloadPackagerMethodBlock _block; - dispatch_queue_t _callbackQueue; -} - -- (instancetype)initWithReloadCommand:(RCTReloadPackagerMethodBlock)block callbackQueue:(dispatch_queue_t)callbackQueue -{ - if (self = [super init]) { - _block = [block copy]; - _callbackQueue = callbackQueue; - } - return self; -} - -- (void)handleRequest:(__unused id)params withResponder:(RCTPackagerClientResponder *)responder -{ - [responder respondWithError:[NSString stringWithFormat: @"%@ does not support onRequest", [self class]]]; -} - -- (void)handleNotification:(id)params -{ - _block(params); -} - -- (dispatch_queue_t)methodQueue -{ - return _callbackQueue; -} - -@end - -#endif diff --git a/React/DevSupport/RCTSamplingProfilerPackagerMethod.mm b/React/DevSupport/RCTSamplingProfilerPackagerMethod.mm deleted file mode 100644 index a8bde1fbf57f37..00000000000000 --- a/React/DevSupport/RCTSamplingProfilerPackagerMethod.mm +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "RCTSamplingProfilerPackagerMethod.h" - -#import - -#import - -#import "RCTJSEnvironment.h" -#import "RCTLog.h" - -#if RCT_DEV // Only supported in dev mode - -@implementation RCTSamplingProfilerPackagerMethod { - __weak id _jsEnvironment; -} - -- (instancetype)initWithJSEnvironment:(id)jsEnvironment -{ - if (self = [super init]) { - _jsEnvironment = jsEnvironment; - } - return self; -} - -- (void)handleRequest:(__unused id)params withResponder:(RCTPackagerClientResponder *)responder -{ - JSGlobalContextRef globalContext = _jsEnvironment.jsContextRef; - if (!JSC_JSSamplingProfilerEnabled(globalContext)) { - [responder respondWithError:@"The JSSamplingProfiler is disabled. See 'iOS specific setup' section here https://fburl.com/u4lw7xeq for some help"]; - return; - } - - // JSPokeSamplingProfiler() toggles the profiling process - JSValueRef jsResult = JSC_JSPokeSamplingProfiler(globalContext); - if (JSC_JSValueGetType(globalContext, jsResult) == kJSTypeNull) { - [responder respondWithResult:@"started"]; - } else { - JSContext *context = _jsEnvironment.jsContext; - NSString *results = [[JSC_JSValue(globalContext) valueWithJSValueRef:jsResult inContext:context] toObject]; - [responder respondWithResult:results]; - } -} - -- (void)handleNotification:(__unused id)params -{ - RCTLogError(@"%@ does not implement onNotification", [self class]); -} - -@end - -#endif diff --git a/React/Modules/RCTDevSettings.h b/React/Modules/RCTDevSettings.h index a0e3afc3ad5377..e3b2a8b152b4cf 100644 --- a/React/Modules/RCTDevSettings.h +++ b/React/Modules/RCTDevSettings.h @@ -93,9 +93,7 @@ @property (nonatomic, assign) BOOL isPerfMonitorShown; #if RCT_DEV - -- (void)addHandler:(id)handler forPackagerMethod:(NSString *)name; - +- (void)addHandler:(id)handler forPackagerMethod:(NSString *)name __deprecated_msg("Use RCTPackagerConnection directly instead"); #endif @end diff --git a/React/Modules/RCTDevSettings.mm b/React/Modules/RCTDevSettings.mm index 964b3dca9d3c8d..f8e79f84fad0fc 100644 --- a/React/Modules/RCTDevSettings.mm +++ b/React/Modules/RCTDevSettings.mm @@ -19,8 +19,8 @@ #import "RCTBridgeModule.h" #import "RCTEventDispatcher.h" #import "RCTJSCSamplingProfiler.h" -#import "RCTJSEnvironment.h" #import "RCTLog.h" +#import "RCTPackagerClient.h" #import "RCTProfile.h" #import "RCTUtils.h" @@ -111,9 +111,9 @@ @interface RCTDevSettings () NSURLSessionDataTask *_liveReloadUpdateTask; NSURL *_liveReloadURL; BOOL _isJSLoaded; - #if ENABLE_PACKAGER_CONNECTION - RCTPackagerConnection *_packagerConnection; + RCTHandlerToken _reloadToken; + RCTHandlerToken _pokeSamplingProfilerToken; #endif } @@ -165,7 +165,28 @@ - (void)setBridge:(RCTBridge *)bridge { RCTAssert(_bridge == nil, @"RCTDevSettings module should not be reused"); _bridge = bridge; - [self _configurePackagerConnection]; + +#if ENABLE_PACKAGER_CONNECTION + RCTBridge *__weak weakBridge = bridge; + _reloadToken = + [[RCTPackagerConnection sharedPackagerConnection] + addNotificationHandler:^(id params) { + if (params != (id)kCFNull && [params[@"debug"] boolValue]) { + weakBridge.executorClass = objc_lookUpClass("RCTWebSocketExecutor"); + } + [weakBridge reload]; + } + queue:dispatch_get_main_queue() + forMethod:@"reload"]; + + _pokeSamplingProfilerToken = + [[RCTPackagerConnection sharedPackagerConnection] + addRequestHandler:^(NSDictionary *params, RCTPackagerClientResponder *responder) { + pokeSamplingProfiler(weakBridge, responder); + } + queue:dispatch_get_main_queue() + forMethod:@"pokeSamplingProfiler"]; +#endif #if RCT_ENABLE_INSPECTOR // we need this dispatch back to the main thread because even though this @@ -182,6 +203,30 @@ - (void)setBridge:(RCTBridge *)bridge #endif } +static void pokeSamplingProfiler(RCTBridge *const bridge, RCTPackagerClientResponder *const responder) +{ + if (!bridge) { + [responder respondWithError:@"The bridge is nil. Try again."]; + return; + } + + JSGlobalContextRef globalContext = bridge.jsContextRef; + if (!JSC_JSSamplingProfilerEnabled(globalContext)) { + [responder respondWithError:@"The JSSamplingProfiler is disabled. See 'iOS specific setup' section here https://fburl.com/u4lw7xeq for some help"]; + return; + } + + // JSPokeSamplingProfiler() toggles the profiling process + JSValueRef jsResult = JSC_JSPokeSamplingProfiler(globalContext); + if (JSC_JSValueGetType(globalContext, jsResult) == kJSTypeNull) { + [responder respondWithResult:@"started"]; + } else { + JSContext *context = [JSC_JSContext(globalContext) contextWithJSGlobalContextRef:globalContext]; + NSString *results = [[JSC_JSValue(globalContext) valueWithJSValueRef:jsResult inContext:context] toObject]; + [responder respondWithResult:results]; + } +} + - (dispatch_queue_t)methodQueue { return dispatch_get_main_queue(); @@ -190,6 +235,10 @@ - (dispatch_queue_t)methodQueue - (void)invalidate { [_liveReloadUpdateTask cancel]; +#if ENABLE_PACKAGER_CONNECTION + [[RCTPackagerConnection sharedPackagerConnection] removeHandler:_reloadToken]; + [[RCTPackagerConnection sharedPackagerConnection] removeHandler:_pokeSamplingProfilerToken]; +#endif [[NSNotificationCenter defaultCenter] removeObserver:self]; } @@ -338,12 +387,12 @@ - (BOOL)isHotLoadingEnabled - (void)toggleJSCSamplingProfiler { - JSContext *context = _bridge.jsContext; - JSGlobalContextRef globalContext = context.JSGlobalContextRef; + JSGlobalContextRef globalContext = _bridge.jsContextRef; // JSPokeSamplingProfiler() toggles the profiling process JSValueRef jsResult = JSC_JSPokeSamplingProfiler(globalContext); if (JSC_JSValueGetType(globalContext, jsResult) != kJSTypeNull) { + JSContext *context = [JSC_JSContext(globalContext) contextWithJSGlobalContextRef:globalContext]; NSString *results = [[JSC_JSValue(globalContext) valueWithJSValueRef:jsResult inContext:context] toObject]; RCTJSCSamplingProfiler *profilerModule = [_bridge moduleForClass:[RCTJSCSamplingProfiler class]]; [profilerModule operationCompletedWithResults:results]; @@ -394,33 +443,19 @@ - (void)setExecutorClass:(Class)executorClass } } -#if ENABLE_PACKAGER_CONNECTION +#if RCT_DEV - (void)addHandler:(id)handler forPackagerMethod:(NSString *)name { - RCTAssert(_packagerConnection, @"Expected packager connection"); - [_packagerConnection addHandler:handler forMethod:name]; +#if ENABLE_PACKAGER_CONNECTION + [[RCTPackagerConnection sharedPackagerConnection] addHandler:handler forMethod:name]; +#endif } -#elif RCT_DEV - -- (void)addHandler:(id)handler forPackagerMethod:(NSString *)name {} - #endif #pragma mark - Internal -- (void)_configurePackagerConnection -{ -#if ENABLE_PACKAGER_CONNECTION - if (_packagerConnection) { - return; - } - - _packagerConnection = [RCTPackagerConnection connectionForBridge:_bridge]; -#endif -} - /** * Query the data source for all possible settings and make sure we're doing the right * thing for the state of each setting. diff --git a/React/Modules/RCTRedBox.m b/React/Modules/RCTRedBox.m index ad1a835c5f3283..cb20776b9660ab 100644 --- a/React/Modules/RCTRedBox.m +++ b/React/Modules/RCTRedBox.m @@ -41,7 +41,11 @@ @implementation RCTRedBoxWindow - (instancetype)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { +#if TARGET_OS_TV self.windowLevel = UIWindowLevelAlert + 1000; +#else + self.windowLevel = UIWindowLevelStatusBar - 1; +#endif self.backgroundColor = [UIColor colorWithRed:0.8 green:0 blue:0 alpha:1]; self.hidden = YES; diff --git a/React/Modules/RCTSourceCode.m b/React/Modules/RCTSourceCode.m index 21661fa3f78987..a7c274a006fd86 100644 --- a/React/Modules/RCTSourceCode.m +++ b/React/Modules/RCTSourceCode.m @@ -25,7 +25,8 @@ + (BOOL)requiresMainQueueSetup - (NSDictionary *)constantsToExport { return @{ - @"scriptURL": self.bridge.bundleURL.absoluteString ?: @"" + @"scriptURL": self.bridge.bundleURL.absoluteString ?: @"", + @"embeddedBundleURL": self.bridge.embeddedBundleURL.absoluteString ?: @"" }; } diff --git a/React/Modules/RCTTVNavigationEventEmitter.m b/React/Modules/RCTTVNavigationEventEmitter.m index 26bcf82629e0ae..12d17758401104 100644 --- a/React/Modules/RCTTVNavigationEventEmitter.m +++ b/React/Modules/RCTTVNavigationEventEmitter.m @@ -17,6 +17,11 @@ @implementation RCTTVNavigationEventEmitter RCT_EXPORT_MODULE() ++ (BOOL)requiresMainQueueSetup +{ + return NO; +} + - (instancetype)init { if (self = [super init]) { diff --git a/React/Modules/RCTUIManager.h b/React/Modules/RCTUIManager.h index 237a109238adaf..35e41555668d1d 100644 --- a/React/Modules/RCTUIManager.h +++ b/React/Modules/RCTUIManager.h @@ -29,6 +29,12 @@ RCT_EXTERN NSString *const RCTUIManagerWillUpdateViewsDueToContentSizeMultiplier */ @interface RCTUIManager : NSObject +/** + * Register a root view tag and creates corresponding `rootView` and + * `rootShadowView`. + */ +- (void)registerRootViewTag:(NSNumber *)rootTag; + /** * Register a root view with the RCTUIManager. */ diff --git a/React/Modules/RCTUIManager.m b/React/Modules/RCTUIManager.m index 5984c972ed32ec..dc88c187c01234 100644 --- a/React/Modules/RCTUIManager.m +++ b/React/Modules/RCTUIManager.m @@ -32,6 +32,8 @@ #import "RCTScrollableProtocol.h" #import "RCTShadowView+Internal.h" #import "RCTShadowView.h" +#import "RCTSurfaceRootShadowView.h" +#import "RCTSurfaceRootView.h" #import "RCTUIManagerObserverCoordinator.h" #import "RCTUIManagerUtils.h" #import "RCTUtils.h" @@ -96,7 +98,10 @@ - (void)invalidate RCTExecuteOnMainQueue(^{ RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"UIManager invalidate", nil); for (NSNumber *rootViewTag in self->_rootViewTags) { - [(id)self->_viewRegistry[rootViewTag] invalidate]; + UIView *rootView = self->_viewRegistry[rootViewTag]; + if ([rootView conformsToProtocol:@protocol(RCTInvalidating)]) { + [(id)rootView invalidate]; + } } self->_rootViewTags = nil; @@ -246,6 +251,31 @@ - (dispatch_queue_t)methodQueue return RCTGetUIManagerQueue(); } +- (void)registerRootViewTag:(NSNumber *)rootTag +{ + RCTAssertUIManagerQueue(); + + RCTAssert(RCTIsReactRootView(rootTag), + @"Attempt to register rootTag (%@) which is not actually root tag.", rootTag); + + RCTAssert(![_rootViewTags containsObject:rootTag], + @"Attempt to register rootTag (%@) which was already registred.", rootTag); + + [_rootViewTags addObject:rootTag]; + + // Registering root shadow view + RCTSurfaceRootShadowView *shadowView = [RCTSurfaceRootShadowView new]; + shadowView.reactTag = rootTag; + _shadowViewRegistry[rootTag] = shadowView; + + // Registering root view + RCTExecuteOnMainQueue(^{ + RCTSurfaceRootView *rootView = [RCTSurfaceRootView new]; + rootView.reactTag = rootTag; + self->_viewRegistry[rootTag] = rootView; + }); +} + - (void)registerRootView:(RCTRootContentView *)rootView { RCTAssertMainQueue(); @@ -551,7 +581,9 @@ - (RCTViewManagerUIBlock)uiBlockWithLayoutUpdateForRootView:(RCTRootShadowView * RCTAssert(view != nil, @"view (for ID %@) not found", reactTag); RCTRootView *rootView = (RCTRootView *)[view superview]; - rootView.intrinsicContentSize = contentSize; + if ([rootView isKindOfClass:[RCTRootView class]]) { + rootView.intrinsicContentSize = contentSize; + } }); } } @@ -948,7 +980,8 @@ - (void)_manageChildren:(NSNumber *)containerTag [componentData setProps:props forShadowView:shadowView]; _shadowViewRegistry[reactTag] = shadowView; RCTShadowView *rootView = _shadowViewRegistry[rootTag]; - RCTAssert([rootView isKindOfClass:[RCTRootShadowView class]], + RCTAssert([rootView isKindOfClass:[RCTRootShadowView class]] || + [rootView isKindOfClass:[RCTSurfaceRootShadowView class]], @"Given `rootTag` (%@) does not correspond to a valid root shadow view instance.", rootTag); shadowView.rootView = (RCTRootShadowView *)rootView; } diff --git a/React/Modules/RCTUIManagerUtils.h b/React/Modules/RCTUIManagerUtils.h index 8f0888f252febd..5858255f2c3f79 100644 --- a/React/Modules/RCTUIManagerUtils.h +++ b/React/Modules/RCTUIManagerUtils.h @@ -7,7 +7,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import #import #import @@ -99,3 +99,8 @@ RCT_EXTERN void RCTUnsafeExecuteOnUIManagerQueueSync(dispatch_block_t block); */ #define RCTAssertUIManagerQueue() RCTAssert(RCTIsUIManagerQueue() || RCTIsPseudoUIManagerQueue(), \ @"This function must be called on the UIManager queue") + +/** + * Returns new unique root view tag. + */ +RCT_EXTERN NSNumber *RCTAllocateRootViewTag(void); diff --git a/React/Modules/RCTUIManagerUtils.m b/React/Modules/RCTUIManagerUtils.m index c168c5d817255d..b6c79baa8912dd 100644 --- a/React/Modules/RCTUIManagerUtils.m +++ b/React/Modules/RCTUIManagerUtils.m @@ -9,6 +9,8 @@ #import "RCTUIManagerUtils.h" +#import + #import "RCTAssert.h" char *const RCTUIManagerQueueName = "com.facebook.react.ShadowQueue"; @@ -93,3 +95,10 @@ void RCTUnsafeExecuteOnUIManagerQueueSync(dispatch_block_t block) } } } + +NSNumber *RCTAllocateRootViewTag() +{ + // Numbering of these tags goes from 1, 11, 21, 31, ..., 100501, ... + static int64_t rootViewTagCounter = -1; + return @(OSAtomicIncrement64(&rootViewTagCounter) * 10 + 1); +} diff --git a/React/React.xcodeproj/project.pbxproj b/React/React.xcodeproj/project.pbxproj index a4a87f509da74b..c4efdec32ca0e7 100644 --- a/React/React.xcodeproj/project.pbxproj +++ b/React/React.xcodeproj/project.pbxproj @@ -110,8 +110,6 @@ 13A0C28A1B74F71200B29F6F /* RCTDevMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A0C2881B74F71200B29F6F /* RCTDevMenu.m */; }; 13A1F71E1A75392D00D3D453 /* RCTKeyCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */; }; 13A6E20E1C19AA0C00845B82 /* RCTParserUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A6E20D1C19AA0C00845B82 /* RCTParserUtils.m */; }; - 13AB5E011DF777F2001A8C30 /* YGNodeList.c in Sources */ = {isa = PBXBuildFile; fileRef = 130A77051DF767AF001F9587 /* YGNodeList.c */; }; - 13AB5E021DF777F2001A8C30 /* Yoga.c in Sources */ = {isa = PBXBuildFile; fileRef = 130A77071DF767AF001F9587 /* Yoga.c */; }; 13AB90C11B6FA36700713B4F /* RCTComponentData.m in Sources */ = {isa = PBXBuildFile; fileRef = 13AB90C01B6FA36700713B4F /* RCTComponentData.m */; }; 13AF20451AE707F9005F5298 /* RCTSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 13AF20441AE707F9005F5298 /* RCTSlider.m */; }; 13B07FEF1A69327A00A75B9A /* RCTAlertManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FE81A69327A00A75B9A /* RCTAlertManager.m */; }; @@ -263,6 +261,10 @@ 27595AD61E575C7800CCE2B1 /* Platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0D21E03699D0018521A /* Platform.h */; }; 27595AD71E575C7800CCE2B1 /* SampleCxxModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0D41E03699D0018521A /* SampleCxxModule.h */; }; 27595AD81E575C7800CCE2B1 /* SystraceSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0D51E03699D0018521A /* SystraceSection.h */; }; + 2D16E68E1FA4FD3900B85C8A /* RCTTVNavigationEventEmitter.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D0B842D1EC0B51200B2BD8E /* RCTTVNavigationEventEmitter.h */; }; + 2D1D83CD1F74E2CE00615550 /* libprivatedata-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9936F32F1F5F2E5B0010BF04 /* libprivatedata-tvOS.a */; }; + 2D1D83CE1F74E2DA00615550 /* libdouble-conversion.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D383D621EBD27B9005632C8 /* libdouble-conversion.a */; }; + 2D1D83EF1F74E76C00615550 /* RCTModalManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 91076A871F743AB00081B4FA /* RCTModalManager.m */; }; 2D3B5E931D9B087300451313 /* RCTErrorInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCA8A41D3591E700450C31 /* RCTErrorInfo.m */; }; 2D3B5E941D9B087900451313 /* RCTBundleURLProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 68EFE4ED1CF6EB3900A1DE13 /* RCTBundleURLProvider.m */; }; 2D3B5E951D9B087C00451313 /* RCTAssert.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA4B1A601E3B00E9B192 /* RCTAssert.m */; }; @@ -520,10 +522,8 @@ 3D383D6D1EBD2940005632C8 /* libdouble-conversion.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139D7E881E25C6D100323FB7 /* libdouble-conversion.a */; }; 3D383D6E1EBD2940005632C8 /* libjschelpers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D3CD90B1DE5FBD600167DC4 /* libjschelpers.a */; }; 3D383D6F1EBD2940005632C8 /* libthird-party.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139D7ECE1E25DB7D00323FB7 /* libthird-party.a */; }; - 3D383D701EBD2949005632C8 /* libdouble-conversion.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D383D621EBD27B9005632C8 /* libdouble-conversion.a */; }; 3D383D711EBD2949005632C8 /* libjschelpers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D3CD9181DE5FBD800167DC4 /* libjschelpers.a */; }; 3D383D721EBD2949005632C8 /* libthird-party.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D383D3C1EBD27B6005632C8 /* libthird-party.a */; }; - 3D3C08891DE342FB00C268FA /* libyoga.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D3C059A1DE3340900C268FA /* libyoga.a */; }; 3D3CD93D1DE5FC1400167DC4 /* JavaScriptCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D7A27DC1DE32541002E3F95 /* JavaScriptCore.h */; }; 3D3CD93E1DE5FC1400167DC4 /* JSCWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D7A27DE1DE32541002E3F95 /* JSCWrapper.h */; }; 3D3CD9411DE5FC5300167DC4 /* libcxxreact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D3CD9251DE5FBEC00167DC4 /* libcxxreact.a */; }; @@ -545,16 +545,8 @@ 3D7BFD181EA8E351008DFB7A /* RCTPackagerClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D7BFD0C1EA8E351008DFB7A /* RCTPackagerClient.m */; }; 3D7BFD1D1EA8E351008DFB7A /* RCTPackagerConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D7BFD0F1EA8E351008DFB7A /* RCTPackagerConnection.h */; }; 3D7BFD1E1EA8E351008DFB7A /* RCTPackagerConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D7BFD0F1EA8E351008DFB7A /* RCTPackagerConnection.h */; }; - 3D7BFD1F1EA8E351008DFB7A /* RCTPackagerConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D7BFD101EA8E351008DFB7A /* RCTPackagerConnection.m */; }; - 3D7BFD201EA8E351008DFB7A /* RCTPackagerConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D7BFD101EA8E351008DFB7A /* RCTPackagerConnection.m */; }; - 3D7BFD211EA8E351008DFB7A /* RCTReloadPackagerMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D7BFD111EA8E351008DFB7A /* RCTReloadPackagerMethod.h */; }; - 3D7BFD221EA8E351008DFB7A /* RCTReloadPackagerMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D7BFD111EA8E351008DFB7A /* RCTReloadPackagerMethod.h */; }; - 3D7BFD231EA8E351008DFB7A /* RCTReloadPackagerMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D7BFD121EA8E351008DFB7A /* RCTReloadPackagerMethod.m */; }; - 3D7BFD241EA8E351008DFB7A /* RCTReloadPackagerMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D7BFD121EA8E351008DFB7A /* RCTReloadPackagerMethod.m */; }; - 3D7BFD251EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D7BFD131EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.h */; }; - 3D7BFD261EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D7BFD131EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.h */; }; - 3D7BFD271EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D7BFD141EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.mm */; }; - 3D7BFD281EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D7BFD141EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.mm */; }; + 3D7BFD1F1EA8E351008DFB7A /* RCTPackagerConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D7BFD101EA8E351008DFB7A /* RCTPackagerConnection.mm */; }; + 3D7BFD201EA8E351008DFB7A /* RCTPackagerConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D7BFD101EA8E351008DFB7A /* RCTPackagerConnection.mm */; }; 3D7BFD291EA8E37B008DFB7A /* RCTDevSettings.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 130E3D861E6A082100ACE484 /* RCTDevSettings.h */; }; 3D7BFD2D1EA8E3FA008DFB7A /* RCTReconnectingWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D7BFD2B1EA8E3FA008DFB7A /* RCTReconnectingWebSocket.h */; }; 3D7BFD2E1EA8E3FA008DFB7A /* RCTReconnectingWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D7BFD2B1EA8E3FA008DFB7A /* RCTReconnectingWebSocket.h */; }; @@ -971,8 +963,6 @@ 3DC159E51E83E1E9007B1282 /* JSBigString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27B958731E57587D0096647A /* JSBigString.cpp */; }; 3DC159E61E83E1FA007B1282 /* JSBigString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27B958731E57587D0096647A /* JSBigString.cpp */; }; 3DCC92B91E94456500EF89A8 /* YGNodeList.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 130A77061DF767AF001F9587 /* YGNodeList.h */; }; - 3DCC92BC1E94459100EF89A8 /* YGEnums.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DCC92BA1E94458B00EF89A8 /* YGEnums.c */; }; - 3DCC92BD1E94459100EF89A8 /* YGEnums.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DCC92BA1E94458B00EF89A8 /* YGEnums.c */; }; 3DCC92BE1E9445B100EF89A8 /* YGNodeList.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 130A77061DF767AF001F9587 /* YGNodeList.h */; }; 3DCD185D1DF978E7007FE5A1 /* RCTReloadCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = A2440AA11DF8D854006E7BFC /* RCTReloadCommand.m */; }; 3DDEC1521DDCE0CA0020BBDF /* RCTJSCSamplingProfiler.m in Sources */ = {isa = PBXBuildFile; fileRef = 369123E01DDC75850095B341 /* RCTJSCSamplingProfiler.m */; }; @@ -990,9 +980,17 @@ 3DFE0D1A1DF8575800459392 /* YGEnums.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 130A77031DF767AF001F9587 /* YGEnums.h */; }; 3DFE0D1B1DF8575800459392 /* YGMacros.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 130A77041DF767AF001F9587 /* YGMacros.h */; }; 3DFE0D1C1DF8575800459392 /* Yoga.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 130A77081DF767AF001F9587 /* Yoga.h */; }; - 3DFE0D1D1DF857FF00459392 /* YGNodeList.c in Sources */ = {isa = PBXBuildFile; fileRef = 130A77051DF767AF001F9587 /* YGNodeList.c */; }; - 3DFE0D1E1DF857FF00459392 /* Yoga.c in Sources */ = {isa = PBXBuildFile; fileRef = 130A77071DF767AF001F9587 /* Yoga.c */; }; 3EDCA8A51D3591E700450C31 /* RCTErrorInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCA8A41D3591E700450C31 /* RCTErrorInfo.m */; }; + 53D123971FBF1DF5001B8A10 /* libyoga.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D3C059A1DE3340900C268FA /* libyoga.a */; }; + 53D1239A1FBF1EF2001B8A10 /* YGEnums.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53CBF1861FB4FE80002CBB31 /* YGEnums.cpp */; }; + 53D1239B1FBF1EF4001B8A10 /* YGEnums.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53CBF1861FB4FE80002CBB31 /* YGEnums.cpp */; }; + 53D1239C1FBF1EF7001B8A10 /* YGNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53CBF1881FB4FE80002CBB31 /* YGNodeList.cpp */; }; + 53D1239D1FBF1EF7001B8A10 /* YGNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53CBF1881FB4FE80002CBB31 /* YGNodeList.cpp */; }; + 53D1239E1FBF1EFB001B8A10 /* Yoga-internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 53CBF1851FB4FE80002CBB31 /* Yoga-internal.h */; }; + 53D1239F1FBF1EFB001B8A10 /* Yoga-internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 53CBF1851FB4FE80002CBB31 /* Yoga-internal.h */; }; + 53D123A01FBF1EFF001B8A10 /* Yoga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53CBF1871FB4FE80002CBB31 /* Yoga.cpp */; }; + 53D123A11FBF1EFF001B8A10 /* Yoga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53CBF1871FB4FE80002CBB31 /* Yoga.cpp */; }; + 53D123B21FBF220F001B8A10 /* Yoga.h in Headers */ = {isa = PBXBuildFile; fileRef = 130A77081DF767AF001F9587 /* Yoga.h */; }; 58114A161AAE854800E7D092 /* RCTPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A131AAE854800E7D092 /* RCTPicker.m */; }; 58114A171AAE854800E7D092 /* RCTPickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A151AAE854800E7D092 /* RCTPickerManager.m */; }; 58114A501AAE93D500E7D092 /* RCTAsyncLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A4E1AAE93D500E7D092 /* RCTAsyncLocalStorage.m */; }; @@ -1023,13 +1021,36 @@ 597633371F4E021D005BE8A4 /* RCTShadowView+Internal.m in Sources */ = {isa = PBXBuildFile; fileRef = 597633341F4E021D005BE8A4 /* RCTShadowView+Internal.m */; }; 597633381F4E021D005BE8A4 /* RCTShadowView+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 597633351F4E021D005BE8A4 /* RCTShadowView+Internal.h */; }; 597633391F4E021D005BE8A4 /* RCTShadowView+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 597633351F4E021D005BE8A4 /* RCTShadowView+Internal.h */; }; - 598FD1911F816998006C54CB /* JSIndexedRAMBundleRegistry.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = C6D3801E1F71D91600621378 /* JSIndexedRAMBundleRegistry.h */; }; 598FD1921F816A2A006C54CB /* RAMBundleRegistry.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = C6D380181F71D75B00621378 /* RAMBundleRegistry.h */; }; 598FD1931F817284006C54CB /* PrivateDataBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9936F3351F5F2F480010BF04 /* PrivateDataBase.cpp */; }; 598FD1941F8172A9006C54CB /* PrivateDataBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 9936F3361F5F2F480010BF04 /* PrivateDataBase.h */; }; 598FD1951F817335006C54CB /* RCTModalManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 91076A881F743AB00081B4FA /* RCTModalManager.h */; }; 598FD1961F817335006C54CB /* RCTModalManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 91076A871F743AB00081B4FA /* RCTModalManager.m */; }; 598FD1971F817336006C54CB /* RCTModalManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 91076A881F743AB00081B4FA /* RCTModalManager.h */; }; + 599FAA361FB274980058CCF6 /* RCTSurface.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA2A1FB274970058CCF6 /* RCTSurface.h */; }; + 599FAA371FB274980058CCF6 /* RCTSurface.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA2A1FB274970058CCF6 /* RCTSurface.h */; }; + 599FAA381FB274980058CCF6 /* RCTSurface.mm in Sources */ = {isa = PBXBuildFile; fileRef = 599FAA2B1FB274970058CCF6 /* RCTSurface.mm */; }; + 599FAA391FB274980058CCF6 /* RCTSurface.mm in Sources */ = {isa = PBXBuildFile; fileRef = 599FAA2B1FB274970058CCF6 /* RCTSurface.mm */; }; + 599FAA3A1FB274980058CCF6 /* RCTSurfaceDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA2C1FB274970058CCF6 /* RCTSurfaceDelegate.h */; }; + 599FAA3B1FB274980058CCF6 /* RCTSurfaceDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA2C1FB274970058CCF6 /* RCTSurfaceDelegate.h */; }; + 599FAA3C1FB274980058CCF6 /* RCTSurfaceRootShadowView.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA2D1FB274970058CCF6 /* RCTSurfaceRootShadowView.h */; }; + 599FAA3D1FB274980058CCF6 /* RCTSurfaceRootShadowView.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA2D1FB274970058CCF6 /* RCTSurfaceRootShadowView.h */; }; + 599FAA3E1FB274980058CCF6 /* RCTSurfaceRootShadowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 599FAA2E1FB274970058CCF6 /* RCTSurfaceRootShadowView.m */; }; + 599FAA3F1FB274980058CCF6 /* RCTSurfaceRootShadowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 599FAA2E1FB274970058CCF6 /* RCTSurfaceRootShadowView.m */; }; + 599FAA401FB274980058CCF6 /* RCTSurfaceRootShadowViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA2F1FB274970058CCF6 /* RCTSurfaceRootShadowViewDelegate.h */; }; + 599FAA411FB274980058CCF6 /* RCTSurfaceRootShadowViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA2F1FB274970058CCF6 /* RCTSurfaceRootShadowViewDelegate.h */; }; + 599FAA421FB274980058CCF6 /* RCTSurfaceRootView.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA301FB274970058CCF6 /* RCTSurfaceRootView.h */; }; + 599FAA431FB274980058CCF6 /* RCTSurfaceRootView.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA301FB274970058CCF6 /* RCTSurfaceRootView.h */; }; + 599FAA441FB274980058CCF6 /* RCTSurfaceRootView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 599FAA311FB274970058CCF6 /* RCTSurfaceRootView.mm */; }; + 599FAA451FB274980058CCF6 /* RCTSurfaceRootView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 599FAA311FB274970058CCF6 /* RCTSurfaceRootView.mm */; }; + 599FAA461FB274980058CCF6 /* RCTSurfaceStage.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA321FB274970058CCF6 /* RCTSurfaceStage.h */; }; + 599FAA471FB274980058CCF6 /* RCTSurfaceStage.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA321FB274970058CCF6 /* RCTSurfaceStage.h */; }; + 599FAA481FB274980058CCF6 /* RCTSurfaceView+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA331FB274970058CCF6 /* RCTSurfaceView+Internal.h */; }; + 599FAA491FB274980058CCF6 /* RCTSurfaceView+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA331FB274970058CCF6 /* RCTSurfaceView+Internal.h */; }; + 599FAA4A1FB274980058CCF6 /* RCTSurfaceView.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA341FB274970058CCF6 /* RCTSurfaceView.h */; }; + 599FAA4B1FB274980058CCF6 /* RCTSurfaceView.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA341FB274970058CCF6 /* RCTSurfaceView.h */; }; + 599FAA4C1FB274980058CCF6 /* RCTSurfaceView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 599FAA351FB274970058CCF6 /* RCTSurfaceView.mm */; }; + 599FAA4D1FB274980058CCF6 /* RCTSurfaceView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 599FAA351FB274970058CCF6 /* RCTSurfaceView.mm */; }; 59A7B9FD1E577DBF0068EDBF /* RCTRootContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = 59A7B9FB1E577DBF0068EDBF /* RCTRootContentView.h */; }; 59A7B9FE1E577DBF0068EDBF /* RCTRootContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 59A7B9FC1E577DBF0068EDBF /* RCTRootContentView.m */; }; 59B1EBC91EBD46250047B19B /* RCTShadowView+Layout.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 590D7BFB1EBD458B00D8A370 /* RCTShadowView+Layout.h */; }; @@ -1125,28 +1146,13 @@ C606692F1F3CC60500E67165 /* RCTModuleMethod.mm in Sources */ = {isa = PBXBuildFile; fileRef = C606692D1F3CC60500E67165 /* RCTModuleMethod.mm */; }; C60669361F3CCF1B00E67165 /* RCTManagedPointer.mm in Sources */ = {isa = PBXBuildFile; fileRef = C60669351F3CCF1B00E67165 /* RCTManagedPointer.mm */; }; C60669371F3CCF1B00E67165 /* RCTManagedPointer.mm in Sources */ = {isa = PBXBuildFile; fileRef = C60669351F3CCF1B00E67165 /* RCTManagedPointer.mm */; }; - C6194AAC1EF156280034D062 /* RCTPackagerConnectionBridgeConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = C6194AA91EF156280034D062 /* RCTPackagerConnectionBridgeConfig.h */; }; - C6194AAD1EF156280034D062 /* RCTPackagerConnectionBridgeConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = C6194AA91EF156280034D062 /* RCTPackagerConnectionBridgeConfig.h */; }; - C6194AAE1EF156280034D062 /* RCTPackagerConnectionBridgeConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = C6194AAA1EF156280034D062 /* RCTPackagerConnectionBridgeConfig.m */; }; - C6194AAF1EF156280034D062 /* RCTPackagerConnectionBridgeConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = C6194AAA1EF156280034D062 /* RCTPackagerConnectionBridgeConfig.m */; }; - C6194AB01EF156280034D062 /* RCTPackagerConnectionConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = C6194AAB1EF156280034D062 /* RCTPackagerConnectionConfig.h */; }; - C6194AB11EF156280034D062 /* RCTPackagerConnectionConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = C6194AAB1EF156280034D062 /* RCTPackagerConnectionConfig.h */; }; C654505E1F3BD9280090799B /* RCTManagedPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = C654505D1F3BD9280090799B /* RCTManagedPointer.h */; }; C654505F1F3BD9280090799B /* RCTManagedPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = C654505D1F3BD9280090799B /* RCTManagedPointer.h */; }; C669D8981F72E3DE006748EB /* RAMBundleRegistry.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = C6D380181F71D75B00621378 /* RAMBundleRegistry.h */; }; - C669D8B91F72E4B7006748EB /* JSIndexedRAMBundleRegistry.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = C6D3801E1F71D91600621378 /* JSIndexedRAMBundleRegistry.h */; }; - C6827DF61EF17CCC00D66BEF /* RCTJSEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = C6827DF51EF17CCC00D66BEF /* RCTJSEnvironment.h */; }; - C6827DF71EF17CCC00D66BEF /* RCTJSEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = C6827DF51EF17CCC00D66BEF /* RCTJSEnvironment.h */; }; - C6827DFB1EF1800E00D66BEF /* RCTJSEnvironment.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = C6827DF51EF17CCC00D66BEF /* RCTJSEnvironment.h */; }; - C6827DFC1EF1801B00D66BEF /* RCTJSEnvironment.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = C6827DF51EF17CCC00D66BEF /* RCTJSEnvironment.h */; }; C6D3801A1F71D76100621378 /* RAMBundleRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = C6D380181F71D75B00621378 /* RAMBundleRegistry.h */; }; C6D3801B1F71D76200621378 /* RAMBundleRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = C6D380181F71D75B00621378 /* RAMBundleRegistry.h */; }; C6D3801C1F71D76700621378 /* RAMBundleRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D380191F71D75B00621378 /* RAMBundleRegistry.cpp */; }; C6D3801D1F71D76800621378 /* RAMBundleRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D380191F71D75B00621378 /* RAMBundleRegistry.cpp */; }; - C6D380201F71D91D00621378 /* JSIndexedRAMBundleRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = C6D3801E1F71D91600621378 /* JSIndexedRAMBundleRegistry.h */; }; - C6D380211F71D91E00621378 /* JSIndexedRAMBundleRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = C6D3801E1F71D91600621378 /* JSIndexedRAMBundleRegistry.h */; }; - C6D380221F71D92300621378 /* JSIndexedRAMBundleRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D3801F1F71D91600621378 /* JSIndexedRAMBundleRegistry.cpp */; }; - C6D380231F71D92400621378 /* JSIndexedRAMBundleRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D3801F1F71D91600621378 /* JSIndexedRAMBundleRegistry.cpp */; }; CF2731C01E7B8DE40044CA4F /* RCTDeviceInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = CF2731BE1E7B8DE40044CA4F /* RCTDeviceInfo.h */; }; CF2731C11E7B8DE40044CA4F /* RCTDeviceInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = CF2731BF1E7B8DE40044CA4F /* RCTDeviceInfo.m */; }; CF2731C21E7B8DEF0044CA4F /* RCTDeviceInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = CF2731BE1E7B8DE40044CA4F /* RCTDeviceInfo.h */; }; @@ -1211,19 +1217,19 @@ remoteGlobalIDString = 3D3CD8FF1DE5FBD600167DC4; remoteInfo = jschelpers; }; - 3D8ED92A1E5B11EA00D83D20 /* PBXContainerItemProxy */ = { + 3DC159E71E83E2A0007B1282 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; proxyType = 1; - remoteGlobalIDString = 3D3C04B91DE3340900C268FA; - remoteInfo = yoga; + remoteGlobalIDString = 3D3CD90C1DE5FBD800167DC4; + remoteInfo = "jschelpers-tvOS"; }; - 3DC159E71E83E2A0007B1282 /* PBXContainerItemProxy */ = { + 53D123981FBF1E0C001B8A10 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; proxyType = 1; - remoteGlobalIDString = 3D3CD90C1DE5FBD800167DC4; - remoteInfo = "jschelpers-tvOS"; + remoteGlobalIDString = 3D3C04B91DE3340900C268FA; + remoteInfo = yoga; }; 9936F33F1F5F305D0010BF04 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -1281,11 +1287,11 @@ dstPath = include/React; dstSubfolderSpec = 16; files = ( + 2D16E68E1FA4FD3900B85C8A /* RCTTVNavigationEventEmitter.h in Copy Headers */, 59500D481F71C67600B122B7 /* RCTUIManagerUtils.h in Copy Headers */, 3D0E37901F1CC5E100DCAC9F /* RCTWebSocketModule.h in Copy Headers */, 5960C1BF1F0804F50066FD5B /* RCTLayoutAnimation.h in Copy Headers */, 5960C1C01F0804F50066FD5B /* RCTLayoutAnimationGroup.h in Copy Headers */, - C6827DFC1EF1801B00D66BEF /* RCTJSEnvironment.h in Copy Headers */, 59EB6DC01EBD70130072A5E7 /* RCTUIManagerObserverCoordinator.h in Copy Headers */, 59B1EBCA1EBD47520047B19B /* RCTShadowView+Layout.h in Copy Headers */, 3D0B84271EC0B45400B2BD8E /* RCTLinkingManager.h in Copy Headers */, @@ -1431,7 +1437,6 @@ dstSubfolderSpec = 16; files = ( 598FD1921F816A2A006C54CB /* RAMBundleRegistry.h in Copy Headers */, - 598FD1911F816998006C54CB /* JSIndexedRAMBundleRegistry.h in Copy Headers */, 3DA9823B1E5B1053004F2374 /* CxxModule.h in Copy Headers */, 3DA9823C1E5B1053004F2374 /* CxxNativeModule.h in Copy Headers */, 3DA9823D1E5B1053004F2374 /* JSExecutor.h in Copy Headers */, @@ -1509,7 +1514,6 @@ 3D0E378F1F1CC5CF00DCAC9F /* RCTWebSocketModule.h in Copy Headers */, 5960C1BD1F0804DF0066FD5B /* RCTLayoutAnimation.h in Copy Headers */, 5960C1BE1F0804DF0066FD5B /* RCTLayoutAnimationGroup.h in Copy Headers */, - C6827DFB1EF1800E00D66BEF /* RCTJSEnvironment.h in Copy Headers */, 59EB6DBF1EBD6FFC0072A5E7 /* RCTUIManagerObserverCoordinator.h in Copy Headers */, 59B1EBC91EBD46250047B19B /* RCTShadowView+Layout.h in Copy Headers */, 3D383D1F1EBD27A8005632C8 /* RCTBridge+Private.h in Copy Headers */, @@ -1650,7 +1654,6 @@ dstPath = include/cxxreact; dstSubfolderSpec = 16; files = ( - C669D8B91F72E4B7006748EB /* JSIndexedRAMBundleRegistry.h in Copy Headers */, C669D8981F72E3DE006748EB /* RAMBundleRegistry.h in Copy Headers */, 3DA981A01E5B0E34004F2374 /* CxxModule.h in Copy Headers */, 3DA981A11E5B0E34004F2374 /* CxxNativeModule.h in Copy Headers */, @@ -1741,9 +1744,7 @@ 130443D71E401AD800D93A67 /* RCTTVView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTVView.m; sourceTree = ""; }; 130A77031DF767AF001F9587 /* YGEnums.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGEnums.h; sourceTree = ""; }; 130A77041DF767AF001F9587 /* YGMacros.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGMacros.h; sourceTree = ""; }; - 130A77051DF767AF001F9587 /* YGNodeList.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = YGNodeList.c; sourceTree = ""; }; 130A77061DF767AF001F9587 /* YGNodeList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGNodeList.h; sourceTree = ""; }; - 130A77071DF767AF001F9587 /* Yoga.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Yoga.c; sourceTree = ""; }; 130A77081DF767AF001F9587 /* Yoga.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Yoga.h; sourceTree = ""; }; 130E3D861E6A082100ACE484 /* RCTDevSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDevSettings.h; sourceTree = ""; }; 130E3D871E6A082100ACE484 /* RCTDevSettings.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTDevSettings.mm; sourceTree = ""; }; @@ -1997,11 +1998,7 @@ 3D7BFD0B1EA8E351008DFB7A /* RCTPackagerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPackagerClient.h; sourceTree = ""; }; 3D7BFD0C1EA8E351008DFB7A /* RCTPackagerClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPackagerClient.m; sourceTree = ""; }; 3D7BFD0F1EA8E351008DFB7A /* RCTPackagerConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPackagerConnection.h; sourceTree = ""; }; - 3D7BFD101EA8E351008DFB7A /* RCTPackagerConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPackagerConnection.m; sourceTree = ""; }; - 3D7BFD111EA8E351008DFB7A /* RCTReloadPackagerMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTReloadPackagerMethod.h; sourceTree = ""; }; - 3D7BFD121EA8E351008DFB7A /* RCTReloadPackagerMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTReloadPackagerMethod.m; sourceTree = ""; }; - 3D7BFD131EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSamplingProfilerPackagerMethod.h; sourceTree = ""; }; - 3D7BFD141EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTSamplingProfilerPackagerMethod.mm; sourceTree = ""; }; + 3D7BFD101EA8E351008DFB7A /* RCTPackagerConnection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTPackagerConnection.mm; sourceTree = ""; }; 3D7BFD2B1EA8E3FA008DFB7A /* RCTReconnectingWebSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTReconnectingWebSocket.h; path = WebSocket/RCTReconnectingWebSocket.h; sourceTree = ""; }; 3D7BFD2C1EA8E3FA008DFB7A /* RCTSRWebSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTSRWebSocket.h; path = WebSocket/RCTSRWebSocket.h; sourceTree = ""; }; 3D92B0A71E03699D0018521A /* CxxModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CxxModule.h; sourceTree = ""; }; @@ -2049,12 +2046,16 @@ 3D92B10B1E0369AD0018521A /* Unicode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Unicode.h; sourceTree = ""; }; 3D92B10C1E0369AD0018521A /* Value.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Value.cpp; sourceTree = ""; }; 3D92B10D1E0369AD0018521A /* Value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Value.h; sourceTree = ""; }; - 3DCC92BA1E94458B00EF89A8 /* YGEnums.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = YGEnums.c; sourceTree = ""; }; 3DF1BE801F26576400068F1A /* JSCTracing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCTracing.cpp; sourceTree = ""; }; 3DF1BE811F26576400068F1A /* JSCTracing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCTracing.h; sourceTree = ""; }; 3EDCA8A21D3591E700450C31 /* RCTErrorCustomizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTErrorCustomizer.h; sourceTree = ""; }; 3EDCA8A31D3591E700450C31 /* RCTErrorInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTErrorInfo.h; sourceTree = ""; }; 3EDCA8A41D3591E700450C31 /* RCTErrorInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTErrorInfo.m; sourceTree = ""; }; + 53CBF1851FB4FE80002CBB31 /* Yoga-internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Yoga-internal.h"; sourceTree = ""; }; + 53CBF1861FB4FE80002CBB31 /* YGEnums.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YGEnums.cpp; sourceTree = ""; }; + 53CBF1871FB4FE80002CBB31 /* Yoga.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Yoga.cpp; sourceTree = ""; }; + 53CBF1881FB4FE80002CBB31 /* YGNodeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YGNodeList.cpp; sourceTree = ""; }; + 53D123831FBF1D49001B8A10 /* libyoga.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libyoga.a; path = "../../../../../../../../../Library/Developer/Xcode/DerivedData/yoga-hdfifpwsinitsibujacpiefkjfdy/Build/Products/Debug/libyoga.a"; sourceTree = ""; }; 58114A121AAE854800E7D092 /* RCTPicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPicker.h; sourceTree = ""; }; 58114A131AAE854800E7D092 /* RCTPicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPicker.m; sourceTree = ""; }; 58114A141AAE854800E7D092 /* RCTPickerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPickerManager.h; sourceTree = ""; }; @@ -2073,6 +2074,18 @@ 5960C1B41F0804A00066FD5B /* RCTLayoutAnimationGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTLayoutAnimationGroup.m; sourceTree = ""; }; 597633341F4E021D005BE8A4 /* RCTShadowView+Internal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTShadowView+Internal.m"; sourceTree = ""; }; 597633351F4E021D005BE8A4 /* RCTShadowView+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTShadowView+Internal.h"; sourceTree = ""; }; + 599FAA2A1FB274970058CCF6 /* RCTSurface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSurface.h; sourceTree = ""; }; + 599FAA2B1FB274970058CCF6 /* RCTSurface.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTSurface.mm; sourceTree = ""; }; + 599FAA2C1FB274970058CCF6 /* RCTSurfaceDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSurfaceDelegate.h; sourceTree = ""; }; + 599FAA2D1FB274970058CCF6 /* RCTSurfaceRootShadowView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSurfaceRootShadowView.h; sourceTree = ""; }; + 599FAA2E1FB274970058CCF6 /* RCTSurfaceRootShadowView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSurfaceRootShadowView.m; sourceTree = ""; }; + 599FAA2F1FB274970058CCF6 /* RCTSurfaceRootShadowViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSurfaceRootShadowViewDelegate.h; sourceTree = ""; }; + 599FAA301FB274970058CCF6 /* RCTSurfaceRootView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSurfaceRootView.h; sourceTree = ""; }; + 599FAA311FB274970058CCF6 /* RCTSurfaceRootView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTSurfaceRootView.mm; sourceTree = ""; }; + 599FAA321FB274970058CCF6 /* RCTSurfaceStage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSurfaceStage.h; sourceTree = ""; }; + 599FAA331FB274970058CCF6 /* RCTSurfaceView+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTSurfaceView+Internal.h"; sourceTree = ""; }; + 599FAA341FB274970058CCF6 /* RCTSurfaceView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSurfaceView.h; sourceTree = ""; }; + 599FAA351FB274970058CCF6 /* RCTSurfaceView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTSurfaceView.mm; sourceTree = ""; }; 59A7B9FB1E577DBF0068EDBF /* RCTRootContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRootContentView.h; sourceTree = ""; }; 59A7B9FC1E577DBF0068EDBF /* RCTRootContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRootContentView.m; sourceTree = ""; }; 59D031E51F8353D3008361F0 /* RCTSafeAreaShadowView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSafeAreaShadowView.h; sourceTree = ""; }; @@ -2151,15 +2164,9 @@ C60128AA1F3D1258009DF9FF /* RCTCxxConvert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTCxxConvert.m; sourceTree = ""; }; C606692D1F3CC60500E67165 /* RCTModuleMethod.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTModuleMethod.mm; sourceTree = ""; }; C60669351F3CCF1B00E67165 /* RCTManagedPointer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTManagedPointer.mm; sourceTree = ""; }; - C6194AA91EF156280034D062 /* RCTPackagerConnectionBridgeConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPackagerConnectionBridgeConfig.h; sourceTree = ""; }; - C6194AAA1EF156280034D062 /* RCTPackagerConnectionBridgeConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPackagerConnectionBridgeConfig.m; sourceTree = ""; }; - C6194AAB1EF156280034D062 /* RCTPackagerConnectionConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPackagerConnectionConfig.h; sourceTree = ""; }; C654505D1F3BD9280090799B /* RCTManagedPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTManagedPointer.h; sourceTree = ""; }; - C6827DF51EF17CCC00D66BEF /* RCTJSEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJSEnvironment.h; sourceTree = ""; }; C6D380181F71D75B00621378 /* RAMBundleRegistry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RAMBundleRegistry.h; sourceTree = ""; }; C6D380191F71D75B00621378 /* RAMBundleRegistry.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RAMBundleRegistry.cpp; sourceTree = ""; }; - C6D3801E1F71D91600621378 /* JSIndexedRAMBundleRegistry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSIndexedRAMBundleRegistry.h; sourceTree = ""; }; - C6D3801F1F71D91600621378 /* JSIndexedRAMBundleRegistry.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSIndexedRAMBundleRegistry.cpp; sourceTree = ""; }; CF2731BE1E7B8DE40044CA4F /* RCTDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDeviceInfo.h; sourceTree = ""; }; CF2731BF1E7B8DE40044CA4F /* RCTDeviceInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDeviceInfo.m; sourceTree = ""; }; E3BBC8EB1ADE6F47001BBD81 /* RCTTextDecorationLineType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTTextDecorationLineType.h; sourceTree = ""; }; @@ -2172,11 +2179,11 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 53D123971FBF1DF5001B8A10 /* libyoga.a in Frameworks */, 3D383D6D1EBD2940005632C8 /* libdouble-conversion.a in Frameworks */, 3D383D6E1EBD2940005632C8 /* libjschelpers.a in Frameworks */, 3D383D6F1EBD2940005632C8 /* libthird-party.a in Frameworks */, 3D3CD9411DE5FC5300167DC4 /* libcxxreact.a in Frameworks */, - 3D3C08891DE342FB00C268FA /* libyoga.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2184,7 +2191,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 3D383D701EBD2949005632C8 /* libdouble-conversion.a in Frameworks */, + 2D1D83CE1F74E2DA00615550 /* libdouble-conversion.a in Frameworks */, + 2D1D83CD1F74E2CE00615550 /* libprivatedata-tvOS.a in Frameworks */, 3D383D711EBD2949005632C8 /* libjschelpers.a in Frameworks */, 3D383D721EBD2949005632C8 /* libthird-party.a in Frameworks */, 3D8ED92C1E5B120100D83D20 /* libcxxreact.a in Frameworks */, @@ -2207,12 +2215,13 @@ 130A77021DF767AF001F9587 /* yoga */ = { isa = PBXGroup; children = ( - 3DCC92BA1E94458B00EF89A8 /* YGEnums.c */, + 53CBF1861FB4FE80002CBB31 /* YGEnums.cpp */, + 53CBF1881FB4FE80002CBB31 /* YGNodeList.cpp */, + 53CBF1851FB4FE80002CBB31 /* Yoga-internal.h */, + 53CBF1871FB4FE80002CBB31 /* Yoga.cpp */, 130A77031DF767AF001F9587 /* YGEnums.h */, 130A77041DF767AF001F9587 /* YGMacros.h */, - 130A77051DF767AF001F9587 /* YGNodeList.c */, 130A77061DF767AF001F9587 /* YGNodeList.h */, - 130A77071DF767AF001F9587 /* Yoga.c */, 130A77081DF767AF001F9587 /* Yoga.h */, ); name = yoga; @@ -2613,14 +2622,7 @@ 3D7BFD0B1EA8E351008DFB7A /* RCTPackagerClient.h */, 3D7BFD0C1EA8E351008DFB7A /* RCTPackagerClient.m */, 3D7BFD0F1EA8E351008DFB7A /* RCTPackagerConnection.h */, - 3D7BFD101EA8E351008DFB7A /* RCTPackagerConnection.m */, - C6194AA91EF156280034D062 /* RCTPackagerConnectionBridgeConfig.h */, - C6194AAA1EF156280034D062 /* RCTPackagerConnectionBridgeConfig.m */, - C6194AAB1EF156280034D062 /* RCTPackagerConnectionConfig.h */, - 3D7BFD111EA8E351008DFB7A /* RCTReloadPackagerMethod.h */, - 3D7BFD121EA8E351008DFB7A /* RCTReloadPackagerMethod.m */, - 3D7BFD131EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.h */, - 3D7BFD141EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.mm */, + 3D7BFD101EA8E351008DFB7A /* RCTPackagerConnection.mm */, ); path = DevSupport; sourceTree = ""; @@ -2647,6 +2649,33 @@ path = "../third-party"; sourceTree = ""; }; + 53D123821FBF1D49001B8A10 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 53D123831FBF1D49001B8A10 /* libyoga.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 599FAA291FB274970058CCF6 /* Surface */ = { + isa = PBXGroup; + children = ( + 599FAA2A1FB274970058CCF6 /* RCTSurface.h */, + 599FAA2B1FB274970058CCF6 /* RCTSurface.mm */, + 599FAA2C1FB274970058CCF6 /* RCTSurfaceDelegate.h */, + 599FAA2D1FB274970058CCF6 /* RCTSurfaceRootShadowView.h */, + 599FAA2E1FB274970058CCF6 /* RCTSurfaceRootShadowView.m */, + 599FAA2F1FB274970058CCF6 /* RCTSurfaceRootShadowViewDelegate.h */, + 599FAA301FB274970058CCF6 /* RCTSurfaceRootView.h */, + 599FAA311FB274970058CCF6 /* RCTSurfaceRootView.mm */, + 599FAA321FB274970058CCF6 /* RCTSurfaceStage.h */, + 599FAA331FB274970058CCF6 /* RCTSurfaceView+Internal.h */, + 599FAA341FB274970058CCF6 /* RCTSurfaceView.h */, + 599FAA351FB274970058CCF6 /* RCTSurfaceView.mm */, + ); + path = Surface; + sourceTree = ""; + }; 59D031E41F8353D3008361F0 /* SafeAreaView */ = { isa = PBXGroup; children = ( @@ -2681,6 +2710,7 @@ 3D1FA0781DE4F2CD00E03CC6 /* Libraries */, 3D92B1151E036A690018521A /* ThirdParty */, 83CBBA001A601CBA00E9B192 /* Products */, + 53D123821FBF1D49001B8A10 /* Frameworks */, ); indentWidth = 2; sourceTree = ""; @@ -2760,7 +2790,6 @@ AC70D2E81DE489E4002E6351 /* RCTJavaScriptLoader.mm */, 135A9BF91E7B0EAE00587AEB /* RCTJSCErrorHandling.h */, 135A9BFA1E7B0EAE00587AEB /* RCTJSCErrorHandling.mm */, - C6827DF51EF17CCC00D66BEF /* RCTJSEnvironment.h */, 008341F51D1DB34400876D9A /* RCTJSStackFrame.h */, 008341F41D1DB34400876D9A /* RCTJSStackFrame.m */, 13A1F71C1A75392D00D3D453 /* RCTKeyCommands.h */, @@ -2803,6 +2832,7 @@ 83CBBA4F1A601E3B00E9B192 /* RCTUtils.h */, 83CBBA501A601E3B00E9B192 /* RCTUtils.m */, 199B8A6E1F44DB16005DEF67 /* RCTVersion.h */, + 599FAA291FB274970058CCF6 /* Surface */, ); path = Base; sourceTree = ""; @@ -2849,8 +2879,6 @@ 3D92B0AB1E03699D0018521A /* JSExecutor.h */, 3D92B0C61E03699D0018521A /* JSIndexedRAMBundle.cpp */, 3D92B0C71E03699D0018521A /* JSIndexedRAMBundle.h */, - C6D3801F1F71D91600621378 /* JSIndexedRAMBundleRegistry.cpp */, - C6D3801E1F71D91600621378 /* JSIndexedRAMBundleRegistry.h */, 3D92B0C81E03699D0018521A /* JSModulesUnbundle.h */, 3D92B0C91E03699D0018521A /* MessageQueueThread.h */, 3D92B0CA1E03699D0018521A /* MethodCall.cpp */, @@ -2920,7 +2948,6 @@ 3D302F261DF828F800D6DDAE /* RCTResizeMode.h in Headers */, 3D302F271DF828F800D6DDAE /* RCTLinkingManager.h in Headers */, 3D7BFD161EA8E351008DFB7A /* RCTPackagerClient.h in Headers */, - C6827DF71EF17CCC00D66BEF /* RCTJSEnvironment.h in Headers */, 3D302F281DF828F800D6DDAE /* RCTNetworking.h in Headers */, 3D302F291DF828F800D6DDAE /* RCTNetworkTask.h in Headers */, 3D7BFD2E1EA8E3FA008DFB7A /* RCTReconnectingWebSocket.h in Headers */, @@ -2949,10 +2976,12 @@ 59D031F61F8353D3008361F0 /* RCTSafeAreaViewLocalData.h in Headers */, 3D302F3C1DF828F800D6DDAE /* RCTJavaScriptLoader.h in Headers */, 3D302F3D1DF828F800D6DDAE /* RCTJSStackFrame.h in Headers */, + 599FAA491FB274980058CCF6 /* RCTSurfaceView+Internal.h in Headers */, 3D302F3E1DF828F800D6DDAE /* RCTKeyCommands.h in Headers */, 135A9C031E7B0F6100587AEB /* RCTJSCErrorHandling.h in Headers */, - 3D7BFD261EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.h in Headers */, + 599FAA411FB274980058CCF6 /* RCTSurfaceRootShadowViewDelegate.h in Headers */, 3D302F3F1DF828F800D6DDAE /* RCTLog.h in Headers */, + 599FAA431FB274980058CCF6 /* RCTSurfaceRootView.h in Headers */, 3D302F401DF828F800D6DDAE /* RCTModuleData.h in Headers */, 5960C1B61F0804A00066FD5B /* RCTLayoutAnimation.h in Headers */, 3D302F411DF828F800D6DDAE /* RCTModuleMethod.h in Headers */, @@ -2968,7 +2997,6 @@ 3D302F4B1DF828F800D6DDAE /* RCTTouchEvent.h in Headers */, 59D031F21F8353D3008361F0 /* RCTSafeAreaView.h in Headers */, 3D302F4C1DF828F800D6DDAE /* RCTTouchHandler.h in Headers */, - 3D7BFD221EA8E351008DFB7A /* RCTReloadPackagerMethod.h in Headers */, 3D302F4D1DF828F800D6DDAE /* RCTURLRequestDelegate.h in Headers */, 3D302F4E1DF828F800D6DDAE /* RCTURLRequestHandler.h in Headers */, 59500D441F71C63F00B122B7 /* RCTUIManagerUtils.h in Headers */, @@ -2988,15 +3016,17 @@ 3D302F5C1DF828F800D6DDAE /* RCTEventEmitter.h in Headers */, 652971261EE976BD003C8BD5 /* InspectorInterfaces.h in Headers */, 3D302F5D1DF828F800D6DDAE /* RCTExceptionsManager.h in Headers */, + 599FAA4B1FB274980058CCF6 /* RCTSurfaceView.h in Headers */, + 599FAA3D1FB274980058CCF6 /* RCTSurfaceRootShadowView.h in Headers */, 3D302F5E1DF828F800D6DDAE /* RCTI18nManager.h in Headers */, 3D302F5F1DF828F800D6DDAE /* RCTI18nUtil.h in Headers */, 3D302F601DF828F800D6DDAE /* RCTKeyboardObserver.h in Headers */, - C6194AB11EF156280034D062 /* RCTPackagerConnectionConfig.h in Headers */, 3D302F611DF828F800D6DDAE /* RCTRedBox.h in Headers */, 3D302F621DF828F800D6DDAE /* RCTSourceCode.h in Headers */, 3D302F631DF828F800D6DDAE /* RCTStatusBarManager.h in Headers */, 3D302F641DF828F800D6DDAE /* RCTTiming.h in Headers */, 3D302F651DF828F800D6DDAE /* RCTUIManager.h in Headers */, + 599FAA3B1FB274980058CCF6 /* RCTSurfaceDelegate.h in Headers */, 3D302F661DF828F800D6DDAE /* RCTFPSGraph.h in Headers */, 3D302F681DF828F800D6DDAE /* RCTMacros.h in Headers */, 3D302F691DF828F800D6DDAE /* RCTProfile.h in Headers */, @@ -3023,7 +3053,6 @@ 130443DD1E401AF500D93A67 /* RCTConvert+Transform.h in Headers */, 134D63C41F1FEC65008872B5 /* RCTCxxBridgeDelegate.h in Headers */, 3D302F801DF828F800D6DDAE /* RCTNavItem.h in Headers */, - C6194AAD1EF156280034D062 /* RCTPackagerConnectionBridgeConfig.h in Headers */, 3D302F811DF828F800D6DDAE /* RCTNavItemManager.h in Headers */, 135A9C061E7B0F7800587AEB /* RCTJSCHelpers.h in Headers */, 3D302F841DF828F800D6DDAE /* RCTPointerEvents.h in Headers */, @@ -3039,6 +3068,7 @@ 3D302F8A1DF828F800D6DDAE /* RCTScrollView.h in Headers */, CF2731C21E7B8DEF0044CA4F /* RCTDeviceInfo.h in Headers */, 3D302F8B1DF828F800D6DDAE /* RCTScrollViewManager.h in Headers */, + 599FAA371FB274980058CCF6 /* RCTSurface.h in Headers */, 3D302F8C1DF828F800D6DDAE /* RCTSegmentedControl.h in Headers */, 66CD94B21F1045E700CB3C7C /* RCTMaskedView.h in Headers */, 3D302F8D1DF828F800D6DDAE /* RCTSegmentedControlManager.h in Headers */, @@ -3057,6 +3087,7 @@ 3D302F9A1DF828F800D6DDAE /* RCTViewManager.h in Headers */, 3D302F9D1DF828F800D6DDAE /* RCTWrapperViewController.h in Headers */, 3D302F9F1DF828F800D6DDAE /* UIView+React.h in Headers */, + 599FAA471FB274980058CCF6 /* RCTSurfaceStage.h in Headers */, 13134CA11E296B2A00B9F3CB /* RCTCxxUtils.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -3065,6 +3096,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 53D1239F1FBF1EFB001B8A10 /* Yoga-internal.h in Headers */, 3DFE0D161DF8574D00459392 /* YGEnums.h in Headers */, 3DFE0D171DF8574D00459392 /* YGMacros.h in Headers */, 3DFE0D181DF8574D00459392 /* YGNodeList.h in Headers */, @@ -3090,7 +3122,6 @@ 27595AC61E575C7800CCE2B1 /* JsArgumentHelpers.h in Headers */, 27595AD71E575C7800CCE2B1 /* SampleCxxModule.h in Headers */, 27595AD21E575C7800CCE2B1 /* MethodCall.h in Headers */, - C6D380211F71D91E00621378 /* JSIndexedRAMBundleRegistry.h in Headers */, 3D3030221DF8294C00D6DDAE /* JSBundleType.h in Headers */, 27595ACA1E575C7800CCE2B1 /* JSCMemory.h in Headers */, 3D74547D1E54758900E74ADD /* JSBigString.h in Headers */, @@ -3142,6 +3173,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 53D1239E1FBF1EFB001B8A10 /* Yoga-internal.h in Headers */, 133957881DF76D3500EC27BE /* YGEnums.h in Headers */, 1339578B1DF76D3500EC27BE /* Yoga.h in Headers */, 1339578A1DF76D3500EC27BE /* YGNodeList.h in Headers */, @@ -3180,7 +3212,6 @@ 27595AAB1E575C7800CCE2B1 /* JsArgumentHelpers.h in Headers */, 27595ABC1E575C7800CCE2B1 /* SampleCxxModule.h in Headers */, 27595AB71E575C7800CCE2B1 /* MethodCall.h in Headers */, - C6D380201F71D91D00621378 /* JSIndexedRAMBundleRegistry.h in Headers */, 3D3CD9471DE5FC7800167DC4 /* oss-compat-util.h in Headers */, 27595AAF1E575C7800CCE2B1 /* JSCMemory.h in Headers */, 3D74547C1E54758900E74ADD /* JSBigString.h in Headers */, @@ -3219,12 +3250,14 @@ 3D80DA211DF820620028D040 /* RCTBridge.h in Headers */, 13F880381E296D2800C3C7A1 /* JSCWrapper.h in Headers */, 3D80DA221DF820620028D040 /* RCTBridge+Private.h in Headers */, - 3D7BFD211EA8E351008DFB7A /* RCTReloadPackagerMethod.h in Headers */, + 599FAA461FB274980058CCF6 /* RCTSurfaceStage.h in Headers */, + 599FAA361FB274980058CCF6 /* RCTSurface.h in Headers */, 3D80DA231DF820620028D040 /* RCTBridgeDelegate.h in Headers */, 3D80DA241DF820620028D040 /* RCTBridgeMethod.h in Headers */, 3D7BFD151EA8E351008DFB7A /* RCTPackagerClient.h in Headers */, 3D80DA251DF820620028D040 /* RCTBridgeModule.h in Headers */, 3D80DA261DF820620028D040 /* RCTBundleURLProvider.h in Headers */, + 599FAA401FB274980058CCF6 /* RCTSurfaceRootShadowViewDelegate.h in Headers */, 5960C1B51F0804A00066FD5B /* RCTLayoutAnimation.h in Headers */, 3D80DA271DF820620028D040 /* RCTConvert.h in Headers */, 3D80DA281DF820620028D040 /* RCTDefines.h in Headers */, @@ -3239,7 +3272,7 @@ 3D80DA2E1DF820620028D040 /* RCTImageSource.h in Headers */, 3D80DA2F1DF820620028D040 /* RCTInvalidating.h in Headers */, 598FD1971F817336006C54CB /* RCTModalManager.h in Headers */, - 3D7BFD251EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.h in Headers */, + 599FAA3A1FB274980058CCF6 /* RCTSurfaceDelegate.h in Headers */, 9936F3381F5F2F480010BF04 /* PrivateDataBase.h in Headers */, 3D80DA301DF820620028D040 /* RCTJavaScriptExecutor.h in Headers */, 135A9BFF1E7B0EE600587AEB /* RCTJSCHelpers.h in Headers */, @@ -3253,8 +3286,10 @@ 3D80DA361DF820620028D040 /* RCTModuleMethod.h in Headers */, 3D80DA371DF820620028D040 /* RCTMultipartDataTask.h in Headers */, 3D80DA381DF820620028D040 /* RCTMultipartStreamReader.h in Headers */, + 53D123B21FBF220F001B8A10 /* Yoga.h in Headers */, 3D80DA391DF820620028D040 /* RCTNullability.h in Headers */, 3D80DA3A1DF820620028D040 /* RCTParserUtils.h in Headers */, + 599FAA421FB274980058CCF6 /* RCTSurfaceRootView.h in Headers */, 59D031F91F8353D3008361F0 /* RCTSafeAreaViewManager.h in Headers */, 3D80DA3B1DF820620028D040 /* RCTPerformanceLogger.h in Headers */, 59D031F51F8353D3008361F0 /* RCTSafeAreaViewLocalData.h in Headers */, @@ -3283,7 +3318,6 @@ 3D80DA511DF820620028D040 /* RCTEventEmitter.h in Headers */, 59A7B9FD1E577DBF0068EDBF /* RCTRootContentView.h in Headers */, 3D80DA521DF820620028D040 /* RCTExceptionsManager.h in Headers */, - C6194AAC1EF156280034D062 /* RCTPackagerConnectionBridgeConfig.h in Headers */, 3D80DA531DF820620028D040 /* RCTI18nManager.h in Headers */, 3D7BFD2F1EA8E3FA008DFB7A /* RCTSRWebSocket.h in Headers */, 3D80DA541DF820620028D040 /* RCTI18nUtil.h in Headers */, @@ -3300,7 +3334,6 @@ 3D80DA601DF820620028D040 /* RCTActivityIndicatorViewManager.h in Headers */, 59500D431F71C63F00B122B7 /* RCTUIManagerUtils.h in Headers */, 5960C1B91F0804A00066FD5B /* RCTLayoutAnimationGroup.h in Headers */, - C6194AB01EF156280034D062 /* RCTPackagerConnectionConfig.h in Headers */, CF2731C01E7B8DE40044CA4F /* RCTDeviceInfo.h in Headers */, 3D80DA611DF820620028D040 /* RCTAnimationType.h in Headers */, 3D0E378A1F1CC40000DCAC9F /* RCTWebSocketModule.h in Headers */, @@ -3342,7 +3375,7 @@ 3D80DA7F1DF820620028D040 /* RCTScrollView.h in Headers */, 3D80DA801DF820620028D040 /* RCTScrollViewManager.h in Headers */, 3D80DA811DF820620028D040 /* RCTSegmentedControl.h in Headers */, - C6827DF61EF17CCC00D66BEF /* RCTJSEnvironment.h in Headers */, + 599FAA3C1FB274980058CCF6 /* RCTSurfaceRootShadowView.h in Headers */, 3D80DA821DF820620028D040 /* RCTSegmentedControlManager.h in Headers */, 3D80DA831DF820620028D040 /* RCTShadowView.h in Headers */, 3D80DA841DF820620028D040 /* RCTSlider.h in Headers */, @@ -3361,6 +3394,7 @@ 590D7BFD1EBD458B00D8A370 /* RCTShadowView+Layout.h in Headers */, 3D80DA8F1DF820620028D040 /* RCTViewManager.h in Headers */, 13134CA01E296B2A00B9F3CB /* RCTCxxUtils.h in Headers */, + 599FAA4A1FB274980058CCF6 /* RCTSurfaceView.h in Headers */, 3D80DA901DF820620028D040 /* RCTWebView.h in Headers */, 652971251EE976BA003C8BD5 /* InspectorInterfaces.h in Headers */, 3D80DA911DF820620028D040 /* RCTWebViewManager.h in Headers */, @@ -3368,6 +3402,7 @@ 3D80DA931DF820620028D040 /* UIView+Private.h in Headers */, 59FBEFB01E46D91C0095D885 /* RCTScrollContentShadowView.h in Headers */, 3D80DA941DF820620028D040 /* UIView+React.h in Headers */, + 599FAA481FB274980058CCF6 /* RCTSurfaceView+Internal.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3604,7 +3639,7 @@ buildRules = ( ); dependencies = ( - 3D8ED92B1E5B11EA00D83D20 /* PBXTargetDependency */, + 53D123991FBF1E0C001B8A10 /* PBXTargetDependency */, 3D3CD94C1DE5FCE700167DC4 /* PBXTargetDependency */, ); name = React; @@ -3724,7 +3759,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:-8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi"; + shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi"; showEnvVarsInLog = 0; }; 142C4F7F1B582EA6001F0B58 /* Include RCTJSCProfiler */ = { @@ -3850,7 +3885,6 @@ 3D80D91B1DF6F8200028D040 /* RCTPlatform.m in Sources */, 2DD0EFE11DA84F2800B0C975 /* RCTStatusBarManager.m in Sources */, 2D3B5EC91D9B095C00451313 /* RCTBorderDrawing.m in Sources */, - C6194AAF1EF156280034D062 /* RCTPackagerConnectionBridgeConfig.m in Sources */, 66CD94B81F1045E700CB3C7C /* RCTMaskedViewManager.m in Sources */, 2D3B5E991D9B089A00451313 /* RCTDisplayLink.m in Sources */, 2D3B5EA11D9B08B600451313 /* RCTModuleData.mm in Sources */, @@ -3860,6 +3894,7 @@ 2D3B5ECA1D9B095F00451313 /* RCTComponentData.m in Sources */, 2D3B5EA31D9B08BE00451313 /* RCTParserUtils.m in Sources */, 59500D461F71C63F00B122B7 /* RCTUIManagerUtils.m in Sources */, + 599FAA4D1FB274980058CCF6 /* RCTSurfaceView.mm in Sources */, 2D3B5EA01D9B08B200451313 /* RCTLog.mm in Sources */, 2D3B5EE21D9B09B400451313 /* RCTScrollViewManager.m in Sources */, 5960C1BC1F0804A00066FD5B /* RCTLayoutAnimationGroup.m in Sources */, @@ -3874,7 +3909,7 @@ 13134C9F1E296B2A00B9F3CB /* RCTCxxModule.mm in Sources */, 2D3B5EE31D9B09B700451313 /* RCTSegmentedControl.m in Sources */, 130443A41E3FEAC600D93A67 /* RCTFollyConvert.mm in Sources */, - 3D7BFD201EA8E351008DFB7A /* RCTPackagerConnection.m in Sources */, + 3D7BFD201EA8E351008DFB7A /* RCTPackagerConnection.mm in Sources */, 5960C1B81F0804A00066FD5B /* RCTLayoutAnimation.m in Sources */, 2D3B5EB71D9B091800451313 /* RCTRedBox.m in Sources */, 3D7AA9C61E548CDD001955CF /* NSDataBigString.mm in Sources */, @@ -3890,7 +3925,6 @@ 2D3B5EED1D9B09D700451313 /* RCTTabBarManager.m in Sources */, 2D3B5EEF1D9B09DC00451313 /* RCTViewManager.m in Sources */, 13134C971E296B2A00B9F3CB /* RCTObjcExecutor.mm in Sources */, - 3D7BFD241EA8E351008DFB7A /* RCTReloadPackagerMethod.m in Sources */, 2D3B5EE11D9B09B000451313 /* RCTScrollView.m in Sources */, 130E3D8B1E6A083900ACE484 /* RCTDevSettings.mm in Sources */, 2D3B5ED81D9B098A00451313 /* RCTNavigatorManager.m in Sources */, @@ -3900,11 +3934,13 @@ 2D3B5EB61D9B091400451313 /* RCTExceptionsManager.m in Sources */, 2D3B5EEB1D9B09D000451313 /* RCTTabBarItem.m in Sources */, 2D3B5ED41D9B097D00451313 /* RCTModalHostView.m in Sources */, + 599FAA391FB274980058CCF6 /* RCTSurface.mm in Sources */, C606692F1F3CC60500E67165 /* RCTModuleMethod.mm in Sources */, 2D3B5E9F1D9B08AF00451313 /* RCTKeyCommands.m in Sources */, 2D3B5EA51D9B08C700451313 /* RCTRootView.m in Sources */, 13134C871E296B2A00B9F3CB /* RCTCxxBridge.mm in Sources */, CF2731C31E7B8DF30044CA4F /* RCTDeviceInfo.m in Sources */, + 599FAA3F1FB274980058CCF6 /* RCTSurfaceRootShadowView.m in Sources */, 597633371F4E021D005BE8A4 /* RCTShadowView+Internal.m in Sources */, 2D3B5EB11D9B090100451313 /* RCTAppState.m in Sources */, 1384E20B1E806D5B00545659 /* RCTNativeModule.mm in Sources */, @@ -3927,6 +3963,7 @@ 2D3B5EBD1D9B092A00451313 /* RCTTiming.m in Sources */, 135A9C041E7B0F6400587AEB /* RCTJSCErrorHandling.mm in Sources */, 2D3B5EA81D9B08D300451313 /* RCTUtils.m in Sources */, + 599FAA451FB274980058CCF6 /* RCTSurfaceRootView.mm in Sources */, 2D3B5EC81D9B095800451313 /* RCTActivityIndicatorViewManager.m in Sources */, 598FD1961F817335006C54CB /* RCTModalManager.m in Sources */, 3DCD185D1DF978E7007FE5A1 /* RCTReloadCommand.m in Sources */, @@ -3935,6 +3972,7 @@ 2D3B5EC61D9B095000451313 /* RCTProfileTrampoline-x86_64.S in Sources */, 2D3B5EA61D9B08CA00451313 /* RCTTouchEvent.m in Sources */, 2D8C2E331DA40441000EE098 /* RCTMultipartStreamReader.m in Sources */, + 2D1D83EF1F74E76C00615550 /* RCTModalManager.m in Sources */, 2D3B5EF01D9B09E300451313 /* RCTWrapperViewController.m in Sources */, 2D3B5EEC1D9B09D400451313 /* RCTTabBarItemManager.m in Sources */, 2D3B5EB01D9B08FE00451313 /* RCTAlertManager.m in Sources */, @@ -3951,7 +3989,6 @@ 2D3B5EC51D9B094D00451313 /* RCTProfileTrampoline-i386.S in Sources */, 657734951EE8356100A0E9EA /* RCTInspectorPackagerConnection.m in Sources */, 2D3B5EC41D9B094B00451313 /* RCTProfileTrampoline-arm64.S in Sources */, - 3D7BFD281EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.mm in Sources */, 2D3B5EBB1D9B092300451313 /* RCTI18nManager.m in Sources */, 2D3B5EBE1D9B092D00451313 /* RCTUIManager.m in Sources */, C60128AE1F3D1258009DF9FF /* RCTCxxConvert.m in Sources */, @@ -4013,9 +4050,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 13AB5E011DF777F2001A8C30 /* YGNodeList.c in Sources */, - 13AB5E021DF777F2001A8C30 /* Yoga.c in Sources */, - 3DCC92BC1E94459100EF89A8 /* YGEnums.c in Sources */, + 53D123A01FBF1EFF001B8A10 /* Yoga.cpp in Sources */, + 53D1239A1FBF1EF2001B8A10 /* YGEnums.cpp in Sources */, + 53D1239C1FBF1EF7001B8A10 /* YGNodeList.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4023,9 +4060,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3DFE0D1D1DF857FF00459392 /* YGNodeList.c in Sources */, - 3DFE0D1E1DF857FF00459392 /* Yoga.c in Sources */, - 3DCC92BD1E94459100EF89A8 /* YGEnums.c in Sources */, + 53D123A11FBF1EFF001B8A10 /* Yoga.cpp in Sources */, + 53D1239B1FBF1EF4001B8A10 /* YGEnums.cpp in Sources */, + 53D1239D1FBF1EF7001B8A10 /* YGNodeList.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4057,7 +4094,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C6D380221F71D92300621378 /* JSIndexedRAMBundleRegistry.cpp in Sources */, 3DC159E51E83E1E9007B1282 /* JSBigString.cpp in Sources */, 13F8877B1E29726200C3C7A1 /* JSIndexedRAMBundle.cpp in Sources */, 13F8877D1E29726200C3C7A1 /* ModuleRegistry.cpp in Sources */, @@ -4083,7 +4119,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C6D380231F71D92400621378 /* JSIndexedRAMBundleRegistry.cpp in Sources */, 3DC159E61E83E1FA007B1282 /* JSBigString.cpp in Sources */, 13F8878E1E29726300C3C7A1 /* JSIndexedRAMBundle.cpp in Sources */, 13F887901E29726300C3C7A1 /* ModuleRegistry.cpp in Sources */, @@ -4120,7 +4155,7 @@ 14C2CA761B3AC64F00E6CBB2 /* RCTFrameUpdate.m in Sources */, 13134C861E296B2A00B9F3CB /* RCTCxxBridge.mm in Sources */, 13B07FEF1A69327A00A75B9A /* RCTAlertManager.m in Sources */, - 3D7BFD231EA8E351008DFB7A /* RCTReloadPackagerMethod.m in Sources */, + 599FAA4C1FB274980058CCF6 /* RCTSurfaceView.mm in Sources */, 352DCFF01D19F4C20056D623 /* RCTI18nUtil.m in Sources */, 66CD94B71F1045E700CB3C7C /* RCTMaskedViewManager.m in Sources */, 008341F61D1DB34400876D9A /* RCTJSStackFrame.m in Sources */, @@ -4131,7 +4166,6 @@ 830A229E1A66C68A008503DA /* RCTRootView.m in Sources */, 13B07FF01A69327A00A75B9A /* RCTExceptionsManager.m in Sources */, 13A0C28A1B74F71200B29F6F /* RCTDevMenu.m in Sources */, - 3D7BFD271EA8E351008DFB7A /* RCTSamplingProfilerPackagerMethod.mm in Sources */, 13BCE8091C99CB9D00DD7AAD /* RCTRootShadowView.m in Sources */, 006FC4141D9B20820057AAAD /* RCTMultipartDataTask.m in Sources */, 13CC8A821B17642100940AE7 /* RCTBorderDrawing.m in Sources */, @@ -4148,6 +4182,7 @@ 3D7BFD171EA8E351008DFB7A /* RCTPackagerClient.m in Sources */, 14F3620D1AABD06A001CE568 /* RCTSwitch.m in Sources */, 13134C8E1E296B2A00B9F3CB /* RCTMessageThread.mm in Sources */, + 599FAA381FB274980058CCF6 /* RCTSurface.mm in Sources */, 59D031EF1F8353D3008361F0 /* RCTSafeAreaShadowView.m in Sources */, 3D1E68DB1CABD13900DD7465 /* RCTDisplayLink.m in Sources */, 14F3620E1AABD06A001CE568 /* RCTSwitchManager.m in Sources */, @@ -4159,6 +4194,7 @@ C606692E1F3CC60500E67165 /* RCTModuleMethod.mm in Sources */, 1450FF8A1BCFF28A00208362 /* RCTProfileTrampoline-x86_64.S in Sources */, 13D9FEEB1CDCCECF00158BD7 /* RCTEventEmitter.m in Sources */, + 599FAA3E1FB274980058CCF6 /* RCTSurfaceRootShadowView.m in Sources */, AC70D2E91DE489E4002E6351 /* RCTJavaScriptLoader.mm in Sources */, 14F7A0EC1BDA3B3C003C6C10 /* RCTPerfMonitor.m in Sources */, 5960C1B71F0804A00066FD5B /* RCTLayoutAnimation.m in Sources */, @@ -4169,6 +4205,7 @@ 13B080061A6947C200A75B9A /* RCTScrollViewManager.m in Sources */, 137327EA1AA5CF210034F82E /* RCTTabBarManager.m in Sources */, 369123E11DDC75850095B341 /* RCTJSCSamplingProfiler.m in Sources */, + 599FAA441FB274980058CCF6 /* RCTSurfaceRootView.mm in Sources */, C60669361F3CCF1B00E67165 /* RCTManagedPointer.mm in Sources */, 13B080261A694A8400A75B9A /* RCTWrapperViewController.m in Sources */, 13B080051A6947C200A75B9A /* RCTScrollView.m in Sources */, @@ -4198,7 +4235,7 @@ 13D9FEEE1CDCD93000158BD7 /* RCTKeyboardObserver.m in Sources */, 135A9C001E7B0EE600587AEB /* RCTJSCHelpers.mm in Sources */, B233E6EA1D2D845D00BC68BA /* RCTI18nManager.m in Sources */, - 3D7BFD1F1EA8E351008DFB7A /* RCTPackagerConnection.m in Sources */, + 3D7BFD1F1EA8E351008DFB7A /* RCTPackagerConnection.mm in Sources */, 13456E931ADAD2DE009F94A7 /* RCTConvert+CoreLocation.m in Sources */, 137327E91AA5CF210034F82E /* RCTTabBarItemManager.m in Sources */, 13A1F71E1A75392D00D3D453 /* RCTKeyCommands.m in Sources */, @@ -4210,7 +4247,6 @@ 590D7BFF1EBD458B00D8A370 /* RCTShadowView+Layout.m in Sources */, 66CD94B31F1045E700CB3C7C /* RCTMaskedView.m in Sources */, 13C156061AB1A2840079392D /* RCTWebViewManager.m in Sources */, - C6194AAE1EF156280034D062 /* RCTPackagerConnectionBridgeConfig.m in Sources */, 58114A161AAE854800E7D092 /* RCTPicker.m in Sources */, 137327E81AA5CF210034F82E /* RCTTabBarItem.m in Sources */, 83A1FE8C1B62640A00BE0E65 /* RCTModalHostView.m in Sources */, @@ -4304,16 +4340,16 @@ target = 3D3CD8FF1DE5FBD600167DC4 /* jschelpers */; targetProxy = 3D3CD94F1DE5FDB900167DC4 /* PBXContainerItemProxy */; }; - 3D8ED92B1E5B11EA00D83D20 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3D3C04B91DE3340900C268FA /* yoga */; - targetProxy = 3D8ED92A1E5B11EA00D83D20 /* PBXContainerItemProxy */; - }; 3DC159E81E83E2A0007B1282 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 3D3CD90C1DE5FBD800167DC4 /* jschelpers-tvOS */; targetProxy = 3DC159E71E83E2A0007B1282 /* PBXContainerItemProxy */; }; + 53D123991FBF1E0C001B8A10 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3D3C04B91DE3340900C268FA /* yoga */; + targetProxy = 53D123981FBF1E0C001B8A10 /* PBXContainerItemProxy */; + }; 9936F3401F5F305D0010BF04 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 9936F2F81F5F2E4B0010BF04 /* privatedata */; diff --git a/React/ReactLegacy.xcodeproj/project.pbxproj b/React/ReactLegacy.xcodeproj/project.pbxproj index 8b8f8fb3d001e6..99f9374ca3624f 100644 --- a/React/ReactLegacy.xcodeproj/project.pbxproj +++ b/React/ReactLegacy.xcodeproj/project.pbxproj @@ -27,14 +27,11 @@ 137327E81AA5CF210034F82E /* RCTTabBarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 137327E21AA5CF210034F82E /* RCTTabBarItem.m */; }; 137327E91AA5CF210034F82E /* RCTTabBarItemManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 137327E41AA5CF210034F82E /* RCTTabBarItemManager.m */; }; 137327EA1AA5CF210034F82E /* RCTTabBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 137327E61AA5CF210034F82E /* RCTTabBarManager.m */; }; - 138FDE6B1E92EA4F005FEEDD /* YGEnums.c in Sources */ = {isa = PBXBuildFile; fileRef = 138FDE6A1E92EA4F005FEEDD /* YGEnums.c */; }; 139324FE1E70B069009FD7E0 /* RCTJSCErrorHandling.h in Headers */ = {isa = PBXBuildFile; fileRef = 139324FC1E70B069009FD7E0 /* RCTJSCErrorHandling.h */; }; 139324FF1E70B069009FD7E0 /* RCTJSCErrorHandling.mm in Sources */ = {isa = PBXBuildFile; fileRef = 139324FD1E70B069009FD7E0 /* RCTJSCErrorHandling.mm */; }; 13A0C2891B74F71200B29F6F /* RCTDevLoadingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A0C2861B74F71200B29F6F /* RCTDevLoadingView.m */; }; 13A1F71E1A75392D00D3D453 /* RCTKeyCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */; }; 13A6E20E1C19AA0C00845B82 /* RCTParserUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A6E20D1C19AA0C00845B82 /* RCTParserUtils.m */; }; - 13AB5E011DF777F2001A8C30 /* YGNodeList.c in Sources */ = {isa = PBXBuildFile; fileRef = 130A77051DF767AF001F9587 /* YGNodeList.c */; }; - 13AB5E021DF777F2001A8C30 /* Yoga.c in Sources */ = {isa = PBXBuildFile; fileRef = 130A77071DF767AF001F9587 /* Yoga.c */; }; 13AB90C11B6FA36700713B4F /* RCTComponentData.m in Sources */ = {isa = PBXBuildFile; fileRef = 13AB90C01B6FA36700713B4F /* RCTComponentData.m */; }; 13AF20451AE707F9005F5298 /* RCTSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 13AF20441AE707F9005F5298 /* RCTSlider.m */; }; 13B07FEF1A69327A00A75B9A /* RCTAlertManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FE81A69327A00A75B9A /* RCTAlertManager.m */; }; @@ -157,7 +154,6 @@ 2D7FEB891E734B5700D3238C /* systemJSCWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65F3E41D1E73031C009375BD /* systemJSCWrapper.cpp */; }; 2D8C2E331DA40441000EE098 /* RCTMultipartStreamReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 001BFCCF1D8381DE008E587E /* RCTMultipartStreamReader.m */; }; 2DD0EFE11DA84F2800B0C975 /* RCTStatusBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13723B4F1A82FD3C00F88898 /* RCTStatusBarManager.m */; }; - 2DDD72161E931C25007C55D1 /* YGEnums.c in Sources */ = {isa = PBXBuildFile; fileRef = 138FDE6A1E92EA4F005FEEDD /* YGEnums.c */; }; 352DCFF01D19F4C20056D623 /* RCTI18nUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 352DCFEF1D19F4C20056D623 /* RCTI18nUtil.m */; }; 369123E11DDC75850095B341 /* RCTJSCSamplingProfiler.m in Sources */ = {isa = PBXBuildFile; fileRef = 369123E01DDC75850095B341 /* RCTJSCSamplingProfiler.m */; }; 391E86A41C623EC800009732 /* RCTTouchEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 391E86A21C623EC800009732 /* RCTTouchEvent.m */; }; @@ -430,8 +426,8 @@ 3D7749441DC1065C007EC8D8 /* RCTPlatform.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D7749431DC1065C007EC8D8 /* RCTPlatform.m */; }; 3D7BFCE71EA8E1F4008DFB7A /* RCTPackagerConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D7BFCE51EA8E1F4008DFB7A /* RCTPackagerConnection.h */; }; 3D7BFCE81EA8E1F4008DFB7A /* RCTPackagerConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D7BFCE51EA8E1F4008DFB7A /* RCTPackagerConnection.h */; }; - 3D7BFCE91EA8E1F4008DFB7A /* RCTPackagerConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D7BFCE61EA8E1F4008DFB7A /* RCTPackagerConnection.m */; }; - 3D7BFCEA1EA8E1F4008DFB7A /* RCTPackagerConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D7BFCE61EA8E1F4008DFB7A /* RCTPackagerConnection.m */; }; + 3D7BFCE91EA8E1F4008DFB7A /* RCTPackagerConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D7BFCE61EA8E1F4008DFB7A /* RCTPackagerConnection.mm */; }; + 3D7BFCEA1EA8E1F4008DFB7A /* RCTPackagerConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D7BFCE61EA8E1F4008DFB7A /* RCTPackagerConnection.mm */; }; 3D7BFCEB1EA8E23A008DFB7A /* RCTDevSettings.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = B505583C1E43DFB900F71A00 /* RCTDevSettings.h */; }; 3D80D9171DF6F7A80028D040 /* JSBundleType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AC70D2EB1DE48A22002E6351 /* JSBundleType.cpp */; }; 3D80D9181DF6F7A80028D040 /* JSBundleType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AC70D2EB1DE48A22002E6351 /* JSBundleType.cpp */; }; @@ -682,9 +678,11 @@ 3DFE0D1A1DF8575800459392 /* YGEnums.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 130A77031DF767AF001F9587 /* YGEnums.h */; }; 3DFE0D1B1DF8575800459392 /* YGMacros.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 130A77041DF767AF001F9587 /* YGMacros.h */; }; 3DFE0D1C1DF8575800459392 /* Yoga.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 130A77081DF767AF001F9587 /* Yoga.h */; }; - 3DFE0D1D1DF857FF00459392 /* YGNodeList.c in Sources */ = {isa = PBXBuildFile; fileRef = 130A77051DF767AF001F9587 /* YGNodeList.c */; }; - 3DFE0D1E1DF857FF00459392 /* Yoga.c in Sources */ = {isa = PBXBuildFile; fileRef = 130A77071DF767AF001F9587 /* Yoga.c */; }; 3EDCA8A51D3591E700450C31 /* RCTErrorInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCA8A41D3591E700450C31 /* RCTErrorInfo.m */; }; + 53CBF1BF1FB50263002CBB31 /* Yoga-internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 53CBF1BB1FB50262002CBB31 /* Yoga-internal.h */; }; + 53CBF1C01FB50263002CBB31 /* YGEnums.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53CBF1BC1FB50263002CBB31 /* YGEnums.cpp */; }; + 53CBF1C11FB50263002CBB31 /* Yoga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53CBF1BD1FB50263002CBB31 /* Yoga.cpp */; }; + 53CBF1C21FB50263002CBB31 /* YGNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53CBF1BE1FB50263002CBB31 /* YGNodeList.cpp */; }; 58114A161AAE854800E7D092 /* RCTPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A131AAE854800E7D092 /* RCTPicker.m */; }; 58114A171AAE854800E7D092 /* RCTPickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A151AAE854800E7D092 /* RCTPickerManager.m */; }; 58114A501AAE93D500E7D092 /* RCTAsyncLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A4E1AAE93D500E7D092 /* RCTAsyncLocalStorage.m */; }; @@ -742,14 +740,6 @@ A12E9E251E5DEB4D0029001B /* RCTPackagerClient.m in Sources */ = {isa = PBXBuildFile; fileRef = A12E9E181E5DEA350029001B /* RCTPackagerClient.m */; }; A12E9E2A1E5DEB860029001B /* RCTReconnectingWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = A12E9E281E5DEB860029001B /* RCTReconnectingWebSocket.h */; }; A12E9E2B1E5DEB860029001B /* RCTSRWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = A12E9E291E5DEB860029001B /* RCTSRWebSocket.h */; }; - A12E9E5A1E5DF8600029001B /* RCTReloadPackagerMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = A12E9E581E5DF8600029001B /* RCTReloadPackagerMethod.h */; }; - A12E9E5B1E5DF8600029001B /* RCTReloadPackagerMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = A12E9E591E5DF8600029001B /* RCTReloadPackagerMethod.m */; }; - A12E9E5C1E5DF86F0029001B /* RCTReloadPackagerMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = A12E9E581E5DF8600029001B /* RCTReloadPackagerMethod.h */; }; - A12E9E5D1E5DF8720029001B /* RCTReloadPackagerMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = A12E9E591E5DF8600029001B /* RCTReloadPackagerMethod.m */; }; - A12E9E8E1E5DFA620029001B /* RCTSamplingProfilerPackagerMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = A12E9E8C1E5DFA620029001B /* RCTSamplingProfilerPackagerMethod.h */; }; - A12E9E8F1E5DFA620029001B /* RCTSamplingProfilerPackagerMethod.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12E9E8D1E5DFA620029001B /* RCTSamplingProfilerPackagerMethod.mm */; }; - A12E9E901E5DFA6E0029001B /* RCTSamplingProfilerPackagerMethod.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12E9E8D1E5DFA620029001B /* RCTSamplingProfilerPackagerMethod.mm */; }; - A12E9E911E5DFA720029001B /* RCTSamplingProfilerPackagerMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = A12E9E8C1E5DFA620029001B /* RCTSamplingProfilerPackagerMethod.h */; }; A2440AA21DF8D854006E7BFC /* RCTReloadCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = A2440AA01DF8D854006E7BFC /* RCTReloadCommand.h */; }; A2440AA31DF8D854006E7BFC /* RCTReloadCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = A2440AA11DF8D854006E7BFC /* RCTReloadCommand.m */; }; A2440AA41DF8D865006E7BFC /* RCTReloadCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = A2440AA01DF8D854006E7BFC /* RCTReloadCommand.h */; }; @@ -770,18 +760,8 @@ C60669321F3CC7BD00E67165 /* RCTModuleMethod.mm in Sources */ = {isa = PBXBuildFile; fileRef = C60669301F3CC7BD00E67165 /* RCTModuleMethod.mm */; }; C60669391F3CCF3F00E67165 /* RCTManagedPointer.mm in Sources */ = {isa = PBXBuildFile; fileRef = C60669381F3CCF3F00E67165 /* RCTManagedPointer.mm */; }; C606693A1F3CCF3F00E67165 /* RCTManagedPointer.mm in Sources */ = {isa = PBXBuildFile; fileRef = C60669381F3CCF3F00E67165 /* RCTManagedPointer.mm */; }; - C6194AB51EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = C6194AB21EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.h */; }; - C6194AB61EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = C6194AB21EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.h */; }; - C6194AB71EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = C6194AB31EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.m */; }; - C6194AB81EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = C6194AB31EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.m */; }; - C6194AB91EF1569C0034D062 /* RCTPackagerConnectionConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = C6194AB41EF1569C0034D062 /* RCTPackagerConnectionConfig.h */; }; - C6194ABA1EF1569C0034D062 /* RCTPackagerConnectionConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = C6194AB41EF1569C0034D062 /* RCTPackagerConnectionConfig.h */; }; C65450611F3BD94C0090799B /* RCTManagedPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = C65450601F3BD94C0090799B /* RCTManagedPointer.h */; }; C65450621F3BD94C0090799B /* RCTManagedPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = C65450601F3BD94C0090799B /* RCTManagedPointer.h */; }; - C6827DF91EF17DC100D66BEF /* RCTJSEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = C6827DF81EF17DC100D66BEF /* RCTJSEnvironment.h */; }; - C6827DFA1EF17DC100D66BEF /* RCTJSEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = C6827DF81EF17DC100D66BEF /* RCTJSEnvironment.h */; }; - C6827DFD1EF1803F00D66BEF /* RCTJSEnvironment.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = C6827DF81EF17DC100D66BEF /* RCTJSEnvironment.h */; }; - C6827DFE1EF1804600D66BEF /* RCTJSEnvironment.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = C6827DF81EF17DC100D66BEF /* RCTJSEnvironment.h */; }; C6FC33521F70494E00643E54 /* RCTShadowView+Internal.m in Sources */ = {isa = PBXBuildFile; fileRef = C6FC33511F7048A800643E54 /* RCTShadowView+Internal.m */; }; C6FC33531F70494F00643E54 /* RCTShadowView+Internal.m in Sources */ = {isa = PBXBuildFile; fileRef = C6FC33511F7048A800643E54 /* RCTShadowView+Internal.m */; }; C6FC33541F70495200643E54 /* RCTShadowView+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = C6FC33501F7048A800643E54 /* RCTShadowView+Internal.h */; }; @@ -853,7 +833,6 @@ dstSubfolderSpec = 16; files = ( 59DA56301F71C73F00D9EADA /* RCTUIManagerUtils.h in Copy Headers */, - C6827DFE1EF1804600D66BEF /* RCTJSEnvironment.h in Copy Headers */, 598C22DB1EDCBF82009AF445 /* RCTUIManagerObserverCoordinator.h in Copy Headers */, 5954055C1EC03A8E00766D3C /* RCTShadowView+Layout.h in Copy Headers */, 2D7B05391E9D82080032604E /* RCTBridge+Private.h in Copy Headers */, @@ -1016,7 +995,6 @@ dstSubfolderSpec = 16; files = ( 59DA562F1F71C73400D9EADA /* RCTUIManagerUtils.h in Copy Headers */, - C6827DFD1EF1803F00D66BEF /* RCTJSEnvironment.h in Copy Headers */, 598C22DA1EDCBF61009AF445 /* RCTUIManagerObserverCoordinator.h in Copy Headers */, 5954055B1EC03A7F00766D3C /* RCTShadowView+Layout.h in Copy Headers */, 3D7BFCEB1EA8E23A008DFB7A /* RCTDevSettings.h in Copy Headers */, @@ -1188,9 +1166,7 @@ 008341F51D1DB34400876D9A /* RCTJSStackFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJSStackFrame.h; sourceTree = ""; }; 130A77031DF767AF001F9587 /* YGEnums.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGEnums.h; sourceTree = ""; }; 130A77041DF767AF001F9587 /* YGMacros.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGMacros.h; sourceTree = ""; }; - 130A77051DF767AF001F9587 /* YGNodeList.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = YGNodeList.c; sourceTree = ""; }; 130A77061DF767AF001F9587 /* YGNodeList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGNodeList.h; sourceTree = ""; }; - 130A77071DF767AF001F9587 /* Yoga.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Yoga.c; sourceTree = ""; }; 130A77081DF767AF001F9587 /* Yoga.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Yoga.h; sourceTree = ""; }; 131B6AF01AF1093D00FFC3E0 /* RCTSegmentedControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSegmentedControl.h; sourceTree = ""; }; 131B6AF11AF1093D00FFC3E0 /* RCTSegmentedControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSegmentedControl.m; sourceTree = ""; }; @@ -1221,7 +1197,6 @@ 137327E41AA5CF210034F82E /* RCTTabBarItemManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTabBarItemManager.m; sourceTree = ""; }; 137327E51AA5CF210034F82E /* RCTTabBarManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTabBarManager.h; sourceTree = ""; }; 137327E61AA5CF210034F82E /* RCTTabBarManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTabBarManager.m; sourceTree = ""; }; - 138FDE6A1E92EA4F005FEEDD /* YGEnums.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = YGEnums.c; sourceTree = ""; }; 139324FC1E70B069009FD7E0 /* RCTJSCErrorHandling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJSCErrorHandling.h; sourceTree = ""; }; 139324FD1E70B069009FD7E0 /* RCTJSCErrorHandling.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTJSCErrorHandling.mm; sourceTree = ""; }; 13A0C2851B74F71200B29F6F /* RCTDevLoadingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = RCTDevLoadingView.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; @@ -1368,10 +1343,14 @@ 3D7A27DD1DE32541002E3F95 /* JSCWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCWrapper.cpp; sourceTree = ""; }; 3D7A27DE1DE32541002E3F95 /* JSCWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCWrapper.h; sourceTree = ""; }; 3D7BFCE51EA8E1F4008DFB7A /* RCTPackagerConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPackagerConnection.h; sourceTree = ""; }; - 3D7BFCE61EA8E1F4008DFB7A /* RCTPackagerConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPackagerConnection.m; sourceTree = ""; }; + 3D7BFCE61EA8E1F4008DFB7A /* RCTPackagerConnection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTPackagerConnection.mm; sourceTree = ""; }; 3EDCA8A21D3591E700450C31 /* RCTErrorCustomizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTErrorCustomizer.h; sourceTree = ""; }; 3EDCA8A31D3591E700450C31 /* RCTErrorInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTErrorInfo.h; sourceTree = ""; }; 3EDCA8A41D3591E700450C31 /* RCTErrorInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTErrorInfo.m; sourceTree = ""; }; + 53CBF1BB1FB50262002CBB31 /* Yoga-internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Yoga-internal.h"; sourceTree = ""; }; + 53CBF1BC1FB50263002CBB31 /* YGEnums.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YGEnums.cpp; sourceTree = ""; }; + 53CBF1BD1FB50263002CBB31 /* Yoga.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Yoga.cpp; sourceTree = ""; }; + 53CBF1BE1FB50263002CBB31 /* YGNodeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YGNodeList.cpp; sourceTree = ""; }; 58114A121AAE854800E7D092 /* RCTPicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPicker.h; sourceTree = ""; }; 58114A131AAE854800E7D092 /* RCTPicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPicker.m; sourceTree = ""; }; 58114A141AAE854800E7D092 /* RCTPickerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPickerManager.h; sourceTree = ""; }; @@ -1431,10 +1410,6 @@ A12E9E181E5DEA350029001B /* RCTPackagerClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPackagerClient.m; sourceTree = ""; }; A12E9E281E5DEB860029001B /* RCTReconnectingWebSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTReconnectingWebSocket.h; path = WebSocket/RCTReconnectingWebSocket.h; sourceTree = ""; }; A12E9E291E5DEB860029001B /* RCTSRWebSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTSRWebSocket.h; path = WebSocket/RCTSRWebSocket.h; sourceTree = ""; }; - A12E9E581E5DF8600029001B /* RCTReloadPackagerMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTReloadPackagerMethod.h; sourceTree = ""; }; - A12E9E591E5DF8600029001B /* RCTReloadPackagerMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTReloadPackagerMethod.m; sourceTree = ""; }; - A12E9E8C1E5DFA620029001B /* RCTSamplingProfilerPackagerMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSamplingProfilerPackagerMethod.h; sourceTree = ""; }; - A12E9E8D1E5DFA620029001B /* RCTSamplingProfilerPackagerMethod.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTSamplingProfilerPackagerMethod.mm; sourceTree = ""; }; A2440AA01DF8D854006E7BFC /* RCTReloadCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTReloadCommand.h; sourceTree = ""; }; A2440AA11DF8D854006E7BFC /* RCTReloadCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTReloadCommand.m; sourceTree = ""; }; AC70D2E81DE489E4002E6351 /* RCTJavaScriptLoader.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTJavaScriptLoader.mm; sourceTree = ""; }; @@ -1452,11 +1427,7 @@ C60128B01F3D128C009DF9FF /* RCTCxxConvert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTCxxConvert.m; sourceTree = ""; }; C60669301F3CC7BD00E67165 /* RCTModuleMethod.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTModuleMethod.mm; sourceTree = ""; }; C60669381F3CCF3F00E67165 /* RCTManagedPointer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTManagedPointer.mm; sourceTree = ""; }; - C6194AB21EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPackagerConnectionBridgeConfig.h; sourceTree = ""; }; - C6194AB31EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPackagerConnectionBridgeConfig.m; sourceTree = ""; }; - C6194AB41EF1569C0034D062 /* RCTPackagerConnectionConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPackagerConnectionConfig.h; sourceTree = ""; }; C65450601F3BD94C0090799B /* RCTManagedPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTManagedPointer.h; sourceTree = ""; }; - C6827DF81EF17DC100D66BEF /* RCTJSEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJSEnvironment.h; sourceTree = ""; }; C6FC33501F7048A800643E54 /* RCTShadowView+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RCTShadowView+Internal.h"; sourceTree = ""; }; C6FC33511F7048A800643E54 /* RCTShadowView+Internal.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "RCTShadowView+Internal.m"; sourceTree = ""; }; CF85BC301E79EC6B00F1EF3B /* RCTDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDeviceInfo.h; sourceTree = ""; }; @@ -1493,12 +1464,13 @@ 130A77021DF767AF001F9587 /* yoga */ = { isa = PBXGroup; children = ( - 138FDE6A1E92EA4F005FEEDD /* YGEnums.c */, + 53CBF1BC1FB50263002CBB31 /* YGEnums.cpp */, + 53CBF1BE1FB50263002CBB31 /* YGNodeList.cpp */, + 53CBF1BB1FB50262002CBB31 /* Yoga-internal.h */, + 53CBF1BD1FB50263002CBB31 /* Yoga.cpp */, 130A77031DF767AF001F9587 /* YGEnums.h */, 130A77041DF767AF001F9587 /* YGMacros.h */, - 130A77051DF767AF001F9587 /* YGNodeList.c */, 130A77061DF767AF001F9587 /* YGNodeList.h */, - 130A77071DF767AF001F9587 /* Yoga.c */, 130A77081DF767AF001F9587 /* Yoga.h */, ); name = yoga; @@ -1845,7 +1817,6 @@ AC70D2E81DE489E4002E6351 /* RCTJavaScriptLoader.mm */, 139324FC1E70B069009FD7E0 /* RCTJSCErrorHandling.h */, 139324FD1E70B069009FD7E0 /* RCTJSCErrorHandling.mm */, - C6827DF81EF17DC100D66BEF /* RCTJSEnvironment.h */, 008341F51D1DB34400876D9A /* RCTJSStackFrame.h */, 008341F41D1DB34400876D9A /* RCTJSStackFrame.m */, 13A1F71C1A75392D00D3D453 /* RCTKeyCommands.h */, @@ -1901,14 +1872,7 @@ A12E9E171E5DEA350029001B /* RCTPackagerClient.h */, A12E9E181E5DEA350029001B /* RCTPackagerClient.m */, 3D7BFCE51EA8E1F4008DFB7A /* RCTPackagerConnection.h */, - 3D7BFCE61EA8E1F4008DFB7A /* RCTPackagerConnection.m */, - C6194AB21EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.h */, - C6194AB31EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.m */, - C6194AB41EF1569C0034D062 /* RCTPackagerConnectionConfig.h */, - A12E9E581E5DF8600029001B /* RCTReloadPackagerMethod.h */, - A12E9E591E5DF8600029001B /* RCTReloadPackagerMethod.m */, - A12E9E8C1E5DFA620029001B /* RCTSamplingProfilerPackagerMethod.h */, - A12E9E8D1E5DFA620029001B /* RCTSamplingProfilerPackagerMethod.mm */, + 3D7BFCE61EA8E1F4008DFB7A /* RCTPackagerConnection.mm */, ); path = DevSupport; sourceTree = ""; @@ -1947,7 +1911,6 @@ 3D302F251DF828F800D6DDAE /* RCTImageStoreManager.h in Headers */, 3D302F261DF828F800D6DDAE /* RCTResizeMode.h in Headers */, 3D302F271DF828F800D6DDAE /* RCTLinkingManager.h in Headers */, - C6194AB61EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.h in Headers */, 3D302F281DF828F800D6DDAE /* RCTNetworking.h in Headers */, 3D302F291DF828F800D6DDAE /* RCTNetworkTask.h in Headers */, 3D7BFCE81EA8E1F4008DFB7A /* RCTPackagerConnection.h in Headers */, @@ -1968,7 +1931,6 @@ 3D4153741F2770A3005B8EFE /* RCTMaskedViewManager.h in Headers */, 3D302F351DF828F800D6DDAE /* RCTErrorCustomizer.h in Headers */, 3D302F361DF828F800D6DDAE /* RCTErrorInfo.h in Headers */, - A12E9E911E5DFA720029001B /* RCTSamplingProfilerPackagerMethod.h in Headers */, 3D302F371DF828F800D6DDAE /* RCTEventDispatcher.h in Headers */, 3D302F381DF828F800D6DDAE /* RCTFrameUpdate.h in Headers */, 598C22D71EDCBEE1009AF445 /* RCTUIManagerObserverCoordinator.h in Headers */, @@ -1979,7 +1941,6 @@ 3D302F3A1DF828F800D6DDAE /* RCTInvalidating.h in Headers */, 3D302F3B1DF828F800D6DDAE /* RCTJavaScriptExecutor.h in Headers */, 3D302F3C1DF828F800D6DDAE /* RCTJavaScriptLoader.h in Headers */, - C6194ABA1EF1569C0034D062 /* RCTPackagerConnectionConfig.h in Headers */, 3D302F3D1DF828F800D6DDAE /* RCTJSStackFrame.h in Headers */, 3D302F3E1DF828F800D6DDAE /* RCTKeyCommands.h in Headers */, 3D302F3F1DF828F800D6DDAE /* RCTLog.h in Headers */, @@ -2006,7 +1967,6 @@ 3D302F561DF828F800D6DDAE /* RCTAlertManager.h in Headers */, 3D302F571DF828F800D6DDAE /* RCTAppState.h in Headers */, 3D302F581DF828F800D6DDAE /* RCTAsyncLocalStorage.h in Headers */, - A12E9E5C1E5DF86F0029001B /* RCTReloadPackagerMethod.h in Headers */, 3D302F591DF828F800D6DDAE /* RCTClipboard.h in Headers */, 3D302F5A1DF828F800D6DDAE /* RCTDevLoadingView.h in Headers */, 3D302F5B1DF828F800D6DDAE /* RCTDevMenu.h in Headers */, @@ -2035,7 +1995,6 @@ 3D302F6E1DF828F800D6DDAE /* RCTBorderDrawing.h in Headers */, 3D302F6F1DF828F800D6DDAE /* RCTBorderStyle.h in Headers */, 3D302F701DF828F800D6DDAE /* RCTComponent.h in Headers */, - C6827DFA1EF17DC100D66BEF /* RCTJSEnvironment.h in Headers */, 3D302F711DF828F800D6DDAE /* RCTComponentData.h in Headers */, 3D302F721DF828F800D6DDAE /* RCTConvert+CoreLocation.h in Headers */, 3D302F761DF828F800D6DDAE /* RCTFont.h in Headers */, @@ -2144,7 +2103,6 @@ buildActionMask = 2147483647; files = ( 3D80DA191DF820620028D040 /* RCTImageLoader.h in Headers */, - A12E9E8E1E5DFA620029001B /* RCTSamplingProfilerPackagerMethod.h in Headers */, 3D80DA1A1DF820620028D040 /* RCTImageStoreManager.h in Headers */, 3D80DA1B1DF820620028D040 /* RCTResizeMode.h in Headers */, C65450611F3BD94C0090799B /* RCTManagedPointer.h in Headers */, @@ -2173,7 +2131,6 @@ 3D80DA2E1DF820620028D040 /* RCTImageSource.h in Headers */, 3D80DA2F1DF820620028D040 /* RCTInvalidating.h in Headers */, 3D80DA301DF820620028D040 /* RCTJavaScriptExecutor.h in Headers */, - A12E9E5A1E5DF8600029001B /* RCTReloadPackagerMethod.h in Headers */, A12E9E2A1E5DEB860029001B /* RCTReconnectingWebSocket.h in Headers */, 3D80DA311DF820620028D040 /* RCTJavaScriptLoader.h in Headers */, 3D80DA321DF820620028D040 /* RCTJSStackFrame.h in Headers */, @@ -2193,7 +2150,6 @@ 3D80DA3E1DF820620028D040 /* RCTRootViewDelegate.h in Headers */, 3D80DA3F1DF820620028D040 /* RCTRootViewInternal.h in Headers */, 3D80DA401DF820620028D040 /* RCTTouchEvent.h in Headers */, - C6194AB91EF1569C0034D062 /* RCTPackagerConnectionConfig.h in Headers */, 3D80DA411DF820620028D040 /* RCTTouchHandler.h in Headers */, 3D80DA421DF820620028D040 /* RCTURLRequestDelegate.h in Headers */, 3D80DA431DF820620028D040 /* RCTURLRequestHandler.h in Headers */, @@ -2207,7 +2163,6 @@ 3D80DA4E1DF820620028D040 /* RCTClipboard.h in Headers */, 3D80DA4F1DF820620028D040 /* RCTDevLoadingView.h in Headers */, 3D80DA501DF820620028D040 /* RCTDevMenu.h in Headers */, - C6827DF91EF17DC100D66BEF /* RCTJSEnvironment.h in Headers */, 3D80DA511DF820620028D040 /* RCTEventEmitter.h in Headers */, 3D41536B1F277087005B8EFE /* RCTMaskedView.h in Headers */, 3D80DA521DF820620028D040 /* RCTExceptionsManager.h in Headers */, @@ -2230,8 +2185,8 @@ 3D80DA611DF820620028D040 /* RCTAnimationType.h in Headers */, 3D80DA621DF820620028D040 /* RCTAutoInsetsProtocol.h in Headers */, 3D4153711F277092005B8EFE /* RCTConvert+Transform.h in Headers */, + 53CBF1BF1FB50263002CBB31 /* Yoga-internal.h in Headers */, 3D80DA631DF820620028D040 /* RCTBorderDrawing.h in Headers */, - C6194AB51EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.h in Headers */, 3D80DA641DF820620028D040 /* RCTBorderStyle.h in Headers */, 3D80DA651DF820620028D040 /* RCTComponent.h in Headers */, 3D80DA661DF820620028D040 /* RCTComponentData.h in Headers */, @@ -2559,9 +2514,8 @@ 2D3B5E991D9B089A00451313 /* RCTDisplayLink.m in Sources */, 2D3B5EA11D9B08B600451313 /* RCTModuleData.mm in Sources */, 2D3B5EEA1D9B09CD00451313 /* RCTTabBar.m in Sources */, - 3D7BFCEA1EA8E1F4008DFB7A /* RCTPackagerConnection.m in Sources */, + 3D7BFCEA1EA8E1F4008DFB7A /* RCTPackagerConnection.mm in Sources */, 2D3B5EAE1D9B08F800451313 /* RCTEventEmitter.m in Sources */, - A12E9E901E5DFA6E0029001B /* RCTSamplingProfilerPackagerMethod.mm in Sources */, C606693A1F3CCF3F00E67165 /* RCTManagedPointer.mm in Sources */, 2D3B5ECA1D9B095F00451313 /* RCTComponentData.m in Sources */, 2D3B5EA31D9B08BE00451313 /* RCTParserUtils.m in Sources */, @@ -2575,7 +2529,6 @@ 3D4153571F276EE1005B8EFE /* RCTLayoutAnimation.m in Sources */, 59DA562E1F71C6C700D9EADA /* RCTUIManagerUtils.m in Sources */, 2D3B5E971D9B089000451313 /* RCTBridge.m in Sources */, - C6194AB81EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.m in Sources */, 2D3B5E9B1D9B08A000451313 /* RCTFrameUpdate.m in Sources */, 2D3B5EE41D9B09BB00451313 /* RCTSegmentedControlManager.m in Sources */, 2D3B5EE31D9B09B700451313 /* RCTSegmentedControl.m in Sources */, @@ -2624,7 +2577,6 @@ C6FC33531F70494F00643E54 /* RCTShadowView+Internal.m in Sources */, 2D3B5EC61D9B095000451313 /* RCTProfileTrampoline-x86_64.S in Sources */, 594AD5D41E46D87500B07237 /* RCTScrollContentViewManager.m in Sources */, - A12E9E5D1E5DF8720029001B /* RCTReloadPackagerMethod.m in Sources */, 3D5AC71A1E0056E0000F9153 /* RCTTVNavigationEventEmitter.m in Sources */, 2D3B5EA61D9B08CA00451313 /* RCTTouchEvent.m in Sources */, 5954055A1EC03A1700766D3C /* RCTShadowView+Layout.m in Sources */, @@ -2663,9 +2615,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 13AB5E011DF777F2001A8C30 /* YGNodeList.c in Sources */, - 13AB5E021DF777F2001A8C30 /* Yoga.c in Sources */, - 138FDE6B1E92EA4F005FEEDD /* YGEnums.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2673,9 +2622,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3DFE0D1D1DF857FF00459392 /* YGNodeList.c in Sources */, - 3DFE0D1E1DF857FF00459392 /* Yoga.c in Sources */, - 2DDD72161E931C25007C55D1 /* YGEnums.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2726,14 +2672,12 @@ 133CAE8E1B8E5CFD00F6AD92 /* RCTDatePicker.m in Sources */, 14C2CA761B3AC64F00E6CBB2 /* RCTFrameUpdate.m in Sources */, 13B07FEF1A69327A00A75B9A /* RCTAlertManager.m in Sources */, - C6194AB71EF1569C0034D062 /* RCTPackagerConnectionBridgeConfig.m in Sources */, 352DCFF01D19F4C20056D623 /* RCTI18nUtil.m in Sources */, 008341F61D1DB34400876D9A /* RCTJSStackFrame.m in Sources */, 83CBBACC1A6023D300E9B192 /* RCTConvert.m in Sources */, 131B6AF41AF1093D00FFC3E0 /* RCTSegmentedControl.m in Sources */, 830A229E1A66C68A008503DA /* RCTRootView.m in Sources */, 13B07FF01A69327A00A75B9A /* RCTExceptionsManager.m in Sources */, - A12E9E8F1E5DFA620029001B /* RCTSamplingProfilerPackagerMethod.mm in Sources */, 13BCE8091C99CB9D00DD7AAD /* RCTRootShadowView.m in Sources */, 595405591EC03A1700766D3C /* RCTShadowView+Layout.m in Sources */, 006FC4141D9B20820057AAAD /* RCTMultipartDataTask.m in Sources */, @@ -2752,7 +2696,7 @@ 14F3620E1AABD06A001CE568 /* RCTSwitchManager.m in Sources */, 13B080201A69489C00A75B9A /* RCTActivityIndicatorViewManager.m in Sources */, 13E067561A70F44B002CDEE1 /* RCTViewManager.m in Sources */, - 3D7BFCE91EA8E1F4008DFB7A /* RCTPackagerConnection.m in Sources */, + 3D7BFCE91EA8E1F4008DFB7A /* RCTPackagerConnection.mm in Sources */, 13BB3D021BECD54500932C10 /* RCTImageSource.m in Sources */, 58C571C11AA56C1900CDF9C8 /* RCTDatePickerManager.m in Sources */, 1450FF8A1BCFF28A00208362 /* RCTProfileTrampoline-x86_64.S in Sources */, @@ -2762,6 +2706,7 @@ AC70D2E91DE489E4002E6351 /* RCTJavaScriptLoader.mm in Sources */, 14F7A0EC1BDA3B3C003C6C10 /* RCTPerfMonitor.m in Sources */, 1450FF881BCFF28A00208362 /* RCTProfileTrampoline-arm64.S in Sources */, + 53CBF1C11FB50263002CBB31 /* Yoga.cpp in Sources */, 13E41EEB1C05CA0B00CD8DAC /* RCTProfileTrampoline-i386.S in Sources */, 3D37B5821D522B190042D5B5 /* RCTFont.mm in Sources */, 13B080061A6947C200A75B9A /* RCTScrollViewManager.m in Sources */, @@ -2803,12 +2748,14 @@ 191E3EC11C29DC3800C180A6 /* RCTRefreshControl.m in Sources */, 13C156051AB1A2840079392D /* RCTWebView.m in Sources */, 83CBBA601A601EAA00E9B192 /* RCTBridge.m in Sources */, + 53CBF1C21FB50263002CBB31 /* YGNodeList.cpp in Sources */, 13C156061AB1A2840079392D /* RCTWebViewManager.m in Sources */, 58114A161AAE854800E7D092 /* RCTPicker.m in Sources */, 137327E81AA5CF210034F82E /* RCTTabBarItem.m in Sources */, 83A1FE8C1B62640A00BE0E65 /* RCTModalHostView.m in Sources */, C60669311F3CC7BD00E67165 /* RCTModuleMethod.mm in Sources */, 13E067551A70F44B002CDEE1 /* RCTShadowView.m in Sources */, + 53CBF1C01FB50263002CBB31 /* YGEnums.cpp in Sources */, 1450FF871BCFF28A00208362 /* RCTProfileTrampoline-arm.S in Sources */, 131B6AF51AF1093D00FFC3E0 /* RCTSegmentedControlManager.m in Sources */, 58114A171AAE854800E7D092 /* RCTPickerManager.m in Sources */, @@ -2822,7 +2769,6 @@ 13B0801C1A69489C00A75B9A /* RCTNavItem.m in Sources */, 83CBBA691A601EF300E9B192 /* RCTEventDispatcher.m in Sources */, 3D41536E1F277087005B8EFE /* RCTMaskedViewManager.m in Sources */, - A12E9E5B1E5DF8600029001B /* RCTReloadPackagerMethod.m in Sources */, 83A1FE8F1B62643A00BE0E65 /* RCTModalHostViewManager.m in Sources */, 13E0674A1A70F434002CDEE1 /* RCTUIManager.m in Sources */, 391E86A41C623EC800009732 /* RCTTouchEvent.m in Sources */, diff --git a/React/Views/RCTBorderDrawing.m b/React/Views/RCTBorderDrawing.m index 2c661a2e36d248..ec85e92c4d68ec 100644 --- a/React/Views/RCTBorderDrawing.m +++ b/React/Views/RCTBorderDrawing.m @@ -59,6 +59,15 @@ RCTCornerInsets RCTGetCornerInsets(RCTCornerRadii cornerRadii, }; } +static UIEdgeInsets RCTRoundInsetsToPixel(UIEdgeInsets edgeInsets) { + edgeInsets.top = RCTRoundPixelValue(edgeInsets.top); + edgeInsets.bottom = RCTRoundPixelValue(edgeInsets.bottom); + edgeInsets.left = RCTRoundPixelValue(edgeInsets.left); + edgeInsets.right = RCTRoundPixelValue(edgeInsets.right); + + return edgeInsets; +} + static void RCTPathAddEllipticArc(CGMutablePathRef path, const CGAffineTransform *m, CGPoint origin, @@ -195,6 +204,11 @@ static CGContextRef RCTUIGraphicsBeginImageContext(CGSize size, CGColorRef backg const BOOL hasCornerRadii = RCTCornerRadiiAreAboveThreshold(cornerRadii); const RCTCornerInsets cornerInsets = RCTGetCornerInsets(cornerRadii, borderInsets); + // Incorrect render for borders that are not proportional to device pixel: borders get stretched and become + // significantly bigger than expected. + // Rdar: http://www.openradar.me/15959788 + borderInsets = RCTRoundInsetsToPixel(borderInsets); + const BOOL makeStretchable = (borderInsets.left + cornerInsets.topLeft.width + borderInsets.right + cornerInsets.bottomRight.width <= viewSize.width) && diff --git a/React/Views/RCTModalHostView.h b/React/Views/RCTModalHostView.h index 40b5a35e2e8aac..e638df3246bace 100644 --- a/React/Views/RCTModalHostView.h +++ b/React/Views/RCTModalHostView.h @@ -15,6 +15,7 @@ @class RCTBridge; @class RCTModalHostViewController; +@class RCTTVRemoteHandler; @protocol RCTModalHostViewInteractor; @@ -35,6 +36,7 @@ #if TARGET_OS_TV @property (nonatomic, copy) RCTDirectEventBlock onRequestClose; +@property (nonatomic, strong) RCTTVRemoteHandler *tvRemoteHandler; #endif - (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER; diff --git a/React/Views/RCTModalHostView.m b/React/Views/RCTModalHostView.m index a42c23a437163f..50f44697e92e20 100644 --- a/React/Views/RCTModalHostView.m +++ b/React/Views/RCTModalHostView.m @@ -18,6 +18,7 @@ #import "RCTUIManager.h" #import "RCTUtils.h" #import "UIView+React.h" +#import "RCTTVRemoteHandler.h" @implementation RCTModalHostView { @@ -49,6 +50,7 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge #if TARGET_OS_TV _menuButtonGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(menuButtonPressed:)]; _menuButtonGestureRecognizer.allowedPressTypes = @[@(UIPressTypeMenu)]; + self.tvRemoteHandler = [RCTTVRemoteHandler new]; #endif _isPresented = NO; @@ -118,6 +120,11 @@ - (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex [super insertReactSubview:subview atIndex:atIndex]; [_touchHandler attachToView:subview]; #if TARGET_OS_TV + for (NSString *key in [self.tvRemoteHandler.tvRemoteGestureRecognizers allKeys]) { + if (![key isEqualToString:RCTTVRemoteEventMenu]) { + [subview addGestureRecognizer:self.tvRemoteHandler.tvRemoteGestureRecognizers[key]]; + } + } if (_onRequestClose) { [subview addGestureRecognizer:_menuButtonGestureRecognizer]; } @@ -139,6 +146,9 @@ - (void)removeReactSubview:(UIView *)subview if (_menuButtonGestureRecognizer) { [subview removeGestureRecognizer:_menuButtonGestureRecognizer]; } + for (UIGestureRecognizer *gr in self.tvRemoteHandler.tvRemoteGestureRecognizers) { + [subview removeGestureRecognizer:gr]; + } #endif _reactSubview = nil; } diff --git a/React/Views/RCTRefreshControl.m b/React/Views/RCTRefreshControl.m index ee73bf9a475565..37b3bb3baf7d61 100644 --- a/React/Views/RCTRefreshControl.m +++ b/React/Views/RCTRefreshControl.m @@ -72,7 +72,7 @@ - (void)endRefreshing // endRefreshing otherwise the next pull to refresh will not work properly. UIScrollView *scrollView = (UIScrollView *)self.superview; if (scrollView.contentOffset.y < 0) { - CGPoint offset = {scrollView.contentOffset.x, -scrollView.contentInset.top}; + CGPoint offset = {scrollView.contentOffset.x, 0}; [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionBeginFromCurrentState diff --git a/ReactAndroid/src/main/java/com/facebook/react/BridgeCorePackage.java b/ReactAndroid/src/main/java/com/facebook/react/BridgeCorePackage.java deleted file mode 100644 index 7554c223f1c49e..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/BridgeCorePackage.java +++ /dev/null @@ -1,132 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -package com.facebook.react; - -import com.facebook.react.bridge.ModuleSpec; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.module.annotations.ReactModuleList; -import com.facebook.react.module.model.ReactModuleInfoProvider; -import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; -import com.facebook.react.modules.core.DeviceEventManagerModule; -import com.facebook.react.modules.core.ExceptionsManagerModule; -import com.facebook.react.modules.core.HeadlessJsTaskSupportModule; -import com.facebook.react.modules.core.Timing; -import com.facebook.react.modules.debug.SourceCodeModule; -import com.facebook.react.modules.deviceinfo.DeviceInfoModule; -import com.facebook.react.modules.systeminfo.AndroidInfoModule; -import java.util.ArrayList; -import java.util.List; -import javax.inject.Provider; - -/** - * Package defining core framework modules for basic JS interop. - * It should be used for modules that are always necessary for interacting with - * JS, not for modules that provide RN specific functionality - */ -@ReactModuleList( - nativeModules = { - AndroidInfoModule.class, - DeviceEventManagerModule.class, - ExceptionsManagerModule.class, - HeadlessJsTaskSupportModule.class, - SourceCodeModule.class, - Timing.class, - DeviceInfoModule.class, - } -) -/* package */ class BridgeCorePackage extends LazyReactPackage { - - private final ReactInstanceManager mReactInstanceManager; - private final DefaultHardwareBackBtnHandler mHardwareBackBtnHandler; - - BridgeCorePackage( - ReactInstanceManager reactInstanceManager, - DefaultHardwareBackBtnHandler hardwareBackBtnHandler) { - mReactInstanceManager = reactInstanceManager; - mHardwareBackBtnHandler = hardwareBackBtnHandler; - } - - @Override - public List getNativeModules(final ReactApplicationContext reactContext) { - List moduleSpecList = new ArrayList<>(); - - moduleSpecList.add( - ModuleSpec.nativeModuleSpec( - AndroidInfoModule.class, - new Provider() { - @Override - public NativeModule get() { - return new AndroidInfoModule(); - } - })); - moduleSpecList.add( - ModuleSpec.nativeModuleSpec( - DeviceEventManagerModule.class, - new Provider() { - @Override - public NativeModule get() { - return new DeviceEventManagerModule(reactContext, mHardwareBackBtnHandler); - } - })); - moduleSpecList.add( - ModuleSpec.nativeModuleSpec( - ExceptionsManagerModule.class, - new Provider() { - @Override - public NativeModule get() { - return new ExceptionsManagerModule(mReactInstanceManager.getDevSupportManager()); - } - })); - moduleSpecList.add( - ModuleSpec.nativeModuleSpec( - HeadlessJsTaskSupportModule.class, - new Provider() { - @Override - public NativeModule get() { - return new HeadlessJsTaskSupportModule(reactContext); - } - })); - moduleSpecList.add( - ModuleSpec.nativeModuleSpec( - SourceCodeModule.class, - new Provider() { - @Override - public NativeModule get() { - return new SourceCodeModule(reactContext); - } - })); - moduleSpecList.add( - ModuleSpec.nativeModuleSpec( - Timing.class, - new Provider() { - @Override - public NativeModule get() { - return new Timing(reactContext, mReactInstanceManager.getDevSupportManager()); - } - })); - moduleSpecList.add( - ModuleSpec.nativeModuleSpec( - DeviceInfoModule.class, - new Provider() { - @Override - public NativeModule get() { - return new DeviceInfoModule(reactContext); - } - })); - - return moduleSpecList; - } - - @Override - public ReactModuleInfoProvider getReactModuleInfoProvider() { - return LazyReactPackage.getReactModuleInfoProviderViaReflection(this); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java b/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java index 293ca70b58a4e0..7b0ac3253bf402 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java +++ b/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java @@ -18,9 +18,6 @@ import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactMarker; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.devsupport.JSCHeapCapture; -import com.facebook.react.devsupport.JSCSamplingProfiler; import com.facebook.react.module.annotations.ReactModuleList; import com.facebook.react.module.model.ReactModuleInfoProvider; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; @@ -28,7 +25,6 @@ import com.facebook.react.modules.core.ExceptionsManagerModule; import com.facebook.react.modules.core.HeadlessJsTaskSupportModule; import com.facebook.react.modules.core.Timing; -import com.facebook.react.modules.debug.AnimationsDebugModule; import com.facebook.react.modules.debug.SourceCodeModule; import com.facebook.react.modules.deviceinfo.DeviceInfoModule; import com.facebook.react.modules.systeminfo.AndroidInfoModule; @@ -36,35 +32,24 @@ import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.ViewManager; import com.facebook.systrace.Systrace; -import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import javax.annotation.Nullable; import javax.inject.Provider; + /** - * This module should be removed following the completion of an experiment into splitting this into - * three modules to allow for more light-weight instantiations of the bridge without UIManager - * The core modules are now in BridgeCorePackage - * The debug modules are now in DebugCorePackage - * The UI manager is in ReactNativeCorePackage - * - * Package defining core framework modules (e.g. UIManager). It should be used for modules that - * require special integration with other framework parts (e.g. with the list of packages to load - * view managers from). + * This is the basic module to support React Native. The debug modules are now in DebugCorePackage. */ @ReactModuleList( nativeModules = { AndroidInfoModule.class, - AnimationsDebugModule.class, DeviceEventManagerModule.class, + DeviceInfoModule.class, ExceptionsManagerModule.class, HeadlessJsTaskSupportModule.class, SourceCodeModule.class, Timing.class, UIManagerModule.class, - DeviceInfoModule.class, - // Debug only - JSCHeapCapture.class, - JSCSamplingProfiler.class, } ) /* package */ class CoreModulesPackage extends LazyReactPackage implements ReactPackageLogger { @@ -90,9 +75,7 @@ @Override public List getNativeModules(final ReactApplicationContext reactContext) { - List moduleSpecList = new ArrayList<>(); - - moduleSpecList.add( + return Arrays.asList( ModuleSpec.nativeModuleSpec( AndroidInfoModule.class, new Provider() { @@ -100,18 +83,7 @@ public List getNativeModules(final ReactApplicationContext reactCont public NativeModule get() { return new AndroidInfoModule(); } - })); - moduleSpecList.add( - ModuleSpec.nativeModuleSpec( - AnimationsDebugModule.class, - new Provider() { - @Override - public NativeModule get() { - return new AnimationsDebugModule( - reactContext, mReactInstanceManager.getDevSupportManager().getDevSettings()); - } - })); - moduleSpecList.add( + }), ModuleSpec.nativeModuleSpec( DeviceEventManagerModule.class, new Provider() { @@ -119,8 +91,7 @@ public NativeModule get() { public NativeModule get() { return new DeviceEventManagerModule(reactContext, mHardwareBackBtnHandler); } - })); - moduleSpecList.add( + }), ModuleSpec.nativeModuleSpec( ExceptionsManagerModule.class, new Provider() { @@ -128,8 +99,7 @@ public NativeModule get() { public NativeModule get() { return new ExceptionsManagerModule(mReactInstanceManager.getDevSupportManager()); } - })); - moduleSpecList.add( + }), ModuleSpec.nativeModuleSpec( HeadlessJsTaskSupportModule.class, new Provider() { @@ -137,8 +107,7 @@ public NativeModule get() { public NativeModule get() { return new HeadlessJsTaskSupportModule(reactContext); } - })); - moduleSpecList.add( + }), ModuleSpec.nativeModuleSpec( SourceCodeModule.class, new Provider() { @@ -146,8 +115,7 @@ public NativeModule get() { public NativeModule get() { return new SourceCodeModule(reactContext); } - })); - moduleSpecList.add( + }), ModuleSpec.nativeModuleSpec( Timing.class, new Provider() { @@ -155,8 +123,7 @@ public NativeModule get() { public NativeModule get() { return new Timing(reactContext, mReactInstanceManager.getDevSupportManager()); } - })); - moduleSpecList.add( + }), ModuleSpec.nativeModuleSpec( UIManagerModule.class, new Provider() { @@ -164,8 +131,7 @@ public NativeModule get() { public NativeModule get() { return createUIManager(reactContext); } - })); - moduleSpecList.add( + }), ModuleSpec.nativeModuleSpec( DeviceInfoModule.class, new Provider() { @@ -174,29 +140,6 @@ public NativeModule get() { return new DeviceInfoModule(reactContext); } })); - - if (ReactBuildConfig.DEBUG) { - moduleSpecList.add( - ModuleSpec.nativeModuleSpec( - JSCHeapCapture.class, - new Provider() { - @Override - public NativeModule get() { - return new JSCHeapCapture(reactContext); - } - })); - moduleSpecList.add( - ModuleSpec.nativeModuleSpec( - JSCSamplingProfiler.class, - new Provider() { - @Override - public NativeModule get() { - return new JSCSamplingProfiler(reactContext); - } - })); - } - - return moduleSpecList; } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index ab850f9cf521fe..bc2a500ac818dc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -152,42 +152,10 @@ public interface ReactInstanceEventListener { // Identifies whether the instance manager destroy function is in process, // while true any spawned create thread should wait for proper clean up before initializing private volatile Boolean mHasStartedDestroying = false; - private final UIImplementationProvider mUIImplementationProvider; private final MemoryPressureRouter mMemoryPressureRouter; private final @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler; private final boolean mLazyNativeModulesEnabled; - private final boolean mLazyViewManagersEnabled; private final boolean mDelayViewManagerClassLoadsEnabled; - private final boolean mUseSeparateUIBackgroundThread; - private final int mMinNumShakes; - private final int mMinTimeLeftInFrameForNonBatchedOperationMs; - - private final ReactInstanceDevCommandsHandler mDevInterface = - new ReactInstanceDevCommandsHandler() { - - @Override - public void onReloadWithJSDebugger(JavaJSExecutor.Factory jsExecutorFactory) { - ReactInstanceManager.this.onReloadWithJSDebugger(jsExecutorFactory); - } - - @Override - public void onJSBundleLoadedFromServer() { - ReactInstanceManager.this.onJSBundleLoadedFromServer(); - } - - @Override - public void toggleElementInspector() { - ReactInstanceManager.this.toggleElementInspector(); - } - }; - - private final DefaultHardwareBackBtnHandler mBackBtnHandler = - new DefaultHardwareBackBtnHandler() { - @Override - public void invokeDefaultOnBackPressed() { - ReactInstanceManager.this.invokeDefaultOnBackPressed(); - } - }; private class ReactContextInitParams { private final JavaScriptExecutorFactory mJsExecutorFactory; @@ -234,10 +202,7 @@ public static ReactInstanceManagerBuilder builder() { boolean lazyViewManagersEnabled, boolean delayViewManagerClassLoadsEnabled, @Nullable DevBundleDownloadListener devBundleDownloadListener, - boolean useSeparateUIBackgroundThread, int minNumShakes, - boolean splitPackagesEnabled, - boolean useOnlyDefaultPackages, int minTimeLeftInFrameForNonBatchedOperationMs) { Log.d(ReactConstants.TAG, "ReactInstanceManager.ctor()"); initializeSoLoaderIfNecessary(applicationContext); @@ -253,49 +218,38 @@ public static ReactInstanceManagerBuilder builder() { mPackages = new ArrayList<>(); mInitFunctions = new ArrayList<>(); mUseDeveloperSupport = useDeveloperSupport; - mDevSupportManager = DevSupportManagerFactory.create( - applicationContext, - mDevInterface, - mJSMainModulePath, - useDeveloperSupport, - redBoxHandler, - devBundleDownloadListener, - minNumShakes); + mDevSupportManager = + DevSupportManagerFactory.create( + applicationContext, + createDevInterface(), + mJSMainModulePath, + useDeveloperSupport, + redBoxHandler, + devBundleDownloadListener, + minNumShakes); mBridgeIdleDebugListener = bridgeIdleDebugListener; mLifecycleState = initialLifecycleState; - mUIImplementationProvider = uiImplementationProvider; mMemoryPressureRouter = new MemoryPressureRouter(applicationContext); mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler; mLazyNativeModulesEnabled = lazyNativeModulesEnabled; - mLazyViewManagersEnabled = lazyViewManagersEnabled; mDelayViewManagerClassLoadsEnabled = delayViewManagerClassLoadsEnabled; - mMinTimeLeftInFrameForNonBatchedOperationMs = minTimeLeftInFrameForNonBatchedOperationMs; - mUseSeparateUIBackgroundThread = useSeparateUIBackgroundThread; - mMinNumShakes = minNumShakes; synchronized (mPackages) { - if (!splitPackagesEnabled) { - CoreModulesPackage coreModulesPackage = - new CoreModulesPackage( - this, - mBackBtnHandler, - mUIImplementationProvider, - mLazyViewManagersEnabled, - mMinTimeLeftInFrameForNonBatchedOperationMs); - mPackages.add(coreModulesPackage); - } else { - PrinterHolder.getPrinter().logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: Use Split Packages"); - mPackages.add(new BridgeCorePackage(this, mBackBtnHandler)); - if (mUseDeveloperSupport) { - mPackages.add(new DebugCorePackage()); - } - if (!useOnlyDefaultPackages) { - mPackages.add( - new ReactNativeCorePackage( - this, - mUIImplementationProvider, - mLazyViewManagersEnabled, - mMinTimeLeftInFrameForNonBatchedOperationMs)); - } + PrinterHolder.getPrinter() + .logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: Use Split Packages"); + mPackages.add( + new CoreModulesPackage( + this, + new DefaultHardwareBackBtnHandler() { + @Override + public void invokeDefaultOnBackPressed() { + ReactInstanceManager.this.invokeDefaultOnBackPressed(); + } + }, + uiImplementationProvider, + lazyViewManagersEnabled, + minTimeLeftInFrameForNonBatchedOperationMs)); + if (mUseDeveloperSupport) { + mPackages.add(new DebugCorePackage()); } mPackages.addAll(packages); } @@ -307,6 +261,25 @@ public static ReactInstanceManagerBuilder builder() { } } + private ReactInstanceDevCommandsHandler createDevInterface() { + return new ReactInstanceDevCommandsHandler() { + @Override + public void onReloadWithJSDebugger(JavaJSExecutor.Factory jsExecutorFactory) { + ReactInstanceManager.this.onReloadWithJSDebugger(jsExecutorFactory); + } + + @Override + public void onJSBundleLoadedFromServer() { + ReactInstanceManager.this.onJSBundleLoadedFromServer(); + } + + @Override + public void toggleElementInspector() { + ReactInstanceManager.this.toggleElementInspector(); + } + }; + } + public DevSupportManager getDevSupportManager() { return mDevSupportManager; } @@ -791,8 +764,14 @@ public List createAllViewManagers( } public @Nullable ViewManager createViewManager(String viewManagerName) { - ReactApplicationContext context = - Assertions.assertNotNull((ReactApplicationContext) getCurrentReactContext()); + ReactApplicationContext context; + synchronized (mReactContextLock) { + context = (ReactApplicationContext) getCurrentReactContext(); + if (context == null || !context.hasActiveCatalystInstance()) { + return null; + } + } + synchronized (mPackages) { for (ReactPackage reactPackage : mPackages) { if (reactPackage instanceof ViewManagerOnDemandReactPackage) { @@ -808,9 +787,15 @@ public List createAllViewManagers( return null; } - public List getViewManagerNames() { - ReactApplicationContext context = - Assertions.assertNotNull((ReactApplicationContext) getCurrentReactContext()); + public @Nullable List getViewManagerNames() { + ReactApplicationContext context; + synchronized(mReactContextLock) { + context = (ReactApplicationContext) getCurrentReactContext(); + if (context == null || !context.hasActiveCatalystInstance()) { + return null; + } + } + synchronized (mPackages) { Set uniqueNames = new HashSet<>(); for (ReactPackage reactPackage : mPackages) { @@ -852,10 +837,6 @@ public LifecycleState getLifecycleState() { return mLifecycleState; } - public int getMinNumShakes() { - return mMinNumShakes; - } - @ThreadConfined(UI) private void onReloadWithJSDebugger(JavaJSExecutor.Factory jsExecutorFactory) { Log.d(ReactConstants.TAG, "ReactInstanceManager.onReloadWithJSDebugger()"); @@ -1017,15 +998,6 @@ public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); } }); - if (mUseSeparateUIBackgroundThread) { - reactContext.runOnUiBackgroundQueueThread( - new Runnable() { - @Override - public void run() { - Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); - } - }); - } } private void attachRootViewToInstance( @@ -1102,9 +1074,7 @@ private ReactApplicationContext createReactContext( ? mNativeModuleCallExceptionHandler : mDevSupportManager; CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder() - .setReactQueueConfigurationSpec(mUseSeparateUIBackgroundThread ? - ReactQueueConfigurationSpec.createWithSeparateUIBackgroundThread() : - ReactQueueConfigurationSpec.createDefault()) + .setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault()) .setJSExecutor(jsExecutor) .setRegistry(nativeModuleRegistry) .setJSBundleLoader(jsBundleLoader) diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java index 59eaa71e724161..f7fc31e2c62d77 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java @@ -46,10 +46,7 @@ public class ReactInstanceManagerBuilder { private boolean mDelayViewManagerClassLoadsEnabled; private @Nullable DevBundleDownloadListener mDevBundleDownloadListener; private @Nullable JavaScriptExecutorFactory mJavaScriptExecutorFactory; - private boolean mUseSeparateUIBackgroundThread; private int mMinNumShakes = 1; - private boolean mEnableSplitPackage; - private boolean mUseOnlyDefaultPackages; private int mMinTimeLeftInFrameForNonBatchedOperationMs = -1; /* package protected */ ReactInstanceManagerBuilder() { @@ -216,27 +213,11 @@ public ReactInstanceManagerBuilder setDevBundleDownloadListener( return this; } - public ReactInstanceManagerBuilder setUseSeparateUIBackgroundThread( - boolean useSeparateUIBackgroundThread) { - mUseSeparateUIBackgroundThread = useSeparateUIBackgroundThread; - return this; - } - public ReactInstanceManagerBuilder setMinNumShakes(int minNumShakes) { mMinNumShakes = minNumShakes; return this; } - public ReactInstanceManagerBuilder setEnableSplitPackage(boolean enableSplitPackage) { - mEnableSplitPackage = enableSplitPackage; - return this; - } - - public ReactInstanceManagerBuilder setUseOnlyDefaultPackages(boolean useOnlyDefaultPackages) { - mUseOnlyDefaultPackages = useOnlyDefaultPackages; - return this; - } - public ReactInstanceManagerBuilder setMinTimeLeftInFrameForNonBatchedOperationMs( int minTimeLeftInFrameForNonBatchedOperationMs) { mMinTimeLeftInFrameForNonBatchedOperationMs = minTimeLeftInFrameForNonBatchedOperationMs; @@ -298,10 +279,7 @@ public ReactInstanceManager build() { mLazyViewManagersEnabled, mDelayViewManagerClassLoadsEnabled, mDevBundleDownloadListener, - mUseSeparateUIBackgroundThread, mMinNumShakes, - mEnableSplitPackage, - mUseOnlyDefaultPackages, mMinTimeLeftInFrameForNonBatchedOperationMs); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactNativeCorePackage.java b/ReactAndroid/src/main/java/com/facebook/react/ReactNativeCorePackage.java deleted file mode 100644 index 0e7b36edbf7b11..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactNativeCorePackage.java +++ /dev/null @@ -1,114 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -package com.facebook.react; - -import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_END; -import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_START; - -import com.facebook.react.bridge.ModuleSpec; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactMarker; -import com.facebook.react.module.annotations.ReactModuleList; -import com.facebook.react.module.model.ReactModuleInfoProvider; -import com.facebook.react.uimanager.UIImplementationProvider; -import com.facebook.react.uimanager.UIManagerModule; -import com.facebook.react.uimanager.ViewManager; -import com.facebook.systrace.Systrace; -import java.util.Collections; -import java.util.List; -import javax.annotation.Nullable; -import javax.inject.Provider; - -/** - * Package defining core framework modules for initializing ReactNative (e.g. UIManager). It should be used for modules that - * require special integration with other framework parts (e.g. with the list of packages to load - * view managers from). - */ -@ReactModuleList( - nativeModules = { - UIManagerModule.class, - } -) -public class ReactNativeCorePackage extends LazyReactPackage { - - private final ReactInstanceManager mReactInstanceManager; - private final UIImplementationProvider mUIImplementationProvider; - private final boolean mLazyViewManagersEnabled; - private final int mMinTimeLeftInFrameForNonBatchedOperationMs; - - public ReactNativeCorePackage( - ReactInstanceManager reactInstanceManager, - UIImplementationProvider uiImplementationProvider, - boolean lazyViewManagersEnabled, - int minTimeLeftInFrameForNonBatchedOperationMs) { - mReactInstanceManager = reactInstanceManager; - mUIImplementationProvider = uiImplementationProvider; - mLazyViewManagersEnabled = lazyViewManagersEnabled; - mMinTimeLeftInFrameForNonBatchedOperationMs = minTimeLeftInFrameForNonBatchedOperationMs; - } - - @Override - public List getNativeModules(final ReactApplicationContext reactContext) { - return Collections.singletonList( - ModuleSpec.nativeModuleSpec( - UIManagerModule.class, - new Provider() { - @Override - public NativeModule get() { - return createUIManager(reactContext); - } - })); - } - - @Override - public ReactModuleInfoProvider getReactModuleInfoProvider() { - // This has to be done via reflection or we break open source. - ReactModuleInfoProvider reactModuleInfoProvider = - LazyReactPackage.getReactModuleInfoProviderViaReflection(this); - return reactModuleInfoProvider; - } - - private UIManagerModule createUIManager(final ReactApplicationContext reactContext) { - ReactMarker.logMarker(CREATE_UI_MANAGER_MODULE_START); - Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "createUIManagerModule"); - try { - if (mLazyViewManagersEnabled) { - UIManagerModule.ViewManagerResolver viewManagerResolver = - new UIManagerModule.ViewManagerResolver() { - @Override - public @Nullable ViewManager getViewManager(String viewManagerName) { - return mReactInstanceManager.createViewManager(viewManagerName); - } - - @Override - public List getViewManagerNames() { - return mReactInstanceManager.getViewManagerNames(); - } - }; - - return new UIManagerModule( - reactContext, - viewManagerResolver, - mUIImplementationProvider, - mMinTimeLeftInFrameForNonBatchedOperationMs); - } else { - return new UIManagerModule( - reactContext, - mReactInstanceManager.createAllViewManagers(reactContext), - mUIImplementationProvider, - mMinTimeLeftInFrameForNonBatchedOperationMs); - } - } finally { - Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); - ReactMarker.logMarker(CREATE_UI_MANAGER_MODULE_END); - } - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java index 87c5f5902468e0..05cfc8d776ed80 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java @@ -330,7 +330,7 @@ private void updateRootLayoutSpecs(final int widthMeasureSpec, final int heightM } final ReactContext reactApplicationContext = mReactInstanceManager.getCurrentReactContext(); if (reactApplicationContext != null) { - reactApplicationContext.runUIBackgroundRunnable( + reactApplicationContext.runOnNativeModulesQueueThread( new GuardedRunnable(reactApplicationContext) { @Override public void runGuarded() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/ViewManagerOnDemandReactPackage.java b/ReactAndroid/src/main/java/com/facebook/react/ViewManagerOnDemandReactPackage.java index 1e0ee9570bf774..e78d0ca2f13cdf 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ViewManagerOnDemandReactPackage.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ViewManagerOnDemandReactPackage.java @@ -21,7 +21,7 @@ public interface ViewManagerOnDemandReactPackage { * * @param loadClasses defines if View Managers classes should be loaded or be avoided. */ - List getViewManagerNames(ReactApplicationContext reactContext, boolean loadClasses); + @Nullable List getViewManagerNames(ReactApplicationContext reactContext, boolean loadClasses); /** * Creates and returns a ViewManager with a specific name {@param viewManagerName}. It's up to an * implementing package how to interpret the name. diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/InterpolationAnimatedNode.java b/ReactAndroid/src/main/java/com/facebook/react/animated/InterpolationAnimatedNode.java index 4f9e5fbc7b974d..6c38e12e229f29 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/InterpolationAnimatedNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/InterpolationAnimatedNode.java @@ -1,9 +1,15 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. All rights reserved. + * + *

This source code is licensed under the BSD-style license found in the LICENSE file in the root + * directory of this source tree. An additional grant of patent rights can be found in the PATENTS + * file in the same directory. + */ package com.facebook.react.animated; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; - import javax.annotation.Nullable; /** @@ -133,8 +139,9 @@ public void onDetachedFromNode(AnimatedNode parent) { @Override public void update() { if (mParent == null) { - throw new IllegalStateException("Trying to update interpolation node that has not been " + - "attached to the parent"); + // The graph is in the middle of being created, just skip this + // unattached node. + return; } mValue = interpolate(mParent.getValue(), mInputRange, mOutputRange, mExtrapolateLeft, mExtrapolateRight); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java index 518b9d32be3c8d..29f03a1a17c1e0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java @@ -86,6 +86,9 @@ void callFunction( */ void removeBridgeIdleDebugListener(NotThreadSafeBridgeIdleDebugListener listener); + /** This method registers the file path of an additional JS segment by its ID. */ + void registerSegment(int segmentId, String path); + @VisibleForTesting void setGlobalVariable(String propName, String jsonValue); diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java index c0aacb67a2a21d..7afc565c2f9418 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java @@ -83,7 +83,6 @@ public String toString() { private final NativeModuleRegistry mNativeModuleRegistry; private final NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler; private final MessageQueueThread mNativeModulesQueueThread; - private final @Nullable MessageQueueThread mUIBackgroundQueueThread; private boolean mInitialized = false; private volatile boolean mAcceptCalls = false; @@ -114,7 +113,6 @@ private CatalystInstanceImpl( mJSBundleLoader = jsBundleLoader; mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler; mNativeModulesQueueThread = mReactQueueConfiguration.getNativeModulesQueueThread(); - mUIBackgroundQueueThread = mReactQueueConfiguration.getUIBackgroundQueueThread(); mTraceListener = new JSProfilerTraceListener(this); Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge before initializeBridge"); @@ -123,7 +121,6 @@ private CatalystInstanceImpl( jsExecutor, mReactQueueConfiguration.getJSQueueThread(), mNativeModulesQueueThread, - mUIBackgroundQueueThread, mNativeModuleRegistry.getJavaModules(this), mNativeModuleRegistry.getCxxModules()); Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge after initializeBridge"); @@ -191,7 +188,6 @@ private native void initializeBridge( JavaScriptExecutor jsExecutor, MessageQueueThread jsQueue, MessageQueueThread moduleQueue, - MessageQueueThread uiBackgroundQueue, Collection javaModules, Collection cxxModules); @@ -210,8 +206,9 @@ private native void initializeBridge( jniSetSourceURL(remoteURL); } - /* package */ void setJsBundlesDirectory(String directoryPath) { - jniSetJsBundlesDirectory(directoryPath); + @Override + public void registerSegment(int segmentId, String path) { + jniRegisterSegment(segmentId, path); } /* package */ void loadScriptFromAssets(AssetManager assetManager, String assetURL, boolean loadSynchronously) { @@ -225,7 +222,7 @@ private native void initializeBridge( } private native void jniSetSourceURL(String sourceURL); - private native void jniSetJsBundlesDirectory(String directoryPath); + private native void jniRegisterSegment(int segmentId, String path); private native void jniLoadScriptFromAssets(AssetManager assetManager, String assetURL, boolean loadSynchronously); private native void jniLoadScriptFromFile(String fileName, String sourceURL, boolean loadSynchronously); diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.java index 0c5476bbfe6448..7700071c55c02a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.java @@ -96,21 +96,6 @@ public String loadScript(CatalystInstanceImpl instance) { }; } - /** - * This loader is used to wrap other loaders and set js bundles directory before executing - * application script. - */ - public static JSBundleLoader createSplitBundlesLoader( - final String jsBundlesDirectory, final JSBundleLoader delegate) { - return new JSBundleLoader() { - @Override - public String loadScript(CatalystInstanceImpl instance) { - instance.setJsBundlesDirectory(jsBundlesDirectory); - return delegate.loadScript(instance); - } - }; - } - /** Loads the script, returning the URL of the source it loaded. */ public abstract String loadScript(CatalystInstanceImpl instance); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java index 4148889d3bf2aa..bac4fdf8a885bb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -44,7 +44,6 @@ public class ReactContext extends ContextWrapper { private @Nullable CatalystInstance mCatalystInstance; private @Nullable LayoutInflater mInflater; private @Nullable MessageQueueThread mUiMessageQueueThread; - private @Nullable MessageQueueThread mUiBackgroundMessageQueueThread; private @Nullable MessageQueueThread mNativeModulesMessageQueueThread; private @Nullable MessageQueueThread mJSMessageQueueThread; private @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler; @@ -69,7 +68,6 @@ public void initializeWithInstance(CatalystInstance catalystInstance) { ReactQueueConfiguration queueConfig = catalystInstance.getReactQueueConfiguration(); mUiMessageQueueThread = queueConfig.getUIQueueThread(); - mUiBackgroundMessageQueueThread = queueConfig.getUIBackgroundQueueThread(); mNativeModulesMessageQueueThread = queueConfig.getNativeModulesQueueThread(); mJSMessageQueueThread = queueConfig.getJSQueueThread(); } @@ -143,16 +141,20 @@ public void addLifecycleEventListener(final LifecycleEventListener listener) { case BEFORE_RESUME: break; case RESUMED: - runOnUiQueueThread(new Runnable() { - @Override - public void run() { - try { - listener.onHostResume(); - } catch (RuntimeException e) { - handleException(e); - } - } - }); + runOnUiQueueThread( + new Runnable() { + @Override + public void run() { + if (!mLifecycleEventListeners.contains(listener)) { + return; + } + try { + listener.onHostResume(); + } catch (RuntimeException e) { + handleException(e); + } + } + }); break; default: throw new RuntimeException("Unhandled lifecycle state."); @@ -269,14 +271,6 @@ public void runOnUiQueueThread(Runnable runnable) { Assertions.assertNotNull(mUiMessageQueueThread).runOnQueue(runnable); } - public void assertOnUiBackgroundQueueThread() { - Assertions.assertNotNull(mUiBackgroundMessageQueueThread).assertIsOnThread(); - } - - public void runOnUiBackgroundQueueThread(Runnable runnable) { - Assertions.assertNotNull(mUiBackgroundMessageQueueThread).runOnQueue(runnable); - } - public void assertOnNativeModulesQueueThread() { Assertions.assertNotNull(mNativeModulesMessageQueueThread).assertIsOnThread(); } @@ -305,26 +299,6 @@ public void runOnJSQueueThread(Runnable runnable) { Assertions.assertNotNull(mJSMessageQueueThread).runOnQueue(runnable); } - public boolean hasUIBackgroundRunnableThread() { - return mUiBackgroundMessageQueueThread != null; - } - - public void assertOnUIBackgroundOrNativeModulesThread() { - if (mUiBackgroundMessageQueueThread == null) { - assertOnNativeModulesQueueThread(); - } else { - assertOnUiBackgroundQueueThread(); - } - } - - public void runUIBackgroundRunnable(Runnable runnable) { - if (mUiBackgroundMessageQueueThread == null) { - runOnNativeModulesQueueThread(runnable); - } else { - runOnUiBackgroundQueueThread(runnable); - } - } - /** * Passes the given exception to the current * {@link com.facebook.react.bridge.NativeModuleCallExceptionHandler} if one exists, rethrowing diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfiguration.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfiguration.java index 68a42a82f1fabc..b5b44a9a2c51a0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfiguration.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfiguration.java @@ -9,7 +9,6 @@ package com.facebook.react.bridge.queue; -import javax.annotation.Nullable; /** * Specifies which {@link MessageQueueThread}s must be used to run the various contexts of @@ -22,8 +21,6 @@ */ public interface ReactQueueConfiguration { MessageQueueThread getUIQueueThread(); - @Nullable - MessageQueueThread getUIBackgroundQueueThread(); MessageQueueThread getNativeModulesQueueThread(); MessageQueueThread getJSQueueThread(); void destroy(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationImpl.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationImpl.java index 05b37c5977f29c..60d7e0eb164302 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationImpl.java @@ -9,8 +9,6 @@ package com.facebook.react.bridge.queue; -import javax.annotation.Nullable; - import java.util.Map; import android.os.Looper; @@ -20,17 +18,14 @@ public class ReactQueueConfigurationImpl implements ReactQueueConfiguration { private final MessageQueueThreadImpl mUIQueueThread; - private final @Nullable MessageQueueThreadImpl mUIBackgroundQueueThread; private final MessageQueueThreadImpl mNativeModulesQueueThread; private final MessageQueueThreadImpl mJSQueueThread; private ReactQueueConfigurationImpl( - MessageQueueThreadImpl uiQueueThread, - @Nullable MessageQueueThreadImpl uiBackgroundQueueThread, - MessageQueueThreadImpl nativeModulesQueueThread, - MessageQueueThreadImpl jsQueueThread) { + MessageQueueThreadImpl uiQueueThread, + MessageQueueThreadImpl nativeModulesQueueThread, + MessageQueueThreadImpl jsQueueThread) { mUIQueueThread = uiQueueThread; - mUIBackgroundQueueThread = uiBackgroundQueueThread; mNativeModulesQueueThread = nativeModulesQueueThread; mJSQueueThread = jsQueueThread; } @@ -40,11 +35,6 @@ public MessageQueueThread getUIQueueThread() { return mUIQueueThread; } - @Override - public @Nullable MessageQueueThread getUIBackgroundQueueThread() { - return mUIBackgroundQueueThread; - } - @Override public MessageQueueThread getNativeModulesQueueThread() { return mNativeModulesQueueThread; @@ -60,10 +50,6 @@ public MessageQueueThread getJSQueueThread() { * is destroyed so that we shut down the proper queue threads. */ public void destroy() { - if (mUIBackgroundQueueThread != null && - mUIBackgroundQueueThread.getLooper() != Looper.getMainLooper()) { - mUIBackgroundQueueThread.quitSynchronous(); - } if (mNativeModulesQueueThread.getLooper() != Looper.getMainLooper()) { mNativeModulesQueueThread.quitSynchronous(); } @@ -94,16 +80,8 @@ public static ReactQueueConfigurationImpl create( MessageQueueThreadImpl.create(spec.getNativeModulesQueueThreadSpec(), exceptionHandler); } - MessageQueueThreadImpl uiBackgroundThread = - specsToThreads.get(spec.getUIBackgroundQueueThreadSpec()); - if (uiBackgroundThread == null && spec.getUIBackgroundQueueThreadSpec() != null) { - uiBackgroundThread = - MessageQueueThreadImpl.create(spec.getUIBackgroundQueueThreadSpec(), exceptionHandler); - } - return new ReactQueueConfigurationImpl( uiThread, - uiBackgroundThread, nativeModulesThread, jsThread); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationSpec.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationSpec.java index 6b23bfd716431d..a112f217c608de 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationSpec.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationSpec.java @@ -25,23 +25,16 @@ public class ReactQueueConfigurationSpec { private static final long LEGACY_STACK_SIZE_BYTES = 2000000; - private final @Nullable MessageQueueThreadSpec mUIBackgroundQueueThreadSpec; private final MessageQueueThreadSpec mNativeModulesQueueThreadSpec; private final MessageQueueThreadSpec mJSQueueThreadSpec; private ReactQueueConfigurationSpec( - @Nullable MessageQueueThreadSpec uiBackgroundQueueThreadSpec, MessageQueueThreadSpec nativeModulesQueueThreadSpec, MessageQueueThreadSpec jsQueueThreadSpec) { - mUIBackgroundQueueThreadSpec = uiBackgroundQueueThreadSpec; mNativeModulesQueueThreadSpec = nativeModulesQueueThreadSpec; mJSQueueThreadSpec = jsQueueThreadSpec; } - public @Nullable MessageQueueThreadSpec getUIBackgroundQueueThreadSpec() { - return mUIBackgroundQueueThreadSpec; - } - public MessageQueueThreadSpec getNativeModulesQueueThreadSpec() { return mNativeModulesQueueThreadSpec; } @@ -64,32 +57,11 @@ public static ReactQueueConfigurationSpec createDefault() { .build(); } - public static ReactQueueConfigurationSpec createWithSeparateUIBackgroundThread() { - MessageQueueThreadSpec spec = Build.VERSION.SDK_INT < 21 ? - MessageQueueThreadSpec.newBackgroundThreadSpec("native_modules", LEGACY_STACK_SIZE_BYTES) : - MessageQueueThreadSpec.newBackgroundThreadSpec("native_modules"); - return builder() - .setJSQueueThreadSpec(MessageQueueThreadSpec.newBackgroundThreadSpec("js")) - .setNativeModulesQueueThreadSpec(spec) - .setUIBackgroundQueueThreadSpec( - MessageQueueThreadSpec.newUIBackgroundTreadSpec("ui_background")) - .build(); - } - public static class Builder { - private @Nullable MessageQueueThreadSpec mUIBackgroundQueueSpec; private @Nullable MessageQueueThreadSpec mNativeModulesQueueSpec; private @Nullable MessageQueueThreadSpec mJSQueueSpec; - public Builder setUIBackgroundQueueThreadSpec(MessageQueueThreadSpec spec) { - Assertions.assertCondition( - mUIBackgroundQueueSpec == null, - "Setting UI background queue multiple times!"); - mUIBackgroundQueueSpec = spec; - return this; - } - public Builder setNativeModulesQueueThreadSpec(MessageQueueThreadSpec spec) { Assertions.assertCondition( mNativeModulesQueueSpec == null, @@ -106,7 +78,6 @@ public Builder setJSQueueThreadSpec(MessageQueueThreadSpec spec) { public ReactQueueConfigurationSpec build() { return new ReactQueueConfigurationSpec( - mUIBackgroundQueueSpec, Assertions.assertNotNull(mNativeModulesQueueSpec), Assertions.assertNotNull(mJSQueueSpec)); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java index 5f61917cc9e5fe..3218d1e9de2402 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java @@ -9,24 +9,23 @@ package com.facebook.react.devsupport; +import android.util.JsonReader; +import android.util.JsonToken; import android.util.Log; -import javax.annotation.Nullable; - +import com.facebook.common.logging.FLog; +import com.facebook.infer.annotation.Assertions; +import com.facebook.react.common.DebugServerException; +import com.facebook.react.common.ReactConstants; +import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStreamReader; +import java.util.LinkedHashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; - -import com.facebook.common.logging.FLog; -import com.facebook.infer.annotation.Assertions; -import com.facebook.react.common.ReactConstants; -import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; -import com.facebook.react.common.DebugServerException; - -import org.json.JSONException; -import org.json.JSONObject; - +import javax.annotation.Nullable; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; @@ -36,6 +35,8 @@ import okio.BufferedSource; import okio.Okio; import okio.Sink; +import org.json.JSONException; +import org.json.JSONObject; public class BundleDownloader { private static final String TAG = "BundleDownloader"; @@ -45,6 +46,11 @@ public class BundleDownloader { private final OkHttpClient mClient; + private final LinkedHashMap mPreModules = new LinkedHashMap<>(); + private final LinkedHashMap mDeltaModules = new LinkedHashMap<>(); + private final LinkedHashMap mPostModules = new LinkedHashMap<>(); + + private @Nullable String mDeltaId; private @Nullable Call mDownloadBundleFromURLCall; public static class BundleInfo { @@ -102,13 +108,22 @@ public void downloadBundleFromURL( final File outputFile, final String bundleURL, final @Nullable BundleInfo bundleInfo) { - final Request request = new Request.Builder() - .url(bundleURL) - // FIXME: there is a bug that makes MultipartStreamReader to never find the end of the - // multipart message. This temporarily disables the multipart mode to work around it, but - // it means there is no progress bar displayed in the React Native overlay anymore. - //.addHeader("Accept", "multipart/mixed") - .build(); + + String finalUrl = bundleURL; + + if (isDeltaUrl(bundleURL) && mDeltaId != null) { + finalUrl += "&deltaBundleId=" + mDeltaId; + } + + final Request request = + new Request.Builder() + .url(finalUrl) + // FIXME: there is a bug that makes MultipartStreamReader to never find the end of the + // multipart message. This temporarily disables the multipart mode to work around it, + // but + // it means there is no progress bar displayed in the React Native overlay anymore. + // .addHeader("Accept", "multipart/mixed") + .build(); mDownloadBundleFromURLCall = Assertions.assertNotNull(mClient.newCall(request)); mDownloadBundleFromURLCall.enqueue(new Callback() { @Override @@ -161,6 +176,7 @@ public void execute(Map headers, Buffer body, boolean finished) if (!headers.containsKey("Content-Type") || !headers.get("Content-Type").equals("application/json")) { return; } + try { JSONObject progress = new JSONObject(body.readUtf8()); String status = null; @@ -202,14 +218,15 @@ public void cancelDownloadBundleFromURL() { } } - private static void processBundleResult( + private void processBundleResult( String url, int statusCode, okhttp3.Headers headers, BufferedSource body, File outputFile, BundleInfo bundleInfo, - DevBundleDownloadListener callback) throws IOException { + DevBundleDownloadListener callback) + throws IOException { // Check for server errors. If the server error has the expected form, fail with more info. if (statusCode != 200) { String bodyString = body.readUtf8(); @@ -232,9 +249,32 @@ private static void processBundleResult( } File tmpFile = new File(outputFile.getPath() + ".tmp"); + + boolean bundleUpdated; + + if (isDeltaUrl(url)) { + // If the bundle URL has the delta extension, we need to use the delta patching logic. + bundleUpdated = storeDeltaInFile(body, tmpFile); + } else { + resetDeltaCache(); + bundleUpdated = storePlainJSInFile(body, tmpFile); + } + + if (bundleUpdated) { + // If we have received a new bundle from the server, move it to its final destination. + if (!tmpFile.renameTo(outputFile)) { + throw new IOException("Couldn't rename " + tmpFile + " to " + outputFile); + } + } + + callback.onSuccess(); + } + + private static boolean storePlainJSInFile(BufferedSource body, File outputFile) + throws IOException { Sink output = null; try { - output = Okio.sink(tmpFile); + output = Okio.sink(outputFile); body.readAll(output); } finally { if (output != null) { @@ -242,11 +282,102 @@ private static void processBundleResult( } } - if (tmpFile.renameTo(outputFile)) { - callback.onSuccess(); - } else { - throw new IOException("Couldn't rename " + tmpFile + " to " + outputFile); + return true; + } + + private boolean storeDeltaInFile(BufferedSource body, File outputFile) throws IOException { + + JsonReader jsonReader = new JsonReader(new InputStreamReader(body.inputStream())); + + jsonReader.beginObject(); + + int numChangedModules = 0; + + while (jsonReader.hasNext()) { + String name = jsonReader.nextName(); + if (name.equals("id")) { + mDeltaId = jsonReader.nextString(); + } else if (name.equals("pre")) { + numChangedModules += patchDelta(jsonReader, mPreModules); + } else if (name.equals("post")) { + numChangedModules += patchDelta(jsonReader, mPostModules); + } else if (name.equals("delta")) { + numChangedModules += patchDelta(jsonReader, mDeltaModules); + } else { + jsonReader.skipValue(); + } + } + + jsonReader.endObject(); + jsonReader.close(); + + if (numChangedModules == 0) { + // If we receive an empty delta, we don't need to save the file again (it'll have the + // same content). + return false; } + + FileOutputStream fileOutputStream = new FileOutputStream(outputFile); + + try { + for (byte[] code : mPreModules.values()) { + fileOutputStream.write(code); + fileOutputStream.write('\n'); + } + + for (byte[] code : mDeltaModules.values()) { + fileOutputStream.write(code); + fileOutputStream.write('\n'); + } + + for (byte[] code : mPostModules.values()) { + fileOutputStream.write(code); + fileOutputStream.write('\n'); + } + } finally { + fileOutputStream.flush(); + fileOutputStream.close(); + } + + return true; + } + + private static int patchDelta(JsonReader jsonReader, LinkedHashMap map) + throws IOException { + jsonReader.beginArray(); + + int numModules = 0; + while (jsonReader.hasNext()) { + jsonReader.beginArray(); + + int moduleId = jsonReader.nextInt(); + + if (jsonReader.peek() == JsonToken.NULL) { + jsonReader.skipValue(); + map.remove(moduleId); + } else { + map.put(moduleId, jsonReader.nextString().getBytes()); + } + + jsonReader.endArray(); + numModules++; + } + + jsonReader.endArray(); + + return numModules; + } + + private void resetDeltaCache() { + mDeltaId = null; + + mDeltaModules.clear(); + mPreModules.clear(); + mPostModules.clear(); + } + + private static boolean isDeltaUrl(String bundleUrl) { + return bundleUrl.indexOf(".delta?") != -1; } private static void populateBundleInfo(String url, okhttp3.Headers headers, BundleInfo bundleInfo) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java index bfd8d0403f0e05..53fb08e5b04cbb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java @@ -9,12 +9,10 @@ package com.facebook.react.devsupport; -import javax.annotation.Nullable; - +import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; - import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.react.modules.debug.interfaces.DeveloperSettings; import com.facebook.react.packagerconnection.PackagerConnectionSettings; @@ -32,6 +30,7 @@ public class DevInternalSettings implements private static final String PREFS_FPS_DEBUG_KEY = "fps_debug"; private static final String PREFS_JS_DEV_MODE_DEBUG_KEY = "js_dev_mode_debug"; private static final String PREFS_JS_MINIFY_DEBUG_KEY = "js_minify_debug"; + private static final String PREFS_JS_BUNDLE_DELTAS_KEY = "js_bundle_deltas"; private static final String PREFS_ANIMATIONS_DEBUG_KEY = "animations_debug"; private static final String PREFS_RELOAD_ON_JS_CHANGE_KEY = "reload_on_js_change"; private static final String PREFS_INSPECTOR_DEBUG_KEY = "inspector_debug"; @@ -81,10 +80,11 @@ public boolean isJSMinifyEnabled() { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (mListener != null) { - if (PREFS_FPS_DEBUG_KEY.equals(key) || - PREFS_RELOAD_ON_JS_CHANGE_KEY.equals(key) || - PREFS_JS_DEV_MODE_DEBUG_KEY.equals(key) || - PREFS_JS_MINIFY_DEBUG_KEY.equals(key)) { + if (PREFS_FPS_DEBUG_KEY.equals(key) + || PREFS_RELOAD_ON_JS_CHANGE_KEY.equals(key) + || PREFS_JS_DEV_MODE_DEBUG_KEY.equals(key) + || PREFS_JS_BUNDLE_DELTAS_KEY.equals(key) + || PREFS_JS_MINIFY_DEBUG_KEY.equals(key)) { mListener.onInternalSettingsChanged(); } } @@ -114,6 +114,16 @@ public void setElementInspectorEnabled(boolean enabled) { mPreferences.edit().putBoolean(PREFS_INSPECTOR_DEBUG_KEY, enabled).apply(); } + @SuppressLint("SharedPreferencesUse") + public boolean isBundleDeltasEnabled() { + return mPreferences.getBoolean(PREFS_JS_BUNDLE_DELTAS_KEY, false); + } + + @SuppressLint("SharedPreferencesUse") + public void setBundleDeltasEnabled(boolean enabled) { + mPreferences.edit().putBoolean(PREFS_JS_BUNDLE_DELTAS_KEY, enabled).apply(); + } + @Override public boolean isRemoteJSDebugEnabled() { return mPreferences.getBoolean(PREFS_REMOTE_JS_DEBUG_KEY, false); diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java index 16204c6eeb377b..0bea52b3fa8be6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java @@ -63,10 +63,8 @@ public class DevServerHelper { private static final String RELOAD_APP_ACTION_SUFFIX = ".RELOAD_APP_ACTION"; private static final String BUNDLE_URL_FORMAT = - "http://%s/%s.bundle?platform=android&dev=%s&minify=%s"; + "http://%s/%s.%s?platform=android&dev=%s&minify=%s"; private static final String RESOURCE_URL_FORMAT = "http://%s/%s"; - private static final String SOURCE_MAP_URL_FORMAT = - BUNDLE_URL_FORMAT.replaceFirst("\\.bundle", ".map"); private static final String LAUNCH_JS_DEVTOOLS_COMMAND_URL_FORMAT = "http://%s/launch-js-devtools"; private static final String ONCHANGE_ENDPOINT_URL_FORMAT = @@ -357,11 +355,15 @@ private boolean getJSMinifyMode() { } private static String createBundleURL( - String host, - String jsModulePath, - boolean devMode, - boolean jsMinify) { - return String.format(Locale.US, BUNDLE_URL_FORMAT, host, jsModulePath, devMode, jsMinify); + String host, String jsModulePath, boolean devMode, boolean jsMinify, boolean useDeltas) { + return String.format( + Locale.US, + BUNDLE_URL_FORMAT, + host, + jsModulePath, + useDeltas ? "delta" : "bundle", + devMode, + jsMinify); } private static String createResourceURL(String host, String resourcePath) { @@ -378,10 +380,11 @@ private static String createOpenStackFrameURL(String host) { public String getDevServerBundleURL(final String jsModulePath) { return createBundleURL( - mSettings.getPackagerConnectionSettings().getDebugServerHost(), - jsModulePath, - getDevMode(), - getJSMinifyMode()); + mSettings.getPackagerConnectionSettings().getDebugServerHost(), + jsModulePath, + getDevMode(), + getJSMinifyMode(), + mSettings.isBundleDeltasEnabled()); } public void isPackagerRunning(final PackagerStatusCallback callback) { @@ -540,9 +543,10 @@ public void onResponse(Call call, Response response) throws IOException { public String getSourceMapUrl(String mainModuleName) { return String.format( Locale.US, - SOURCE_MAP_URL_FORMAT, + BUNDLE_URL_FORMAT, mSettings.getPackagerConnectionSettings().getDebugServerHost(), mainModuleName, + "map", getDevMode(), getJSMinifyMode()); } @@ -553,6 +557,7 @@ public String getSourceUrl(String mainModuleName) { BUNDLE_URL_FORMAT, mSettings.getPackagerConnectionSettings().getDebugServerHost(), mainModuleName, + mSettings.isBundleDeltasEnabled() ? "delta" : "bundle", getDevMode(), getJSMinifyMode()); } @@ -562,10 +567,7 @@ public String getJSBundleURLForRemoteDebugging(String mainModuleName) { // same as the one needed to connect to the same server from the JavaScript proxy running on the // host itself. return createBundleURL( - getHostForJSProxy(), - mainModuleName, - getDevMode(), - getJSMinifyMode()); + getHostForJSProxy(), mainModuleName, getDevMode(), getJSMinifyMode(), false); } /** diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java index 0cc918d9d28557..58c57387eba9b5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java @@ -124,6 +124,7 @@ private void registerReceiver() { filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); getReactApplicationContext().registerReceiver(mConnectivityBroadcastReceiver, filter); mConnectivityBroadcastReceiver.setRegistered(true); + updateAndSendConnectionType(); } private void unregisterReceiver() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java index 297cd1ef4ff2fc..58fd605459397c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java @@ -235,8 +235,9 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) { String contentEncoding = requestHeaders.get(CONTENT_ENCODING_HEADER_NAME); requestBuilder.headers(requestHeaders); + RequestBody requestBody; if (data == null) { - requestBuilder.method(method, RequestBodyUtil.getEmptyBody(method)); + requestBody = RequestBodyUtil.getEmptyBody(method); } else if (data.hasKey(REQUEST_BODY_KEY_STRING)) { if (contentType == null) { ResponseUtil.onRequestError( @@ -249,14 +250,13 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) { String body = data.getString(REQUEST_BODY_KEY_STRING); MediaType contentMediaType = MediaType.parse(contentType); if (RequestBodyUtil.isGzipEncoding(contentEncoding)) { - RequestBody requestBody = RequestBodyUtil.createGzip(contentMediaType, body); + requestBody = RequestBodyUtil.createGzip(contentMediaType, body); if (requestBody == null) { ResponseUtil.onRequestError(eventEmitter, requestId, "Failed to gzip request body", null); return; } - requestBuilder.method(method, requestBody); } else { - requestBuilder.method(method, RequestBody.create(contentMediaType, body)); + requestBody = RequestBody.create(contentMediaType, body); } } else if (data.hasKey(REQUEST_BODY_KEY_BASE64)) { if (contentType == null) { @@ -269,9 +269,7 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) { } String base64String = data.getString(REQUEST_BODY_KEY_BASE64); MediaType contentMediaType = MediaType.parse(contentType); - requestBuilder.method( - method, - RequestBody.create(contentMediaType, ByteString.decodeBase64(base64String))); + requestBody = RequestBody.create(contentMediaType, ByteString.decodeBase64(base64String)); } else if (data.hasKey(REQUEST_BODY_KEY_URI)) { if (contentType == null) { ResponseUtil.onRequestError( @@ -292,9 +290,7 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) { null); return; } - requestBuilder.method( - method, - RequestBodyUtil.create(MediaType.parse(contentType), fileInputStream)); + requestBody = RequestBodyUtil.create(MediaType.parse(contentType), fileInputStream); } else if (data.hasKey(REQUEST_BODY_KEY_FORMDATA)) { if (contentType == null) { contentType = "multipart/form-data"; @@ -305,28 +301,16 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) { if (multipartBuilder == null) { return; } - - requestBuilder.method( - method, - RequestBodyUtil.createProgressRequest( - multipartBuilder.build(), - new ProgressListener() { - long last = System.nanoTime(); - - @Override - public void onProgress(long bytesWritten, long contentLength, boolean done) { - long now = System.nanoTime(); - if (done || shouldDispatch(now, last)) { - ResponseUtil.onDataSend(eventEmitter, requestId, bytesWritten, contentLength); - last = now; - } - } - })); + requestBody = multipartBuilder.build(); } else { // Nothing in data payload, at least nothing we could understand anyway. - requestBuilder.method(method, RequestBodyUtil.getEmptyBody(method)); + requestBody = RequestBodyUtil.getEmptyBody(method); } + requestBuilder.method( + method, + wrapRequestBodyWithProgressEmitter(requestBody, eventEmitter, requestId)); + addRequest(requestId); client.newCall(requestBuilder.build()).enqueue( new Callback() { @@ -394,6 +378,29 @@ public void onResponse(Call call, Response response) throws IOException { }); } + private RequestBody wrapRequestBodyWithProgressEmitter( + final RequestBody requestBody, + final RCTDeviceEventEmitter eventEmitter, + final int requestId) { + if(requestBody == null) { + return null; + } + return RequestBodyUtil.createProgressRequest( + requestBody, + new ProgressListener() { + long last = System.nanoTime(); + + @Override + public void onProgress(long bytesWritten, long contentLength, boolean done) { + long now = System.nanoTime(); + if (done || shouldDispatch(now, last)) { + ResponseUtil.onDataSend(eventEmitter, requestId, bytesWritten, contentLength); + last = now; + } + } + }); + } + private void readWithProgress( RCTDeviceEventEmitter eventEmitter, int requestId, diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java index 54e19763a93a12..7becf4ad48f221 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -43,7 +43,7 @@ import java.util.Map; import javax.annotation.Nullable; - /** +/** *

Native module to allow JS to create and update native Views.

* *

@@ -245,7 +245,7 @@ private static Map createConstants( try { Map viewManagerConstants = UIManagerModuleConstantsHelper.createConstantsForViewManager( - targetView, null, mCustomDirectEvents); + targetView, null, null, null, mCustomDirectEvents); if (viewManagerConstants != null) { return Arguments.makeNativeMap(viewManagerConstants); } @@ -305,7 +305,7 @@ public int addRootVi new SizeMonitoringFrameLayout.OnSizeChangedListener() { @Override public void onSizeChanged(final int width, final int height, int oldW, int oldH) { - reactApplicationContext.runUIBackgroundRunnable( + reactApplicationContext.runOnNativeModulesQueueThread( new GuardedRunnable(reactApplicationContext) { @Override public void runGuarded() { @@ -325,7 +325,7 @@ public void removeRootView(int rootViewTag) { } public void updateNodeSize(int nodeViewTag, int newWidth, int newHeight) { - getReactApplicationContext().assertOnUIBackgroundOrNativeModulesThread(); + getReactApplicationContext().assertOnNativeModulesQueueThread(); mUIImplementation.updateNodeSize(nodeViewTag, newWidth, newHeight); } @@ -344,7 +344,7 @@ public void setViewLocalData(final int tag, final Object data) { reactApplicationContext.assertOnUiQueueThread(); - reactApplicationContext.runUIBackgroundRunnable( + reactApplicationContext.runOnNativeModulesQueueThread( new GuardedRunnable(reactApplicationContext) { @Override public void runGuarded() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java index f9062e9355fe16..76e0b9ecea2d20 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java @@ -93,6 +93,8 @@ try { Map viewManagerConstants = createConstantsForViewManager( viewManager, + null, + null, allBubblingEventTypes, allDirectEventTypes); if (!viewManagerConstants.isEmpty()) { @@ -110,6 +112,8 @@ /* package */ static Map createConstantsForViewManager( ViewManager viewManager, + @Nullable Map defaultBubblingEvents, + @Nullable Map defaultDirectEvents, @Nullable Map cumulativeBubblingEventTypes, @Nullable Map cumulativeDirectEventTypes) { Map viewManagerConstants = MapBuilder.newHashMap(); @@ -117,13 +121,19 @@ Map viewManagerBubblingEvents = viewManager.getExportedCustomBubblingEventTypeConstants(); if (viewManagerBubblingEvents != null) { recursiveMerge(cumulativeBubblingEventTypes, viewManagerBubblingEvents); + recursiveMerge(viewManagerBubblingEvents, defaultBubblingEvents); viewManagerConstants.put(BUBBLING_EVENTS_KEY, viewManagerBubblingEvents); + } else if (defaultBubblingEvents != null) { + viewManagerConstants.put(BUBBLING_EVENTS_KEY, defaultBubblingEvents); } Map viewManagerDirectEvents = viewManager.getExportedCustomDirectEventTypeConstants(); if (viewManagerDirectEvents != null) { recursiveMerge(cumulativeDirectEventTypes, viewManagerDirectEvents); + recursiveMerge(viewManagerDirectEvents, defaultDirectEvents); viewManagerConstants.put(DIRECT_EVENTS_KEY, viewManagerDirectEvents); + } else if (defaultDirectEvents != null) { + viewManagerConstants.put(DIRECT_EVENTS_KEY, defaultDirectEvents); } Map customViewConstants = viewManager.getExportedViewConstants(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java index 30b73bc518ed28..940ae7f1b002de 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java @@ -229,11 +229,11 @@ public void onFailure(String id, Throwable throwable) { } public void setBlurRadius(float blurRadius) { - if (blurRadius == 0) { + int pixelBlurRadius = (int) PixelUtil.toPixelFromDIP(blurRadius); + if (pixelBlurRadius == 0) { mIterativeBoxBlurPostProcessor = null; } else { - mIterativeBoxBlurPostProcessor = - new IterativeBoxBlurPostProcessor((int) PixelUtil.toPixelFromDIP(blurRadius)); + mIterativeBoxBlurPostProcessor = new IterativeBoxBlurPostProcessor(pixelBlurRadius); } mIsDirty = true; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java index 705e455020418d..674c6ef80675b6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java @@ -306,7 +306,7 @@ protected void onSizeChanged(final int w, final int h, int oldw, int oldh) { if (getChildCount() > 0) { final int viewTag = getChildAt(0).getId(); ReactContext reactContext = (ReactContext) getContext(); - reactContext.runUIBackgroundRunnable( + reactContext.runOnNativeModulesQueueThread( new GuardedRunnable(reactContext) { @Override public void runGuarded() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index 70d9a461b3de5e..b4908385af81eb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -332,6 +332,11 @@ private void setCursorColor(ReactEditText view, @Nullable Integer color) { cursorDrawableResField.setAccessible(true); int drawableResId = cursorDrawableResField.getInt(view); + // The view has no cursor drawable. + if (drawableResId == 0) { + return; + } + Drawable drawable = ContextCompat.getDrawable(view.getContext(), drawableResId); if (color != null) { drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java index 477526d86acf5f..4990dd4236a893 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java @@ -109,6 +109,7 @@ private static enum BorderStyle { private @Nullable float[] mBorderCornerRadii; private final Context mContext; + private int mLayoutDirection; public enum BorderRadiusLocation { TOP_LEFT, @@ -128,16 +129,29 @@ public ReactViewBackgroundDrawable(Context context) { @Override public void draw(Canvas canvas) { updatePathEffect(); - boolean roundedBorders = mBorderCornerRadii != null || - (!YogaConstants.isUndefined(mBorderRadius) && mBorderRadius > 0); - - if (!roundedBorders) { + if (!hasRoundedBorders()) { drawRectangularBackgroundWithBorders(canvas); } else { drawRoundedBackgroundWithBorders(canvas); } } + public boolean hasRoundedBorders() { + if (!YogaConstants.isUndefined(mBorderRadius) && mBorderRadius > 0) { + return true; + } + + if (mBorderCornerRadii != null) { + for (final float borderRadii : mBorderCornerRadii) { + if (!YogaConstants.isUndefined(borderRadii) && borderRadii > 0) { + return true; + } + } + } + + return false; + } + @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); @@ -290,6 +304,25 @@ public void setColor(int color) { invalidateSelf(); } + /** Similar to Drawable.getLayoutDirection, but available in APIs < 23. */ + public int getResolvedLayoutDirection() { + return mLayoutDirection; + } + + /** Similar to Drawable.setLayoutDirection, but available in APIs < 23. */ + public boolean setResolvedLayoutDirection(int layoutDirection) { + if (mLayoutDirection != layoutDirection) { + mLayoutDirection = layoutDirection; + return onResolvedLayoutDirectionChanged(layoutDirection); + } + return false; + } + + /** Similar to Drawable.onLayoutDirectionChanged, but available in APIs < 23. */ + public boolean onResolvedLayoutDirectionChanged(int layoutDirection) { + return false; + } + @VisibleForTesting public int getColor() { return mColor; @@ -323,8 +356,8 @@ private void drawRoundedBackgroundWithBorders(Canvas canvas) { int colorRight = getBorderColor(Spacing.RIGHT); int colorBottom = getBorderColor(Spacing.BOTTOM); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - final boolean isRTL = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + final boolean isRTL = getResolvedLayoutDirection() == View.LAYOUT_DIRECTION_RTL; int colorStart = getBorderColor(Spacing.START); int colorEnd = getBorderColor(Spacing.END); @@ -478,13 +511,13 @@ private void updatePath() { float bottomRightRadius = getBorderRadiusOrDefaultTo(borderRadius, BorderRadiusLocation.BOTTOM_RIGHT); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - final boolean isRTL = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + final boolean isRTL = getResolvedLayoutDirection() == View.LAYOUT_DIRECTION_RTL; float topStartRadius = getBorderRadius(BorderRadiusLocation.TOP_START); float topEndRadius = getBorderRadius(BorderRadiusLocation.TOP_END); float bottomStartRadius = getBorderRadius(BorderRadiusLocation.BOTTOM_START); float bottomEndRadius = getBorderRadius(BorderRadiusLocation.BOTTOM_END); - + if (I18nUtil.getInstance().doLeftAndRightSwapInRTL(mContext)) { if (YogaConstants.isUndefined(topStartRadius)) { topStartRadius = topLeftRadius; @@ -600,23 +633,29 @@ private void updatePath() { * border of V will render inside O. * *

Let BorderWidth = (borderTop, borderLeft, borderBottom, borderRight). + * *

Let I (for inner) = O - BorderWidth. * *

Then, remembering that O and I are rectangles and that I is inside O, O - I gives us the * border of V. Therefore, we can use canvas.clipPath to draw V's border. * *

canvas.clipPath(O, Region.OP.INTERSECT); + * *

canvas.clipPath(I, Region.OP.DIFFERENCE); + * *

canvas.drawRect(O, paint); * *

This lets us draw non-rounded single-color borders. * *

To extend this algorithm to rounded single-color borders, we: + * *

1. Curve the corners of O by the (border radii of V) using Path#addRoundRect. + * *

2. Curve the corners of I by (border radii of V - border widths of V) using * Path#addRoundRect. * *

Let O' = curve(O, border radii of V). + * *

Let I' = curve(I, border radii of V - border widths of V) * *

The rationale behind this decision is the (first sentence of the) following section in the @@ -627,7 +666,9 @@ private void updatePath() { * render curved single-color borders: * *

canvas.clipPath(O, Region.OP.INTERSECT); + * *

canvas.clipPath(I, Region.OP.DIFFERENCE); + * *

canvas.drawRect(O, paint); * *

To extend this algorithm to rendering multi-colored rounded borders, we render each side @@ -635,8 +676,11 @@ private void updatePath() { * border radii are 0. Then, the four quadrilaterals would be: * *

Left: (O.left, O.top), (I.left, I.top), (I.left, I.bottom), (O.left, O.bottom) + * *

Top: (O.left, O.top), (I.left, I.top), (I.right, I.top), (O.right, O.top) + * *

Right: (O.right, O.top), (I.right, I.top), (I.right, I.bottom), (O.right, O.bottom) + * *

Bottom: (O.right, O.bottom), (I.right, I.bottom), (I.left, I.bottom), (O.left, O.bottom) * *

Now, lets consider what happens when we render a rounded border (radii != 0). For the sake @@ -930,8 +974,8 @@ private void drawRectangularBackgroundWithBorders(Canvas canvas) { int colorRight = getBorderColor(Spacing.RIGHT); int colorBottom = getBorderColor(Spacing.BOTTOM); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - final boolean isRTL = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + final boolean isRTL = getResolvedLayoutDirection() == View.LAYOUT_DIRECTION_RTL; int colorStart = getBorderColor(Spacing.START); int colorEnd = getBorderColor(Spacing.END); @@ -1140,8 +1184,8 @@ public RectF getDirectionAwareBorderInsets() { float borderLeftWidth = getBorderWidthOrDefaultTo(borderWidth, Spacing.LEFT); float borderRightWidth = getBorderWidthOrDefaultTo(borderWidth, Spacing.RIGHT); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && mBorderWidth != null) { - final boolean isRTL = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && mBorderWidth != null) { + final boolean isRTL = getResolvedLayoutDirection() == View.LAYOUT_DIRECTION_RTL; float borderStartWidth = mBorderWidth.getRaw(Spacing.START); float borderEndWidth = mBorderWidth.getRaw(Spacing.END); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 592f328e9663ff..3d7a4299ec0546 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -129,9 +129,9 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto @Override public void onRtlPropertiesChanged(int layoutDirection) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { if (mReactBackgroundDrawable != null) { - mReactBackgroundDrawable.setLayoutDirection(mLayoutDirection); + mReactBackgroundDrawable.setResolvedLayoutDirection(mLayoutDirection); } } } @@ -233,7 +233,20 @@ public void setBorderRadius(float borderRadius) { } public void setBorderRadius(float borderRadius, int position) { - getOrCreateReactViewBackground().setRadius(borderRadius, position); + ReactViewBackgroundDrawable backgroundDrawable = getOrCreateReactViewBackground(); + backgroundDrawable.setRadius(borderRadius, position); + + if (Build.VERSION_CODES.HONEYCOMB < Build.VERSION.SDK_INT + && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { + final int UPDATED_LAYER_TYPE = + backgroundDrawable.hasRoundedBorders() + ? View.LAYER_TYPE_SOFTWARE + : View.LAYER_TYPE_HARDWARE; + + if (UPDATED_LAYER_TYPE != getLayerType()) { + setLayerType(UPDATED_LAYER_TYPE, null); + } + } } public void setBorderStyle(@Nullable String style) { @@ -589,12 +602,12 @@ private ReactViewBackgroundDrawable getOrCreateReactViewBackground() { updateBackgroundDrawable(layerDrawable); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { mLayoutDirection = I18nUtil.getInstance().isRTL(getContext()) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR; - mReactBackgroundDrawable.setLayoutDirection(mLayoutDirection); + mReactBackgroundDrawable.setResolvedLayoutDirection(mLayoutDirection); } } return mReactBackgroundDrawable; @@ -671,7 +684,7 @@ protected void dispatchDraw(Canvas canvas) { mReactBackgroundDrawable.getBorderRadiusOrDefaultTo( borderRadius, ReactViewBackgroundDrawable.BorderRadiusLocation.BOTTOM_RIGHT); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { final boolean isRTL = mLayoutDirection == View.LAYOUT_DIRECTION_RTL; float topStartBorderRadius = mReactBackgroundDrawable.getBorderRadius( diff --git a/ReactAndroid/src/main/jni/react/jni/Android.mk b/ReactAndroid/src/main/jni/react/jni/Android.mk index cc4cfbb5d446bd..8d8b992d52432e 100644 --- a/ReactAndroid/src/main/jni/react/jni/Android.mk +++ b/ReactAndroid/src/main/jni/react/jni/Android.mk @@ -14,7 +14,6 @@ LOCAL_SRC_FILES := \ JSLoader.cpp \ JSLogging.cpp \ JniJSModulesUnbundle.cpp \ - JniRAMBundleRegistry.cpp \ MethodInvoker.cpp \ ModuleRegistryBuilder.cpp \ NativeArray.cpp \ diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp index 1706e2d3e65f0c..7b136f0d0cdf14 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp @@ -10,10 +10,10 @@ #include #include #include -#include #include -#include #include +#include +#include #include #include #include @@ -22,9 +22,8 @@ #include "CxxModuleWrapper.h" #include "JavaScriptExecutorHolder.h" -#include "JniJSModulesUnbundle.h" -#include "JniRAMBundleRegistry.h" #include "JNativeRunnable.h" +#include "JniJSModulesUnbundle.h" #include "NativeArray.h" using namespace facebook::jni; @@ -90,9 +89,6 @@ CatalystInstanceImpl::~CatalystInstanceImpl() { if (moduleMessageQueue_ != NULL) { moduleMessageQueue_->quitSynchronous(); } - if (uiBackgroundMessageQueue_ != NULL) { - uiBackgroundMessageQueue_->quitSynchronous(); - } } void CatalystInstanceImpl::registerNatives() { @@ -101,7 +97,7 @@ void CatalystInstanceImpl::registerNatives() { makeNativeMethod("initializeBridge", CatalystInstanceImpl::initializeBridge), makeNativeMethod("jniExtendNativeModules", CatalystInstanceImpl::extendNativeModules), makeNativeMethod("jniSetSourceURL", CatalystInstanceImpl::jniSetSourceURL), - makeNativeMethod("jniSetJsBundlesDirectory", CatalystInstanceImpl::jniSetJsBundlesDirectory), + makeNativeMethod("jniRegisterSegment", CatalystInstanceImpl::jniRegisterSegment), makeNativeMethod("jniLoadScriptFromAssets", CatalystInstanceImpl::jniLoadScriptFromAssets), makeNativeMethod("jniLoadScriptFromFile", CatalystInstanceImpl::jniLoadScriptFromFile), makeNativeMethod("jniCallJSFunction", CatalystInstanceImpl::jniCallJSFunction), @@ -120,15 +116,11 @@ void CatalystInstanceImpl::initializeBridge( JavaScriptExecutorHolder* jseh, jni::alias_ref jsQueue, jni::alias_ref nativeModulesQueue, - jni::alias_ref uiBackgroundQueue, jni::alias_ref::javaobject> javaModules, jni::alias_ref::javaobject> cxxModules) { // TODO mhorowitz: how to assert here? // Assertions.assertCondition(mBridge == null, "initializeBridge should be called once"); moduleMessageQueue_ = std::make_shared(nativeModulesQueue); - if (uiBackgroundQueue.get() != nullptr) { - uiBackgroundMessageQueue_ = std::make_shared(uiBackgroundQueue); - } // This used to be: // @@ -151,13 +143,12 @@ void CatalystInstanceImpl::initializeBridge( std::weak_ptr(instance_), javaModules, cxxModules, - moduleMessageQueue_, - uiBackgroundMessageQueue_)); + moduleMessageQueue_)); instance_->initializeBridge( folly::make_unique( callback, - uiBackgroundMessageQueue_ != NULL ? uiBackgroundMessageQueue_ : moduleMessageQueue_), + moduleMessageQueue_), jseh->getExecutorFactory(), folly::make_unique(jsQueue), moduleRegistry_); @@ -170,16 +161,15 @@ void CatalystInstanceImpl::extendNativeModules( std::weak_ptr(instance_), javaModules, cxxModules, - moduleMessageQueue_, - uiBackgroundMessageQueue_)); + moduleMessageQueue_)); } void CatalystInstanceImpl::jniSetSourceURL(const std::string& sourceURL) { instance_->setSourceURL(sourceURL); } -void CatalystInstanceImpl::jniSetJsBundlesDirectory(const std::string& directoryPath) { - jsBundlesDirectory_ = directoryPath; +void CatalystInstanceImpl::jniRegisterSegment(int segmentId, const std::string& path) { + instance_->registerBundle((uint32_t)segmentId, path); } void CatalystInstanceImpl::jniLoadScriptFromAssets( @@ -193,9 +183,7 @@ void CatalystInstanceImpl::jniLoadScriptFromAssets( auto script = loadScriptFromAssets(manager, sourceURL); if (JniJSModulesUnbundle::isUnbundle(manager, sourceURL)) { auto bundle = JniJSModulesUnbundle::fromEntryFile(manager, sourceURL); - auto registry = jsBundlesDirectory_.empty() - ? folly::make_unique(std::move(bundle)) - : folly::make_unique(std::move(bundle), manager, sourceURL); + auto registry = RAMBundleRegistry::singleBundleRegistry(std::move(bundle)); instance_->loadRAMBundle( std::move(registry), std::move(script), diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h index f1bd47e8e8d9d5..5f7b1be15157e6 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h @@ -46,7 +46,6 @@ class CatalystInstanceImpl : public jni::HybridClass { JavaScriptExecutorHolder* jseh, jni::alias_ref jsQueue, jni::alias_ref moduleQueue, - jni::alias_ref uiBackgroundQueue, jni::alias_ref::javaobject> javaModules, jni::alias_ref::javaobject> cxxModules); @@ -60,10 +59,10 @@ class CatalystInstanceImpl : public jni::HybridClass { void jniSetSourceURL(const std::string& sourceURL); /** - * Sets the path to folder where additional bundles are located. - * Needs to be invoked before "loadScript" methods are called. + * Registers the file path of an additional JS segment by its ID. + * */ - void jniSetJsBundlesDirectory(const std::string& directoryPath); + void jniRegisterSegment(int segmentId, const std::string& path); void jniLoadScriptFromAssets(jni::alias_ref assetManager, const std::string& assetURL, bool loadSynchronously); void jniLoadScriptFromFile(const std::string& fileName, const std::string& sourceURL, bool loadSynchronously); @@ -74,14 +73,11 @@ class CatalystInstanceImpl : public jni::HybridClass { jlong getJavaScriptContext(); void handleMemoryPressure(int pressureLevel); - std::string jsBundlesDirectory_; - // This should be the only long-lived strong reference, but every C++ class // will have a weak reference. std::shared_ptr instance_; std::shared_ptr moduleRegistry_; std::shared_ptr moduleMessageQueue_; - std::shared_ptr uiBackgroundMessageQueue_; }; }} diff --git a/ReactAndroid/src/main/jni/react/jni/JniRAMBundleRegistry.cpp b/ReactAndroid/src/main/jni/react/jni/JniRAMBundleRegistry.cpp deleted file mode 100644 index 3f2219a20f50e3..00000000000000 --- a/ReactAndroid/src/main/jni/react/jni/JniRAMBundleRegistry.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "JniRAMBundleRegistry.h" - -#include -#include - -#include "JniJSModulesUnbundle.h" - -namespace facebook { -namespace react { - -JniRAMBundleRegistry::JniRAMBundleRegistry(std::unique_ptr mainBundle, AAssetManager *assetManager, const std::string& baseDirectoryPath) : - RAMBundleRegistry(std::move(mainBundle)), - m_assetManager(assetManager), - m_baseDirectoryPath(baseDirectoryPath) {} - -std::unique_ptr JniRAMBundleRegistry::bundleById(uint32_t index) const { - std::string bundlePathById = m_baseDirectoryPath + folly::to(index) + "/js-modules/"; - return folly::make_unique(m_assetManager, bundlePathById); -} - -} -} diff --git a/ReactAndroid/src/main/jni/react/jni/JniRAMBundleRegistry.h b/ReactAndroid/src/main/jni/react/jni/JniRAMBundleRegistry.h deleted file mode 100644 index 255fa89e2edecc..00000000000000 --- a/ReactAndroid/src/main/jni/react/jni/JniRAMBundleRegistry.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include -#include - -namespace facebook { -namespace react { - -class JniRAMBundleRegistry : public RAMBundleRegistry { -public: - JniRAMBundleRegistry(std::unique_ptr mainBundle, AAssetManager *assetManager, const std::string& baseDirectoryPath); - -protected: - virtual std::unique_ptr bundleById(uint32_t index) const override; -private: - AAssetManager *m_assetManager = nullptr; - std::string m_baseDirectoryPath; -}; - -} -} diff --git a/ReactAndroid/src/main/jni/react/jni/ModuleRegistryBuilder.cpp b/ReactAndroid/src/main/jni/react/jni/ModuleRegistryBuilder.cpp index 9706a43dc1c18d..eb204dd3ee91b3 100644 --- a/ReactAndroid/src/main/jni/react/jni/ModuleRegistryBuilder.cpp +++ b/ReactAndroid/src/main/jni/react/jni/ModuleRegistryBuilder.cpp @@ -33,25 +33,12 @@ std::vector> buildNativeModuleList( std::weak_ptr winstance, jni::alias_ref::javaobject> javaModules, jni::alias_ref::javaobject> cxxModules, - std::shared_ptr moduleMessageQueue, - std::shared_ptr uiBackgroundMessageQueue) { + std::shared_ptr moduleMessageQueue) { std::vector> modules; if (javaModules) { for (const auto& jm : *javaModules) { - std::string name = jm->getName(); - if (uiBackgroundMessageQueue != NULL && - // This is techinically a hack. Perhaps we should bind the specific queue to the module - // in the module holder or wrapper. - // TODO expose as module configuration option - (name == "UIManager" || - name == "NativeAnimatedModule" || - name == "FBFacebookReactNavigator")) { - modules.emplace_back(folly::make_unique( - winstance, jm, uiBackgroundMessageQueue)); - } else { - modules.emplace_back(folly::make_unique( - winstance, jm, moduleMessageQueue)); - } + modules.emplace_back(folly::make_unique( + winstance, jm, moduleMessageQueue)); } } if (cxxModules) { diff --git a/ReactAndroid/src/main/jni/react/jni/ModuleRegistryBuilder.h b/ReactAndroid/src/main/jni/react/jni/ModuleRegistryBuilder.h index 6e31adc898d3bd..3a8cc09258e00f 100644 --- a/ReactAndroid/src/main/jni/react/jni/ModuleRegistryBuilder.h +++ b/ReactAndroid/src/main/jni/react/jni/ModuleRegistryBuilder.h @@ -27,7 +27,6 @@ std::vector> buildNativeModuleList( std::weak_ptr winstance, jni::alias_ref::javaobject> javaModules, jni::alias_ref::javaobject> cxxModules, - std::shared_ptr moduleMessageQueue, - std::shared_ptr uiBackgroundMessageQueue); + std::shared_ptr moduleMessageQueue); } } diff --git a/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.cpp b/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.cpp index d79f4f96d6e30c..1b9395ceae4c9f 100644 --- a/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.cpp +++ b/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.cpp @@ -90,6 +90,12 @@ void ProxyExecutor::setBundleRegistry(std::unique_ptr) { "Loading application RAM bundles is not supported for proxy executors"); } +void ProxyExecutor::registerBundle(uint32_t bundleId, const std::string& bundlePath) { + jni::throwNewJavaException( + "java/lang/UnsupportedOperationException", + "Loading application RAM bundles is not supported for proxy executors"); +} + void ProxyExecutor::callFunction(const std::string& moduleId, const std::string& methodId, const folly::dynamic& arguments) { auto call = folly::dynamic::array(moduleId, methodId, std::move(arguments)); diff --git a/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h b/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h index 30758073a79eef..b77d35f63745cd 100644 --- a/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h +++ b/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h @@ -37,6 +37,8 @@ class ProxyExecutor : public JSExecutor { std::string sourceURL) override; virtual void setBundleRegistry( std::unique_ptr bundle) override; + virtual void registerBundle( + uint32_t bundleId, const std::string& bundlePath) override; virtual void callFunction( const std::string& moduleId, const std::string& methodId, diff --git a/ReactAndroid/src/main/res/devsupport/xml/preferences.xml b/ReactAndroid/src/main/res/devsupport/xml/preferences.xml index 4e69a0e5a648ed..7ce20de3fa5bc2 100644 --- a/ReactAndroid/src/main/res/devsupport/xml/preferences.xml +++ b/ReactAndroid/src/main/res/devsupport/xml/preferences.xml @@ -19,6 +19,12 @@ android:summary="Load JavaScript bundle with minify=true for debugging minification issues." android:defaultValue="false" /> + () { @Override @@ -211,12 +215,13 @@ public Object answer(InvocationOnMock invocation) throws Throwable { OkHttpClient.Builder clientBuilder = mock(OkHttpClient.Builder.class); when(clientBuilder.build()).thenReturn(httpClient); when(httpClient.newBuilder()).thenReturn(clientBuilder); - NetworkingModule networkingModule = - new NetworkingModule(mock(ReactApplicationContext.class), "", httpClient); + NetworkingModule networkingModule = new NetworkingModule(context, "", httpClient); JavaOnlyMap body = new JavaOnlyMap(); body.putString("string", "This is request body"); + mockEvents(); + networkingModule.sendRequest( "POST", "http://somedomain/bar", diff --git a/ReactCommon/cxxreact/Android.mk b/ReactCommon/cxxreact/Android.mk index 7e64ce3f91f1d3..fae8dbaabba4e0 100644 --- a/ReactCommon/cxxreact/Android.mk +++ b/ReactCommon/cxxreact/Android.mk @@ -18,7 +18,6 @@ LOCAL_SRC_FILES := \ JSCTracing.cpp \ JSCUtils.cpp \ JSIndexedRAMBundle.cpp \ - JSIndexedRAMBundleRegistry.cpp \ MethodCall.cpp \ ModuleRegistry.cpp \ NativeToJsBridge.cpp \ diff --git a/ReactCommon/cxxreact/BUCK b/ReactCommon/cxxreact/BUCK index 4012972acd58cc..6b567cca03b7ec 100644 --- a/ReactCommon/cxxreact/BUCK +++ b/ReactCommon/cxxreact/BUCK @@ -80,7 +80,6 @@ CXXREACT_PUBLIC_HEADERS = [ "JSCExecutor.h", "JSCNativeModules.h", "JSIndexedRAMBundle.h", - "JSIndexedRAMBundleRegistry.h", "JSModulesUnbundle.h", "MessageQueueThread.h", "MethodCall.h", diff --git a/ReactCommon/cxxreact/Instance.cpp b/ReactCommon/cxxreact/Instance.cpp index 0226801518dc6f..01ead37316cba6 100644 --- a/ReactCommon/cxxreact/Instance.cpp +++ b/ReactCommon/cxxreact/Instance.cpp @@ -111,7 +111,7 @@ void Instance::loadRAMBundleFromFile(const std::string& sourcePath, bool loadSynchronously) { auto bundle = folly::make_unique(sourcePath.c_str()); auto startupScript = bundle->getStartupCode(); - auto registry = folly::make_unique(std::move(bundle)); + auto registry = RAMBundleRegistry::multipleBundlesRegistry(std::move(bundle), JSIndexedRAMBundle::buildFactory()); loadRAMBundle( std::move(registry), std::move(startupScript), @@ -156,6 +156,10 @@ void Instance::callJSCallback(uint64_t callbackId, folly::dynamic &¶ms) { nativeToJsBridge_->invokeCallback((double)callbackId, std::move(params)); } +void Instance::registerBundle(uint32_t bundleId, const std::string& bundlePath) { + nativeToJsBridge_->registerBundle(bundleId, bundlePath); +} + const ModuleRegistry &Instance::getModuleRegistry() const { return *moduleRegistry_; } diff --git a/ReactCommon/cxxreact/Instance.h b/ReactCommon/cxxreact/Instance.h index 6999fb60de1edc..d04bcb3563721c 100644 --- a/ReactCommon/cxxreact/Instance.h +++ b/ReactCommon/cxxreact/Instance.h @@ -59,6 +59,9 @@ class RN_EXPORT Instance { folly::dynamic &¶ms); void callJSCallback(uint64_t callbackId, folly::dynamic &¶ms); + // This method is experimental, and may be modified or removed. + void registerBundle(uint32_t bundleId, const std::string& bundlePath); + // This method is experimental, and may be modified or removed. template Value callFunctionSync(const std::string &module, const std::string &method, diff --git a/ReactCommon/cxxreact/JSCExecutor.cpp b/ReactCommon/cxxreact/JSCExecutor.cpp index 3dfe2db47257d4..0b66c8c3c6da8f 100644 --- a/ReactCommon/cxxreact/JSCExecutor.cpp +++ b/ReactCommon/cxxreact/JSCExecutor.cpp @@ -458,6 +458,12 @@ namespace facebook { m_bundleRegistry = std::move(bundleRegistry); } + void JSCExecutor::registerBundle(uint32_t bundleId, const std::string& bundlePath) { + if (m_bundleRegistry) { + m_bundleRegistry->registerBundle(bundleId, bundlePath); + } + } + void JSCExecutor::bindBridge() throw(JSException) { SystraceSection s("JSCExecutor::bindBridge"); std::call_once(m_bindFlag, [this] { diff --git a/ReactCommon/cxxreact/JSCExecutor.h b/ReactCommon/cxxreact/JSCExecutor.h index f2dc8c61ed571d..c646677d6022c4 100644 --- a/ReactCommon/cxxreact/JSCExecutor.h +++ b/ReactCommon/cxxreact/JSCExecutor.h @@ -66,6 +66,7 @@ class RN_EXPORT JSCExecutor : public JSExecutor, public PrivateDataBase { std::string sourceURL) override; virtual void setBundleRegistry(std::unique_ptr bundleRegistry) override; + virtual void registerBundle(uint32_t bundleId, const std::string& bundlePath) override; virtual void callFunction( const std::string& moduleId, diff --git a/ReactCommon/cxxreact/JSExecutor.h b/ReactCommon/cxxreact/JSExecutor.h index b8cc3d3f13709d..83f9e15344fbd7 100644 --- a/ReactCommon/cxxreact/JSExecutor.h +++ b/ReactCommon/cxxreact/JSExecutor.h @@ -53,6 +53,11 @@ class JSExecutor { */ virtual void setBundleRegistry(std::unique_ptr bundleRegistry) = 0; + /** + * Register a file path for an additional "RAM" bundle + */ + virtual void registerBundle(uint32_t bundleId, const std::string& bundlePath) = 0; + /** * Executes BatchedBridge.callFunctionReturnFlushedQueue with the module ID, * method ID and optional additional arguments in JS. The executor is responsible diff --git a/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp b/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp index 1fb50627e1636c..b5db5203fa74ad 100644 --- a/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp +++ b/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp @@ -2,11 +2,19 @@ #include "JSIndexedRAMBundle.h" +#include + #include "oss-compat-util.h" namespace facebook { namespace react { +std::function(std::string)> JSIndexedRAMBundle::buildFactory() { + return [](const std::string& bundlePath){ + return folly::make_unique(bundlePath.c_str()); + }; +} + JSIndexedRAMBundle::JSIndexedRAMBundle(const char *sourcePath) : m_bundle (sourcePath, std::ios_base::in) { if (!m_bundle) { diff --git a/ReactCommon/cxxreact/JSIndexedRAMBundle.h b/ReactCommon/cxxreact/JSIndexedRAMBundle.h index 79e2587f30eeb8..6467977279fa53 100644 --- a/ReactCommon/cxxreact/JSIndexedRAMBundle.h +++ b/ReactCommon/cxxreact/JSIndexedRAMBundle.h @@ -17,6 +17,8 @@ namespace react { class RN_EXPORT JSIndexedRAMBundle : public JSModulesUnbundle { public: + static std::function(std::string)> buildFactory(); + // Throws std::runtime_error on failure. JSIndexedRAMBundle(const char *sourceURL); diff --git a/ReactCommon/cxxreact/JSIndexedRAMBundleRegistry.cpp b/ReactCommon/cxxreact/JSIndexedRAMBundleRegistry.cpp deleted file mode 100644 index 44a58e36181137..00000000000000 --- a/ReactCommon/cxxreact/JSIndexedRAMBundleRegistry.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "JSIndexedRAMBundleRegistry.h" - -#include -#include - -#include "oss-compat-util.h" - -namespace facebook { -namespace react { - -JSIndexedRAMBundleRegistry::JSIndexedRAMBundleRegistry(std::unique_ptr mainBundle, const std::string& baseDirectoryPath): -RAMBundleRegistry(std::move(mainBundle)), m_baseDirectoryPath(baseDirectoryPath) {} - -std::unique_ptr JSIndexedRAMBundleRegistry::bundleById(uint32_t index) const { - std::string bundlePathById = m_baseDirectoryPath + toString(index) + ".jsbundle"; - return folly::make_unique(bundlePathById.c_str()); -} - -} // namespace react -} // namespace facebook diff --git a/ReactCommon/cxxreact/JSIndexedRAMBundleRegistry.h b/ReactCommon/cxxreact/JSIndexedRAMBundleRegistry.h deleted file mode 100644 index 199f26772a54ce..00000000000000 --- a/ReactCommon/cxxreact/JSIndexedRAMBundleRegistry.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include - -#ifndef RN_EXPORT -#define RN_EXPORT __attribute__((visibility("default"))) -#endif - -namespace facebook { -namespace react { - -class RN_EXPORT JSIndexedRAMBundleRegistry: public RAMBundleRegistry { -public: - JSIndexedRAMBundleRegistry(std::unique_ptr mainBundle, const std::string& baseDirectoryPath); - -protected: - virtual std::unique_ptr bundleById(uint32_t index) const override; -private: - std::string m_baseDirectoryPath; -}; - -} // namespace react -} // namespace facebook diff --git a/ReactCommon/cxxreact/NativeToJsBridge.cpp b/ReactCommon/cxxreact/NativeToJsBridge.cpp index 3f1f78c8336637..51bad86f746f92 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.cpp +++ b/ReactCommon/cxxreact/NativeToJsBridge.cpp @@ -171,6 +171,12 @@ void NativeToJsBridge::invokeCallback(double callbackId, folly::dynamic&& argume }); } +void NativeToJsBridge::registerBundle(uint32_t bundleId, const std::string& bundlePath) { + runOnExecutorQueue([bundleId, bundlePath] (JSExecutor* executor) { + executor->registerBundle(bundleId, bundlePath); + }); +} + void NativeToJsBridge::setGlobalVariable(std::string propName, std::unique_ptr jsonValue) { runOnExecutorQueue([propName=std::move(propName), jsonValue=folly::makeMoveWrapper(std::move(jsonValue))] diff --git a/ReactCommon/cxxreact/NativeToJsBridge.h b/ReactCommon/cxxreact/NativeToJsBridge.h index dee12b6e3273b3..093707f2e8215a 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.h +++ b/ReactCommon/cxxreact/NativeToJsBridge.h @@ -98,6 +98,7 @@ class NativeToJsBridge { std::unique_ptr startupCode, std::string sourceURL); + void registerBundle(uint32_t bundleId, const std::string& bundlePath); void setGlobalVariable(std::string propName, std::unique_ptr jsonValue); void* getJavaScriptContext(); diff --git a/ReactCommon/cxxreact/RAMBundleRegistry.cpp b/ReactCommon/cxxreact/RAMBundleRegistry.cpp index 5159475bb41c6c..635875b3b79cbe 100644 --- a/ReactCommon/cxxreact/RAMBundleRegistry.cpp +++ b/ReactCommon/cxxreact/RAMBundleRegistry.cpp @@ -2,6 +2,8 @@ #include "RAMBundleRegistry.h" +#include + #include namespace facebook { @@ -9,13 +11,35 @@ namespace react { constexpr uint32_t RAMBundleRegistry::MAIN_BUNDLE_ID; -RAMBundleRegistry::RAMBundleRegistry(std::unique_ptr mainBundle) { +std::unique_ptr RAMBundleRegistry::singleBundleRegistry(std::unique_ptr mainBundle) { + RAMBundleRegistry *registry = new RAMBundleRegistry(std::move(mainBundle)); + return std::unique_ptr(registry); +} + +std::unique_ptr RAMBundleRegistry::multipleBundlesRegistry(std::unique_ptr mainBundle, std::function(std::string)> factory) { + RAMBundleRegistry *registry = new RAMBundleRegistry(std::move(mainBundle), std::move(factory)); + return std::unique_ptr(registry); +} + +RAMBundleRegistry::RAMBundleRegistry(std::unique_ptr mainBundle, std::function(std::string)> factory): m_factory(factory) { m_bundles.emplace(MAIN_BUNDLE_ID, std::move(mainBundle)); } +void RAMBundleRegistry::registerBundle(uint32_t bundleId, std::string bundlePath) { + m_bundlePaths.emplace(bundleId, bundlePath); +} + JSModulesUnbundle::Module RAMBundleRegistry::getModule(uint32_t bundleId, uint32_t moduleId) { if (m_bundles.find(bundleId) == m_bundles.end()) { - m_bundles.emplace(bundleId, this->bundleById(bundleId)); + if (!m_factory) { + throw std::runtime_error("You need to register factory function in order to support multiple RAM bundles."); + } + + auto bundlePath = m_bundlePaths.find(bundleId); + if (bundlePath == m_bundlePaths.end()) { + throw std::runtime_error("In order to fetch RAM bundle from the registry, its file path needs to be registered first."); + } + m_bundles.emplace(bundleId, m_factory(bundlePath->second)); } return getBundle(bundleId)->getModule(moduleId); diff --git a/ReactCommon/cxxreact/RAMBundleRegistry.h b/ReactCommon/cxxreact/RAMBundleRegistry.h index 950379b83f4ee2..2d628f22c35d7c 100644 --- a/ReactCommon/cxxreact/RAMBundleRegistry.h +++ b/ReactCommon/cxxreact/RAMBundleRegistry.h @@ -3,6 +3,7 @@ #pragma once #include +#include #include #include #include @@ -19,22 +20,26 @@ namespace react { class RN_EXPORT RAMBundleRegistry : noncopyable { public: + using unique_ram_bundle = std::unique_ptr; + using bundle_path = std::string; constexpr static uint32_t MAIN_BUNDLE_ID = 0; - explicit RAMBundleRegistry(std::unique_ptr mainBundle); + static std::unique_ptr singleBundleRegistry(unique_ram_bundle mainBundle); + static std::unique_ptr multipleBundlesRegistry(unique_ram_bundle mainBundle, std::function factory); + RAMBundleRegistry(RAMBundleRegistry&&) = default; RAMBundleRegistry& operator=(RAMBundleRegistry&&) = default; + void registerBundle(uint32_t bundleId, bundle_path bundlePath); JSModulesUnbundle::Module getModule(uint32_t bundleId, uint32_t moduleId); virtual ~RAMBundleRegistry() {}; -protected: - virtual std::unique_ptr bundleById(uint32_t index) const { - throw std::runtime_error("Please, override this method in a subclass to support multiple RAM bundles."); - } private: + explicit RAMBundleRegistry(unique_ram_bundle mainBundle, std::function factory = {}); JSModulesUnbundle *getBundle(uint32_t bundleId) const; - std::unordered_map> m_bundles; + std::function m_factory; + std::unordered_map m_bundlePaths; + std::unordered_map m_bundles; }; } // namespace react diff --git a/ReactCommon/yoga/Android.mk b/ReactCommon/yoga/Android.mk index e03438cb5970b9..b9a460e7ca7b99 100644 --- a/ReactCommon/yoga/Android.mk +++ b/ReactCommon/yoga/Android.mk @@ -5,13 +5,13 @@ include $(CLEAR_VARS) LOCAL_MODULE := yogacore LOCAL_SRC_FILES := \ - yoga/Yoga.c \ - yoga/YGEnums.c \ - yoga/YGNodeList.c + yoga/Yoga.cpp \ + yoga/YGEnums.cpp \ + yoga/YGNodeList.cpp LOCAL_C_INCLUDES := $(LOCAL_PATH) LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) -LOCAL_CFLAGS := -Wall -Werror -fexceptions -frtti -std=c99 -O3 +LOCAL_CFLAGS := -Wall -Werror -fexceptions -frtti -std=c++1y -O3 include $(BUILD_STATIC_LIBRARY) diff --git a/ReactCommon/yoga/BUCK b/ReactCommon/yoga/BUCK index 20e4bdbd1fa509..6e6f1b2e998a9d 100644 --- a/ReactCommon/yoga/BUCK +++ b/ReactCommon/yoga/BUCK @@ -1,17 +1,17 @@ cxx_library( name = "yoga", - srcs = glob(["yoga/*.c"]), + srcs = glob(["yoga/*.cpp"]), + header_namespace = "", + exported_headers = glob(["yoga/*.h"]), compiler_flags = [ "-fno-omit-frame-pointer", "-fexceptions", "-Wall", "-Werror", - "-std=c99", + "-std=c++1y", "-O3", ], - exported_headers = glob(["yoga/*.h"]), force_static = True, - header_namespace = "", visibility = ["PUBLIC"], deps = [ ], diff --git a/ReactCommon/yoga/yoga.podspec b/ReactCommon/yoga/yoga.podspec index 29706c1fb75735..4d0577e80dbec5 100644 --- a/ReactCommon/yoga/yoga.podspec +++ b/ReactCommon/yoga/yoga.podspec @@ -29,7 +29,7 @@ Pod::Spec.new do |spec| '-fexceptions', '-Wall', '-Werror', - '-std=c11', + '-std=c++1y', '-fPIC' ] @@ -38,7 +38,7 @@ Pod::Spec.new do |spec| # Set this environment variable when not using the `:path` option to install the pod. # E.g. when publishing this spec to a spec repo. - source_files = 'yoga/**/*.{c,h}' + source_files = 'yoga/**/*.{cpp,h}' source_files = File.join('ReactCommon/yoga', source_files) if ENV['INSTALL_YOGA_WITHOUT_PATH_OPTION'] spec.source_files = source_files end diff --git a/ReactCommon/yoga/yoga/YGEnums.c b/ReactCommon/yoga/yoga/YGEnums.cpp similarity index 99% rename from ReactCommon/yoga/yoga/YGEnums.c rename to ReactCommon/yoga/yoga/YGEnums.cpp index f554c367978c14..7baf5c26243020 100644 --- a/ReactCommon/yoga/yoga/YGEnums.c +++ b/ReactCommon/yoga/yoga/YGEnums.cpp @@ -224,4 +224,3 @@ const char *YGWrapToString(const YGWrap value){ } return "unknown"; } - diff --git a/ReactCommon/yoga/yoga/YGNodeList.c b/ReactCommon/yoga/yoga/YGNodeList.cpp similarity index 78% rename from ReactCommon/yoga/yoga/YGNodeList.c rename to ReactCommon/yoga/yoga/YGNodeList.cpp index 5bac4d85a58b1d..e05ffa290eeb1b 100644 --- a/ReactCommon/yoga/yoga/YGNodeList.c +++ b/ReactCommon/yoga/yoga/YGNodeList.cpp @@ -11,10 +11,6 @@ #include "YGNodeList.h" -extern YGMalloc gYGMalloc; -extern YGRealloc gYGRealloc; -extern YGFree gYGFree; - struct YGNodeList { uint32_t capacity; uint32_t count; @@ -22,21 +18,22 @@ struct YGNodeList { }; YGNodeListRef YGNodeListNew(const uint32_t initialCapacity) { - const YGNodeListRef list = gYGMalloc(sizeof(struct YGNodeList)); - YGAssert(list != NULL, "Could not allocate memory for list"); + const YGNodeListRef list = + (const YGNodeListRef)malloc(sizeof(struct YGNodeList)); + YGAssert(list != nullptr, "Could not allocate memory for list"); list->capacity = initialCapacity; list->count = 0; - list->items = gYGMalloc(sizeof(YGNodeRef) * list->capacity); - YGAssert(list->items != NULL, "Could not allocate memory for items"); + list->items = (YGNodeRef*)malloc(sizeof(YGNodeRef) * list->capacity); + YGAssert(list->items != nullptr, "Could not allocate memory for items"); return list; } void YGNodeListFree(const YGNodeListRef list) { if (list) { - gYGFree(list->items); - gYGFree(list); + free(list->items); + free(list); } } @@ -62,8 +59,9 @@ void YGNodeListInsert(YGNodeListRef *listp, const YGNodeRef node, const uint32_t if (list->count == list->capacity) { list->capacity *= 2; - list->items = gYGRealloc(list->items, sizeof(YGNodeRef) * list->capacity); - YGAssert(list->items != NULL, "Could not extend allocation for items"); + list->items = + (YGNodeRef*)realloc(list->items, sizeof(YGNodeRef) * list->capacity); + YGAssert(list->items != nullptr, "Could not extend allocation for items"); } for (uint32_t i = list->count; i > index; i--) { @@ -80,18 +78,18 @@ void YGNodeListReplace(YGNodeListRef list, const uint32_t index, const YGNodeRef void YGNodeListRemoveAll(const YGNodeListRef list) { for (uint32_t i = 0; i < list->count; i++) { - list->items[i] = NULL; + list->items[i] = nullptr; } list->count = 0; } YGNodeRef YGNodeListRemove(const YGNodeListRef list, const uint32_t index) { const YGNodeRef removed = list->items[index]; - list->items[index] = NULL; + list->items[index] = nullptr; for (uint32_t i = index; i < list->count - 1; i++) { list->items[i] = list->items[i + 1]; - list->items[i + 1] = NULL; + list->items[i + 1] = nullptr; } list->count--; @@ -105,7 +103,7 @@ YGNodeRef YGNodeListDelete(const YGNodeListRef list, const YGNodeRef node) { } } - return NULL; + return nullptr; } YGNodeRef YGNodeListGet(const YGNodeListRef list, const uint32_t index) { @@ -113,16 +111,16 @@ YGNodeRef YGNodeListGet(const YGNodeListRef list, const uint32_t index) { return list->items[index]; } - return NULL; + return nullptr; } YGNodeListRef YGNodeListClone(const YGNodeListRef oldList) { if (!oldList) { - return NULL; + return nullptr; } const uint32_t count = oldList->count; if (count == 0) { - return NULL; + return nullptr; } const YGNodeListRef newList = YGNodeListNew(count); memcpy(newList->items, oldList->items, sizeof(YGNodeRef) * count); diff --git a/ReactCommon/yoga/yoga/Yoga.c b/ReactCommon/yoga/yoga/Yoga.cpp similarity index 95% rename from ReactCommon/yoga/yoga/Yoga.c rename to ReactCommon/yoga/yoga/Yoga.cpp index 45b37b9d8d0ce1..960a4f3bb3f582 100644 --- a/ReactCommon/yoga/yoga/Yoga.c +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -18,7 +18,6 @@ #ifndef isnan #define isnan _isnan #endif - #ifndef __cplusplus #define inline __inline #endif @@ -157,55 +156,74 @@ static const float kDefaultFlexGrow = 0.0f; static const float kDefaultFlexShrink = 0.0f; static const float kWebDefaultFlexShrink = 1.0f; +static const YGStyle gYGNodeStyleDefaults = { + .direction = YGDirectionInherit, + .flexDirection = YGFlexDirectionColumn, + .justifyContent = YGJustifyFlexStart, + .alignContent = YGAlignFlexStart, + .alignItems = YGAlignStretch, + .alignSelf = YGAlignAuto, + .positionType = YGPositionTypeRelative, + .flexWrap = YGWrapNoWrap, + .overflow = YGOverflowVisible, + .display = YGDisplayFlex, + .flex = YGUndefined, + .flexGrow = YGUndefined, + .flexShrink = YGUndefined, + .flexBasis = YG_AUTO_VALUES, + .margin = YG_DEFAULT_EDGE_VALUES_UNIT, + .position = YG_DEFAULT_EDGE_VALUES_UNIT, + .padding = YG_DEFAULT_EDGE_VALUES_UNIT, + .border = YG_DEFAULT_EDGE_VALUES_UNIT, + .dimensions = YG_DEFAULT_DIMENSION_VALUES_AUTO_UNIT, + .minDimensions = YG_DEFAULT_DIMENSION_VALUES_UNIT, + .maxDimensions = YG_DEFAULT_DIMENSION_VALUES_UNIT, + .aspectRatio = YGUndefined, +}; + +static const YGLayout gYGNodeLayoutDefaults = { + .position = {}, + .dimensions = YG_DEFAULT_DIMENSION_VALUES, + .margin = {}, + .border = {}, + .padding = {}, + .direction = YGDirectionInherit, + .computedFlexBasisGeneration = 0, + .computedFlexBasis = YGUndefined, + .hadOverflow = false, + .generationCount = 0, + .lastParentDirection = (YGDirection)-1, + .nextCachedMeasurementsIndex = 0, + .cachedMeasurements = {}, + .measuredDimensions = YG_DEFAULT_DIMENSION_VALUES, + .cachedLayout = + { + .availableWidth = 0, + .availableHeight = 0, + .widthMeasureMode = (YGMeasureMode)-1, + .heightMeasureMode = (YGMeasureMode)-1, + .computedWidth = -1, + .computedHeight = -1, + }, +}; + static const YGNode gYGNodeDefaults = { - .parent = NULL, - .children = NULL, - .hasNewLayout = true, + .style = gYGNodeStyleDefaults, + .layout = gYGNodeLayoutDefaults, + .lineIndex = 0, + .parent = nullptr, + .children = nullptr, + .nextChild = nullptr, + .measure = nullptr, + .baseline = nullptr, + .print = nullptr, + .config = nullptr, + .context = nullptr, .isDirty = false, + .hasNewLayout = true, .nodeType = YGNodeTypeDefault, .resolvedDimensions = {[YGDimensionWidth] = &YGValueUndefined, [YGDimensionHeight] = &YGValueUndefined}, - - .style = - { - .flex = YGUndefined, - .flexGrow = YGUndefined, - .flexShrink = YGUndefined, - .flexBasis = YG_AUTO_VALUES, - .justifyContent = YGJustifyFlexStart, - .alignItems = YGAlignStretch, - .alignContent = YGAlignFlexStart, - .direction = YGDirectionInherit, - .flexDirection = YGFlexDirectionColumn, - .overflow = YGOverflowVisible, - .display = YGDisplayFlex, - .dimensions = YG_DEFAULT_DIMENSION_VALUES_AUTO_UNIT, - .minDimensions = YG_DEFAULT_DIMENSION_VALUES_UNIT, - .maxDimensions = YG_DEFAULT_DIMENSION_VALUES_UNIT, - .position = YG_DEFAULT_EDGE_VALUES_UNIT, - .margin = YG_DEFAULT_EDGE_VALUES_UNIT, - .padding = YG_DEFAULT_EDGE_VALUES_UNIT, - .border = YG_DEFAULT_EDGE_VALUES_UNIT, - .aspectRatio = YGUndefined, - }, - - .layout = - { - .dimensions = YG_DEFAULT_DIMENSION_VALUES, - .lastParentDirection = (YGDirection) -1, - .nextCachedMeasurementsIndex = 0, - .computedFlexBasis = YGUndefined, - .hadOverflow = false, - .measuredDimensions = YG_DEFAULT_DIMENSION_VALUES, - - .cachedLayout = - { - .widthMeasureMode = (YGMeasureMode) -1, - .heightMeasureMode = (YGMeasureMode) -1, - .computedWidth = -1, - .computedHeight = -1, - }, - }, }; #ifdef ANDROID @@ -225,25 +243,22 @@ static int YGDefaultLog(const YGConfigRef config, static YGConfig gYGConfigDefaults = { .experimentalFeatures = { - [YGExperimentalFeatureWebFlexBasis] = false, + [YGExperimentalFeatureWebFlexBasis] = false, }, .useWebDefaults = false, + .useLegacyStretchBehaviour = false, .pointScaleFactor = 1.0f, #ifdef ANDROID .logger = &YGAndroidLog, #else .logger = &YGDefaultLog, #endif - .context = NULL, + .cloneNodeCallback = nullptr, + .context = nullptr, }; static void YGNodeMarkDirtyInternal(const YGNodeRef node); -YGMalloc gYGMalloc = &malloc; -YGCalloc gYGCalloc = &calloc; -YGRealloc gYGRealloc = &realloc; -YGFree gYGFree = &free; - static YGValue YGValueZero = {.value = 0, .unit = YGUnitPoint}; #ifdef ANDROID @@ -297,6 +312,10 @@ static int YGDefaultLog(const YGConfigRef config, } #endif +bool YGFloatIsUndefined(const float value) { + return isnan(value); +} + static inline const YGValue *YGComputedEdgeValue(const YGValue edges[YGEdgeCount], const YGEdge edge, const YGValue *const defaultValue) { @@ -346,8 +365,9 @@ int32_t gNodeInstanceCount = 0; int32_t gConfigInstanceCount = 0; WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) { - const YGNodeRef node = gYGMalloc(sizeof(YGNode)); - YGAssertWithConfig(config, node != NULL, "Could not allocate memory for node"); + const YGNodeRef node = (const YGNodeRef)malloc(sizeof(YGNode)); + YGAssertWithConfig( + config, node != nullptr, "Could not allocate memory for node"); gNodeInstanceCount++; memcpy(node, &gYGNodeDefaults, sizeof(YGNode)); @@ -364,30 +384,31 @@ YGNodeRef YGNodeNew(void) { } YGNodeRef YGNodeClone(const YGNodeRef oldNode) { - const YGNodeRef node = gYGMalloc(sizeof(YGNode)); - YGAssertWithConfig(oldNode->config, node != NULL, "Could not allocate memory for node"); + const YGNodeRef node = (const YGNodeRef)malloc(sizeof(YGNode)); + YGAssertWithConfig( + oldNode->config, node != nullptr, "Could not allocate memory for node"); gNodeInstanceCount++; memcpy(node, oldNode, sizeof(YGNode)); node->children = YGNodeListClone(oldNode->children); - node->parent = NULL; + node->parent = nullptr; return node; } void YGNodeFree(const YGNodeRef node) { if (node->parent) { YGNodeListDelete(node->parent->children, node); - node->parent = NULL; + node->parent = nullptr; } const uint32_t childCount = YGNodeGetChildCount(node); for (uint32_t i = 0; i < childCount; i++) { const YGNodeRef child = YGNodeGetChild(node, i); - child->parent = NULL; + child->parent = nullptr; } YGNodeListFree(node->children); - gYGFree(node); + free(node); gNodeInstanceCount--; } @@ -408,7 +429,10 @@ void YGNodeReset(const YGNodeRef node) { YGAssertWithNode(node, YGNodeGetChildCount(node) == 0, "Cannot reset a node which still has children attached"); - YGAssertWithNode(node, node->parent == NULL, "Cannot reset a node still attached to a parent"); + YGAssertWithNode( + node, + node->parent == nullptr, + "Cannot reset a node still attached to a parent"); YGNodeListFree(node->children); @@ -435,8 +459,8 @@ YGConfigRef YGConfigGetDefault() { } YGConfigRef YGConfigNew(void) { - const YGConfigRef config = gYGMalloc(sizeof(YGConfig)); - YGAssert(config != NULL, "Could not allocate memory for config"); + const YGConfigRef config = (const YGConfigRef)malloc(sizeof(YGConfig)); + YGAssert(config != nullptr, "Could not allocate memory for config"); gConfigInstanceCount++; memcpy(config, &gYGConfigDefaults, sizeof(YGConfig)); @@ -444,7 +468,7 @@ YGConfigRef YGConfigNew(void) { } void YGConfigFree(const YGConfigRef config) { - gYGFree(config); + free(config); gConfigInstanceCount--; } @@ -463,8 +487,8 @@ static void YGNodeMarkDirtyInternal(const YGNodeRef node) { } void YGNodeSetMeasureFunc(const YGNodeRef node, YGMeasureFunc measureFunc) { - if (measureFunc == NULL) { - node->measure = NULL; + if (measureFunc == nullptr) { + node->measure = nullptr; // TODO: t18095186 Move nodeType to opt-in function and mark appropriate places in Litho node->nodeType = YGNodeTypeDefault; } else { @@ -519,12 +543,14 @@ static void YGCloneChildrenIfNeeded(const YGNodeRef parent) { } void YGNodeInsertChild(const YGNodeRef node, const YGNodeRef child, const uint32_t index) { - YGAssertWithNode(node, - child->parent == NULL, - "Child already has a parent, it must be removed first."); - YGAssertWithNode(node, - node->measure == NULL, - "Cannot add child: Nodes with measure functions cannot have children."); + YGAssertWithNode( + node, + child->parent == nullptr, + "Child already has a parent, it must be removed first."); + YGAssertWithNode( + node, + node->measure == nullptr, + "Cannot add child: Nodes with measure functions cannot have children."); YGCloneChildrenIfNeeded(node); @@ -544,9 +570,9 @@ void YGNodeRemoveChild(const YGNodeRef parent, const YGNodeRef excludedChild) { if (firstChild->parent == parent) { // If the first child has this node as its parent, we assume that it is already unique. // We can now try to delete a child in this list. - if (YGNodeListDelete(parent->children, excludedChild) != NULL) { + if (YGNodeListDelete(parent->children, excludedChild) != nullptr) { excludedChild->layout = gYGNodeDefaults.layout; // layout is no longer valid - excludedChild->parent = NULL; + excludedChild->parent = nullptr; YGNodeMarkDirtyInternal(parent); } return; @@ -592,14 +618,14 @@ void YGNodeRemoveAllChildren(const YGNodeRef parent) { for (uint32_t i = 0; i < childCount; i++) { const YGNodeRef oldChild = YGNodeGetChild(parent, i); oldChild->layout = gYGNodeDefaults.layout; // layout is no longer valid - oldChild->parent = NULL; + oldChild->parent = nullptr; } YGNodeListRemoveAll(parent->children); YGNodeMarkDirtyInternal(parent); return; } // Otherwise, we are not the owner of the child set. We don't have to do anything to clear it. - parent->children = NULL; + parent->children = nullptr; YGNodeMarkDirtyInternal(parent); } @@ -616,10 +642,11 @@ uint32_t YGNodeGetChildCount(const YGNodeRef node) { } void YGNodeMarkDirty(const YGNodeRef node) { - YGAssertWithNode(node, - node->measure != NULL, - "Only leaf nodes with custom measure functions" - "should manually mark themselves as dirty"); + YGAssertWithNode( + node, + node->measure != nullptr, + "Only leaf nodes with custom measure functions" + "should manually mark themselves as dirty"); YGNodeMarkDirtyInternal(node); } @@ -637,7 +664,7 @@ void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode) { static inline float YGResolveFlexGrow(const YGNodeRef node) { // Root nodes flexGrow should always be 0 - if (node->parent == NULL) { + if (node->parent == nullptr) { return 0.0; } if (!YGFloatIsUndefined(node->style.flexGrow)) { @@ -661,7 +688,7 @@ float YGNodeStyleGetFlexShrink(const YGNodeRef node) { static inline float YGNodeResolveFlexShrink(const YGNodeRef node) { // Root nodes flexShrink should always be 0 - if (node->parent == NULL) { + if (node->parent == nullptr) { return 0.0; } if (!YGFloatIsUndefined(node->style.flexShrink)) { @@ -913,10 +940,6 @@ bool YGLayoutNodeInternal(const YGNodeRef node, const char *reason, const YGConfigRef config); -inline bool YGFloatIsUndefined(const float value) { - return isnan(value); -} - static inline bool YGValueEqual(const YGValue a, const YGValue b) { if (a.unit != b.unit) { return false; @@ -930,7 +953,7 @@ static inline bool YGValueEqual(const YGValue a, const YGValue b) { } static inline void YGResolveDimensions(YGNodeRef node) { - for (YGDimension dim = YGDimensionWidth; dim <= YGDimensionHeight; dim++) { + for (uint32_t dim = YGDimensionWidth; dim < YGDimensionCount; dim++) { if (node->style.maxDimensions[dim].unit != YGUnitUndefined && YGValueEqual(node->style.maxDimensions[dim], node->style.minDimensions[dim])) { node->resolvedDimensions[dim] = &node->style.maxDimensions[dim]; @@ -959,11 +982,11 @@ static void YGWriteToStringStream(YGStringStream *stream, const char *format, .. va_list argsCopy; va_copy(argsCopy, args); int available = stream->capacity - stream->length; - int required = vsnprintf(NULL, 0, format, args); + int required = vsnprintf(nullptr, 0, format, args); va_end(args); if (required >= available) { char *newStr = (char *) realloc(stream->str, sizeof(char) * (stream->capacity) * 2); - if (newStr != NULL) { + if (newStr != nullptr) { stream->str = newStr; stream->capacity *= 2; available = stream->capacity - stream->length; @@ -1037,9 +1060,9 @@ static void YGPrintEdges(YGStringStream *stream, const char *str, const YGValue if (YGFourValuesEqual(edges)) { YGPrintNumberIfNotZero(stream, str, &edges[YGEdgeLeft]); } else { - for (YGEdge edge = YGEdgeLeft; edge < YGEdgeCount; edge++) { + for (uint32_t edge = 0; edge < YGEdgeCount; edge++) { char buf[30]; - snprintf(buf, sizeof(buf), "%s-%s", str, YGEdgeToString(edge)); + snprintf(buf, sizeof(buf), "%s-%s", str, YGEdgeToString((YGEdge)edge)); YGPrintNumberIfNotZero(stream, buf, &edges[edge]); } } @@ -1127,7 +1150,7 @@ static void YGNodeToString(YGStringStream *stream, YGPrintEdgeIfNotUndefined(stream, "bottom", node->style.position, YGEdgeBottom); YGWriteToStringStream(stream, "\" "); - if (node->measure != NULL) { + if (node->measure != nullptr) { YGWriteToStringStream(stream, "has-custom-measure=\"true\""); } } @@ -1151,7 +1174,7 @@ static void YGNodePrintInternal(const YGNodeRef node, stream.str = (char *) malloc(sizeof(char) * 1024); stream.length = 0; stream.capacity = 1024; - if (stream.str != NULL) { + if (stream.str != nullptr) { YGNodeToString(&stream, node, options, 0); YGLog(node, YGLogLevelDebug, stream.str); free(stream.str); @@ -1305,7 +1328,7 @@ static inline YGDirection YGNodeResolveDirection(const YGNodeRef node, } static float YGBaseline(const YGNodeRef node) { - if (node->baseline != NULL) { + if (node->baseline != nullptr) { const float baseline = node->baseline(node, node->layout.measuredDimensions[YGDimensionWidth], node->layout.measuredDimensions[YGDimensionHeight]); @@ -1315,7 +1338,7 @@ static float YGBaseline(const YGNodeRef node) { return baseline; } - YGNodeRef baselineChild = NULL; + YGNodeRef baselineChild = nullptr; const uint32_t childCount = YGNodeGetChildCount(node); for (uint32_t i = 0; i < childCount; i++) { const YGNodeRef child = YGNodeGetChild(node, i); @@ -1330,12 +1353,12 @@ static float YGBaseline(const YGNodeRef node) { break; } - if (baselineChild == NULL) { + if (baselineChild == nullptr) { baselineChild = child; } } - if (baselineChild == NULL) { + if (baselineChild == nullptr) { return node->layout.measuredDimensions[YGDimensionHeight]; } @@ -1563,7 +1586,8 @@ static void YGNodeSetPosition(const YGNodeRef node, const float crossSize, const float parentWidth) { /* Root nodes should be always layouted as LTR, so we don't return negative values. */ - const YGDirection directionRespectingRoot = node->parent != NULL ? direction : YGDirectionLTR; + const YGDirection directionRespectingRoot = + node->parent != nullptr ? direction : YGDirectionLTR; const YGFlexDirection mainAxis = YGResolveFlexDirection(node->style.flexDirection, directionRespectingRoot); const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, directionRespectingRoot); @@ -1889,7 +1913,10 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions(const YGNodeRef node, const YGMeasureMode heightMeasureMode, const float parentWidth, const float parentHeight) { - YGAssertWithNode(node, node->measure != NULL, "Expected node to have custom measure function"); + YGAssertWithNode( + node, + node->measure != nullptr, + "Expected node to have custom measure function"); const float paddingAndBorderAxisRow = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, availableWidth); @@ -2207,8 +2234,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, const float mainAxisParentSize = isMainAxisRow ? parentWidth : parentHeight; const float crossAxisParentSize = isMainAxisRow ? parentHeight : parentWidth; - YGNodeRef firstAbsoluteChild = NULL; - YGNodeRef currentAbsoluteChild = NULL; + YGNodeRef firstAbsoluteChild = nullptr; + YGNodeRef currentAbsoluteChild = nullptr; const float leadingPaddingAndBorderMain = YGNodeLeadingPaddingAndBorder(node, mainAxis, parentWidth); @@ -2267,14 +2294,14 @@ static void YGNodelayoutImpl(const YGNodeRef node, // If there is only one child with flexGrow + flexShrink it means we can set the // computedFlexBasis to 0 instead of measuring and shrinking / flexing the child to exactly // match the remaining space - YGNodeRef singleFlexChild = NULL; + YGNodeRef singleFlexChild = nullptr; if (measureModeMainDim == YGMeasureModeExactly) { for (uint32_t i = 0; i < childCount; i++) { const YGNodeRef child = YGNodeGetChild(node, i); if (singleFlexChild) { if (YGNodeIsFlex(child)) { // There is already a flexible child, abort. - singleFlexChild = NULL; + singleFlexChild = nullptr; break; } } else if (YGResolveFlexGrow(child) > 0.0f && YGNodeResolveFlexShrink(child) > 0.0f) { @@ -2310,14 +2337,14 @@ static void YGNodelayoutImpl(const YGNodeRef node, if (child->style.positionType == YGPositionTypeAbsolute) { // Store a private linked list of absolutely positioned children // so that we can efficiently traverse them later. - if (firstAbsoluteChild == NULL) { + if (firstAbsoluteChild == nullptr) { firstAbsoluteChild = child; } - if (currentAbsoluteChild != NULL) { + if (currentAbsoluteChild != nullptr) { currentAbsoluteChild->nextChild = child; } currentAbsoluteChild = child; - child->nextChild = NULL; + child->nextChild = nullptr; } else { if (child == singleFlexChild) { child->layout.computedFlexBasisGeneration = gCurrentGenerationCount; @@ -2381,8 +2408,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, float totalFlexShrinkScaledFactors = 0; // Maintain a linked list of the child nodes that can shrink and/or grow. - YGNodeRef firstRelativeChild = NULL; - YGNodeRef currentRelativeChild = NULL; + YGNodeRef firstRelativeChild = nullptr; + YGNodeRef currentRelativeChild = nullptr; // Add items to the current line until it's full or we run out of items. for (uint32_t i = startOfLineIndex; i < childCount; i++, endOfLineIndex++) { @@ -2426,14 +2453,14 @@ static void YGNodelayoutImpl(const YGNodeRef node, } // Store a private linked list of children that need to be layed out. - if (firstRelativeChild == NULL) { + if (firstRelativeChild == nullptr) { firstRelativeChild = child; } - if (currentRelativeChild != NULL) { + if (currentRelativeChild != nullptr) { currentRelativeChild->nextChild = child; } currentRelativeChild = child; - child->nextChild = NULL; + child->nextChild = nullptr; } } @@ -2526,7 +2553,7 @@ static void YGNodelayoutImpl(const YGNodeRef node, float deltaFlexShrinkScaledFactors = 0; float deltaFlexGrowFactors = 0; currentRelativeChild = firstRelativeChild; - while (currentRelativeChild != NULL) { + while (currentRelativeChild != nullptr) { childFlexBasis = fminf(YGResolveValue(¤tRelativeChild->style.maxDimensions[dim[mainAxis]], mainAxisParentSize), @@ -2594,7 +2621,7 @@ static void YGNodelayoutImpl(const YGNodeRef node, // Second pass: resolve the sizes of the flexible items deltaFreeSpace = 0; currentRelativeChild = firstRelativeChild; - while (currentRelativeChild != NULL) { + while (currentRelativeChild != nullptr) { childFlexBasis = fminf(YGResolveValue(¤tRelativeChild->style.maxDimensions[dim[mainAxis]], mainAxisParentSize), @@ -3215,7 +3242,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, if (performLayout) { // STEP 10: SIZING AND POSITIONING ABSOLUTE CHILDREN - for (currentAbsoluteChild = firstAbsoluteChild; currentAbsoluteChild != NULL; + for (currentAbsoluteChild = firstAbsoluteChild; + currentAbsoluteChild != nullptr; currentAbsoluteChild = currentAbsoluteChild->nextChild) { YGNodeAbsoluteLayoutChild(node, currentAbsoluteChild, @@ -3322,7 +3350,8 @@ float YGRoundValueToPixelGrid(const float value, scaledValue = scaledValue - fractial; } else { // Finally we just round the value - scaledValue = scaledValue - fractial + (fractial > 0.5f || YGFloatsEqual(fractial, 0.5f) ? 1.0f : 0.0f); + scaledValue = scaledValue - fractial + + (fractial > 0.5f || YGFloatsEqual(fractial, 0.5f) ? 1.0f : 0.0f); } return scaledValue / pointScaleFactor; } @@ -3343,7 +3372,8 @@ bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode, if (lastComputedHeight < 0 || lastComputedWidth < 0) { return false; } - bool useRoundedComparison = config != NULL && config->pointScaleFactor != 0; + bool useRoundedComparison = + config != nullptr && config->pointScaleFactor != 0; const float effectiveWidth = useRoundedComparison ? YGRoundValueToPixelGrid(width, config->pointScaleFactor, false, false) : width; @@ -3425,7 +3455,7 @@ bool YGLayoutNodeInternal(const YGNodeRef node, layout->cachedLayout.computedHeight = -1; } - YGCachedMeasurement *cachedResults = NULL; + YGCachedMeasurement* cachedResults = nullptr; // Determine whether the results are already cached. We maintain a separate // cache for layouts and measurements. A layout operation modifies the @@ -3498,36 +3528,48 @@ bool YGLayoutNodeInternal(const YGNodeRef node, } } - if (!needToVisitNode && cachedResults != NULL) { + if (!needToVisitNode && cachedResults != nullptr) { layout->measuredDimensions[YGDimensionWidth] = cachedResults->computedWidth; layout->measuredDimensions[YGDimensionHeight] = cachedResults->computedHeight; if (gPrintChanges && gPrintSkips) { - printf("%s%d.{[skipped] ", YGSpacer(gDepth), gDepth); + YGLog(node, YGLogLevelVerbose, "%s%d.{[skipped] ", YGSpacer(gDepth), gDepth); if (node->print) { node->print(node); } - printf("wm: %s, hm: %s, aw: %f ah: %f => d: (%f, %f) %s\n", - YGMeasureModeName(widthMeasureMode, performLayout), - YGMeasureModeName(heightMeasureMode, performLayout), - availableWidth, - availableHeight, - cachedResults->computedWidth, - cachedResults->computedHeight, - reason); + YGLog( + node, + YGLogLevelVerbose, + "wm: %s, hm: %s, aw: %f ah: %f => d: (%f, %f) %s\n", + YGMeasureModeName(widthMeasureMode, performLayout), + YGMeasureModeName(heightMeasureMode, performLayout), + availableWidth, + availableHeight, + cachedResults->computedWidth, + cachedResults->computedHeight, + reason); } } else { if (gPrintChanges) { - printf("%s%d.{%s", YGSpacer(gDepth), gDepth, needToVisitNode ? "*" : ""); + YGLog( + node, + YGLogLevelVerbose, + "%s%d.{%s", + YGSpacer(gDepth), + gDepth, + needToVisitNode ? "*" : ""); if (node->print) { node->print(node); } - printf("wm: %s, hm: %s, aw: %f ah: %f %s\n", - YGMeasureModeName(widthMeasureMode, performLayout), - YGMeasureModeName(heightMeasureMode, performLayout), - availableWidth, - availableHeight, - reason); + YGLog( + node, + YGLogLevelVerbose, + "wm: %s, hm: %s, aw: %f ah: %f %s\n", + YGMeasureModeName(widthMeasureMode, performLayout), + YGMeasureModeName(heightMeasureMode, performLayout), + availableWidth, + availableHeight, + reason); } YGNodelayoutImpl(node, @@ -3542,24 +3584,33 @@ bool YGLayoutNodeInternal(const YGNodeRef node, config); if (gPrintChanges) { - printf("%s%d.}%s", YGSpacer(gDepth), gDepth, needToVisitNode ? "*" : ""); + YGLog( + node, + YGLogLevelVerbose, + "%s%d.}%s", + YGSpacer(gDepth), + gDepth, + needToVisitNode ? "*" : ""); if (node->print) { node->print(node); } - printf("wm: %s, hm: %s, d: (%f, %f) %s\n", - YGMeasureModeName(widthMeasureMode, performLayout), - YGMeasureModeName(heightMeasureMode, performLayout), - layout->measuredDimensions[YGDimensionWidth], - layout->measuredDimensions[YGDimensionHeight], - reason); + YGLog( + node, + YGLogLevelVerbose, + "wm: %s, hm: %s, d: (%f, %f) %s\n", + YGMeasureModeName(widthMeasureMode, performLayout), + YGMeasureModeName(heightMeasureMode, performLayout), + layout->measuredDimensions[YGDimensionWidth], + layout->measuredDimensions[YGDimensionHeight], + reason); } layout->lastParentDirection = parentDirection; - if (cachedResults == NULL) { + if (cachedResults == nullptr) { if (layout->nextCachedMeasurementsIndex == YG_MAX_CACHED_RESULT_COUNT) { if (gPrintChanges) { - printf("Out of cache entries!\n"); + YGLog(node, YGLogLevelVerbose, "Out of cache entries!\n"); } layout->nextCachedMeasurementsIndex = 0; } @@ -3592,7 +3643,7 @@ bool YGLayoutNodeInternal(const YGNodeRef node, gDepth--; layout->generationCount = gCurrentGenerationCount; - return (needToVisitNode || cachedResults == NULL); + return (needToVisitNode || cachedResults == nullptr); } void YGConfigSetPointScaleFactor(const YGConfigRef config, const float pixelsInPoint) { @@ -3719,13 +3770,17 @@ void YGNodeCalculateLayout(const YGNodeRef node, YGRoundToPixelGrid(node, node->config->pointScaleFactor, 0.0f, 0.0f); if (gPrintTree) { - YGNodePrint(node, YGPrintOptionsLayout | YGPrintOptionsChildren | YGPrintOptionsStyle); + YGNodePrint( + node, + (YGPrintOptions)( + YGPrintOptionsLayout | YGPrintOptionsChildren | + YGPrintOptionsStyle)); } } } void YGConfigSetLogger(const YGConfigRef config, YGLogger logger) { - if (logger != NULL) { + if (logger != nullptr) { config->logger = logger; } else { #ifdef ANDROID @@ -3741,7 +3796,7 @@ static void YGVLog(const YGConfigRef config, YGLogLevel level, const char *format, va_list args) { - const YGConfigRef logConfig = config != NULL ? config : &gYGConfigDefaults; + const YGConfigRef logConfig = config != nullptr ? config : &gYGConfigDefaults; logConfig->logger(logConfig, node, level, format, args); if (level == YGLogLevelFatal) { @@ -3752,20 +3807,20 @@ static void YGVLog(const YGConfigRef config, void YGLogWithConfig(const YGConfigRef config, YGLogLevel level, const char *format, ...) { va_list args; va_start(args, format); - YGVLog(config, NULL, level, format, args); + YGVLog(config, nullptr, level, format, args); va_end(args); } void YGLog(const YGNodeRef node, YGLogLevel level, const char *format, ...) { va_list args; va_start(args, format); - YGVLog(node == NULL ? NULL : node->config, node, level, format, args); + YGVLog(node == nullptr ? nullptr : node->config, node, level, format, args); va_end(args); } void YGAssert(const bool condition, const char *message) { if (!condition) { - YGLog(NULL, YGLogLevelFatal, "%s\n", message); + YGLog(nullptr, YGLogLevelFatal, "%s\n", message); } } @@ -3816,23 +3871,3 @@ void *YGConfigGetContext(const YGConfigRef config) { void YGConfigSetNodeClonedFunc(const YGConfigRef config, const YGNodeClonedFunc callback) { config->cloneNodeCallback = callback; } - -void YGSetMemoryFuncs(YGMalloc ygmalloc, YGCalloc yccalloc, YGRealloc ygrealloc, YGFree ygfree) { - YGAssert(gNodeInstanceCount == 0 && gConfigInstanceCount == 0, - "Cannot set memory functions: all node must be freed first"); - YGAssert((ygmalloc == NULL && yccalloc == NULL && ygrealloc == NULL && ygfree == NULL) || - (ygmalloc != NULL && yccalloc != NULL && ygrealloc != NULL && ygfree != NULL), - "Cannot set memory functions: functions must be all NULL or Non-NULL"); - - if (ygmalloc == NULL || yccalloc == NULL || ygrealloc == NULL || ygfree == NULL) { - gYGMalloc = &malloc; - gYGCalloc = &calloc; - gYGRealloc = &realloc; - gYGFree = &free; - } else { - gYGMalloc = ygmalloc; - gYGCalloc = yccalloc; - gYGRealloc = ygrealloc; - gYGFree = ygfree; - } -} diff --git a/ReactCommon/yoga/yoga/Yoga.h b/ReactCommon/yoga/yoga/Yoga.h index ae954c5125ea35..370b8f770fe19f 100644 --- a/ReactCommon/yoga/yoga/Yoga.h +++ b/ReactCommon/yoga/yoga/Yoga.h @@ -65,11 +65,6 @@ typedef void (*YGNodeClonedFunc)(YGNodeRef oldNode, YGNodeRef parent, int childIndex); -typedef void *(*YGMalloc)(size_t size); -typedef void *(*YGCalloc)(size_t count, size_t size); -typedef void *(*YGRealloc)(void *ptr, size_t size); -typedef void (*YGFree)(void *ptr); - // YGNode WIN_EXPORT YGNodeRef YGNodeNew(void); WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config); @@ -279,7 +274,4 @@ WIN_EXPORT YGConfigRef YGConfigGetDefault(void); WIN_EXPORT void YGConfigSetContext(const YGConfigRef config, void *context); WIN_EXPORT void *YGConfigGetContext(const YGConfigRef config); -WIN_EXPORT void -YGSetMemoryFuncs(YGMalloc ygmalloc, YGCalloc yccalloc, YGRealloc ygrealloc, YGFree ygfree); - YG_EXTERN_C_END diff --git a/blog/2017-11-06-react-native-monthly-5.md b/blog/2017-11-06-react-native-monthly-5.md new file mode 100644 index 00000000000000..a5e65d05bbd3a9 --- /dev/null +++ b/blog/2017-11-06-react-native-monthly-5.md @@ -0,0 +1,61 @@ +--- +title: React Native Monthly #5 +author: Tomislav Tenodi +authorTitle: Founder at Speck +authorURL: https://github.com/tenodi +authorImage: https://pbs.twimg.com/profile_images/877237660225609729/bKFDwfAq.jpg +authorTwitter: TomislavTenodi +category: engineering +--- + +The React Native monthly meeting continues! Let's see what our teams are up to. + +### Callstack + +- We’ve been working on React Native CI. Most importantly, we have migrated from Travis to Circle, leaving React Native with a single, unified CI pipeline. +- We’ve organised [Hacktoberfest - React Native edition](https://blog.callstack.io/announcing-hacktoberfest-7313ea5ccf4f) where, together with attendees, we tried to submit many pull requests to open source projects. +- We keep working on [Haul](https://github.com/callstack/haul). Last month, we have submitted two new releases, including Webpack 3 support. We plan to add [CRNA](https://github.com/react-community/create-react-native-app) and [Expo](https://github.com/expo/expo) support as well as work on better HMR. Our roadmap is public on the issue tracker. If you would like to suggest improvements or give feedback, let us know! + +### Expo + +- Released [Expo SDK 22](https://blog.expo.io/expo-sdk-v22-0-0-is-now-available-7745bfe97fc6) (using React Native 0.49) and updated [CRNA](https://github.com/react-community/create-react-native-app) for it. + - Includes improved splash screen API, basic ARKit support, “DeviceMotion” API, SFAuthenticationSession support on iOS11, and [more](https://blog.expo.io/expo-sdk-v22-0-0-is-now-available-7745bfe97fc6). +- Your [snacks](https://snack.expo.io) can now have multiple JavaScript files and you can upload images and other assets by just dragging them into the editor. +- Contribute to [react-navigation](https://github.com/react-community/react-navigation) to add support for iPhone X. +- Focus our attention on rough edges when building large applications with Expo. For example: + - First-class support for deploying to multiple environments: staging, production, and arbitrary channels. Channels will support rolling back and setting the active release for a given channel. Let us know if you want to be an early tester, [@expo_io](https://twitter.com/expo_io). + - We are also working on improving our standalone app building infrastructure and adding support for bundling images and other non-code assets in standalone app builds while keeping the ability to update assets over the air. + +### Facebook + +- Better RTL support: + - We’re introducing a number of direction-aware styles. + - Position: + - (left|right) → (start|end) + - Margin: + - margin(Left|Right) → margin(Start|End) + - Padding: + - padding(Left|Right) → padding(Start|End) + - Border: + - borderTop(Left|Right)Radius → borderTop(Start|End)Radius + - borderBottom(Left|Right)Radius → borderBottom(Start|End)Radius + - border(Left|Right)Width → border(Start|End)Width + - border(Left|Right)Color → border(Start|End)Color + - The meaning of “left” and “right” were swapped in RTL for position, margin, padding, and border styles. Within a few months, we’re going to remove this behaviour and make “left” always mean “left,” and “right” always mean “right”. The breaking changes are hidden under a flag. Use `I18nManager.swapLeftAndRightInRTL(false)` in your React Native components to opt into them. +- Working on [Flow](https://github.com/facebook/flow) typing our internal native modules and using those to generate interfaces in Java and protocols in ObjC that the native implementations must implement. We hope this codegen becomes open source next year, at the earliest. + + +### Infinite Red + +- New OSS tool for helping React Native and other projects. More [here](https://shift.infinite.red/solidarity-the-cli-for-developer-sanity-672fa81b98e9). +- Revamping [Ignite](https://github.com/infinitered/ignite) for a new boilerplate release (Code name: Bowser) + +### Shoutem + +- Improving the development flow on Shoutem. We want to streamline the process from creating an app to first custom screen and make it really easy, thus lowering the barrier for new React Native developers. Prepared a few workshops to test out new features. We also improved [Shoutem CLI](https://github.com/shoutem/cli) to support new flows. +- [Shoutem UI](https://github.com/shoutem/ui) received a few component improvements and bugfixes. We also checked compatibility with latest React Native versions. +- Shoutem platform received a few notable updates, new integrations are available as part of the [open-source extensions project](https://github.com/shoutem/extensions). We are really excited to see active development on Shoutem extensions from other developers. We actively contact and offer advice and guidance about their extensions. + +## Next session + +The next session is scheduled for Wednesday 6, December 2017. Feel free to ping me [on Twitter](https://twitter.com/TomislavTenodi) if you have any suggestion on how we should improve the output of the meeting. diff --git a/docs/AndroidUIPerformance.md b/docs/AndroidUIPerformance.md deleted file mode 100644 index b19442995b1276..00000000000000 --- a/docs/AndroidUIPerformance.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -id: android-ui-performance -title: Profiling Android UI Performance -layout: redirect -permalink: docs/android-ui-performance.html -destinationUrl: performance.html ---- diff --git a/docs/Images.md b/docs/Images.md index 4e05595ebe3452..6a709d6d6997ae 100644 --- a/docs/Images.md +++ b/docs/Images.md @@ -4,7 +4,7 @@ title: Images layout: docs category: Guides permalink: docs/images.html -next: animations +next: animations previous: navigation --- diff --git a/docs/RunningOnDeviceAndroid.md b/docs/RunningOnDeviceAndroid.md deleted file mode 100644 index cb8b3e58d9e4ea..00000000000000 --- a/docs/RunningOnDeviceAndroid.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -id: running-on-device-android -title: Running On Device -layout: redirect -permalink: docs/running-on-device-android.html -destinationUrl: running-on-device.html ---- diff --git a/docs/RunningOnDeviceIOS.md b/docs/RunningOnDeviceIOS.md deleted file mode 100644 index 886c000d6c4fcd..00000000000000 --- a/docs/RunningOnDeviceIOS.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -id: running-on-device-ios -title: Running On Device -layout: redirect -permalink: docs/running-on-device-ios.html -destinationUrl: running-on-device.html ---- diff --git a/docs/StyleGuide.md b/docs/StyleGuide.md deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/docs/accessibilityinfo.md b/docs/accessibilityinfo.md new file mode 100644 index 00000000000000..bbccd499b6f42d --- /dev/null +++ b/docs/accessibilityinfo.md @@ -0,0 +1,157 @@ +--- +id: accessibilityinfo +title: AccessibilityInfo +layout: docs +category: APIs +permalink: docs/accessibilityinfo.html +next: actionsheetios +previous: webview +--- + +Sometimes it's useful to know whether or not the device has a screen reader that is currently active. The `AccessibilityInfo` API is designed for this purpose. You can use it to query the current state of the screen reader as well as to register to be notified when the state of the screen reader changes. + +Here's a small example illustrating how to use `AccessibilityInfo`: + +```javascript +class ScreenReaderStatusExample extends React.Component { + state = { + screenReaderEnabled: false, + } + + componentDidMount() { + AccessibilityInfo.addEventListener( + 'change', + this._handleScreenReaderToggled + ); + AccessibilityInfo.fetch().done((isEnabled) => { + this.setState({ + screenReaderEnabled: isEnabled + }); + }); + } + + componentWillUnmount() { + AccessibilityInfo.removeEventListener( + 'change', + this._handleScreenReaderToggled + ); + } + + _handleScreenReaderToggled = (isEnabled) => { + this.setState({ + screenReaderEnabled: isEnabled, + }); + } + + render() { + return ( + + + The screen reader is {this.state.screenReaderEnabled ? 'enabled' : 'disabled'}. + + + ); + } +} +``` + +### Methods + +- [`fetch`](docs/accessibilityinfo.html#fetch) +- [`addEventListener`](docs/accessibilityinfo.html#addeventlistener) +- [`setAccessibilityFocus`](docs/accessibilityinfo.html#setaccessibilityfocus) +- [`announceForAccessibility`](docs/accessibilityinfo.html#announceforaccessibility) +- [`removeEventListener`](docs/accessibilityinfo.html#removeeventlistener) + +--- + +# Reference + +## Methods + +### `fetch()` + +```javascript +AccessibilityInfo.fetch() +``` + +Query whether a screen reader is currently enabled. Returns a promise which resolves to a boolean. The result is `true` when a screen reader is enabled and `false` otherwise. + +--- + +### `addEventListener()` + +```javascript +AccessibilityInfo.addEventListener(eventName, handler) +``` + +Add an event handler. + +| Name | Type | Required | Description | +| - | - | - | - | +| eventName | string | Yes | Name of the event | +| handler | function | Yes | Event handler | + +Supported events: + +- `change`: Fires when the state of the screen reader changes. The argument + to the event handler is a boolean. The boolean is `true` when a screen + reader is enabled and `false` otherwise. +- `announcementFinished`: iOS-only event. Fires when the screen reader has + finished making an announcement. The argument to the event handler is a dictionary + with these keys: + - `announcement`: The string announced by the screen reader. + - `success`: A boolean indicating whether the announcement was successfully made. + +--- + +### `setAccessibilityFocus()` + +```javascript +AccessibilityInfo.setAccessibilityFocus(reactTag) +``` + +Set accessibility focus to a React component. + +| Name | Type | Required | Description | +| - | - | - | - | +| reactTag | number | Yes | React component tag | + +| Platform | +| - | +| iOS | + + +--- + +### `announceForAccessibility()` + +```javascript +AccessibilityInfo.announceForAccessibility(announcement) +``` + +Post a string to be announced by the screen reader. + +| Name | Type | Required | Description | +| - | - | - | - | +| announcement | string | Yes | String to be announced | + +| Platform | +| - | +| iOS | + +--- + +### `removeEventListener()` + +```javascript +AccessibilityInfo.removeEventListener(eventName, handler) +``` + +Remove an event handler. + +| Name | Type | Required | Description | +| - | - | - | - | +| eventName | string | Yes | Name of the event | +| handler | function | Yes | Event handler | + diff --git a/docs/actionsheetios.md b/docs/actionsheetios.md new file mode 100644 index 00000000000000..6d0382bfa31c7f --- /dev/null +++ b/docs/actionsheetios.md @@ -0,0 +1,96 @@ +--- +id: actionsheetios +title: ActionSheetIOS +layout: docs +category: APIs +permalink: docs/actionsheetios.html +next: alert +previous: accessibilityinfo +--- + +Display action sheets and share sheets on iOS. + +### Methods + +- [`showActionSheetWithOptions`](docs/actionsheetios.html#showactionsheetwithoptions) +- [`showShareActionSheetWithOptions`](docs/actionsheetios.html#showshareactionsheetwithoptions) + + + + +--- + +# Reference + +## Methods + +### `showActionSheetWithOptions()` + +```javascript +ActionSheetIOS.showActionSheetWithOptions(options, callback) +``` + +Display an iOS action sheet. + +| Name | Type | Required | Description | +| - | - | - | - | +| options | object | Yes | See below. | +| callback | function | Yes | Provides index for the selected item. | + +The `options` object must contain one or more of: + +- `options` (array of strings) - a list of button titles (required) +- `cancelButtonIndex` (int) - index of cancel button in `options` +- `destructiveButtonIndex` (int) - index of destructive button in `options` +- `title` (string) - a title to show above the action sheet +- `message` (string) - a message to show below the title + +The 'callback' function takes one parameter, the zero-based index +of the selected item. + +Minimal example: + +``` +ActionSheetIOS.showActionSheetWithOptions({ + options: ['Remove', 'Cancel'], + destructiveButtonIndex: 1, + cancelButtonIndex: 0, +}, +(buttonIndex) => { + if (buttonIndex === 1) { // destructive action } +}); +``` + +--- + +### `showShareActionSheetWithOptions()` + +```javascript +ActionSheetIOS.showShareActionSheetWithOptions(options, failureCallback, successCallback) +``` + +Display the iOS share sheet. + +| Name | Type | Required | Description | +| - | - | - | - | +| options | object | Yes | See below. | +| failureCallback | function | Yes | See below. | +| successCallback | function | Yes | See below. | + +The `options` object should contain one or both of `message` and `url` and can additionally have a `subject` or `excludedActivityTypes`: + +- `url` (string) - a URL to share +- `message` (string) - a message to share +- `subject` (string) - a subject for the message +- `excludedActivityTypes` (array) - the activities to exclude from the ActionSheet + +> NOTE: +> If `url` points to a local file, or is a base64-encoded uri, the file it points to will be loaded and shared directly. In this way, you can share images, videos, PDF files, etc. + +The 'failureCallback' function takes one parameter, an error object. The only property defined on this object is an optional `stack` property of type `string`. + +The 'successCallback' function takes two parameters: + +- a boolean value signifying success or failure +- a string that, in the case of success, indicates the method of sharing + diff --git a/docs/activityindicator.md b/docs/activityindicator.md new file mode 100644 index 00000000000000..4cb00f56312deb --- /dev/null +++ b/docs/activityindicator.md @@ -0,0 +1,106 @@ +--- +id: activityindicator +title: ActivityIndicator +layout: docs +category: components +permalink: docs/activityindicator.html +next: button +--- + +Displays a circular loading indicator. + +### Example + +```ReactNativeWebPlayer +import React, { Component } from 'react' +import { + ActivityIndicator, + AppRegistry, + StyleSheet, + Text, + View, +} from 'react-native' + +class App extends Component { + render() { + return ( + + + + + + + ) + } +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center' + }, + horizontal: { + flexDirection: 'row', + justifyContent: 'space-around', + padding: 10 + } +}) + +AppRegistry.registerComponent('App', () => App) +``` + +### Props + +- [`View` props...](docs/view.html#props) +- [`animating`](docs/activityindicator.html#animating) +- [`color`](docs/activityindicator.html#color) +- [`size`](docs/activityindicator.html#size) +- [`hidesWhenStopped`](docs/activityindicator.html#hideswhenstopped) + + +--- + +# Reference + +## Props + +### `animating` + +Whether to show the indicator (`true`, the default) or hide it (`false`). + +| Type | Required | +| - | - | +| bool | No | + +--- + +### `color` + +The foreground color of the spinner (default is gray). + +| Type | Required | +| - | - | +| [color](docs/colors.html) | No | + +--- + +### `size` + +Size of the indicator (default is 'small'). + +Passing a number to the size prop is only supported on Android. + +| Type | Required | +| - | - | +| enum('small', 'large'), number | No | + +--- + +### `hidesWhenStopped` + +Whether the indicator should hide when not animating (true by default). + + +| Type | Required | Platform | +| - | - | - | +| bool | No | iOS | diff --git a/docs/alert.md b/docs/alert.md new file mode 100644 index 00000000000000..114a29b9dab01c --- /dev/null +++ b/docs/alert.md @@ -0,0 +1,79 @@ +--- +id: alert +title: Alert +layout: docs +category: APIs +permalink: docs/alert.html +next: alertios +previous: actionsheetios +--- + +Use `Alert` to display an alert dialog. + +This is an API that works both on iOS and Android and can show static alerts. To show an alert that prompts the user to enter some information, see [`AlertIOS`](docs/alertios.html), as entering text in an alert is common on iOS only. + +Optionally provide a list of buttons. Tapping any button will fire the respective `onPress` callback, and dismiss the alert. If no buttons are provided, a single 'OK' button will be displayed by default. + +On iOS, you can specify any number of buttons. + +On Android, at most three buttons can be specified. Android has a concept of a neutral, negative and a positive button: + +- If you specify one button, it will be the 'positive' one (such as 'OK') +- Two buttons mean 'negative', 'positive' (such as 'Cancel', 'OK') +- Three buttons mean 'neutral', 'negative', 'positive' (such as 'Later', 'Cancel', 'OK') + +Alerts on Android can be dismissed by tapping outside of the alert box. This event can be handled by providing an optional `options` parameter, with an `onDismiss` callback property `{ onDismiss: () => {} }`. + +Alternatively, the dismissing behavior can be disabled altogether by providing an optional `options` parameter with the `cancelable` property set to `false`, i.e. `{ cancelable: false }` + +Example usage: + +``` +// Works on both iOS and Android +Alert.alert( + 'Alert Title', + 'My Alert Msg', + [ + {text: 'Ask me later', onPress: () => console.log('Ask me later pressed')}, + {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'}, + {text: 'OK', onPress: () => console.log('OK Pressed')}, + ], + { cancelable: false } +) +``` + +### Methods + +- [`alert`](docs/alert.html#alert) + +--- + +# Reference + +## Methods + +### `alert()` + +```javascript +Alert.alert(title, [message], [buttons], [options]) +``` + +Launches an alert dialog with the specified title, and optionally a message. + +| Name | Type | Required | Description | +| - | - | - | - | +| title | string | Yes | Alert title | +| message | string | No | Alert message | +| buttons | array | No | Array of buttons | +| options | object | No | See below. | + +The optional `buttons` array should be composed of objects with any of the following: + +- `text` (string) - text to display for this button +- `onPress` (function) - callback to be fired when button is tapped +- `style` (string) - on iOS, specifies the button style, one of 'default', 'cancel', or 'destructive' + +The `options` object may include the following keys: + +- `onDismiss` - provide a callback function to handle dismissal on Android +- `cancelable` - set to false to disable the default dismissal behavior on Android diff --git a/docs/alertios.md b/docs/alertios.md new file mode 100644 index 00000000000000..a767d650e93282 --- /dev/null +++ b/docs/alertios.md @@ -0,0 +1,196 @@ +--- +id: alertios +title: AlertIOS +layout: docs +category: APIs +permalink: docs/alertios.html +next: animated +previous: alert +--- + +Use `AlertIOS` to display an alert dialog with a message or to create a prompt for user input on iOS. If you don't need to prompt for user input, we recommend using [`Alert.alert()`](docs/alert.html#alert) for cross-platform support. + + +### Examples + +Creating an iOS alert: + +``` +AlertIOS.alert( + 'Sync Complete', + 'All your data are belong to us.' +); +``` + +Creating an iOS prompt: + +``` +AlertIOS.prompt( + 'Enter a value', + null, + text => console.log("You entered "+text) +); +``` + +Example with custom buttons: + +```javascript +AlertIOS.alert( + 'Update available', + 'Keep your app up to date to enjoy the latest features', + [ + {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'}, + {text: 'Install', onPress: () => console.log('Install Pressed')}, + ], +); +``` + +Example with custom buttons: + +```javascript +AlertIOS.prompt( + 'Enter password', + 'Enter your password to claim your $1.5B in lottery winnings', + [ + {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'}, + {text: 'OK', onPress: password => console.log('OK Pressed, password: ' + password)}, + ], + 'secure-text' +); +``` + +Example with the default button and a custom callback: + +```javascript +AlertIOS.prompt( + 'Update username', + null, + text => console.log("Your username is "+text), + null, + 'default' +); +``` + + + + +### Methods + +- [`alert`](docs/alertios.html#alert) +- [`prompt`](docs/alertios.html#prompt) + + +### Type Definitions + +- [`AlertType`](docs/alertios.html#alerttype) +- [`AlertButtonStyle`](docs/alertios.html#alertbuttonstyle) +- [`ButtonsArray`](docs/alertios.html#buttonsarray) + + +--- + +# Reference + +## Methods + +### `alert()` + +```javascript +AlertIOS.alert(title, [message], [callbackOrButtons]) +``` + +Create and display a popup alert with a title and an optional message. + +If passed a function in the `callbackOrButtons` param, it will be called when the user taps 'OK'. If passed an array of button configurations, each button should include a `text` key, as well as optional `onPress` and `style` keys. `style` should be one of 'default', 'cancel' or 'destructive'. See [ButtonsArray](docs/alertios.html#buttonsarray) + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| title | string | Yes | The dialog's title. Passing null or '' will hide the title. | +| message | string | No | An optional message that appears below the dialog's title. | +| callbackOrButtons | function, [ButtonsArray](docs/alertios.html#buttonsarray) | No | This optional argument should be either a single-argument function or an [array of buttons](docs/alertios.html#buttonsarray). | + + + +--- + +### `prompt()` + +```javascript +AlertIOS.prompt(title, [message], [callbackOrButtons], [type], [defaultValue], [keyboardType]) +``` + +Create and display a prompt to enter some text. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| title | string | Yes | The dialog's title. | +| message | string | No | An optional message that appears above the text input. | +| callbackOrButtons | function, [ButtonsArray](docs/alertios.html#buttonsarray) | No | This optional argument should be either a single-argument function or an [array of buttons](docs/alertios.html#buttonsarray). | +| type | [AlertType](docs/alertios.html#alerttype) | No | This configures the text input. | +| defaultValue | string | No | The default text in text input. | +| keyboardType | string | No | The keyboard type of first text field(if exists). One of 'default', 'email-address', 'numeric', 'phone-pad', 'ascii-capable', 'numbers-and-punctuation', 'url', 'number-pad', 'name-phone-pad', 'decimal-pad', 'twitter' or 'web-search'. | + + +## Type Definitions + +### AlertType + +An Alert button type. + +| Type | +| - | +| enum('default', 'plain-text', 'secure-text', 'login-password') | + + +**Constants:** + +| Value | Description | +| - | - | +| 'default' | Default alert with no inputs | +| 'plain-text' | Plain text input alert | +| 'secure-text' | Secure text input alert | +| 'login-password' | Login and password alert | + + +--- + +### AlertButtonStyle + +An Alert button style. + +| Type | +| - | +| enum('default', 'cancel', 'destructive') | + + +**Constants:** + +| Value | Description | +| - | - | +| 'default' | Default button style | +| 'cancel' | Cancel button style | +| 'destructive' | Destructive button style | + + +--- + +### ButtonsArray + +Array of objects that describe a button. + +| Type | +| - | +| array of objects | + + +**Properties:** + +| Name | Type | Description | +| - | - | - | +| [text] | string | Button label | +| [onPress] | function | Callback function when button pressed | +| [style] | [AlertButtonStyle](docs/alertios.html#alertbuttonstyle) | Button style | diff --git a/docs/AndroidBuildingFromSource.md b/docs/android-building-from-source.md similarity index 100% rename from docs/AndroidBuildingFromSource.md rename to docs/android-building-from-source.md diff --git a/docs/androiduiperformance.md b/docs/androiduiperformance.md new file mode 100644 index 00000000000000..d24ffd24b83c21 --- /dev/null +++ b/docs/androiduiperformance.md @@ -0,0 +1,8 @@ +--- +id: android-ui-performance +title: Profiling Android UI Performance +layout: redirect +permalink: docs/android-ui-performance.html +destinationUrl: performance.html +--- +Redirecting... \ No newline at end of file diff --git a/docs/animated.md b/docs/animated.md new file mode 100644 index 00000000000000..21d01294106eac --- /dev/null +++ b/docs/animated.md @@ -0,0 +1,603 @@ +--- +id: animated +title: Animated +layout: docs +category: APIs +permalink: docs/animated.html +next: animatedvalue +previous: alertios +--- + +The `Animated` library is designed to make animations fluid, powerful, and easy to build and maintain. `Animated` focuses on declarative relationships between inputs and outputs, with configurable transforms in between, and simple `start`/`stop` methods to control time-based animation execution. + +The simplest workflow for creating an animation is to create an `Animated.Value`, hook it up to one or more style attributes of an animated component, and then drive updates via animations using `Animated.timing()`: + +```javascript +Animated.timing( // Animate value over time + this.state.fadeAnim, // The value to drive + { + toValue: 1, // Animate to final value of 1 + } +).start(); // Start the animation +``` + +Refer to the [Animations](docs/animations.html#animated-api) guide to see additional examples of `Animated` in action. + +## Overview + +There are two value types you can use with `Animated`: + +- [`Animated.Value()`](docs/animatedvalue.html) for single values +- [`Animated.ValueXY()`](docs/animatedvaluexy.html) for vectors + +`Animated.Value` can bind to style properties or other props, and can be interpolated as well. A single `Animated.Value` can drive any number of properties. + +### Configuring animations + +`Animated` provides three types of animation types. Each animation type provides a particular animation curve that controls how your values animate from their initial value to the final value: + +- [`Animated.decay()`](docs/animated.html#decay) starts with an initial velocity and gradually slows to a stop. +- [`Animated.spring()`](docs/animated.html#spring) provides a simple spring physics model. +- [`Animated.timing()`](docs/animated.html#timing) animates a value over time using [easing functions](docs/easing.html). + +In most cases, you will be using `timing()`. By default, it uses a symmetric easeInOut curve that conveys the gradual acceleration of an object to full speed and concludes by gradually decelerating to a stop. + +### Working with animations + +Animations are started by calling `start()` on your animation. `start()` takes a completion callback that will be called when the animation is done. If the animation finished running normally, the completion callback will be invoked with `{finished: true}`. If the animation is done because `stop()` was called on it before it could finish (e.g. because it was interrupted by a gesture or another animation), then it will receive `{finished: false}`. + +```javascript +this.animateValue.spring({}).start(({finished}) => { + if (finished) { + console.log('Animation was completed') + } else { + console.log('Animation was aborted') + } +}) +``` + +### Using the native driver + +By using the native driver, we send everything about the animation to native before starting the animation, allowing native code to perform the animation on the UI thread without having to go through the bridge on every frame. Once the animation has started, the JS thread can be blocked without affecting the animation. + +You can use the native driver by specifying `useNativeDriver: true` in your animation configuration. See the [Animations](docs/animations.html#using-the-native-driver) guide to learn more. + +### Animatable components + +Only animatable components can be animated. These special components do the magic of binding the animated values to the properties, and do targeted native updates to avoid the cost of the react render and reconciliation process on every frame. They also handle cleanup on unmount so they are safe by default. + +- [`createAnimatedComponent()`](docs/animated.html#createanimatedcomponent) can be used to make a component animatable. + +`Animated` exports the following animatable components using the above wrapper: + +- `Animated.Image` +- `Animated.ScrollView` +- `Animated.Text` +- `Animated.View` + +### Composing animations + +Animations can also be combined in complex ways using composition functions: + +- [`Animated.delay()`](docs/animated.html#delay) starts an animation after a given delay. +- [`Animated.parallel()`](docs/animated.html#parallel) starts a number of animations at the same time. +- [`Animated.sequence()`](docs/animated.html#sequence) starts the animations in order, waiting for each to complete before starting the next. +- [`Animated.stagger()`](docs/animated.html#stagger) starts animations in order and in parallel, but with successive delays. + +Animations can also be chained together simply by setting the `toValue` of one animation to be another `Animated.Value`. See [Tracking dynamic values](docs/animations.html#tracking-dynamic-values) in the Animations guide. + +By default, if one animation is stopped or interrupted, then all other animations in the group are also stopped. + +### Combining animated values + +You can combine two animated values via addition, multiplication, division, or modulo to make a new animated value: + +- [`Animated.add()`](docs/animated.html#add) +- [`Animated.divide()`](docs/animated.html#divide) +- [`Animated.modulo()`](docs/animated.html#modulo) +- [`Animated.multiply()`](docs/animated.html#multiply) + +### Interpolation + +The `interpolate()` function allows input ranges to map to different output ranges. By default, it will extrapolate the curve beyond the ranges given, but you can also have it clamp the output value. It uses lineal interpolation by default but also supports easing functions. + +- [`interpolate()`](docs/animatedvalue.html#interpolate) + +Read more about interpolation in the [Animation](docs/animations.html#interpolation) guide. + +### Handling gestures and other events + +Gestures, like panning or scrolling, and other events can map directly to animated values using `Animated.event()`. This is done with a structured map syntax so that values can be extracted from complex event objects. The first level is an array to allow mapping across multiple args, and that array contains nested objects. + +- [`Animated.event()`](docs/animated.html#event) + +For example, when working with horizontal scrolling gestures, you would do the following in order to map `event.nativeEvent.contentOffset.x` to `scrollX` (an `Animated.Value`): + +```javascript + onScroll={Animated.event( + // scrollX = e.nativeEvent.contentOffset.x + [{ nativeEvent: { + contentOffset: { + x: scrollX + } + } + }] + )} +``` + +### Methods + +#### Configuring animations + +- [`decay()`](docs/animated.html#decay) +- [`timing()`](docs/animated.html#timing) +- [`spring()`](docs/animated.html#spring) + +#### Combining animated values + +- [`add`](docs/animated.html#add) +- [`divide`](docs/animated.html#divide) +- [`multiply`](docs/animated.html#multiply) +- [`modulo`](docs/animated.html#modulo) +- [`diffClamp`](docs/animated.html#diffclamp) + +#### Composing animations + +- [`delay`](docs/animated.html#delay) +- [`sequence`](docs/animated.html#sequence) +- [`parallel`](docs/animated.html#parallel) +- [`stagger`](docs/animated.html#stagger) + +#### Handling gestures and other events + +- [`event`](docs/animated.html#event) +- [`attachNativeEvent`](docs/animated.html#attachnativeevent) +- [`forkEvent`](docs/animated.html#forkevent) +- [`unforkEvent`](docs/animated.html#unforkevent) + +#### Others + +- [`loop`](docs/animated.html#loop) +- [`createAnimatedComponent`](docs/animated.html#createanimatedcomponent) + +### Properties + +- [`Value`](docs/animated.html#value) +- [`ValueXY`](docs/animated.html#valuexy) +- [`Interpolation`](docs/animated.html#interpolation) +- [`Node`](docs/animated.html#node) + + +--- + +# Reference + +## Methods + +### `decay()` + +```javascript +Animated.decay(value, config) +``` + +Animates a value from an initial velocity to zero based on a decay coefficient. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| value | AnimatedValue or AnimatedValueXY | Yes | Value to animate. | +| config | object | Yes | See below. | + +Config is an object that may have the following options: + +- `velocity`: Initial velocity. Required. +- `deceleration`: Rate of decay. Default 0.997. +- `isInteraction`: Whether or not this animation creates an "interaction handle" on the + `InteractionManager`. Default true. +- `useNativeDriver`: Uses the native driver when true. Default false. + +--- + +### `timing()` + +```javascript +Animated.timing(value, config) +``` + +Animates a value along a timed easing curve. The [`Easing`](docs/easing.html) module has tons of predefined curves, or you can use your own function. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| value | AnimatedValue or AnimatedValueXY | Yes | Value to animate. | +| config | object | Yes | See below. | + +Config is an object that may have the following options: + + - `duration`: Length of animation (milliseconds). Default 500. + - `easing`: Easing function to define curve. + Default is `Easing.inOut(Easing.ease)`. + - `delay`: Start the animation after delay (milliseconds). Default 0. + - `isInteraction`: Whether or not this animation creates an "interaction handle" on the + `InteractionManager`. Default true. + - `useNativeDriver`: Uses the native driver when true. Default false. + + + + +--- + +### `spring()` + +```javascript +Animated.spring(value, config) +``` + +Animates a value according to an analytical spring model based on [damped harmonic oscillation](https://en.wikipedia.org/wiki/Harmonic_oscillator#Damped_harmonic_oscillator). Tracks velocity state to create fluid motions as the `toValue` updates, and can be chained together. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| value | AnimatedValue or AnimatedValueXY | Yes | Value to animate. | +| config | object | Yes | See below. | + +`config` is an object that may have the following options. + +Note that you can only define one of bounciness/speed, tension/friction, or stiffness/damping/mass, but not more than one: + +The friction/tension or bounciness/speed options match the spring model in [Facebook Pop](https://github.com/facebook/pop), [Rebound](http://facebook.github.io/rebound/), and [Origami](http://origami.design/). + +- `friction`: Controls "bounciness"/overshoot. Default 7. +- `tension`: Controls speed. Default 40. +- `speed`: Controls speed of the animation. Default 12. +- `bounciness`: Controls bounciness. Default 8. + +Specifying stiffness/damping/mass as parameters makes `Animated.spring` use an analytical spring model based on the motion equations of a [damped harmonic oscillator](https://en.wikipedia.org/wiki/Harmonic_oscillator#Damped_harmonic_oscillator). This behavior is slightly more precise and faithful to the physics behind spring dynamics, and closely mimics the implementation in iOS's CASpringAnimation primitive. + +- `stiffness`: The spring stiffness coefficient. Default 100. +- `damping`: Defines how the spring’s motion should be damped due to the forces of friction. Default 10. +- `mass`: The mass of the object attached to the end of the spring. Default 1. + +Other configuration options are as follows: + +- `velocity`: The initial velocity of the object attached to the spring. Default 0 (object is at rest). +- `overshootClamping`: Boolean indiciating whether the spring should be clamped and not bounce. Default false. +- `restDisplacementThreshold`: The threshold of displacement from rest below which the spring should be considered at rest. Default 0.001. +- `restSpeedThreshold`: The speed at which the spring should be considered at rest in pixels per second. Default 0.001. +- `delay`: Start the animation after delay (milliseconds). Default 0. +- `isInteraction`: Whether or not this animation creates an "interaction handle" on the `InteractionManager`. Default true. +- `useNativeDriver`: Uses the native driver when true. Default false. + +--- + +### `add()` + +```javascript +Animated.add(a, b) +``` + +Creates a new Animated value composed from two Animated values added together. + + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| a | AnimatedValue | Yes | Operand. | +| b | AnimatedValue | Yes | Operand. | + + + +--- + +### `divide()` + +```javascript +Animated.divide(a, b) +``` + + +Creates a new Animated value composed by dividing the first Animated value by the second Animated value. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| a | AnimatedValue | Yes | Operand. | +| b | AnimatedValue | Yes | Operand. | + + +--- + +### `multiply()` + +```javascript +Animated.multiply(a, b) +``` + +Creates a new Animated value composed from two Animated values multiplied together. + + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| a | AnimatedValue | Yes | Operand. | +| b | AnimatedValue | Yes | Operand. | + +--- + +### `modulo()` + +```javascript +Animated.modulo(a, modulus) +``` + + +Creates a new Animated value that is the (non-negative) modulo of the provided Animated value. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| a | AnimatedValue | Yes | Operand. | +| modulus | AnimatedValue | Yes | Operand. | + + +--- + +### `diffClamp()` + +```javascript +Animated.diffClamp(a, min, max) +``` + +Create a new Animated value that is limited between 2 values. It uses the difference between the last value so even if the value is far from the bounds it will start changing when the value starts getting closer again. (`value = clamp(value + diff, min, max)`). + +This is useful with scroll events, for example, to show the navbar when scrolling up and to hide it when scrolling down. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| a | AnimatedValue | Yes | Operand. | +| min | number | Yes | Minimum value. | +| max | number | Yes | Maximum value. | + +--- + +### `delay()` + +```javascript +Animated.delay(time) +``` + +Starts an animation after the given delay. + + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| time | number | Yes | Delay in milliseconds. | + +--- + +### `sequence()` + +```javascript +Animated.sequence(animations) +``` + +Starts an array of animations in order, waiting for each to complete before starting the next. If the current running animation is stopped, no following animations will be started. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| animations | array | Yes | Array of animations. | + + + +--- + +### `parallel()` + +```javascript +Animated.parallel(animations, [config]) +``` + +Starts an array of animations all at the same time. By default, if one +of the animations is stopped, they will all be stopped. You can override +this with the `stopTogether` flag through `config`. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| animations | array | Yes | Array of animations. | +| config | object | No | An object with a `stopTogether` key (boolean). | + + +--- + +### `stagger()` + +```javascript +Animated.stagger(time, animations) +``` + +Array of animations may run in parallel (overlap), but are started in +sequence with successive delays. Nice for doing trailing effects. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| time | number | Yes | Delay in milliseconds. | +| animations | array | Yes | Array of animations. | + +--- + +### `loop()` + +```javascript +Animated.loop(animation) +``` + +Loops a given animation continuously, so that each time it reaches the end, it resets and begins again from the start. Can specify number of times to loop using the key `iterations` in the config. Will loop without blocking the UI thread if the child animation is set to `useNativeDriver: true`. In addition, loops can prevent `VirtualizedList`-based components from rendering more rows while the animation is running. You can pass `isInteraction: false` in the child animation config to fix this. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| animation | animation | Yes | Animation to loop. | + +--- + +### `event()` + +```javascript +Animated.event(argMapping, [config]) +``` + +Takes an array of mappings and extracts values from each arg accordingly, then calls `setValue` on the mapped outputs. e.g. + +```javascript +onScroll={Animated.event( + [{nativeEvent: {contentOffset: {x: this._scrollX}}}], + {listener: (event) => console.log(event)}, // Optional async listener +)} +... +onPanResponderMove: Animated.event([ + null, // raw event arg ignored + {dx: this._panX}, // gestureState arg + {listener: (event, gestureState) => console.log(event, gestureState)}, // Optional async listener +]), +``` + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| argMapping | array | Yes | Array of mappings. | +| config | object | No | See below. | + + +Config is an object that may have the following options: + +- `listener`: Optional async listener. +- `useNativeDriver`: Uses the native driver when true. Default false. + +--- + +### `createAnimatedComponent()` + +```javascript +createAnimatedComponent(component) +``` + +Make any React component Animatable. Used to create `Animated.View`, etc. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| component | component | Yes | React component | + +--- + +### `attachNativeEvent()` + +```javascript +attachNativeEvent(viewRef, eventName, argMapping) +``` + +Imperative API to attach an animated value to an event on a view. Prefer using `Animated.event` with `useNativeDrive: true` if possible. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| viewRef | any | Yes | View reference. | +| eventName | string | Yes | Event name. | +| argMapping | array | Yes | Array of mappings. | + +--- + +### `forkEvent()` + +```javascript +Animated.forkEvent(event, listener) +``` + +Advanced imperative API for snooping on animated events that are passed in through props. Use values directly where possible. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| event | event or function | Yes | Event. | +| listener | function | Yes | Handler. | + +--- + +### `unforkEvent()` + +```javascript +Animated.unforkEvent(event, listener) +``` + +Advanced imperative API for snooping on animated events that are passed in through props. Use values directly where possible. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| event | event or function | Yes | Event. | +| listener | function | Yes | Handler. | + + +## Properties + +### Value + +Standard value for driving animations. + +| Type | +| - | +| [`AnimatedValue`](docs/animatedvalue.html) | + +--- + +### ValueXY + +2D value class for driving 2D animations, such as pan gestures. + +| Type | +| - | +| [`AnimatedValueXY`](docs/animatedvaluexy.html) | + +--- + +### Interpolation + +Exported to use the Interpolation type in flow. + +| Type | +| - | +| AnimatedInterpolation | + +--- + +### Node + +Exported for ease of type checking. All animated values derive from this class. See `AnimatedNode.js`. + +| Type | +| - | +| AnimatedNode | + diff --git a/docs/animatedvalue.md b/docs/animatedvalue.md new file mode 100644 index 00000000000000..c766bbc4a4a85c --- /dev/null +++ b/docs/animatedvalue.md @@ -0,0 +1,234 @@ +--- +id: animatedvalue +title: AnimatedValue +layout: docs +category: APIs +permalink: docs/animatedvalue.html +next: animatedvaluexy +previous: animated +--- + +Standard value for driving animations. One `Animated.Value` can drive multiple properties in a synchronized fashion, but can only be driven by one mechanism at a time. Using a new mechanism (e.g. starting a new animation, or calling `setValue`) will stop any previous ones. + +Typically initialized with `new Animated.Value(0);` + +See also [`Animated`](docs/animated.html). + +### Methods + +- [`setValue`](docs/animatedvalue.html#setvalue) +- [`setOffset`](docs/animatedvalue.html#setoffset) +- [`flattenOffset`](docs/animatedvalue.html#flattenoffset) +- [`extractOffset`](docs/animatedvalue.html#extractoffset) +- [`addListener`](docs/animatedvalue.html#addlistener) +- [`removeListener`](docs/animatedvalue.html#removelistener) +- [`removeAllListeners`](docs/animatedvalue.html#removealllisteners) +- [`stopAnimation`](docs/animatedvalue.html#stopanimation) +- [`resetAnimation`](docs/animatedvalue.html#resetanimation) +- [`interpolate`](docs/animatedvalue.html#interpolate) +- [`animate`](docs/animatedvalue.html#animate) +- [`stopTracking`](docs/animatedvalue.html#stoptracking) +- [`track`](docs/animatedvalue.html#track) + +--- + +# Reference + +## Methods + +### `setValue()` + +```javascript +setValue(value) +``` + +Directly set the value. This will stop any animations running on the value and update all the bound properties. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| value | number | Yes | Value | + +--- + +### `setOffset()` + +```javascript +setOffset(offset) +``` + +Sets an offset that is applied on top of whatever value is set, whether via `setValue`, an animation, or `Animated.event`. Useful for compensating things like the start of a pan gesture. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| offset | number | Yes | Offset value | + +--- + +### `flattenOffset()` + +```javascript +flattenOffset() +``` + +Merges the offset value into the base value and resets the offset to zero. The final output of the value is unchanged. + +--- + +### `extractOffset()` + +```javascript +extractOffset() +``` + +Sets the offset value to the base value, and resets the base value to zero. The final output of the value is unchanged. + + +--- + +### `addListener()` + +```javascript +addListener(callback) +``` + +Adds an asynchronous listener to the value so you can observe updates from animations. This is useful because there is no way to synchronously read the value because it might be driven natively. + +Returns a string that serves as an identifier for the listener. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| callback | function | Yes | The callback function which will receive an object with a `value` key set to the new value. | + +--- + +### `removeListener()` + +```javascript +removeListener(id) +``` + +Unregister a listener. The `id` param shall match the identifier previously returned by `addListener()`. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| id | string | Yes | Id for the listener being removed. | + +--- + +### `removeAllListeners()` + +```javascript +removeAllListeners() +``` + +Remove all registered listeners. + +--- + +### `stopAnimation()` + +```javascript +stopAnimation([callback]) +``` + +Stops any running animation or tracking. `callback` is invoked with the final value after stopping the animation, which is useful for updating state to match the animation position with layout. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| callback | function | No | A function that will receive the final value. | + +--- + +### `resetAnimation()` + +```javascript +resetAnimation([callback]) +``` + +Stops any animation and resets the value to its original. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| callback | function | No | A function that will receive the original value. | + +--- + +### `interpolate()` + +```javascript +interpolate(config) +``` + +Interpolates the value before updating the property, e.g. mapping 0-1 to 0-10. + +See `AnimatedInterpolation.js` + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| config | object | Yes | See below. | + +The `config` object is composed of the following keys: + +- `inputRange`: an array of numbers +- `outputRange`: an array of numbers or strings +- `easing` (optional): a function that returns a number, given an input number +- `extrapolate` (optional): a string such as 'extend', 'identity', or 'clamp' +- `extrapolateLeft` (optional): a string such as 'extend', 'identity', or 'clamp' +- `extrapolateRight` (optional): a string such as 'extend', 'identity', or 'clamp' + +--- + +### `animate()` + +```javascript +animate(animation, callback) +``` + +Typically only used internally, but could be used by a custom Animation class. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| animation | Animation | Yes | See `Animation.js`. | +| callback | function | Yes | Callback function. | + +--- + +### `stopTracking()` + +```javascript +stopTracking() +``` + +Typically only used internally. + +--- + +### `track()` + +```javascript +track(tracking) +``` + +Typically only used internally. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| tracking | AnimatedNode | Yes | See `AnimatedNode.js` | diff --git a/docs/animatedvaluexy.md b/docs/animatedvaluexy.md new file mode 100644 index 00000000000000..30cc1fe8afce57 --- /dev/null +++ b/docs/animatedvaluexy.md @@ -0,0 +1,228 @@ +--- +id: animatedvaluexy +title: AnimatedValueXY +layout: docs +category: APIs +permalink: docs/animatedvaluexy.html +next: appregistry +previous: animatedvalue +--- + +2D Value for driving 2D animations, such as pan gestures. Almost identical API to normal [`Animated.Value`](docs/animatedvalue.html), but multiplexed. Contains two regular `Animated.Value`s under the hood. + +See also [`Animated`](docs/animated.html). + +## Example + +```javascript +class DraggableView extends React.Component { + constructor(props) { + super(props); + this.state = { + pan: new Animated.ValueXY(), // inits to zero + }; + this.state.panResponder = PanResponder.create({ + onStartShouldSetPanResponder: () => true, + onPanResponderMove: Animated.event([null, { + dx: this.state.pan.x, // x,y are Animated.Value + dy: this.state.pan.y, + }]), + onPanResponderRelease: () => { + Animated.spring( + this.state.pan, // Auto-multiplexed + {toValue: {x: 0, y: 0}} // Back to zero + ).start(); + }, + }); + } + render() { + return ( + + {this.props.children} + + ); + } +} +``` + + +### Methods + +- [`setValue`](docs/animatedvaluexy.html#setvalue) +- [`setOffset`](docs/animatedvaluexy.html#setoffset) +- [`flattenOffset`](docs/animatedvaluexy.html#flattenoffset) +- [`extractOffset`](docs/animatedvaluexy.html#extractoffset) +- [`addListener`](docs/animatedvaluexy.html#addlistener) +- [`removeListener`](docs/animatedvaluexy.html#removelistener) +- [`removeAllListeners`](docs/animatedvaluexy.html#removealllisteners) +- [`stopAnimation`](docs/animatedvaluexy.html#stopanimation) +- [`resetAnimation`](docs/animatedvaluexy.html#resetanimation) +- [`getLayout`](docs/animatedvaluexy.html#getlayout) +- [`getTranslateTransform`](docs/animatedvaluexy.html#gettranslatetransform) + +--- + +# Reference + +## Methods + +### `setValue()` + +```javascript +setValue(value) +``` + +Directly set the value. This will stop any animations running on the value and update all the bound properties. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| value | number | Yes | | + +--- + +### `setOffset()` + +```javascript +setOffset(offset) +``` + +Sets an offset that is applied on top of whatever value is set, whether via `setValue`, an animation, or `Animated.event`. Useful for compensating things like the start of a pan gesture. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| offset | number | Yes | | + +--- + +### `flattenOffset()` + +```javascript +flattenOffset() +``` + +Merges the offset value into the base value and resets the offset to zero. The final output of the value is unchanged. + +--- + +### `extractOffset()` + +```javascript +extractOffset() +``` + +Sets the offset value to the base value, and resets the base value to zero. The final output of the value is unchanged. + + +--- + +### `addListener()` + +```javascript +addListener(callback) +``` + +Adds an asynchronous listener to the value so you can observe updates from animations. This is useful because there is no way to synchronously read the value because it might be driven natively. + +Returns a string that serves as an identifier for the listener. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| callback | function | Yes | The callback function which will receive an object with a `value` key set to the new value. | + +--- + +### `removeListener()` + +```javascript +removeListener(id) +``` + +Unregister a listener. The `id` param shall match the identifier previously returned by `addListener()`. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| id | string | Yes | Id for the listener being removed. | + +--- + +### `removeAllListeners()` + +```javascript +removeAllListeners() +``` + +Remove all registered listeners. + +--- + +### `stopAnimation()` + +```javascript +stopAnimation([callback]) +``` + +Stops any running animation or tracking. `callback` is invoked with the final value after stopping the animation, which is useful for updating state to match the animation position with layout. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| callback | function | No | A function that will receive the final value. | + +--- + +### `resetAnimation()` + +```javascript +resetAnimation([callback]) +``` + +Stops any animation and resets the value to its original. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| callback | function | No | A function that will receive the original value. | + + +--- + +### `getLayout()` + +```javascript +getLayout() +``` + +Converts `{x, y}` into `{left, top}` for use in style, e.g. + +```javascript +style={this.state.anim.getLayout()} +``` + + +--- + +### `getTranslateTransform()` + +```javascript +getTranslateTransform() +``` + +Converts `{x, y}` into a useable translation transform, e.g. + +```javascript +style={{ + transform: this.state.anim.getTranslateTransform() +}} +``` diff --git a/docs/TodayWidget.md b/docs/app-extensions.md similarity index 100% rename from docs/TodayWidget.md rename to docs/app-extensions.md diff --git a/docs/appregistry.md b/docs/appregistry.md new file mode 100644 index 00000000000000..bf5e419af312f3 --- /dev/null +++ b/docs/appregistry.md @@ -0,0 +1,234 @@ +--- +id: appregistry +title: AppRegistry +layout: docs +category: APIs +permalink: docs/appregistry.html +next: appstate +previous: animated +--- + +

+ +`AppRegistry` is the JavaScript entry point to running all React Native apps. App root components should register themselves with `AppRegistry.registerComponent()`, then the native system can load the bundle for the app and then actually run the app when it's ready by invoking `AppRegistry.runApplication()`. + +To "stop" an application when a view should be destroyed, call `AppRegistry.unmountApplicationComponentAtRootTag()` with the tag that was passed into `runApplication()`. These should always be used as a pair. + +`AppRegistry` should be `require`d early in the `require` sequence to make sure the JavaScript execution environment is set up before other modules are `require`d. + +### Methods + +- [`registerComponent`](docs/appregistry.html#registercomponent) +- [`runApplication`](docs/appregistry.html#runapplication) +- [`unmountApplicationComponentAtRootTag`](docs/appregistry.html#unmountapplicationcomponentatroottag) +- [`registerHeadlessTask`](docs/appregistry.html#registerheadlesstask) +- [`startHeadlessTask`](docs/appregistry.html#startheadlesstask) +- [`setWrapperComponentProvider`](docs/appregistry.html#setwrappercomponentprovider) +- [`registerConfig`](docs/appregistry.html#registerconfig) +- [`registerRunnable`](docs/appregistry.html#registerrunnable) +- [`registerSection`](docs/appregistry.html#registersection) +- [`getAppKeys`](docs/appregistry.html#getappkeys) +- [`getSectionKeys`](docs/appregistry.html#getsectionkeys) +- [`getSections`](docs/appregistry.html#getsections) +- [`getRunnable`](docs/appregistry.html#getrunnable) +- [`getRegistry`](docs/appregistry.html#getregistry) +- [`setComponentProviderInstrumentationHook`](docs/appregistry.html#setcomponentproviderinstrumentationhook) + + +--- + +# Reference + +## Methods + +### `registerComponent()` + +```javascript +AppRegistry.registerComponent(appKey, componentProvider, [section]) +``` + +Registers an app's root component. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| appKey | string | Yes | Application key. | +| componentProvider | function | Yes | A function that returns a React component or element. | +| section | boolean | No | Is this a section? | + +--- + +### `runApplication()` + +```javascript +AppRegistry.runApplication(appKey, appParameters) +``` + +Loads the JavaScript bundle and runs the app. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| appKey | string | Yes | Application key. | +| appParameters | any | Yes | Params. | + +--- + +### `unmountApplicationComponentAtRootTag()` + +```javascript +AppRegistry.unmountApplicationComponentAtRootTag(rootTag) +``` + +Stops an application when a view should be destroyed. The `rootTag` should match the tag that was passed into `runApplication()`. These should always be used as a pair. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| rootTag | number | Yes | React tag. | + +--- + +### `registerHeadlessTask()` + +```javascript +AppRegistry.registerHeadlessTask(taskKey, task) +``` + +Register a headless task. A headless task is a bit of code that runs without a UI. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| taskKey | string | No | The key associated with this task. | +| task | function | No | A promise returning function that takes some data passed from the native side as the only argument; when the promise is resolved or rejected the native side is notified of this event and it may decide to destroy the JS context. | + + +--- + +### `startHeadlessTask()` + +```javascript +AppRegistry.startHeadlessTask(taskId, taskKey, data) +``` + +Only called from native code. Starts a headless task. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| taskId | number | No | The native id for this task instance to keep track of its execution. | +| taskKey | string | No | The key for the task to start. | +| data | any | No | The data to pass to the task. | + + +--- + + +### `setWrapperComponentProvider()` + +```javascript +AppRegistry.setWrapperComponentProvider(provider) +``` + + + +--- + +### `registerConfig()` + +```javascript +AppRegistry.registerConfig(config) +``` + + + +--- + +### `registerRunnable()` + +```javascript +AppRegistry.registerRunnable(appKey, run) +``` + + + +--- + +### `registerSection()` + +```javascript +AppRegistry.registerSection(appKey, component) +``` + + + +--- + +### `getAppKeys()` + +```javascript +AppRegistry.getAppKeys() +``` + + + +--- + +### `getSectionKeys()` + +```javascript +AppRegistry.getSectionKeys() +``` + + + +--- + +### `getSections()` + +```javascript +AppRegistry.getSections() +``` + + + +--- + +### `getRunnable()` + +```javascript +AppRegistry.getRunnable(appKey) +``` + + + +--- + +### `getRegistry()` + +```javascript +AppRegistry.getRegistry() +``` + + + +--- + +### `setComponentProviderInstrumentationHook()` + +```javascript +AppRegistry.setComponentProviderInstrumentationHook(hook) +``` + + diff --git a/docs/appstate.md b/docs/appstate.md new file mode 100644 index 00000000000000..066b30853c0f81 --- /dev/null +++ b/docs/appstate.md @@ -0,0 +1,107 @@ +--- +id: appstate +title: AppState +layout: docs +category: APIs +permalink: docs/appstate.html +next: asyncstorage +previous: appregistry +--- + +`AppState` can tell you if the app is in the foreground or background, and notify you when the state changes. + +App state is frequently used to determine the intent and proper behavior when handling push notifications. + +### App States + +- `active` - The app is running in the foreground +- `background` - The app is running in the background. The user is either + in another app or on the home screen +- `inactive` - This is a state that occurs when transitioning between foreground & background, and during periods of inactivity such as entering the Multitasking view or in the event of an incoming call + +For more information, see [Apple's documentation](https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html). + +### Basic Usage + +To see the current state, you can check `AppState.currentState`, which will be kept up-to-date. However, `currentState` will be null at launch while `AppState` retrieves it over the bridge. + +```javascript +import React, {Component} from 'react' +import {AppState, Text} from 'react-native' + +class AppStateExample extends Component { + + state = { + appState: AppState.currentState + } + + componentDidMount() { + AppState.addEventListener('change', this._handleAppStateChange); + } + + componentWillUnmount() { + AppState.removeEventListener('change', this._handleAppStateChange); + } + + _handleAppStateChange = (nextAppState) => { + if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') { + console.log('App has come to the foreground!') + } + this.setState({appState: nextAppState}); + } + + render() { + return ( + Current state is: {this.state.appState} + ); + } + +} +``` + +This example will only ever appear to say "Current state is: active" because the app is only visible to the user when in the `active` state, and the null state will happen only momentarily. + + +### Methods + +- [`addEventListener`](docs/appstate.html#addeventlistener) +- [`removeEventListener`](docs/appstate.html#removeeventlistener) + + +--- + +# Reference + +## Methods + +### `addEventListener()` + +```javascript +addEventListener(type, handler) +``` + +Add a handler to AppState changes by listening to the `change` event type and providing the handler. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| type | string | Yes | | +| handler | function | Yes | | + +--- + +### `removeEventListener()` + +```javascript +removeEventListener(type, handler) +``` + +Remove a handler by passing the `change` event type and the handler. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| type | string | Yes | | +| handler | function | Yes | | diff --git a/docs/asyncstorage.md b/docs/asyncstorage.md new file mode 100644 index 00000000000000..23693b211219e7 --- /dev/null +++ b/docs/asyncstorage.md @@ -0,0 +1,404 @@ +--- +id: asyncstorage +title: AsyncStorage +layout: docs +category: APIs +permalink: docs/asyncstorage.html +next: backandroid +previous: appstate +--- + +`AsyncStorage` is a simple, unencrypted, asynchronous, persistent, key-value storage system that is global to the app. It should be used instead of LocalStorage. + +It is recommended that you use an abstraction on top of `AsyncStorage` instead of `AsyncStorage` directly for anything more than light usage since it operates globally. + +On iOS, `AsyncStorage` is backed by native code that stores small values in a serialized dictionary and larger values in separate files. On Android, `AsyncStorage` will use either [RocksDB](http://rocksdb.org/) or SQLite based on what is available. + +The `AsyncStorage` JavaScript code is a simple facade that provides a clear JavaScript API, real `Error` objects, and simple non-multi functions. Each method in the API returns a `Promise` object. + +Persisting data: + +```javascript +try { + await AsyncStorage.setItem('@MySuperStore:key', 'I like to save it.'); +} catch (error) { + // Error saving data +} +``` + +Fetching data: + +```javascript +try { + const value = await AsyncStorage.getItem('@MySuperStore:key'); + if (value !== null){ + // We have data!! + console.log(value); + } +} catch (error) { + // Error retrieving data +} +``` + +Merging data: + +```javascript +let UID123_object = { + name: 'Chris', + age: 30, + traits: {hair: 'brown', eyes: 'brown'}, +}; +// You only need to define what will be added or updated +let UID123_delta = { + age: 31, + traits: {eyes: 'blue', shoe_size: 10} +}; + +AsyncStorage.setItem('UID123', JSON.stringify(UID123_object), () => { + AsyncStorage.mergeItem('UID123', JSON.stringify(UID123_delta), () => { + AsyncStorage.getItem('UID123', (err, result) => { + console.log(result); + }); + }); +}); + +// Console log result: +// => {'name':'Chris','age':31,'traits': +// {'shoe_size':10,'hair':'brown','eyes':'blue'}} +``` + + +Multi merge example: + +```javascript + +// first user, initial values +let UID234_object = { + name: 'Chris', + age: 30, + traits: {hair: 'brown', eyes: 'brown'}, +}; + +// first user, delta values +let UID234_delta = { + age: 31, + traits: {eyes: 'blue', shoe_size: 10}, +}; + +// second user, initial values +let UID345_object = { + name: 'Marge', + age: 25, + traits: {hair: 'blonde', eyes: 'blue'}, +}; + +// second user, delta values +let UID345_delta = { + age: 26, + traits: {eyes: 'green', shoe_size: 6}, +}; + +let multi_set_pairs = [['UID234', JSON.stringify(UID234_object)], ['UID345', JSON.stringify(UID345_object)]] +let multi_merge_pairs = [['UID234', JSON.stringify(UID234_delta)], ['UID345', JSON.stringify(UID345_delta)]] + +AsyncStorage.multiSet(multi_set_pairs, (err) => { + AsyncStorage.multiMerge(multi_merge_pairs, (err) => { + AsyncStorage.multiGet(['UID234','UID345'], (err, stores) => { + stores.map( (result, i, store) => { + let key = store[i][0]; + let val = store[i][1]; + console.log(key, val); + }); + }); + }); +}); + +// Console log results: +// => UID234 {"name":"Chris","age":31,"traits":{"shoe_size":10,"hair":"brown","eyes":"blue"}} +// => UID345 {"name":"Marge","age":26,"traits":{"shoe_size":6,"hair":"blonde","eyes":"green"}} +``` + +Fetching multiple items: + +```javascript +AsyncStorage.getAllKeys((err, keys) => { + AsyncStorage.multiGet(keys, (err, stores) => { + stores.map((result, i, store) => { + // get at each store's key/value so you can work with it + let key = store[i][0]; + let value = store[i][1]; + }); + }); +}); +``` + +Removing multiple items: + +```javascript + +let keys = ['k1', 'k2']; +AsyncStorage.multiRemove(keys, (err) => { + // keys k1 & k2 removed, if they existed + // do most stuff after removal (if you want) +}); +``` + + + +### Methods + +- [`getItem`](docs/asyncstorage.html#getitem) +- [`setItem`](docs/asyncstorage.html#setitem) +- [`removeItem`](docs/asyncstorage.html#removeitem) +- [`mergeItem`](docs/asyncstorage.html#mergeitem) +- [`clear`](docs/asyncstorage.html#clear) +- [`getAllKeys`](docs/asyncstorage.html#getallkeys) + +The following batched functions are useful for executing a lot of operations at once, allowing for native optimizations and provide the convenience of a single callback after all operations are complete. + +These functions return arrays of errors, potentially one for every key. For key-specific errors, the Error object will have a key property to indicate which key caused the error. + +- [`flushGetRequests`](docs/asyncstorage.html#flushgetrequests) +- [`multiGet`](docs/asyncstorage.html#multiget) +- [`multiSet`](docs/asyncstorage.html#multiset) +- [`multiRemove`](docs/asyncstorage.html#multiremove) +- [`multiMerge`](docs/asyncstorage.html#multimerge) + + + + +--- + +# Reference + +## Methods + +### `getItem()` + +```javascript +AsyncStorage.getItem(key, [callback]) +``` + +Fetches an item for a `key` and invokes a callback upon completion. +Returns a `Promise` object. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| key | string | Yes | Key of the item to fetch. | +| callback | (error, result) => void | No | Function that will be called with a result if found or any error. | + + + + +--- + +### `setItem()` + +```javascript +AsyncStorage.setItem(key, value, [callback]) +``` + +Sets the value for a `key` and invokes a callback upon completion. + +Returns a `Promise` object. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| key | string | Yes | Key of the item to set. | +| value | string | Yes | Value to set for the `key`. | +| callback | (error) => void | No | Function that will be called with any error. | + + + + +--- + +### `removeItem()` + +```javascript +AsyncStorage.removeItem(key, [callback]) +``` + +Removes an item for a `key` and invokes a callback upon completion. +Returns a `Promise` object. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| key | string | Yes | Key of the item to remove. | +| callback | (error) => void | No | Function that will be called with any error. | + + +--- + +### `mergeItem()` + +```javascript +AsyncStorage.mergeItem(key, value, [callback]) +``` + +Merges an existing `key` value with an input value, assuming both values are stringified JSON. Returns a `Promise` object. + +> Note: +> This is not supported by all native implementations. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| key | string | Yes | Key of the item to modify. | +| value | string | Yes | New value to merge for the `key`. | +| callback | (error) => void | No | Function that will be called with any error. | + + +--- + +### `clear()` + +```javascript +AsyncStorage.clear([callback]) +``` + +Erases *all* `AsyncStorage` for all clients, libraries, etc. You probably don't want to call this; use `removeItem` or `multiRemove` to clear only your app's keys. Returns a `Promise` object. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| callback | (error) => void | No | Function that will be called with any error. | + + + + +--- + +### `getAllKeys()` + +```javascript +AsyncStorage.getAllKeys([callback]) +``` + +Gets *all* keys known to your app; for all callers, libraries, etc. +Returns a `Promise` object. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| callback | (error, keys) => void | No | Function that will be called with an array of keys found, and any error. | + + + + +--- + +### `flushGetRequests()` + +```javascript +AsyncStorage.flushGetRequests() +``` + +Flushes any pending requests using a single batch call to get the data. + +--- + +### `multiGet()` + +```javascript +AsyncStorage.multiGet(keys, [callback]) +``` + +This allows you to batch the fetching of items given an array of `key` inputs. Your callback will be invoked with an array of corresponding key-value pairs found: + +``` +multiGet(['k1', 'k2'], cb) -> cb([['k1', 'val1'], ['k2', 'val2']]) +``` + +The method returns a `Promise` object. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| keys | Array | Yes | Array of key for the items to get. | +| callback | (errors, result) => void | No | Function that will be called with a key-value array of the results, plus an array of any key-specific errors found. | + + + + + +--- + +### `multiSet()` + +```javascript +AsyncStorage.multiSet(keyValuePairs, [callback]) +``` + +Use this as a batch operation for storing multiple key-value pairs. When +the operation completes you'll get a single callback with any errors: + +``` +multiSet([['k1', 'val1'], ['k2', 'val2']], cb); +``` + +The method returns a `Promise` object. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| keyValuePairs | Array> | Yes | Array of key-value array for the items to set. | +| callback | (errors) => void | No | Function that will be called with an array of any key-specific errors found. | + + + + +--- + +### `multiRemove()` + +```javascript +AsyncStorage.multiRemove(keys, [callback]) +``` + +Call this to batch the deletion of all keys in the `keys` array. Returns +a `Promise` object. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| keys | Array | Yes | Array of key for the items to delete. | +| callback | (errors) => void | No | Function that will be called an array of any key-specific errors found. | + + + + +--- + +### `multiMerge()` + +```javascript +AsyncStorage.multiMerge(keyValuePairs, [callback]) +``` + +Batch operation to merge in existing and new values for a given set of +keys. This assumes that the values are stringified JSON. Returns a +`Promise` object. + +**NOTE**: This is not supported by all native implementations. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| keyValuePairs | Array> | Yes | Array of key-value array for the items to merge. | +| callback | (errors) => void | No | Function that will be called with an array of any key-specific errors found. | + + diff --git a/docs/backandroid.md b/docs/backandroid.md new file mode 100644 index 00000000000000..0dd040cd3525c7 --- /dev/null +++ b/docs/backandroid.md @@ -0,0 +1,56 @@ +--- +id: backandroid +title: BackAndroid +layout: docs +category: APIs +permalink: docs/backandroid.html +next: backhandler +previous: asyncstorage +--- + +**Deprecated.** Use [BackHandler](docs/backhandler.html) instead. + + +### Methods + +- [`exitApp`](docs/backandroid.html#exitapp) +- [`addEventListener`](docs/backandroid.html#addeventlistener) +- [`removeEventListener`](docs/backandroid.html#removeeventlistener) + + + + +--- + +# Reference + +## Methods + +### `exitApp()` + +```javascript +BackAndroid.exitApp() +``` + + + +--- + +### `addEventListener()` + +```javascript +BackAndroid.addEventListener(eventName, handler) +``` + + + +--- + +### `removeEventListener()` + +```javascript +BackAndroid.removeEventListener(eventName, handler) +``` + + + diff --git a/docs/backhandler.md b/docs/backhandler.md new file mode 100644 index 00000000000000..57f2a8b9e46805 --- /dev/null +++ b/docs/backhandler.md @@ -0,0 +1,79 @@ +--- +id: backhandler +title: BackHandler +layout: docs +category: APIs +permalink: docs/backhandler.html +next: cameraroll +previous: backhandler +--- + +Detect hardware button presses for back navigation. + +**Android:** Detect hardware back button presses, and programmatically invoke the default back button functionality to exit the app if there are no listeners or if none of the listeners return true. + +**tvOS:** Detect presses of the menu button on the TV remote. Still to be implemented: programmatically disable menu button handling functionality to exit the app if there are no listeners or if none of the listeners return true. + +**iOS:** Not applicable. + +The event subscriptions are called in reverse order (i.e. last registered subscription first), and if one subscription returns true then subscriptions registered earlier will not be called. + +Example: + +```javascript +BackHandler.addEventListener('hardwareBackPress', function() { + // this.onMainScreen and this.goBack are just examples, you need to use your own implementation here + // Typically you would use the navigator here to go to the last state. + + if (!this.onMainScreen()) { + this.goBack(); + return true; + } + return false; +}); +``` + + +### Methods + +- [`exitApp`](docs/backhandler.html#exitapp) +- [`addEventListener`](docs/backhandler.html#addeventlistener) +- [`removeEventListener`](docs/backhandler.html#removeeventlistener) + + + + +--- + +# Reference + +## Methods + +### `exitApp()` + +```javascript +BackHandler.exitApp() +``` + + + +--- + +### `addEventListener()` + +```javascript +BackHandler.addEventListener(eventName, handler) +``` + + + +--- + +### `removeEventListener()` + +```javascript +BackHandler.removeEventListener(eventName, handler) +``` + + + diff --git a/docs/BuildingForAppleTV.md b/docs/building-for-apple-tv.md similarity index 100% rename from docs/BuildingForAppleTV.md rename to docs/building-for-apple-tv.md diff --git a/docs/button.md b/docs/button.md new file mode 100644 index 00000000000000..e3eb4e881d089a --- /dev/null +++ b/docs/button.md @@ -0,0 +1,148 @@ +--- +id: button +title: Button +layout: docs +category: components +permalink: docs/button.html +next: checkbox +previous: activityindicator +--- +A basic button component that should render nicely on any platform. Supports +a minimal level of customization. + +
+ +If this button doesn't look right for your app, you can build your own +button using [TouchableOpacity](docs/touchableopacity.html) +or [TouchableNativeFeedback](docs/touchablenativefeedback.html). +For inspiration, look at the [source code for this button component](https://github.com/facebook/react-native/blob/master/Libraries/Components/Button.js). +Or, take a look at the [wide variety of button components built by the community](https://js.coach/react-native?search=button). + +Example usage: + +``` +import { Button } from 'react-native'; +... + +